mirror of
https://github.com/go-gitea/gitea
synced 2024-11-21 17:01:00 +01:00
Merge remote-tracking branch 'origin/main' into xormigrate
This commit is contained in:
commit
8f61053355
366 changed files with 9161 additions and 7885 deletions
|
@ -27,7 +27,6 @@ plugins:
|
|||
- "@stylistic/eslint-plugin-js"
|
||||
- "@typescript-eslint/eslint-plugin"
|
||||
- eslint-plugin-array-func
|
||||
- eslint-plugin-deprecation
|
||||
- eslint-plugin-github
|
||||
- eslint-plugin-i
|
||||
- eslint-plugin-no-jquery
|
||||
|
@ -248,6 +247,7 @@ rules:
|
|||
"@typescript-eslint/no-base-to-string": [0]
|
||||
"@typescript-eslint/no-confusing-non-null-assertion": [2]
|
||||
"@typescript-eslint/no-confusing-void-expression": [0]
|
||||
"@typescript-eslint/no-deprecated": [2]
|
||||
"@typescript-eslint/no-dupe-class-members": [0]
|
||||
"@typescript-eslint/no-duplicate-enum-values": [2]
|
||||
"@typescript-eslint/no-duplicate-type-constituents": [2, {ignoreUnions: true}]
|
||||
|
@ -359,7 +359,6 @@ rules:
|
|||
default-case-last: [2]
|
||||
default-case: [0]
|
||||
default-param-last: [0]
|
||||
deprecation/deprecation: [2]
|
||||
dot-notation: [0]
|
||||
eqeqeq: [2]
|
||||
for-direction: [2]
|
||||
|
@ -816,6 +815,7 @@ rules:
|
|||
unicorn/catch-error-name: [0]
|
||||
unicorn/consistent-destructuring: [2]
|
||||
unicorn/consistent-empty-array-spread: [2]
|
||||
unicorn/consistent-existence-index-check: [0]
|
||||
unicorn/consistent-function-scoping: [2]
|
||||
unicorn/custom-error-definition: [0]
|
||||
unicorn/empty-brace-spaces: [2]
|
||||
|
@ -892,10 +892,12 @@ rules:
|
|||
unicorn/prefer-dom-node-text-content: [2]
|
||||
unicorn/prefer-event-target: [2]
|
||||
unicorn/prefer-export-from: [0]
|
||||
unicorn/prefer-global-this: [0]
|
||||
unicorn/prefer-includes: [2]
|
||||
unicorn/prefer-json-parse-buffer: [0]
|
||||
unicorn/prefer-keyboard-event-key: [2]
|
||||
unicorn/prefer-logical-operator-over-ternary: [2]
|
||||
unicorn/prefer-math-min-max: [2]
|
||||
unicorn/prefer-math-trunc: [2]
|
||||
unicorn/prefer-modern-dom-apis: [0]
|
||||
unicorn/prefer-modern-math-apis: [2]
|
||||
|
|
27
assets/go-licenses.json
generated
27
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
|
@ -53,8 +53,6 @@ func (e Emoji) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
|
||||
flag.Parse()
|
||||
|
||||
// generate data
|
||||
|
@ -83,8 +81,6 @@ var replacer = strings.NewReplacer(
|
|||
var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
|
||||
|
||||
func generate() ([]byte, error) {
|
||||
var err error
|
||||
|
||||
// load gemoji data
|
||||
res, err := http.Get(gemojiURL)
|
||||
if err != nil {
|
||||
|
|
|
@ -324,6 +324,10 @@ RUN_USER = ; git
|
|||
;; Maximum number of locks returned per page
|
||||
;LFS_LOCKS_PAGING_NUM = 50
|
||||
;;
|
||||
;; When clients make lfs batch requests, reject them if there are more pointers than this number
|
||||
;; zero means 'unlimited'
|
||||
;LFS_MAX_BATCH_SIZE = 0
|
||||
;;
|
||||
;; Allow graceful restarts using SIGHUP to fork
|
||||
;ALLOW_GRACEFUL_RESTARTS = true
|
||||
;;
|
||||
|
@ -2638,6 +2642,16 @@ LEVEL = Info
|
|||
;; override the azure blob base path if storage type is azureblob
|
||||
;AZURE_BLOB_BASE_PATH = lfs/
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; settings for Gitea's LFS client (eg: mirroring an upstream lfs endpoint)
|
||||
;;
|
||||
;[lfs_client]
|
||||
;; Limit the number of pointers in each batch request to this number
|
||||
;BATCH_SIZE = 20
|
||||
;; Limit the number of concurrent upload/download operations within a batch
|
||||
;BATCH_OPERATION_CONCURRENCY = 8
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; settings for packages, will override storage setting
|
||||
|
|
193
go.mod
193
go.mod
|
@ -10,9 +10,9 @@ godebug x509negativeserial=1
|
|||
require (
|
||||
code.gitea.io/actions-proto-go v0.4.0
|
||||
code.gitea.io/gitea-vet v0.2.3
|
||||
code.gitea.io/sdk/gitea v0.17.1
|
||||
code.gitea.io/sdk/gitea v0.19.0
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||
connectrpc.com/connect v1.15.0
|
||||
connectrpc.com/connect v1.17.0
|
||||
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
|
||||
gitea.com/go-chi/cache v0.2.1
|
||||
gitea.com/go-chi/captcha v0.0.0-20240315150714-fb487f629098
|
||||
|
@ -20,21 +20,21 @@ require (
|
|||
gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
|
||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
||||
github.com/42wim/httpsig v1.2.2
|
||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2
|
||||
github.com/42wim/sshsig v0.0.0-20240818000253-e3a6333df815
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||
github.com/ProtonMail/go-crypto v1.0.0
|
||||
github.com/PuerkitoBio/goquery v1.9.2
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
|
||||
github.com/PuerkitoBio/goquery v1.10.0
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3
|
||||
github.com/alecthomas/chroma/v2 v2.14.0
|
||||
github.com/aws/aws-sdk-go v1.43.21
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.25.1
|
||||
github.com/aws/aws-sdk-go v1.55.5
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.42
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.27.3
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.4.2
|
||||
github.com/buildkite/terminal-to-html/v3 v3.12.1
|
||||
github.com/caddyserver/certmagic v0.21.3
|
||||
github.com/buildkite/terminal-to-html/v3 v3.16.3
|
||||
github.com/caddyserver/certmagic v0.21.4
|
||||
github.com/charmbracelet/git-lfs-transfer v0.2.0
|
||||
github.com/chi-middleware/proxy v1.1.1
|
||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
|
||||
|
@ -46,53 +46,53 @@ require (
|
|||
github.com/emersion/go-imap v1.2.1
|
||||
github.com/emirpasic/gods v1.18.1
|
||||
github.com/ethantkoenig/rupture v1.0.1
|
||||
github.com/felixge/fgprof v0.9.4
|
||||
github.com/felixge/fgprof v0.9.5
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/gliderlabs/ssh v0.3.7
|
||||
github.com/go-ap/activitypub v0.0.0-20240408091739-ba76b44c2594
|
||||
github.com/go-ap/activitypub v0.0.0-20240910141749-b4b8c8aa484c
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||
github.com/go-chi/chi/v5 v5.0.13
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-co-op/gocron v1.37.0
|
||||
github.com/go-enry/go-enry/v2 v2.9.1
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-billy/v5 v5.6.0
|
||||
github.com/go-git/go-git/v5 v5.12.0
|
||||
github.com/go-ldap/ldap/v3 v3.4.6
|
||||
github.com/go-ldap/ldap/v3 v3.4.8
|
||||
github.com/go-redsync/redsync/v4 v4.13.0
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/go-swagger/go-swagger v0.31.0
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.11.0
|
||||
github.com/go-webauthn/webauthn v0.10.2
|
||||
github.com/go-webauthn/webauthn v0.11.2
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
|
||||
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/google/go-github/v61 v61.0.0
|
||||
github.com/google/licenseclassifier/v2 v2.0.0
|
||||
github.com/google/pprof v0.0.0-20240618054019-d3b898a103f8
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/feeds v1.2.0
|
||||
github.com/gorilla/sessions v1.3.0
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
github.com/h2non/gock v1.2.0
|
||||
github.com/hashicorp/go-version v1.7.0
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||
github.com/huandu/xstrings v1.5.0
|
||||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056
|
||||
github.com/jhillyerd/enmime v1.2.0
|
||||
github.com/jhillyerd/enmime v1.3.0
|
||||
github.com/json-iterator/go v1.1.12
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4
|
||||
github.com/klauspost/compress v1.17.9
|
||||
github.com/klauspost/compress v1.17.11
|
||||
github.com/klauspost/cpuid/v2 v2.2.8
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/markbates/goth v1.80.0
|
||||
github.com/mattn/go-isatty v0.0.20
|
||||
github.com/mattn/go-sqlite3 v1.14.22
|
||||
github.com/meilisearch/meilisearch-go v0.26.3
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
github.com/meilisearch/meilisearch-go v0.29.0
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
github.com/microcosm-cc/bluemonday v1.0.27
|
||||
github.com/microsoft/go-mssqldb v1.7.2
|
||||
github.com/minio/minio-go/v7 v7.0.77
|
||||
github.com/minio/minio-go/v7 v7.0.80
|
||||
github.com/msteinert/pam v1.2.0
|
||||
github.com/nektos/act v0.2.63
|
||||
github.com/niklasfasching/go-org v1.7.0
|
||||
|
@ -101,9 +101,9 @@ require (
|
|||
github.com/opencontainers/image-spec v1.1.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/quasoft/websspi v1.1.2
|
||||
github.com/redis/go-redis/v9 v9.6.0
|
||||
github.com/redis/go-redis/v9 v9.7.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
|
||||
github.com/sassoftware/go-rpmutils v0.4.0
|
||||
|
@ -113,22 +113,23 @@ require (
|
|||
github.com/syndtr/goleveldb v1.0.0
|
||||
github.com/tstranex/u2f v1.0.0
|
||||
github.com/ulikunitz/xz v0.5.12
|
||||
github.com/urfave/cli/v2 v2.27.2
|
||||
github.com/xanzy/go-gitlab v0.105.0
|
||||
github.com/urfave/cli/v2 v2.27.5
|
||||
github.com/xanzy/go-gitlab v0.112.0
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/yohcop/openid-go v1.0.1
|
||||
github.com/yuin/goldmark v1.7.2
|
||||
github.com/yuin/goldmark v1.7.8
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||
github.com/yuin/goldmark-meta v1.1.0
|
||||
golang.org/x/crypto v0.26.0
|
||||
golang.org/x/image v0.18.0
|
||||
golang.org/x/net v0.28.0
|
||||
golang.org/x/oauth2 v0.21.0
|
||||
golang.org/x/sys v0.24.0
|
||||
golang.org/x/text v0.17.0
|
||||
golang.org/x/tools v0.24.0
|
||||
google.golang.org/grpc v1.62.1
|
||||
google.golang.org/protobuf v1.34.2
|
||||
golang.org/x/crypto v0.28.0
|
||||
golang.org/x/image v0.21.0
|
||||
golang.org/x/net v0.30.0
|
||||
golang.org/x/oauth2 v0.23.0
|
||||
golang.org/x/sync v0.8.0
|
||||
golang.org/x/sys v0.26.0
|
||||
golang.org/x/text v0.19.0
|
||||
golang.org/x/tools v0.26.0
|
||||
google.golang.org/grpc v1.67.1
|
||||
google.golang.org/protobuf v1.35.1
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
|
@ -140,37 +141,37 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.3.0 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.5.2 // indirect
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect
|
||||
github.com/ClickHouse/ch-go v0.61.5 // indirect
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.25.0 // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||
github.com/ClickHouse/ch-go v0.63.1 // indirect
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.24.0 // indirect
|
||||
github.com/DataDog/zstd v1.5.6 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.3.0 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.3.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.9.4 // indirect
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/andybalholm/brotli v1.1.1 // indirect
|
||||
github.com/andybalholm/cascadia v1.3.2 // 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.30.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect
|
||||
github.com/aws/smithy-go v1.20.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect
|
||||
github.com/aws/smithy-go v1.22.0 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.1.10 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.14.3 // indirect
|
||||
github.com/blevesearch/bleve_index_api v1.1.12 // indirect
|
||||
github.com/blevesearch/geo v0.1.20 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.20 // indirect
|
||||
github.com/blevesearch/go-faiss v1.0.23 // indirect
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.15 // indirect
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 // indirect
|
||||
github.com/blevesearch/segment v0.9.1 // indirect
|
||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||
|
@ -179,29 +180,29 @@ require (
|
|||
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.1.5 // indirect
|
||||
github.com/boombuler/barcode v1.0.1 // indirect
|
||||
github.com/blevesearch/zapx/v15 v15.3.16 // indirect
|
||||
github.com/blevesearch/zapx/v16 v16.1.7 // indirect
|
||||
github.com/boombuler/barcode v1.0.2 // indirect
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.9 // indirect
|
||||
github.com/cloudflare/circl v1.5.0 // indirect
|
||||
github.com/couchbase/go-couchbase v0.1.1 // indirect
|
||||
github.com/couchbase/gomemcached v0.3.1 // indirect
|
||||
github.com/couchbase/gomemcached v0.3.2 // indirect
|
||||
github.com/couchbase/goutils v0.1.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dlclark/regexp2 v1.11.0 // indirect
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
|
||||
github.com/fatih/color v1.17.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.11.4 // 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.6.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 // indirect
|
||||
github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0 // indirect
|
||||
github.com/go-ap/errors v0.0.0-20240910140019-1e9d33cc1568 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
||||
github.com/go-enry/go-oniguruma v1.2.1 // indirect
|
||||
github.com/go-faster/city v1.0.1 // indirect
|
||||
|
@ -220,7 +221,7 @@ require (
|
|||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-webauthn/x v0.1.9 // indirect
|
||||
github.com/go-webauthn/x v0.1.15 // indirect
|
||||
github.com/goccy/go-json v0.10.3 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
|
@ -229,9 +230,9 @@ require (
|
|||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/go-tpm v0.9.0 // indirect
|
||||
github.com/google/go-tpm v0.9.1 // 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
|
||||
|
@ -242,9 +243,8 @@ require (
|
|||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jessevdk/go-flags v1.5.0 // 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
|
||||
|
@ -255,9 +255,9 @@ require (
|
|||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/markbates/going v1.0.3 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mholt/acmez/v2 v2.0.1 // indirect
|
||||
github.com/miekg/dns v1.1.61 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mholt/acmez/v2 v2.0.3 // indirect
|
||||
github.com/miekg/dns v1.1.62 // 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
|
||||
|
@ -271,38 +271,35 @@ require (
|
|||
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/onsi/gomega v1.33.1 // indirect
|
||||
github.com/paulmach/orb v0.11.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.21 // indirect
|
||||
github.com/pjbgf/sha1cd v0.3.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/common v0.60.1 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/rhysd/actionlint v1.7.1 // indirect
|
||||
github.com/rhysd/actionlint v1.7.3 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/segmentio/asm v1.2.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.2.2 // indirect
|
||||
github.com/skeema/knownhosts v1.3.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.18.2 // indirect
|
||||
github.com/spf13/viper v1.19.0 // 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/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.55.0 // indirect
|
||||
github.com/valyala/fastjson v1.6.4 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
|
@ -310,19 +307,19 @@ require (
|
|||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.etcd.io/bbolt v1.3.10 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel v1.27.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.27.0 // indirect
|
||||
github.com/zeebo/assert v1.3.0 // indirect
|
||||
github.com/zeebo/blake3 v0.2.4 // indirect
|
||||
go.etcd.io/bbolt v1.3.11 // indirect
|
||||
go.mongodb.org/mongo-driver v1.17.1 // indirect
|
||||
go.opentelemetry.io/otel v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.31.0 // 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
|
||||
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f // indirect
|
||||
golang.org/x/mod v0.20.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
|
460
go.sum
460
go.sum
|
@ -1,17 +1,17 @@
|
|||
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
|
||||
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/compute/metadata v0.5.2 h1:UxK4uu/Tn+I3p2dYWTfiX4wva7aYlKixAHn3fyqngqo=
|
||||
cloud.google.com/go/compute/metadata v0.5.2/go.mod h1:C66sj2AluDcIqakBq/M8lw8/ybHgOZqin2obFxa/E5k=
|
||||
code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
|
||||
code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
||||
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
|
||||
code.gitea.io/gitea-vet v0.2.3/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE=
|
||||
code.gitea.io/sdk/gitea v0.17.1 h1:3jCPOG2ojbl8AcfaUCRYLT5MUcBMFwS0OSK2mA5Zok8=
|
||||
code.gitea.io/sdk/gitea v0.17.1/go.mod h1:aCnBqhHpoEWA180gMbaCtdX9Pl6BWBAuuP2miadoTNM=
|
||||
code.gitea.io/sdk/gitea v0.19.0 h1:8I6s1s4RHgzxiPHhOQdgim1RWIRcr0LVMbHBjBFXq4Y=
|
||||
code.gitea.io/sdk/gitea v0.19.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570/go.mod h1:IIAjsijsd8q1isWX8MACefDEgTQslQ4stk2AeeTt3kM=
|
||||
connectrpc.com/connect v1.15.0 h1:lFdeCbZrVVDydAqwr4xGV2y+ULn+0Z73s5JBj2LikWo=
|
||||
connectrpc.com/connect v1.15.0/go.mod h1:bQmjpDY8xItMnttnurVgOkHUBMRT9cpsNi2O4AjKhmA=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
connectrpc.com/connect v1.17.0 h1:W0ZqMhtVzn9Zhn2yATuUokDLO5N+gIuBWMOnsQrfmZk=
|
||||
connectrpc.com/connect v1.17.0/go.mod h1:0292hj1rnx8oFrStN7cB4jjVBeqs+Yx5yDIC2prWDO8=
|
||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||
|
@ -37,60 +37,59 @@ gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0p
|
|||
gitee.com/travelliu/dm v1.8.11192/go.mod h1:DHTzyhCrM843x9VdKVbZ+GKXGRbKM2sJ4LxihRxShkE=
|
||||
github.com/42wim/httpsig v1.2.2 h1:ofAYoHUNs/MJOLqQ8hIxeyz2QxOz8qdSVvp3PX/oPgA=
|
||||
github.com/42wim/httpsig v1.2.2/go.mod h1:P/UYo7ytNBFwc+dg35IubuAUIs8zj5zzFIgUCEl55WY=
|
||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121 h1:r3qt8PCHnfjOv9PN3H+XXKmDA1dfFMIN1AislhlA/ps=
|
||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121/go.mod h1:Ock8XgA7pvULhIaHGAk/cDnRfNrF9Jey81nPcc403iU=
|
||||
github.com/42wim/sshsig v0.0.0-20240818000253-e3a6333df815 h1:5EoemV++kUK2Sw98yWP/RWyduvP7IaBgWWHe+4BWcSw=
|
||||
github.com/42wim/sshsig v0.0.0-20240818000253-e3a6333df815/go.mod h1:zjsWZdDLrcDojDIfpQg7A6J4YZLT0cbwuAD26AppDBo=
|
||||
github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U=
|
||||
github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0/go.mod h1:T5RfihdXtBDxt1Ch2wobif3TvzTdumDy29kahv6AV9A=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1/go.mod h1:GpPjLhVR9dnUoJMyHWSPy71xY9/lcmpzIPZXmF0FCVY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 h1:YUUxeiOWgdAQE3pXt2H7QXzZs0q8UBjgRbl56qo8GYM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2/go.mod h1:dmXQgZuiSubAecswZE+Sm8jkvEa7kQgTPVRvwL/nd0E=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1 h1:cf+OIKbkmMHBaC3u78AXomweqM0oxQSgBXRZf3WH4yM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1/go.mod h1:ap1dmS6vQKJxSMNiGJcq4QuUQkOynyD93gLw6MDF7ek=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4=
|
||||
github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.25.0 h1:rKscwqgQHzWBTZySZDcHKxgs0Ad+xFULfZvo26W5UlY=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.25.0/go.mod h1:iDTViXk2Fgvf1jn2dbJd1ys+fBkdD1UMRnXlwmhijhQ=
|
||||
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
|
||||
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
github.com/ClickHouse/ch-go v0.63.1 h1:s2JyZvWLTCSAGdtjMBBmAgQQHMco6pawLJMOXi0FODM=
|
||||
github.com/ClickHouse/ch-go v0.63.1/go.mod h1:I1kJJCL3WJcBMGe1m+HVK0+nREaG+JOYYBWjrDrF3R0=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.24.0 h1:L/n/pVVpk95KtkHOiKuSnO7cu2ckeW4gICbbOh5qs74=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.24.0/go.mod h1:iDTViXk2Fgvf1jn2dbJd1ys+fBkdD1UMRnXlwmhijhQ=
|
||||
github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY=
|
||||
github.com/DataDog/zstd v1.5.6/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.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
|
||||
github.com/Masterminds/semver/v3 v3.3.0/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=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE=
|
||||
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
|
||||
github.com/PuerkitoBio/goquery v1.10.0 h1:6fiXdLuUvYs2OJSvNRqlNPoBm6YABE226xrbavY5Wv4=
|
||||
github.com/PuerkitoBio/goquery v1.10.0/go.mod h1:TjZZl68Q3eGHNBA8CWaxAN7rOU1EbDz3CWuolcO5Yu4=
|
||||
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||
github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I=
|
||||
github.com/RoaringBitmap/roaring v1.9.4 h1:yhEIoH4YezLYT04s1nHehNO64EKFTop/wBhxv2QzDdQ=
|
||||
github.com/RoaringBitmap/roaring v1.9.4/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2 h1:cSXom2MoKJ9KPPw29RoZtHvUETY4F4n/kXl8m9btnQ0=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2/go.mod h1:JitQWJ8JuV4Y87l8VsHiiwhb3cgdyn68mX40s7NT6PA=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3 h1:BP0HiyNT3AQEYi+if3wkRcIdQFHtsw6xX3Kx0glckgA=
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.3/go.mod h1:hMNtySovKkn2gdDuLqnqveP+mfhUSaBdoBcr2I7Zt0E=
|
||||
github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE=
|
||||
github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
|
@ -99,14 +98,14 @@ github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4E
|
|||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
|
||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
|
||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58PaB6aA=
|
||||
github.com/anchore/archiver/v3 v3.5.2/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
|
||||
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
|
||||
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
|
@ -116,20 +115,20 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
|
|||
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 v1.43.21 h1:E4S2eX3d2gKJyI/ISrcIrSwXwqjIvCK85gtBMt4sAPE=
|
||||
github.com/aws/aws-sdk-go v1.43.21/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30 h1:aau/oYFtibVovr2rDt8FHlU17BTicFEMAi29V1U+L5Q=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.30/go.mod h1:BPJ/yXV92ZVq6G8uYvbU0gSl8q94UB63nMT5ctNO38g=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.25.1 h1:mOOALIM4JzhYkq3voCBbmZqmyEVEhHsfasMTbVxLkNs=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.25.1/go.mod h1:6zf5j3mIUXKM0s2iz5ttR2Qwq+o47D0jotpAyaKgZRA=
|
||||
github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4=
|
||||
github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
|
||||
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.42 h1:sBP0RPjBU4neGpIYyx8mkU2QqLPl5u9cmdTWVzIpHkM=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.42/go.mod h1:FwZBfU530dJ26rv9saAbxa9Ej3eF/AK0OAY86k13n4M=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 h1:Jw50LwEkVjuVzE1NzkhNKkBf9cRN7MtE1F/b2cOKTUM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22/go.mod h1:Y/SmAyPcOTmpeVaWSzSKiILfXTVJwrGmYZhcRbhWuEY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 h1:981MHwBaRZM7+9QSR6XamDzF/o7ouUGxFzr+nVSIhrs=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22/go.mod h1:1RA1+aBEfn+CAB/Mh0MB6LsdCYCnjZm7tKXtnk499ZQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.27.3 h1:NbAYtQnTXzv4u5uesdDhXGWDTsEtTyFXlzfXELtI6cc=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.27.3/go.mod h1:ZhgiuB7I3d3UU6PnCWwb0IYFgGzJz0VT+DK3Xv1xtF8=
|
||||
github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM=
|
||||
github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
|
@ -137,20 +136,20 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||
github.com/bits-and-blooms/bitset v1.1.10/go.mod h1:w0XsmFg8qg6cmpTtJ0z3pKgjTDBMMnI/+I2syrE6XBE=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
|
||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.14.3 h1:Gd2c8lSNf9pKXom5JtD7AaKO8o7fGQ2LtFj1436qilA=
|
||||
github.com/bits-and-blooms/bitset v1.14.3/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||
github.com/blevesearch/bleve/v2 v2.0.5/go.mod h1:ZjWibgnbRX33c+vBRgla9QhPb4QOjD6fdVJ+R1Bk8LM=
|
||||
github.com/blevesearch/bleve/v2 v2.4.2 h1:NooYP1mb3c0StkiY9/xviiq2LGSaE8BQBCc/pirMx0U=
|
||||
github.com/blevesearch/bleve/v2 v2.4.2/go.mod h1:ATNKj7Yl2oJv/lGuF4kx39bST2dveX6w0th2FFYLkc8=
|
||||
github.com/blevesearch/bleve_index_api v1.0.0/go.mod h1:fiwKS0xLEm+gBRgv5mumf0dhgFr2mDgZah1pqv1c1M4=
|
||||
github.com/blevesearch/bleve_index_api v1.1.10 h1:PDLFhVjrjQWr6jCuU7TwlmByQVCSEURADHdCqVS9+g0=
|
||||
github.com/blevesearch/bleve_index_api v1.1.10/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
|
||||
github.com/blevesearch/bleve_index_api v1.1.12 h1:P4bw9/G/5rulOF7SJ9l4FsDoo7UFJ+5kexNy1RXfegY=
|
||||
github.com/blevesearch/bleve_index_api v1.1.12/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
|
||||
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
|
||||
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
||||
github.com/blevesearch/go-faiss v1.0.20 h1:AIkdTQFWuZ5LQmKQSebgMR4RynGNw8ZseJXaan5kvtI=
|
||||
github.com/blevesearch/go-faiss v1.0.20/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8=
|
||||
github.com/blevesearch/go-faiss v1.0.23 h1:Wmc5AFwDLKGl2L6mjLX1Da3vCL0EKa2uHHSorcIS1Uc=
|
||||
github.com/blevesearch/go-faiss v1.0.23/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||
|
@ -159,8 +158,8 @@ github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+
|
|||
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.0.1/go.mod h1:lq7yK2jQy1yQjtjTfU931aVqz7pYxEudHaDwOt1tXfU=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.15 h1:prV17iU/o+A8FiZi9MXmqbagd8I0bCqM7OKUYPbnb5Y=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.15/go.mod h1:db0cmP03bPNadXrCDuVkKLV6ywFSiRgPFT1YVrestBc=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 h1:uGvKVvG7zvSxCwcm4/ehBa9cCEuZVE+/zvrSl57QUVY=
|
||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16/go.mod h1:VF5oHVbIFTu+znY1v30GjSpT5+9YFs9dV2hjvuh34F0=
|
||||
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
|
||||
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||
|
@ -186,24 +185,24 @@ github.com/blevesearch/zapx/v14 v14.2.0/go.mod h1:GNgZusc1p4ot040cBQMRGEZobvwjCq
|
|||
github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU=
|
||||
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
|
||||
github.com/blevesearch/zapx/v15 v15.2.0/go.mod h1:MmQceLpWfME4n1WrBFIwplhWmaQbQqLQARpaKUEOs/A=
|
||||
github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ=
|
||||
github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
||||
github.com/blevesearch/zapx/v16 v16.1.5 h1:b0sMcarqNFxuXvjoXsF8WtwVahnxyhEvBSRJi/AUHjU=
|
||||
github.com/blevesearch/zapx/v16 v16.1.5/go.mod h1:J4mSF39w1QELc11EWRSBFkPeZuO7r/NPKkHzDCoiaI8=
|
||||
github.com/blevesearch/zapx/v15 v15.3.16 h1:Ct3rv7FUJPfPk99TI/OofdC+Kpb4IdyfdMH48sb+FmE=
|
||||
github.com/blevesearch/zapx/v15 v15.3.16/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
||||
github.com/blevesearch/zapx/v16 v16.1.7 h1:I07qV6l1rPda19zyof9Q2J9E8cjZ57pQhNY0+ePI5vM=
|
||||
github.com/blevesearch/zapx/v16 v16.1.7/go.mod h1:JqQlOqlRVaYDkpLIl3JnKql8u4zKTNlVEa3nLsi0Gn8=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
|
||||
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/buildkite/terminal-to-html/v3 v3.12.1 h1:Wwec2uOu35zNPEQTzDyXQPyr/VUW6lzEwiYede1CaoE=
|
||||
github.com/buildkite/terminal-to-html/v3 v3.12.1/go.mod h1:PfNtCsLnMZs7X9X2gcngOutmgSp7/oGBUIpVzRnD09A=
|
||||
github.com/buildkite/terminal-to-html/v3 v3.16.3 h1:IGuJjboHjuMLWOGsKZKNxbbn41emOLiHzXPmQZk31fk=
|
||||
github.com/buildkite/terminal-to-html/v3 v3.16.3/go.mod h1:r/J7cC9c3EzBzP3/wDz0RJLPwv5PUAMp+KF2w+ntMc0=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/caddyserver/certmagic v0.21.3 h1:pqRRry3yuB4CWBVq9+cUqu+Y6E2z8TswbhNx1AZeYm0=
|
||||
github.com/caddyserver/certmagic v0.21.3/go.mod h1:Zq6pklO9nVRl3DIFUw9gVUfXKdpc/0qwTUAQMBlfgtI=
|
||||
github.com/caddyserver/certmagic v0.21.4 h1:e7VobB8rffHv8ZZpSiZtEwnLDHUwLVYLWzWSa1FfKI0=
|
||||
github.com/caddyserver/certmagic v0.21.4/go.mod h1:swUXjQ1T9ZtMv95qj7/InJvWLXURU85r+CfG0T+ZbDE=
|
||||
github.com/caddyserver/zerossl v0.1.3 h1:onS+pxp3M8HnHpN5MMbOMyNjmTheJyWRaZYwn+YTAyA=
|
||||
github.com/caddyserver/zerossl v0.1.3/go.mod h1:CxA0acn7oEGO6//4rtrRjYgEoa4MFw/XofZnrYwGqG4=
|
||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
|
||||
|
@ -222,8 +221,8 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk
|
|||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE=
|
||||
github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
|
||||
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
|
@ -233,18 +232,18 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7
|
|||
github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k=
|
||||
github.com/couchbase/go-couchbase v0.1.1 h1:ClFXELcKj/ojyoTYbsY34QUrrYCBi/1G749sXSCkdhk=
|
||||
github.com/couchbase/go-couchbase v0.1.1/go.mod h1:+/bddYDxXsf9qt0xpDUtRR47A2GjaXmGGAqQ/k3GJ8A=
|
||||
github.com/couchbase/gomemcached v0.3.1 h1:jfspNuQIXgWy+5GUPQrsQ6yC5uJCfMmd/JKvK6C26r8=
|
||||
github.com/couchbase/gomemcached v0.3.1/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
|
||||
github.com/couchbase/gomemcached v0.3.2 h1:08rxiOoNcv0x5LTxgcYhnx1aPvV7iEtfeyUgqsJyPk0=
|
||||
github.com/couchbase/gomemcached v0.3.2/go.mod h1:mxliKQxOv84gQ0bJWbI+w9Wxdpt9HjDvgW9MjCym5Vo=
|
||||
github.com/couchbase/goutils v0.1.2 h1:gWr8B6XNWPIhfalHNog3qQKfGiYyh4K4VhO3P2o9BCs=
|
||||
github.com/couchbase/goutils v0.1.2/go.mod h1:h89Ek/tiOxxqjz30nPPlwZdQbdB8BwgnuBxeoUe/ViE=
|
||||
github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.5 h1:6iR5tXJ/e6tJZzzdMc1km3Sa7RRIVBKAK32O2s7AYfo=
|
||||
github.com/cyphar/filepath-securejoin v0.2.5/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4 h1:VBWugsJh2ZxJmLFSM06/0qzQyiQX2Qs0ViKrUAcqdZ8=
|
||||
github.com/cyphar/filepath-securejoin v0.3.4/go.mod h1:8s/MCNJREmFK0H02MF6Ihv1nakJe4L/w3WZLHNkvlYM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
|
@ -265,8 +264,8 @@ github.com/djherbis/nio/v3 v3.0.1/go.mod h1:Ng4h80pbZFMla1yKzm61cF0tqqilXZYrogmW
|
|||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
|
||||
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.11.4 h1:rPYF9/LECdNymJufQKmri9gV604RvvABwgOA8un7yAo=
|
||||
github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
|
@ -284,17 +283,17 @@ github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjT
|
|||
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
|
||||
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
|
||||
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY=
|
||||
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk=
|
||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/ethantkoenig/rupture v1.0.1 h1:6aAXghmvtnngMgQzy7SMGdicMvkV86V4n9fT0meE5E4=
|
||||
github.com/ethantkoenig/rupture v1.0.1/go.mod h1:Sjqo/nbffZp1pVVXNGhpugIjsWmuS9KiIB4GtpEBur4=
|
||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
||||
github.com/felixge/fgprof v0.9.4 h1:ocDNwMFlnA0NU0zSB3I52xkO4sFXk80VK9lXjLClu88=
|
||||
github.com/felixge/fgprof v0.9.4/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
|
||||
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=
|
||||
|
@ -305,26 +304,26 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo
|
|||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA=
|
||||
github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1 h1:mtDjlmloH7ytdblogrMz1/8Hqua1y8B4ID+bh3rvod0=
|
||||
github.com/git-lfs/pktline v0.0.0-20230103162542-ca444d533ef1/go.mod h1:fenKRzpXDjNpsIBhuhUzvjCKlDjKam0boRAenTE0Q6A=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-ap/activitypub v0.0.0-20240408091739-ba76b44c2594 h1:er3GvGCm7bJwHostjZlsRy7uiUuCquUVF9Fe0TrwiPI=
|
||||
github.com/go-ap/activitypub v0.0.0-20240408091739-ba76b44c2594/go.mod h1:yRUfFCoZY6C1CWalauqEQ5xYgSckzEBEO/2MBC6BOME=
|
||||
github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0 h1:H9MGShwybHLSln6K8RxHPMHiLcD86Lru+5TVW2TcXHY=
|
||||
github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0/go.mod h1:5x8a6P/dhmMGFxWLcyYlyOuJ2lRNaHGhRv+yu8BaTSI=
|
||||
github.com/go-ap/activitypub v0.0.0-20240910141749-b4b8c8aa484c h1:82lzmsy5Nr6JA6HcLRVxGfbdSoWfW45C6jnY3zFS7Ks=
|
||||
github.com/go-ap/activitypub v0.0.0-20240910141749-b4b8c8aa484c/go.mod h1:rpIPGre4qtTgSpVT0zz3hycAMuLtUt7BNngVNpyXhL8=
|
||||
github.com/go-ap/errors v0.0.0-20240910140019-1e9d33cc1568 h1:eQEXAzWEijFbwtm/Hr2EtFbM0LvATRd1ltpDb+mfjQk=
|
||||
github.com/go-ap/errors v0.0.0-20240910140019-1e9d33cc1568/go.mod h1:Vkh+Z3f24K8nMsJKXo1FHn5ebPsXvB/WDH5JRtYqdNo=
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 h1:GMKIYXyXPGIp+hYiWOhfqK4A023HdgisDT4YGgf99mw=
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.0.13 h1:JlH2F2M8qnwl0N1+JFFzlX9TlKJYas3aPXdiuTmJL+w=
|
||||
github.com/go-chi/chi/v5 v5.0.13/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0=
|
||||
|
@ -337,13 +336,12 @@ github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw=
|
|||
github.com/go-faster/city v1.0.1/go.mod h1:jKcUJId49qdW3L1qKHH/3wPeUstCVpVSXTM6vO3VcTw=
|
||||
github.com/go-faster/errors v0.7.1 h1:MkJTnDoEdi9pDabt1dpWf7AA8/BaSYZqibYyhZ20AYg=
|
||||
github.com/go-faster/errors v0.7.1/go.mod h1:5ySTjWFiphBs07IKuiL69nxdfd5+fzh1u7FPGZP2quo=
|
||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e h1:oRq/fiirun5HqlEWMLIcDmLpIELlG4iGbd0s8iqgPi8=
|
||||
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
|
||||
github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
|
||||
github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
|
||||
github.com/go-git/go-billy/v5 v5.6.0 h1:w2hPNtoehvJIxR00Vb4xX94qHQi/ApZfX+nBE2Cjio8=
|
||||
github.com/go-git/go-billy/v5 v5.6.0/go.mod h1:sFDq7xD3fn3E0GOwUSZqHo9lrkmx8xJhA0ZrfvjBRGM=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
|
||||
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
|
||||
github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys=
|
||||
|
@ -351,8 +349,8 @@ github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXY
|
|||
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-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
|
||||
github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A=
|
||||
github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc=
|
||||
github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ=
|
||||
github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
|
||||
|
@ -395,10 +393,10 @@ 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-testfixtures/testfixtures/v3 v3.11.0 h1:XxQr8AnPORcZkyNd7go5UNLPD3dULN8ixYISlzrlfEQ=
|
||||
github.com/go-testfixtures/testfixtures/v3 v3.11.0/go.mod h1:THmudHF1Ixq++J2/UodcJpxUphfyEd77m83TvDtryqE=
|
||||
github.com/go-webauthn/webauthn v0.10.2 h1:OG7B+DyuTytrEPFmTX503K77fqs3HDK/0Iv+z8UYbq4=
|
||||
github.com/go-webauthn/webauthn v0.10.2/go.mod h1:Gd1IDsGAybuvK1NkwUTLbGmeksxuRJjVN2PE/xsPxHs=
|
||||
github.com/go-webauthn/x v0.1.9 h1:v1oeLmoaa+gPOaZqUdDentu6Rl7HkSSsmOT6gxEQHhE=
|
||||
github.com/go-webauthn/x v0.1.9/go.mod h1:pJNMlIMP1SU7cN8HNlKJpLEnFHCygLCvaLZ8a1xeoQA=
|
||||
github.com/go-webauthn/webauthn v0.11.2 h1:Fgx0/wlmkClTKlnOsdOQ+K5HcHDsDcYIvtYmfhEOSUc=
|
||||
github.com/go-webauthn/webauthn v0.11.2/go.mod h1:aOtudaF94pM71g3jRwTYYwQTG1KyTILTcZqN1srkmD0=
|
||||
github.com/go-webauthn/x v0.1.15 h1:eG1OhggBJTkDE8gUeOlGRbRe8E/PSVG26YG4AyFbwkU=
|
||||
github.com/go-webauthn/x v0.1.15/go.mod h1:pf7VI23raFLHPO9VVIs9/u1etqwAOP0S2KoHGL6WbZ8=
|
||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
|
@ -444,8 +442,8 @@ github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
|||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
|
||||
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
|
@ -459,8 +457,8 @@ github.com/google/go-github/v61 v61.0.0 h1:VwQCBwhyE9JclCI+22/7mLB1PuU9eowCXKY5p
|
|||
github.com/google/go-github/v61 v61.0.0/go.mod h1:0WR+KmsWX75G2EbpyGsGmradjo3IiciuI4BmdVCobQY=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk=
|
||||
github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU=
|
||||
github.com/google/go-tpm v0.9.1 h1:0pGc4X//bAlmZzMKf8iz6IsDo1nYTbYJ6FZN/rg4zdM=
|
||||
github.com/google/go-tpm v0.9.1/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
|
@ -468,12 +466,10 @@ github.com/google/licenseclassifier/v2 v2.0.0 h1:1Y57HHILNf4m0ABuMVb6xk4vAJYEUO0
|
|||
github.com/google/licenseclassifier/v2 v2.0.0/go.mod h1:cOjbdH0kyC9R22sdQbYsFkto4NGCAc+ZSwbeThazEtM=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20240618054019-d3b898a103f8 h1:ASJ/LAqdCHOyMYI+dwNxn7Rd8FscNkMyTr1KZU1JI/M=
|
||||
github.com/google/pprof v0.0.0-20240618054019-d3b898a103f8/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
|
@ -496,8 +492,9 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+
|
|||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/sessions v1.3.0 h1:XYlkq7KcpOB2ZhHBPv5WpjMIxrQosiZanfoy1HLZFzg=
|
||||
github.com/gorilla/sessions v1.3.0/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
||||
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
||||
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
||||
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
|
@ -513,6 +510,9 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l
|
|||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
|
@ -520,14 +520,10 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
|
|||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
|
||||
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
|
||||
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
|
||||
|
@ -585,13 +581,24 @@ github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 h1:iCHtR9CQykt
|
|||
github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jhillyerd/enmime v1.2.0 h1:dIu1IPEymQgoT2dzuB//ttA/xcV40NMPpQtmd4wslHk=
|
||||
github.com/jhillyerd/enmime v1.2.0/go.mod h1:FRFuUPCLh8PByQv+8xRcLO9QHqaqTqreYhopv5eyk4I=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
|
||||
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
|
||||
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
|
||||
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
|
||||
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
|
||||
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/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
|
@ -613,13 +620,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
|||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
|
@ -672,34 +676,32 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||
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-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/meilisearch/meilisearch-go v0.26.3 h1:EYt+C1n7IvjKzgXM3xqce5iJzNBq33F7ayZOKx96TKY=
|
||||
github.com/meilisearch/meilisearch-go v0.26.3/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0=
|
||||
github.com/mholt/acmez/v2 v2.0.1 h1:3/3N0u1pLjMK4sNEAFSI+bcvzbPhRpY383sy1kLHJ6k=
|
||||
github.com/mholt/acmez/v2 v2.0.1/go.mod h1:fX4c9r5jYwMyMsC+7tkYRxHibkOTgta5DIFGoe67e1U=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/meilisearch/meilisearch-go v0.29.0 h1:HZ9NEKN59USINQ/DXJge/aaXq8IrsKbXGTdAoBaaDz4=
|
||||
github.com/meilisearch/meilisearch-go v0.29.0/go.mod h1:2cRCAn4ddySUsFfNDLVPod/plRibQsJkXF/4gLhxbOk=
|
||||
github.com/mholt/acmez/v2 v2.0.3 h1:CgDBlEwg3QBp6s45tPQmFIBrkRIkBT4rW4orMM6p4sw=
|
||||
github.com/mholt/acmez/v2 v2.0.3/go.mod h1:pQ1ysaDeGrIMvJ9dfJMk5kJNkn7L2sb3UhyrX6Q91cw=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||
github.com/microsoft/go-mssqldb v1.7.2 h1:CHkFJiObW7ItKTJfHo1QX7QBBD1iV+mn1eOyRP3b/PA=
|
||||
github.com/microsoft/go-mssqldb v1.7.2/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
|
||||
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||
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.77 h1:GaGghJRg9nwDVlNbwYjSDJT1rqltQkBFDsypWX1v3Bw=
|
||||
github.com/minio/minio-go/v7 v7.0.77/go.mod h1:AVM3IUN6WwKzmwBxVdjzhH8xq+f57JSbbvzqvUzR6eg=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/minio/minio-go/v7 v7.0.80 h1:2mdUHXEykRdY/BigLt3Iuu1otL0JTogT0Nmltg0wujk=
|
||||
github.com/minio/minio-go/v7 v7.0.80/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0=
|
||||
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.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
@ -742,8 +744,8 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042
|
|||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
|
||||
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
|
@ -753,8 +755,8 @@ github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
|
|||
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
|
||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
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.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
|
@ -773,25 +775,25 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
|||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
||||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
|
||||
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
github.com/prometheus/common v0.60.1 h1:FUas6GcOw66yB/73KC+BOZoFJmbo/1pojoILArPAaSc=
|
||||
github.com/prometheus/common v0.60.1/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/quasoft/websspi v1.1.2 h1:/mA4w0LxWlE3novvsoEL6BBA1WnjJATbjkh1kFrTidw=
|
||||
github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.6.0 h1:NLck+Rab3AOTHw21CGRpvQpgTrAU4sgdCswqGtlhGRA=
|
||||
github.com/redis/go-redis/v9 v9.6.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
|
||||
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
||||
github.com/redis/rueidis v1.0.19 h1:s65oWtotzlIFN8eMPhyYwxlwLR1lUdhza2KtWprKYSo=
|
||||
github.com/redis/rueidis v1.0.19/go.mod h1:8B+r5wdnjwK3lTFml5VtxjzGOQAC+5UmujoD12pDrEo=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rhysd/actionlint v1.7.1 h1:WJaDzyT1StBWVKGSsZPYnbV0HF9Y9/vD6KFdZQL42qE=
|
||||
github.com/rhysd/actionlint v1.7.1/go.mod h1:lNjNNlZY0BdBl8l837Z9ZiBpu8v+5lzfoJQFdSk4xss=
|
||||
github.com/rhysd/actionlint v1.7.3 h1:WD919WuLYrSCwY8VGBqJBEuzyVEIL5viXmXqRRcKOVs=
|
||||
github.com/rhysd/actionlint v1.7.3/go.mod h1:rl+8ZoX1rqnbcMWKaTyOHmw08mmb/zlmG/Zu1fY47F4=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
|
@ -802,8 +804,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
|||
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.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
|
@ -812,8 +814,8 @@ github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThC
|
|||
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.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4=
|
||||
|
@ -838,8 +840,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
|
|||
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=
|
||||
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
|
||||
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
|
||||
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
|
||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck=
|
||||
github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
|
@ -852,17 +854,16 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B
|
|||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/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.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
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=
|
||||
|
@ -872,7 +873,6 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
|
@ -883,7 +883,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
|
||||
|
@ -905,21 +904,15 @@ github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
|
|||
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
|
||||
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
||||
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
|
||||
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
||||
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
|
||||
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
|
||||
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ=
|
||||
github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
github.com/xanzy/go-gitlab v0.105.0 h1:3nyLq0ESez0crcaM19o5S//SvezOQguuIHZ3wgX64hM=
|
||||
github.com/xanzy/go-gitlab v0.105.0/go.mod h1:ETg8tcj4OhrB84UEgeE8dSuV/0h4BBL1uOV/qK0vlyI=
|
||||
github.com/xanzy/go-gitlab v0.112.0 h1:6Z0cqEooCvBMfBIHw+CgO4AKGRV8na/9781xOb0+DKw=
|
||||
github.com/xanzy/go-gitlab v0.112.0/go.mod h1:wKNKh3GkYDMOsGmnfuX+ITCmDuSDWFO0G+C4AygL9RY=
|
||||
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
|
||||
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
|
@ -937,6 +930,8 @@ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMx
|
|||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||
github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js=
|
||||
github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
|
@ -945,30 +940,30 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.7.2 h1:NjGd7lO7zrUn/A7eKwn5PEOt4ONYGqpxSEeZuduvgxc=
|
||||
github.com/yuin/goldmark v1.7.2/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
||||
github.com/yuin/goldmark-meta v1.1.0 h1:pWw+JLHGZe8Rk0EGsMVssiNb/AaPMHfSRszZeUeiOUc=
|
||||
github.com/yuin/goldmark-meta v1.1.0/go.mod h1:U4spWENafuA7Zyg+Lj5RqK/MF+ovMYtBvXi1lBb2VP0=
|
||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||
github.com/zeebo/blake3 v0.2.4 h1:KYQPkhpRtcqh0ssGYcKLG1JYvddkEA8QwCM/yBqhaZI=
|
||||
github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCRUjcE=
|
||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
|
||||
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
||||
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
|
||||
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
|
||||
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
|
||||
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
|
||||
go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
|
||||
go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
|
||||
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
||||
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
|
||||
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
|
||||
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
|
@ -1002,20 +997,18 @@ golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5
|
|||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f h1:3CW0unweImhOzd5FmYuRsD4Y4oQFKZIjAnKbjV4WIrw=
|
||||
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY=
|
||||
golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8=
|
||||
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
||||
golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
|
@ -1024,13 +1017,14 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
|
@ -1038,8 +1032,6 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
|
@ -1047,10 +1039,12 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
|
||||
golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
|
||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -1084,11 +1078,8 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -1100,10 +1091,10 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
|
||||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
|
@ -1112,10 +1103,10 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
|||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -1126,12 +1117,11 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
|
||||
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
|
@ -1150,18 +1140,18 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -1170,8 +1160,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
|||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -7,19 +7,17 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestActionScheduleSpec_Parse(t *testing.T) {
|
||||
// Mock the local timezone is not UTC
|
||||
local := time.Local
|
||||
tz, err := time.LoadLocation("Asia/Shanghai")
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
time.Local = local
|
||||
}()
|
||||
time.Local = tz
|
||||
defer test.MockVariableValue(&time.Local, tz)()
|
||||
|
||||
now, err := time.Parse(time.RFC3339, "2024-07-31T15:47:55+08:00")
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -171,7 +171,10 @@ func (a *Action) TableIndices() []*schemas.Index {
|
|||
cudIndex := schemas.NewIndex("c_u_d", schemas.IndexType)
|
||||
cudIndex.AddColumn("created_unix", "user_id", "is_deleted")
|
||||
|
||||
indices := []*schemas.Index{actUserIndex, repoIndex, cudIndex}
|
||||
cuIndex := schemas.NewIndex("c_u", schemas.IndexType)
|
||||
cuIndex.AddColumn("user_id", "is_deleted")
|
||||
|
||||
indices := []*schemas.Index{actUserIndex, repoIndex, cudIndex, cuIndex}
|
||||
|
||||
return indices
|
||||
}
|
||||
|
|
71
models/fixtures/action_artifact.yml
Normal file
71
models/fixtures/action_artifact.yml
Normal file
|
@ -0,0 +1,71 @@
|
|||
-
|
||||
id: 1
|
||||
run_id: 791
|
||||
runner_id: 1
|
||||
repo_id: 4
|
||||
owner_id: 1
|
||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
||||
storage_path: "26/1/1712166500347189545.chunk"
|
||||
file_size: 1024
|
||||
file_compressed_size: 1024
|
||||
content_encoding: ""
|
||||
artifact_path: "abc.txt"
|
||||
artifact_name: "artifact-download"
|
||||
status: 1
|
||||
created_unix: 1712338649
|
||||
updated_unix: 1712338649
|
||||
expired_unix: 1720114649
|
||||
|
||||
-
|
||||
id: 19
|
||||
run_id: 791
|
||||
runner_id: 1
|
||||
repo_id: 4
|
||||
owner_id: 1
|
||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
||||
storage_path: "26/19/1712348022422036662.chunk"
|
||||
file_size: 1024
|
||||
file_compressed_size: 1024
|
||||
content_encoding: ""
|
||||
artifact_path: "abc.txt"
|
||||
artifact_name: "multi-file-download"
|
||||
status: 2
|
||||
created_unix: 1712348022
|
||||
updated_unix: 1712348022
|
||||
expired_unix: 1720124022
|
||||
|
||||
-
|
||||
id: 20
|
||||
run_id: 791
|
||||
runner_id: 1
|
||||
repo_id: 4
|
||||
owner_id: 1
|
||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
||||
storage_path: "26/20/1712348022423431524.chunk"
|
||||
file_size: 1024
|
||||
file_compressed_size: 1024
|
||||
content_encoding: ""
|
||||
artifact_path: "xyz/def.txt"
|
||||
artifact_name: "multi-file-download"
|
||||
status: 2
|
||||
created_unix: 1712348022
|
||||
updated_unix: 1712348022
|
||||
expired_unix: 1720124022
|
||||
|
||||
-
|
||||
id: 22
|
||||
run_id: 792
|
||||
runner_id: 1
|
||||
repo_id: 4
|
||||
owner_id: 1
|
||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
||||
storage_path: "27/5/1730330775594233150.chunk"
|
||||
file_size: 1024
|
||||
file_compressed_size: 1024
|
||||
content_encoding: "application/zip"
|
||||
artifact_path: "artifact-v4-download.zip"
|
||||
artifact_name: "artifact-v4-download"
|
||||
status: 2
|
||||
created_unix: 1730330775
|
||||
updated_unix: 1730330775
|
||||
expired_unix: 1738106775
|
|
@ -136,8 +136,6 @@ var ErrLFSObjectNotExist = db.ErrNotExist{Resource: "LFS Meta object"}
|
|||
// NewLFSMetaObject stores a given populated LFSMetaObject structure in the database
|
||||
// if it is not already present.
|
||||
func NewLFSMetaObject(ctx context.Context, repoID int64, p lfs.Pointer) (*LFSMetaObject, error) {
|
||||
var err error
|
||||
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -84,14 +84,20 @@ func IsRuleNameSpecial(ruleName string) bool {
|
|||
}
|
||||
|
||||
func (protectBranch *ProtectedBranch) loadGlob() {
|
||||
if protectBranch.globRule == nil {
|
||||
var err error
|
||||
protectBranch.globRule, err = glob.Compile(protectBranch.RuleName, '/')
|
||||
if err != nil {
|
||||
log.Warn("Invalid glob rule for ProtectedBranch[%d]: %s %v", protectBranch.ID, protectBranch.RuleName, err)
|
||||
protectBranch.globRule = glob.MustCompile(glob.QuoteMeta(protectBranch.RuleName), '/')
|
||||
}
|
||||
protectBranch.isPlainName = !IsRuleNameSpecial(protectBranch.RuleName)
|
||||
if protectBranch.isPlainName || protectBranch.globRule != nil {
|
||||
return
|
||||
}
|
||||
// detect if it is not glob
|
||||
if !IsRuleNameSpecial(protectBranch.RuleName) {
|
||||
protectBranch.isPlainName = true
|
||||
return
|
||||
}
|
||||
// now we load the glob
|
||||
var err error
|
||||
protectBranch.globRule, err = glob.Compile(protectBranch.RuleName, '/')
|
||||
if err != nil {
|
||||
log.Warn("Invalid glob rule for ProtectedBranch[%d]: %s %v", protectBranch.ID, protectBranch.RuleName, err)
|
||||
protectBranch.globRule = glob.MustCompile(glob.QuoteMeta(protectBranch.RuleName), '/')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -74,3 +74,32 @@ func TestBranchRuleMatchPriority(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBranchRuleSort(t *testing.T) {
|
||||
in := []*ProtectedBranch{{
|
||||
RuleName: "b",
|
||||
CreatedUnix: 1,
|
||||
}, {
|
||||
RuleName: "b/*",
|
||||
CreatedUnix: 3,
|
||||
}, {
|
||||
RuleName: "a/*",
|
||||
CreatedUnix: 2,
|
||||
}, {
|
||||
RuleName: "c",
|
||||
CreatedUnix: 0,
|
||||
}, {
|
||||
RuleName: "a",
|
||||
CreatedUnix: 4,
|
||||
}}
|
||||
expect := []string{"c", "b", "a", "a/*", "b/*"}
|
||||
|
||||
pbr := ProtectedBranchRules(in)
|
||||
pbr.sort()
|
||||
|
||||
var got []string
|
||||
for i := range pbr {
|
||||
got = append(got, pbr[i].RuleName)
|
||||
}
|
||||
assert.Equal(t, expect, got)
|
||||
}
|
|
@ -229,8 +229,7 @@ func TestGetLabelsByOrgID(t *testing.T) {
|
|||
testSuccess(3, "reversealphabetically", []int64{4, 3})
|
||||
testSuccess(3, "default", []int64{3, 4})
|
||||
|
||||
var err error
|
||||
_, err = issues_model.GetLabelsByOrgID(db.DefaultContext, 0, "leastissues", db.ListOptions{})
|
||||
_, err := issues_model.GetLabelsByOrgID(db.DefaultContext, 0, "leastissues", db.ListOptions{})
|
||||
assert.True(t, issues_model.IsErrOrgLabelNotExist(err))
|
||||
|
||||
_, err = issues_model.GetLabelsByOrgID(db.DefaultContext, -1, "leastissues", db.ListOptions{})
|
||||
|
|
|
@ -84,10 +84,9 @@ func (m *Milestone) BeforeUpdate() {
|
|||
// this object.
|
||||
func (m *Milestone) AfterLoad() {
|
||||
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues
|
||||
if m.DeadlineUnix.Year() == 9999 {
|
||||
if m.DeadlineUnix == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
m.DeadlineString = m.DeadlineUnix.FormatDate()
|
||||
if m.IsClosed {
|
||||
m.IsOverdue = m.ClosedDateUnix >= m.DeadlineUnix
|
||||
|
|
|
@ -348,6 +348,8 @@ func prepareMigrationTasks() []*xormigrate.Migration {
|
|||
newMigration(304, "Add index for release sha1", v1_23.AddIndexForReleaseSha1),
|
||||
newMigration(305, "Add Repository Licenses", v1_23.AddRepositoryLicenses),
|
||||
newMigration(306, "Add BlockAdminMergeOverride to ProtectedBranch", v1_23.AddBlockAdminMergeOverrideBranchProtection),
|
||||
newMigration(307, "Fix milestone deadline_unix when there is no due date", v1_23.FixMilestoneNoDueDate),
|
||||
newMigration(308, "Add index(user_id, is_deleted) for action table", v1_23.AddNewIndexForUserDashboard),
|
||||
}
|
||||
return preparedMigrations
|
||||
}
|
||||
|
|
|
@ -4,304 +4,18 @@
|
|||
package v1_23 //nolint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
const (
|
||||
minDBVersion = 70 // Gitea 1.5.3
|
||||
oldMigrationsCount = 230
|
||||
expectedVersion = minDBVersion + oldMigrationsCount
|
||||
)
|
||||
|
||||
var oldMigrationNames = []string{
|
||||
"add issue_dependencies",
|
||||
"protect each scratch token",
|
||||
"add review",
|
||||
"add must_change_password column for users table",
|
||||
"add approval whitelists to protected branches",
|
||||
"clear nonused data which not deleted when user was deleted",
|
||||
"add pull request rebase with merge commit",
|
||||
"add theme to users",
|
||||
"rename repo is_bare to repo is_empty",
|
||||
"add can close issues via commit in any branch",
|
||||
"add is locked to issues",
|
||||
"update U2F counter type",
|
||||
"hot fix for wrong release sha1 on release table",
|
||||
"add uploader id for table attachment",
|
||||
"add table to store original imported gpg keys",
|
||||
"hash application token",
|
||||
"add http method to webhook",
|
||||
"add avatar field to repository",
|
||||
"add commit status context field to commit_status",
|
||||
"add original author/url migration info to issues, comments, and repo ",
|
||||
"change length of some repository columns",
|
||||
"add index on owner_id of repository and type, review_id of comment",
|
||||
"remove orphaned repository index statuses",
|
||||
"add email notification enabled preference to user",
|
||||
"add enable_status_check, status_check_contexts to protected_branch",
|
||||
"add table columns for cross referencing issues",
|
||||
"delete orphaned attachments",
|
||||
"add repo_admin_change_team_access to user",
|
||||
"add original author name and id on migrated release",
|
||||
"add task table and status column for repository table",
|
||||
"update migration repositories' service type",
|
||||
"change length of some external login users columns",
|
||||
"update migration repositories' service type v2",
|
||||
"Add WhitelistDeployKeys to protected branch",
|
||||
"remove unnecessary columns from label",
|
||||
"add includes_all_repositories to teams",
|
||||
"add column `mode` to table watch",
|
||||
"Add template options to repository",
|
||||
"Add comment_id on table notification",
|
||||
"add can_create_org_repo to team",
|
||||
"change review content type to text",
|
||||
"update branch protection for can push and whitelist enable",
|
||||
"remove release attachments which repository deleted",
|
||||
"new feature: change target branch of pull requests",
|
||||
"Remove authentication credentials from stored URL",
|
||||
"add user_id prefix to existing user avatar name",
|
||||
"Extend TrackedTimes",
|
||||
"Add block on rejected reviews branch protection",
|
||||
"Add commit id and stale to reviews",
|
||||
"Fix migrated repositories' git service type",
|
||||
"Add owner_name on table repository",
|
||||
"add is_restricted column for users table",
|
||||
"Add Require Signed Commits to ProtectedBranch",
|
||||
"Add original information for reactions",
|
||||
"Add columns to user and repository",
|
||||
"Add some columns on review for migration",
|
||||
"Fix topic repository count",
|
||||
"add repository code language statistics",
|
||||
"fix merge base for pull requests",
|
||||
"remove dependencies from deleted repositories",
|
||||
"Expand webhooks for more granularity",
|
||||
"Add IsSystemWebhook column to webhooks table",
|
||||
"Add Branch Protection Protected Files Column",
|
||||
"Add EmailHash Table",
|
||||
"Refix merge base for merged pull requests",
|
||||
"Add OrgID column to Labels table",
|
||||
"Add CommitsAhead and CommitsBehind Column to PullRequest Table",
|
||||
"Add Branch Protection Block Outdated Branch",
|
||||
"Add ResolveDoerID to Comment table",
|
||||
"prepend refs/heads/ to issue refs",
|
||||
"Save detected language file size to database instead of percent",
|
||||
"Add KeepActivityPrivate to User table",
|
||||
"Ensure Repository.IsArchived is not null",
|
||||
"recalculate Stars number for all user",
|
||||
"update Matrix Webhook http method to 'PUT'",
|
||||
"Increase Language field to 50 in LanguageStats",
|
||||
"Add projects info to repository table",
|
||||
"create review for 0 review id code comments",
|
||||
"remove issue dependency comments who refer to non existing issues",
|
||||
"Add Created and Updated to Milestone table",
|
||||
"add primary key to repo_topic",
|
||||
"set default password algorithm to Argon2",
|
||||
"add TrustModel field to Repository",
|
||||
"add Team review request support",
|
||||
"add timestamps to Star, Label, Follow, Watch and Collaboration",
|
||||
"add changed_protected_files column for pull_request table",
|
||||
"fix publisher ID for tag releases",
|
||||
"ensure repo topics are up-to-date",
|
||||
"code comment replies should have the commitID of the review they are replying to",
|
||||
"update reactions constraint",
|
||||
"Add block on official review requests branch protection",
|
||||
"Convert task type from int to string",
|
||||
"Convert webhook task type from int to string",
|
||||
"Convert topic name from 25 to 50",
|
||||
"Add scope and nonce columns to oauth2_grant table",
|
||||
"Convert hook task type from char(16) to varchar(16) and trim the column",
|
||||
"Where Password is Valid with Empty String delete it",
|
||||
"Add user redirect",
|
||||
"Recreate user table to fix default values",
|
||||
"Update DeleteBranch comments to set the old_ref to the commit_sha",
|
||||
"Add Dismissed to Review table",
|
||||
"Add Sorting to ProjectBoard table",
|
||||
"Add sessions table for go-chi/session",
|
||||
"Add time_id column to Comment",
|
||||
"Create repo transfer table",
|
||||
"Fix Postgres ID Sequences broken by recreate-table",
|
||||
"Remove invalid labels from comments",
|
||||
"Delete orphaned IssueLabels",
|
||||
"Add LFS columns to Mirror",
|
||||
"Convert avatar url to text",
|
||||
"Delete credentials from past migrations",
|
||||
"Always save primary email on email address table",
|
||||
"Add issue resource index table",
|
||||
"Create PushMirror table",
|
||||
"Rename Task errors to message",
|
||||
"Add new table repo_archiver",
|
||||
"Create protected tag table",
|
||||
"Drop unneeded webhook related columns",
|
||||
"Add key is verified to gpg key",
|
||||
"Unwrap ldap.Sources",
|
||||
"Add agit flow pull request support",
|
||||
"Alter issue/comment table TEXT fields to LONGTEXT",
|
||||
"RecreateIssueResourceIndexTable to have a primary key instead of an unique index",
|
||||
"Add repo id column for attachment table",
|
||||
"Add Branch Protection Unprotected Files Column",
|
||||
"Add table commit_status_index",
|
||||
"Add Color to ProjectBoard table",
|
||||
"Add renamed_branch table",
|
||||
"Add issue content history table",
|
||||
"No-op (remote version is using AppState now)",
|
||||
"Add table app_state",
|
||||
"Drop table remote_version (if exists)",
|
||||
"Create key/value table for user settings",
|
||||
"Add Sorting to ProjectIssue table",
|
||||
"Add key is verified to ssh key",
|
||||
"Migrate to higher varchar on user struct",
|
||||
"Add authorize column to team_unit table",
|
||||
"Add webauthn table and migrate u2f data to webauthn - NO-OPED",
|
||||
"Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED",
|
||||
"Increase WebAuthentication CredentialID size to 410 - NO-OPED",
|
||||
"v208 was completely broken - remigrate",
|
||||
"Create ForeignReference table",
|
||||
"Add package tables",
|
||||
"Add allow edits from maintainers to PullRequest table",
|
||||
"Add auto merge table",
|
||||
"allow to view files in PRs",
|
||||
"No-op (Improve Action table indices v1)",
|
||||
"Alter hook_task table TEXT fields to LONGTEXT",
|
||||
"Improve Action table indices v2",
|
||||
"Add sync_on_commit column to push_mirror table",
|
||||
"Add container repository property",
|
||||
"Store WebAuthentication CredentialID as bytes and increase size to at least 1024",
|
||||
"Drop old CredentialID column",
|
||||
"Rename CredentialIDBytes column to CredentialID",
|
||||
"Add badges to users",
|
||||
"Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT",
|
||||
"Conan and generic packages do not need to be semantically versioned",
|
||||
"Create key/value table for system settings",
|
||||
"Add TeamInvite table",
|
||||
"Update counts of all open milestones",
|
||||
"Add ConfidentialClient column (default true) to OAuth2Application table",
|
||||
"Add index for hook_task",
|
||||
"Alter package_version.metadata_json to LONGTEXT",
|
||||
"Add header_authorization_encrypted column to webhook table",
|
||||
"Add package cleanup rule table",
|
||||
"Add index for access_token",
|
||||
"Create secrets table",
|
||||
"Drop ForeignReference table",
|
||||
"Add updated unix to LFSMetaObject",
|
||||
"Add scope for access_token",
|
||||
"Add actions tables",
|
||||
"Add card_type column to project table",
|
||||
"Alter gpg_key_import content TEXT field to MEDIUMTEXT",
|
||||
"Add exclusive label",
|
||||
"Add NeedApproval to actions tables",
|
||||
"Rename Webhook org_id to owner_id",
|
||||
"Add missed column owner_id for project table",
|
||||
"Fix incorrect project type",
|
||||
"Add version column to action_runner table",
|
||||
"Improve Action table indices v3",
|
||||
"Change Container Metadata",
|
||||
"Fix incorrect owner team unit access mode",
|
||||
"Fix incorrect admin team unit access mode",
|
||||
"Fix ExternalTracker and ExternalWiki accessMode in owner and admin team",
|
||||
"Add ActionTaskOutput table",
|
||||
"Add ArchivedUnix Column",
|
||||
"Add is_internal column to package",
|
||||
"Add Actions Artifact table",
|
||||
"Add PinOrder Column",
|
||||
"Convert scoped access tokens",
|
||||
"Drop custom_labels column of action_runner table",
|
||||
"Add variable table",
|
||||
"Add TriggerEvent to action_run table",
|
||||
"Add git_size and lfs_size columns to repository table",
|
||||
"Add branch table",
|
||||
"Alter Actions Artifact table",
|
||||
"Reduce commit status",
|
||||
"Add action_tasks_version table",
|
||||
"Update Action Ref",
|
||||
"Drop deleted branch table",
|
||||
"Fix PackageProperty typo",
|
||||
"Allow archiving labels",
|
||||
"Add Version to ActionRun table",
|
||||
"Add Action Schedule Table",
|
||||
"Add Actions artifacts expiration date",
|
||||
"Add ScheduleID for ActionRun",
|
||||
"Add RemoteAddress to mirrors",
|
||||
"Add Index to issue_user.issue_id",
|
||||
"Add Index to comment.dependent_issue_id",
|
||||
"Add Index to action.user_id",
|
||||
"Rename user themes",
|
||||
"Add auth_token table",
|
||||
"Add Index to pull_auto_merge.doer_id",
|
||||
"Add combined Index to issue_user.uid and issue_id",
|
||||
"Add ignore stale approval column on branch table",
|
||||
"Add PreviousDuration to ActionRun",
|
||||
"Add support for SHA256 git repositories",
|
||||
"Use Slug instead of ID for Badges",
|
||||
"Add user_blocking table",
|
||||
"Add default_wiki_branch to repository table",
|
||||
"Add PayloadVersion to HookTask",
|
||||
"Add Index to attachment.comment_id",
|
||||
"Ensure every project has exactly one default column - No Op",
|
||||
"Ensure every project has exactly one default column",
|
||||
"Add unique index for project issue table",
|
||||
"Add commit status summary table",
|
||||
"Add missing field of commit status summary table",
|
||||
"Add everyone_access_mode for repo_unit",
|
||||
"Drop wrongly created table o_auth2_application",
|
||||
"Add content version to issue and comment table",
|
||||
"Add force-push branch protection support",
|
||||
"Add skip_secondary_authorization option to oauth2 application table",
|
||||
"Add metadata column for comment table",
|
||||
"Add index for release sha1",
|
||||
"Add Repository Licenses",
|
||||
}
|
||||
|
||||
// Version describes the version table. Should have only one row with id==1
|
||||
type Version struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Version int64
|
||||
}
|
||||
|
||||
func MigrateToXormigrate(x *xorm.Engine) error {
|
||||
if err := x.Sync(new(Version)); err != nil {
|
||||
return fmt.Errorf("sync: %w", err)
|
||||
}
|
||||
|
||||
currentVersion := &Version{ID: 1}
|
||||
has, err := x.Get(currentVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get: %w", err)
|
||||
} else if !has {
|
||||
// This should not happen
|
||||
return fmt.Errorf("could not get version")
|
||||
}
|
||||
|
||||
v := currentVersion.Version
|
||||
if minDBVersion > v {
|
||||
log.Fatal(`Gitea no longer supports auto-migration from your previously installed version.
|
||||
Please try upgrading to i.e. v1.6.4 first, then upgrade to this version.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Downgrading Gitea's database version not supported
|
||||
if int(v-minDBVersion) > oldMigrationsCount {
|
||||
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Gitea, you can not use the newer database for this old Gitea release (%d).", v, expectedVersion)
|
||||
msg += "\nGitea will exit to keep your database safe and unchanged. Please use the correct Gitea release, do not change the migration version manually (incorrect manual operation may lose data)."
|
||||
if !setting.IsProd {
|
||||
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", expectedVersion)
|
||||
}
|
||||
log.Fatal("Migration Error: %s", msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
// add migrations that already have been run
|
||||
for i := v; i < 307; i++ {
|
||||
if _, err := x.Insert(&xormigrate.Migration{ID: fmt.Sprint(i)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old version table
|
||||
return x.DropTables(new(Version))
|
||||
func FixMilestoneNoDueDate(x *xorm.Engine) error {
|
||||
type Milestone struct {
|
||||
DeadlineUnix timeutil.TimeStamp
|
||||
}
|
||||
// Wednesday, December 1, 9999 12:00:00 AM GMT+00:00
|
||||
_, err := x.Table("milestone").Where("deadline_unix > 253399622400").
|
||||
Cols("deadline_unix").
|
||||
Update(&Milestone{DeadlineUnix: 0})
|
||||
return err
|
||||
}
|
||||
|
|
52
models/migrations/v1_23/v308.go
Normal file
52
models/migrations/v1_23/v308.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
||||
type improveActionTableIndicesAction struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"INDEX"` // Receiver user id.
|
||||
OpType int
|
||||
ActUserID int64 // Action user id.
|
||||
RepoID int64
|
||||
CommentID int64 `xorm:"INDEX"`
|
||||
IsDeleted bool `xorm:"NOT NULL DEFAULT false"`
|
||||
RefName string
|
||||
IsPrivate bool `xorm:"NOT NULL DEFAULT false"`
|
||||
Content string `xorm:"TEXT"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||
}
|
||||
|
||||
// TableName sets the name of this table
|
||||
func (*improveActionTableIndicesAction) TableName() string {
|
||||
return "action"
|
||||
}
|
||||
|
||||
func (a *improveActionTableIndicesAction) TableIndices() []*schemas.Index {
|
||||
repoIndex := schemas.NewIndex("r_u_d", schemas.IndexType)
|
||||
repoIndex.AddColumn("repo_id", "user_id", "is_deleted")
|
||||
|
||||
actUserIndex := schemas.NewIndex("au_r_c_u_d", schemas.IndexType)
|
||||
actUserIndex.AddColumn("act_user_id", "repo_id", "created_unix", "user_id", "is_deleted")
|
||||
|
||||
cudIndex := schemas.NewIndex("c_u_d", schemas.IndexType)
|
||||
cudIndex.AddColumn("created_unix", "user_id", "is_deleted")
|
||||
|
||||
cuIndex := schemas.NewIndex("c_u", schemas.IndexType)
|
||||
cuIndex.AddColumn("user_id", "is_deleted")
|
||||
|
||||
indices := []*schemas.Index{actUserIndex, repoIndex, cudIndex, cuIndex}
|
||||
|
||||
return indices
|
||||
}
|
||||
|
||||
func AddNewIndexForUserDashboard(x *xorm.Engine) error {
|
||||
return x.Sync(new(improveActionTableIndicesAction))
|
||||
}
|
307
models/migrations/v1_23/v309.go
Normal file
307
models/migrations/v1_23/v309.go
Normal file
|
@ -0,0 +1,307 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_23 //nolint
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
const (
|
||||
minDBVersion = 70 // Gitea 1.5.3
|
||||
oldMigrationsCount = 230
|
||||
expectedVersion = minDBVersion + oldMigrationsCount
|
||||
)
|
||||
|
||||
var oldMigrationNames = []string{
|
||||
"add issue_dependencies",
|
||||
"protect each scratch token",
|
||||
"add review",
|
||||
"add must_change_password column for users table",
|
||||
"add approval whitelists to protected branches",
|
||||
"clear nonused data which not deleted when user was deleted",
|
||||
"add pull request rebase with merge commit",
|
||||
"add theme to users",
|
||||
"rename repo is_bare to repo is_empty",
|
||||
"add can close issues via commit in any branch",
|
||||
"add is locked to issues",
|
||||
"update U2F counter type",
|
||||
"hot fix for wrong release sha1 on release table",
|
||||
"add uploader id for table attachment",
|
||||
"add table to store original imported gpg keys",
|
||||
"hash application token",
|
||||
"add http method to webhook",
|
||||
"add avatar field to repository",
|
||||
"add commit status context field to commit_status",
|
||||
"add original author/url migration info to issues, comments, and repo ",
|
||||
"change length of some repository columns",
|
||||
"add index on owner_id of repository and type, review_id of comment",
|
||||
"remove orphaned repository index statuses",
|
||||
"add email notification enabled preference to user",
|
||||
"add enable_status_check, status_check_contexts to protected_branch",
|
||||
"add table columns for cross referencing issues",
|
||||
"delete orphaned attachments",
|
||||
"add repo_admin_change_team_access to user",
|
||||
"add original author name and id on migrated release",
|
||||
"add task table and status column for repository table",
|
||||
"update migration repositories' service type",
|
||||
"change length of some external login users columns",
|
||||
"update migration repositories' service type v2",
|
||||
"Add WhitelistDeployKeys to protected branch",
|
||||
"remove unnecessary columns from label",
|
||||
"add includes_all_repositories to teams",
|
||||
"add column `mode` to table watch",
|
||||
"Add template options to repository",
|
||||
"Add comment_id on table notification",
|
||||
"add can_create_org_repo to team",
|
||||
"change review content type to text",
|
||||
"update branch protection for can push and whitelist enable",
|
||||
"remove release attachments which repository deleted",
|
||||
"new feature: change target branch of pull requests",
|
||||
"Remove authentication credentials from stored URL",
|
||||
"add user_id prefix to existing user avatar name",
|
||||
"Extend TrackedTimes",
|
||||
"Add block on rejected reviews branch protection",
|
||||
"Add commit id and stale to reviews",
|
||||
"Fix migrated repositories' git service type",
|
||||
"Add owner_name on table repository",
|
||||
"add is_restricted column for users table",
|
||||
"Add Require Signed Commits to ProtectedBranch",
|
||||
"Add original information for reactions",
|
||||
"Add columns to user and repository",
|
||||
"Add some columns on review for migration",
|
||||
"Fix topic repository count",
|
||||
"add repository code language statistics",
|
||||
"fix merge base for pull requests",
|
||||
"remove dependencies from deleted repositories",
|
||||
"Expand webhooks for more granularity",
|
||||
"Add IsSystemWebhook column to webhooks table",
|
||||
"Add Branch Protection Protected Files Column",
|
||||
"Add EmailHash Table",
|
||||
"Refix merge base for merged pull requests",
|
||||
"Add OrgID column to Labels table",
|
||||
"Add CommitsAhead and CommitsBehind Column to PullRequest Table",
|
||||
"Add Branch Protection Block Outdated Branch",
|
||||
"Add ResolveDoerID to Comment table",
|
||||
"prepend refs/heads/ to issue refs",
|
||||
"Save detected language file size to database instead of percent",
|
||||
"Add KeepActivityPrivate to User table",
|
||||
"Ensure Repository.IsArchived is not null",
|
||||
"recalculate Stars number for all user",
|
||||
"update Matrix Webhook http method to 'PUT'",
|
||||
"Increase Language field to 50 in LanguageStats",
|
||||
"Add projects info to repository table",
|
||||
"create review for 0 review id code comments",
|
||||
"remove issue dependency comments who refer to non existing issues",
|
||||
"Add Created and Updated to Milestone table",
|
||||
"add primary key to repo_topic",
|
||||
"set default password algorithm to Argon2",
|
||||
"add TrustModel field to Repository",
|
||||
"add Team review request support",
|
||||
"add timestamps to Star, Label, Follow, Watch and Collaboration",
|
||||
"add changed_protected_files column for pull_request table",
|
||||
"fix publisher ID for tag releases",
|
||||
"ensure repo topics are up-to-date",
|
||||
"code comment replies should have the commitID of the review they are replying to",
|
||||
"update reactions constraint",
|
||||
"Add block on official review requests branch protection",
|
||||
"Convert task type from int to string",
|
||||
"Convert webhook task type from int to string",
|
||||
"Convert topic name from 25 to 50",
|
||||
"Add scope and nonce columns to oauth2_grant table",
|
||||
"Convert hook task type from char(16) to varchar(16) and trim the column",
|
||||
"Where Password is Valid with Empty String delete it",
|
||||
"Add user redirect",
|
||||
"Recreate user table to fix default values",
|
||||
"Update DeleteBranch comments to set the old_ref to the commit_sha",
|
||||
"Add Dismissed to Review table",
|
||||
"Add Sorting to ProjectBoard table",
|
||||
"Add sessions table for go-chi/session",
|
||||
"Add time_id column to Comment",
|
||||
"Create repo transfer table",
|
||||
"Fix Postgres ID Sequences broken by recreate-table",
|
||||
"Remove invalid labels from comments",
|
||||
"Delete orphaned IssueLabels",
|
||||
"Add LFS columns to Mirror",
|
||||
"Convert avatar url to text",
|
||||
"Delete credentials from past migrations",
|
||||
"Always save primary email on email address table",
|
||||
"Add issue resource index table",
|
||||
"Create PushMirror table",
|
||||
"Rename Task errors to message",
|
||||
"Add new table repo_archiver",
|
||||
"Create protected tag table",
|
||||
"Drop unneeded webhook related columns",
|
||||
"Add key is verified to gpg key",
|
||||
"Unwrap ldap.Sources",
|
||||
"Add agit flow pull request support",
|
||||
"Alter issue/comment table TEXT fields to LONGTEXT",
|
||||
"RecreateIssueResourceIndexTable to have a primary key instead of an unique index",
|
||||
"Add repo id column for attachment table",
|
||||
"Add Branch Protection Unprotected Files Column",
|
||||
"Add table commit_status_index",
|
||||
"Add Color to ProjectBoard table",
|
||||
"Add renamed_branch table",
|
||||
"Add issue content history table",
|
||||
"No-op (remote version is using AppState now)",
|
||||
"Add table app_state",
|
||||
"Drop table remote_version (if exists)",
|
||||
"Create key/value table for user settings",
|
||||
"Add Sorting to ProjectIssue table",
|
||||
"Add key is verified to ssh key",
|
||||
"Migrate to higher varchar on user struct",
|
||||
"Add authorize column to team_unit table",
|
||||
"Add webauthn table and migrate u2f data to webauthn - NO-OPED",
|
||||
"Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED",
|
||||
"Increase WebAuthentication CredentialID size to 410 - NO-OPED",
|
||||
"v208 was completely broken - remigrate",
|
||||
"Create ForeignReference table",
|
||||
"Add package tables",
|
||||
"Add allow edits from maintainers to PullRequest table",
|
||||
"Add auto merge table",
|
||||
"allow to view files in PRs",
|
||||
"No-op (Improve Action table indices v1)",
|
||||
"Alter hook_task table TEXT fields to LONGTEXT",
|
||||
"Improve Action table indices v2",
|
||||
"Add sync_on_commit column to push_mirror table",
|
||||
"Add container repository property",
|
||||
"Store WebAuthentication CredentialID as bytes and increase size to at least 1024",
|
||||
"Drop old CredentialID column",
|
||||
"Rename CredentialIDBytes column to CredentialID",
|
||||
"Add badges to users",
|
||||
"Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT",
|
||||
"Conan and generic packages do not need to be semantically versioned",
|
||||
"Create key/value table for system settings",
|
||||
"Add TeamInvite table",
|
||||
"Update counts of all open milestones",
|
||||
"Add ConfidentialClient column (default true) to OAuth2Application table",
|
||||
"Add index for hook_task",
|
||||
"Alter package_version.metadata_json to LONGTEXT",
|
||||
"Add header_authorization_encrypted column to webhook table",
|
||||
"Add package cleanup rule table",
|
||||
"Add index for access_token",
|
||||
"Create secrets table",
|
||||
"Drop ForeignReference table",
|
||||
"Add updated unix to LFSMetaObject",
|
||||
"Add scope for access_token",
|
||||
"Add actions tables",
|
||||
"Add card_type column to project table",
|
||||
"Alter gpg_key_import content TEXT field to MEDIUMTEXT",
|
||||
"Add exclusive label",
|
||||
"Add NeedApproval to actions tables",
|
||||
"Rename Webhook org_id to owner_id",
|
||||
"Add missed column owner_id for project table",
|
||||
"Fix incorrect project type",
|
||||
"Add version column to action_runner table",
|
||||
"Improve Action table indices v3",
|
||||
"Change Container Metadata",
|
||||
"Fix incorrect owner team unit access mode",
|
||||
"Fix incorrect admin team unit access mode",
|
||||
"Fix ExternalTracker and ExternalWiki accessMode in owner and admin team",
|
||||
"Add ActionTaskOutput table",
|
||||
"Add ArchivedUnix Column",
|
||||
"Add is_internal column to package",
|
||||
"Add Actions Artifact table",
|
||||
"Add PinOrder Column",
|
||||
"Convert scoped access tokens",
|
||||
"Drop custom_labels column of action_runner table",
|
||||
"Add variable table",
|
||||
"Add TriggerEvent to action_run table",
|
||||
"Add git_size and lfs_size columns to repository table",
|
||||
"Add branch table",
|
||||
"Alter Actions Artifact table",
|
||||
"Reduce commit status",
|
||||
"Add action_tasks_version table",
|
||||
"Update Action Ref",
|
||||
"Drop deleted branch table",
|
||||
"Fix PackageProperty typo",
|
||||
"Allow archiving labels",
|
||||
"Add Version to ActionRun table",
|
||||
"Add Action Schedule Table",
|
||||
"Add Actions artifacts expiration date",
|
||||
"Add ScheduleID for ActionRun",
|
||||
"Add RemoteAddress to mirrors",
|
||||
"Add Index to issue_user.issue_id",
|
||||
"Add Index to comment.dependent_issue_id",
|
||||
"Add Index to action.user_id",
|
||||
"Rename user themes",
|
||||
"Add auth_token table",
|
||||
"Add Index to pull_auto_merge.doer_id",
|
||||
"Add combined Index to issue_user.uid and issue_id",
|
||||
"Add ignore stale approval column on branch table",
|
||||
"Add PreviousDuration to ActionRun",
|
||||
"Add support for SHA256 git repositories",
|
||||
"Use Slug instead of ID for Badges",
|
||||
"Add user_blocking table",
|
||||
"Add default_wiki_branch to repository table",
|
||||
"Add PayloadVersion to HookTask",
|
||||
"Add Index to attachment.comment_id",
|
||||
"Ensure every project has exactly one default column - No Op",
|
||||
"Ensure every project has exactly one default column",
|
||||
"Add unique index for project issue table",
|
||||
"Add commit status summary table",
|
||||
"Add missing field of commit status summary table",
|
||||
"Add everyone_access_mode for repo_unit",
|
||||
"Drop wrongly created table o_auth2_application",
|
||||
"Add content version to issue and comment table",
|
||||
"Add force-push branch protection support",
|
||||
"Add skip_secondary_authorization option to oauth2 application table",
|
||||
"Add metadata column for comment table",
|
||||
"Add index for release sha1",
|
||||
"Add Repository Licenses",
|
||||
}
|
||||
|
||||
// Version describes the version table. Should have only one row with id==1
|
||||
type Version struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Version int64
|
||||
}
|
||||
|
||||
func MigrateToXormigrate(x *xorm.Engine) error {
|
||||
if err := x.Sync(new(Version)); err != nil {
|
||||
return fmt.Errorf("sync: %w", err)
|
||||
}
|
||||
|
||||
currentVersion := &Version{ID: 1}
|
||||
has, err := x.Get(currentVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get: %w", err)
|
||||
} else if !has {
|
||||
// This should not happen
|
||||
return fmt.Errorf("could not get version")
|
||||
}
|
||||
|
||||
v := currentVersion.Version
|
||||
if minDBVersion > v {
|
||||
log.Fatal(`Gitea no longer supports auto-migration from your previously installed version.
|
||||
Please try upgrading to i.e. v1.6.4 first, then upgrade to this version.`)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Downgrading Gitea's database version not supported
|
||||
if int(v-minDBVersion) > oldMigrationsCount {
|
||||
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Gitea, you can not use the newer database for this old Gitea release (%d).", v, expectedVersion)
|
||||
msg += "\nGitea will exit to keep your database safe and unchanged. Please use the correct Gitea release, do not change the migration version manually (incorrect manual operation may lose data)."
|
||||
if !setting.IsProd {
|
||||
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", expectedVersion)
|
||||
}
|
||||
log.Fatal("Migration Error: %s", msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
// add migrations that already have been run
|
||||
for i := v; i < 307; i++ {
|
||||
if _, err := x.Insert(&xormigrate.Migration{ID: fmt.Sprint(i)}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Remove old version table
|
||||
return x.DropTables(new(Version))
|
||||
}
|
|
@ -60,3 +60,6 @@ func ParseAccessMode(permission string, allowed ...AccessMode) AccessMode {
|
|||
}
|
||||
return util.Iif(slices.Contains(allowed, m), m, AccessModeNone)
|
||||
}
|
||||
|
||||
// ErrInvalidAccessMode is returned when an invalid access mode is used
|
||||
var ErrInvalidAccessMode = util.NewInvalidArgumentErrorf("Invalid access mode")
|
||||
|
|
|
@ -110,26 +110,28 @@ func GetRepoAssignees(ctx context.Context, repo *Repository) (_ []*user_model.Us
|
|||
return nil, err
|
||||
}
|
||||
|
||||
additionalUserIDs := make([]int64, 0, 10)
|
||||
if err = e.Table("team_user").
|
||||
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
|
||||
Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
|
||||
Where("`team_repo`.repo_id = ? AND (`team_unit`.access_mode >= ? OR (`team_unit`.access_mode = ? AND `team_unit`.`type` = ?))",
|
||||
repo.ID, perm.AccessModeWrite, perm.AccessModeRead, unit.TypePullRequests).
|
||||
Distinct("`team_user`.uid").
|
||||
Select("`team_user`.uid").
|
||||
Find(&additionalUserIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
uniqueUserIDs := make(container.Set[int64])
|
||||
uniqueUserIDs.AddMultiple(userIDs...)
|
||||
uniqueUserIDs.AddMultiple(additionalUserIDs...)
|
||||
|
||||
if repo.Owner.IsOrganization() {
|
||||
additionalUserIDs := make([]int64, 0, 10)
|
||||
if err = e.Table("team_user").
|
||||
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
|
||||
Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
|
||||
Where("`team_repo`.repo_id = ? AND (`team_unit`.access_mode >= ? OR (`team_unit`.access_mode = ? AND `team_unit`.`type` = ?))",
|
||||
repo.ID, perm.AccessModeWrite, perm.AccessModeRead, unit.TypePullRequests).
|
||||
Distinct("`team_user`.uid").
|
||||
Select("`team_user`.uid").
|
||||
Find(&additionalUserIDs); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uniqueUserIDs.AddMultiple(additionalUserIDs...)
|
||||
}
|
||||
|
||||
// Leave a seat for owner itself to append later, but if owner is an organization
|
||||
// and just waste 1 unit is cheaper than re-allocate memory once.
|
||||
users := make([]*user_model.User, 0, len(uniqueUserIDs)+1)
|
||||
if len(userIDs) > 0 {
|
||||
if len(uniqueUserIDs) > 0 {
|
||||
if err = e.In("id", uniqueUserIDs.Values()).
|
||||
Where(builder.Eq{"`user`.is_active": true}).
|
||||
OrderBy(user_model.GetOrderByName()).
|
||||
|
|
|
@ -40,14 +40,12 @@ func TestMaybeRemoveBOM(t *testing.T) {
|
|||
|
||||
func TestToUTF8(t *testing.T) {
|
||||
resetDefaultCharsetsOrder()
|
||||
var res string
|
||||
var err error
|
||||
|
||||
// Note: golang compiler seems so behave differently depending on the current
|
||||
// locale, so some conversions might behave differently. For that reason, we don't
|
||||
// depend on particular conversions but in expected behaviors.
|
||||
|
||||
res, err = ToUTF8([]byte{0x41, 0x42, 0x43}, ConvertOpts{})
|
||||
res, err := ToUTF8([]byte{0x41, 0x42, 0x43}, ConvertOpts{})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "ABC", res)
|
||||
|
||||
|
|
|
@ -4,28 +4,14 @@
|
|||
package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// ErrExecTimeout error when exec timed out
|
||||
type ErrExecTimeout struct {
|
||||
Duration time.Duration
|
||||
}
|
||||
|
||||
// IsErrExecTimeout if some error is ErrExecTimeout
|
||||
func IsErrExecTimeout(err error) bool {
|
||||
_, ok := err.(ErrExecTimeout)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrExecTimeout) Error() string {
|
||||
return fmt.Sprintf("execution is timeout [duration: %v]", err.Duration)
|
||||
}
|
||||
|
||||
// ErrNotExist commit not exist error
|
||||
type ErrNotExist struct {
|
||||
ID string
|
||||
|
@ -62,21 +48,6 @@ func IsErrBadLink(err error) bool {
|
|||
return ok
|
||||
}
|
||||
|
||||
// ErrUnsupportedVersion error when required git version not matched
|
||||
type ErrUnsupportedVersion struct {
|
||||
Required string
|
||||
}
|
||||
|
||||
// IsErrUnsupportedVersion if some error is ErrUnsupportedVersion
|
||||
func IsErrUnsupportedVersion(err error) bool {
|
||||
_, ok := err.(ErrUnsupportedVersion)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUnsupportedVersion) Error() string {
|
||||
return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
|
||||
}
|
||||
|
||||
// ErrBranchNotExist represents a "BranchNotExist" kind of error.
|
||||
type ErrBranchNotExist struct {
|
||||
Name string
|
||||
|
@ -185,3 +156,10 @@ func IsErrMoreThanOne(err error) bool {
|
|||
func (err *ErrMoreThanOne) Error() string {
|
||||
return fmt.Sprintf("ErrMoreThanOne Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
|
||||
}
|
||||
|
||||
func IsErrCanceledOrKilled(err error) bool {
|
||||
// When "cancel()" a git command's context, the returned error of "Run()" could be one of them:
|
||||
// - context.Canceled
|
||||
// - *exec.ExitError: "signal: killed"
|
||||
return err != nil && (errors.Is(err, context.Canceled) || err.Error() == "signal: killed")
|
||||
}
|
||||
|
|
|
@ -166,9 +166,7 @@ func (c *CheckAttributeReader) Run() error {
|
|||
Stdout: c.stdOut,
|
||||
Stderr: stdErr,
|
||||
})
|
||||
if err != nil && // If there is an error we need to return but:
|
||||
c.ctx.Err() != err && // 1. Ignore the context error if the context is cancelled or exceeds the deadline (RunWithContext could return c.ctx.Err() which is Canceled or DeadlineExceeded)
|
||||
err.Error() != "signal: killed" { // 2. We should not pass up errors due to the program being killed
|
||||
if err != nil && !IsErrCanceledOrKilled(err) {
|
||||
return fmt.Errorf("failed to run attr-check. Error: %w\nStderr: %s", err, stdErr.String())
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -50,25 +50,35 @@ func (repo *Repository) readTreeToIndex(id ObjectID, indexFilename ...string) er
|
|||
}
|
||||
|
||||
// ReadTreeToTemporaryIndex reads a treeish to a temporary index file
|
||||
func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (filename, tmpDir string, cancel context.CancelFunc, err error) {
|
||||
tmpDir, err = os.MkdirTemp("", "index")
|
||||
if err != nil {
|
||||
return filename, tmpDir, cancel, err
|
||||
}
|
||||
func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (tmpIndexFilename, tmpDir string, cancel context.CancelFunc, err error) {
|
||||
defer func() {
|
||||
// if error happens and there is a cancel function, do clean up
|
||||
if err != nil && cancel != nil {
|
||||
cancel()
|
||||
cancel = nil
|
||||
}
|
||||
}()
|
||||
|
||||
filename = filepath.Join(tmpDir, ".tmp-index")
|
||||
cancel = func() {
|
||||
err := util.RemoveAll(tmpDir)
|
||||
if err != nil {
|
||||
log.Error("failed to remove tmp index file: %v", err)
|
||||
removeDirFn := func(dir string) func() { // it can't use the return value "tmpDir" directly because it is empty when error occurs
|
||||
return func() {
|
||||
if err := util.RemoveAll(dir); err != nil {
|
||||
log.Error("failed to remove tmp index dir: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
err = repo.ReadTreeToIndex(treeish, filename)
|
||||
|
||||
tmpDir, err = os.MkdirTemp("", "index")
|
||||
if err != nil {
|
||||
defer cancel()
|
||||
return "", "", func() {}, err
|
||||
return "", "", nil, err
|
||||
}
|
||||
return filename, tmpDir, cancel, err
|
||||
|
||||
tmpIndexFilename = filepath.Join(tmpDir, ".tmp-index")
|
||||
cancel = removeDirFn(tmpDir)
|
||||
err = repo.ReadTreeToIndex(treeish, tmpIndexFilename)
|
||||
if err != nil {
|
||||
return "", "", cancel, err
|
||||
}
|
||||
return tmpIndexFilename, tmpDir, cancel, err
|
||||
}
|
||||
|
||||
// EmptyIndex empties the index
|
||||
|
|
|
@ -32,7 +32,7 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
|
|||
graphCmd.AddArguments("--all")
|
||||
}
|
||||
|
||||
graphCmd.AddArguments("-C", "-M", "--date=iso").
|
||||
graphCmd.AddArguments("-C", "-M", "--date=iso-strict").
|
||||
AddOptionFormat("-n %d", setting.UI.GraphMaxCommitNum*page).
|
||||
AddOptionFormat("--pretty=format:%s", format)
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
|
@ -192,6 +193,14 @@ var RelationCommit = &Commit{
|
|||
Row: -1,
|
||||
}
|
||||
|
||||
func parseGitTime(timeStr string) time.Time {
|
||||
t, err := time.Parse(time.RFC3339, timeStr)
|
||||
if err != nil {
|
||||
return time.Unix(0, 0)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// NewCommit creates a new commit from a provided line
|
||||
func NewCommit(row, column int, line []byte) (*Commit, error) {
|
||||
data := bytes.SplitN(line, []byte("|"), 5)
|
||||
|
@ -206,7 +215,7 @@ func NewCommit(row, column int, line []byte) (*Commit, error) {
|
|||
// 1 matches git log --pretty=format:%H => commit hash
|
||||
Rev: string(data[1]),
|
||||
// 2 matches git log --pretty=format:%ad => author date (format respects --date= option)
|
||||
Date: string(data[2]),
|
||||
Date: parseGitTime(string(data[2])),
|
||||
// 3 matches git log --pretty=format:%h => abbreviated commit hash
|
||||
ShortRev: string(data[3]),
|
||||
// 4 matches git log --pretty=format:%s => subject
|
||||
|
@ -245,7 +254,7 @@ type Commit struct {
|
|||
Column int
|
||||
Refs []git.Reference
|
||||
Rev string
|
||||
Date string
|
||||
Date time.Time
|
||||
ShortRev string
|
||||
Subject string
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
type Repository interface {
|
||||
|
@ -59,15 +60,11 @@ func repositoryFromContext(ctx context.Context, repo Repository) *git.Repository
|
|||
return nil
|
||||
}
|
||||
|
||||
type nopCloser func()
|
||||
|
||||
func (nopCloser) Close() error { return nil }
|
||||
|
||||
// RepositoryFromContextOrOpen attempts to get the repository from the context or just opens it
|
||||
func RepositoryFromContextOrOpen(ctx context.Context, repo Repository) (*git.Repository, io.Closer, error) {
|
||||
gitRepo := repositoryFromContext(ctx, repo)
|
||||
if gitRepo != nil {
|
||||
return gitRepo, nopCloser(nil), nil
|
||||
return gitRepo, util.NopCloser{}, nil
|
||||
}
|
||||
|
||||
gitRepo, err := OpenRepository(ctx, repo)
|
||||
|
@ -95,7 +92,7 @@ func repositoryFromContextPath(ctx context.Context, path string) *git.Repository
|
|||
func RepositoryFromContextOrOpenPath(ctx context.Context, path string) (*git.Repository, io.Closer, error) {
|
||||
gitRepo := repositoryFromContextPath(ctx, path)
|
||||
if gitRepo != nil {
|
||||
return gitRepo, nopCloser(nil), nil
|
||||
return gitRepo, util.NopCloser{}, nil
|
||||
}
|
||||
|
||||
gitRepo, err := git.OpenRepository(ctx, path)
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"github.com/blevesearch/bleve/v2/analysis/token/camelcase"
|
||||
"github.com/blevesearch/bleve/v2/analysis/token/lowercase"
|
||||
"github.com/blevesearch/bleve/v2/analysis/token/unicodenorm"
|
||||
"github.com/blevesearch/bleve/v2/analysis/tokenizer/letter"
|
||||
"github.com/blevesearch/bleve/v2/analysis/tokenizer/unicode"
|
||||
"github.com/blevesearch/bleve/v2/mapping"
|
||||
"github.com/blevesearch/bleve/v2/search/query"
|
||||
|
@ -69,7 +70,7 @@ const (
|
|||
filenameIndexerAnalyzer = "filenameIndexerAnalyzer"
|
||||
filenameIndexerTokenizer = "filenameIndexerTokenizer"
|
||||
repoIndexerDocType = "repoIndexerDocType"
|
||||
repoIndexerLatestVersion = 7
|
||||
repoIndexerLatestVersion = 8
|
||||
)
|
||||
|
||||
// generateBleveIndexMapping generates a bleve index mapping for the repo indexer
|
||||
|
@ -105,7 +106,7 @@ func generateBleveIndexMapping() (mapping.IndexMapping, error) {
|
|||
} else if err := mapping.AddCustomAnalyzer(repoIndexerAnalyzer, map[string]any{
|
||||
"type": analyzer_custom.Name,
|
||||
"char_filters": []string{},
|
||||
"tokenizer": unicode.Name,
|
||||
"tokenizer": letter.Name,
|
||||
"token_filters": []string{unicodeNormalizeName, camelcase.Name, lowercase.Name},
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -30,7 +30,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
esRepoIndexerLatestVersion = 2
|
||||
esRepoIndexerLatestVersion = 3
|
||||
// multi-match-types, currently only 2 types are used
|
||||
// Reference: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-multi-match-query.html#multi-match-types
|
||||
esMultiMatchTypeBestFields = "best_fields"
|
||||
|
@ -60,6 +60,10 @@ const (
|
|||
"settings": {
|
||||
"analysis": {
|
||||
"analyzer": {
|
||||
"content_analyzer": {
|
||||
"tokenizer": "content_tokenizer",
|
||||
"filter" : ["lowercase"]
|
||||
},
|
||||
"filename_path_analyzer": {
|
||||
"tokenizer": "path_tokenizer"
|
||||
},
|
||||
|
@ -68,6 +72,10 @@ const (
|
|||
}
|
||||
},
|
||||
"tokenizer": {
|
||||
"content_tokenizer": {
|
||||
"type": "simple_pattern_split",
|
||||
"pattern": "[^a-zA-Z0-9]"
|
||||
},
|
||||
"path_tokenizer": {
|
||||
"type": "path_hierarchy",
|
||||
"delimiter": "/"
|
||||
|
@ -104,7 +112,8 @@ const (
|
|||
"content": {
|
||||
"type": "text",
|
||||
"term_vector": "with_positions_offsets",
|
||||
"index": true
|
||||
"index": true,
|
||||
"analyzer": "content_analyzer"
|
||||
},
|
||||
"commit_id": {
|
||||
"type": "keyword",
|
||||
|
|
|
@ -181,6 +181,55 @@ func testIndexer(name string, t *testing.T, indexer internal.Indexer) {
|
|||
},
|
||||
},
|
||||
},
|
||||
// Search for matches on the contents of files regardless of case.
|
||||
{
|
||||
RepoIDs: nil,
|
||||
Keyword: "dESCRIPTION",
|
||||
Langs: 1,
|
||||
Results: []codeSearchResult{
|
||||
{
|
||||
Filename: "README.md",
|
||||
Content: "# repo1\n\nDescription for repo1",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Search for an exact match on the filename within the repo '62' (case insenstive).
|
||||
// This scenario yields a single result (the file avocado.md on the repo '62')
|
||||
{
|
||||
RepoIDs: []int64{62},
|
||||
Keyword: "AVOCADO.MD",
|
||||
Langs: 1,
|
||||
Results: []codeSearchResult{
|
||||
{
|
||||
Filename: "avocado.md",
|
||||
Content: "# repo1\n\npineaple pie of cucumber juice",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Search for matches on the contents of files when the criteria is a expression.
|
||||
{
|
||||
RepoIDs: []int64{62},
|
||||
Keyword: "console.log",
|
||||
Langs: 1,
|
||||
Results: []codeSearchResult{
|
||||
{
|
||||
Filename: "example-file.js",
|
||||
Content: "console.log(\"Hello, World!\")",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Search for matches on the contents of files when the criteria is part of a expression.
|
||||
{
|
||||
RepoIDs: []int64{62},
|
||||
Keyword: "log",
|
||||
Langs: 1,
|
||||
Results: []codeSearchResult{
|
||||
{
|
||||
Filename: "example-file.js",
|
||||
Content: "console.log(\"Hello, World!\")",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, kw := range keywords {
|
||||
|
|
|
@ -6,12 +6,13 @@ package bleve
|
|||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"unicode"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/blevesearch/bleve/v2"
|
||||
"github.com/blevesearch/bleve/v2/analysis/tokenizer/unicode"
|
||||
unicode_tokenizer "github.com/blevesearch/bleve/v2/analysis/tokenizer/unicode"
|
||||
"github.com/blevesearch/bleve/v2/index/upsidedown"
|
||||
"github.com/ethantkoenig/rupture"
|
||||
)
|
||||
|
@ -57,7 +58,7 @@ func openIndexer(path string, latestVersion int) (bleve.Index, int, error) {
|
|||
// may be different on two string and they still be considered equivalent.
|
||||
// Given a phrasse, its shortest word determines its fuzziness. If a phrase uses CJK (eg: `갃갃갃` `啊啊啊`), the fuzziness is zero.
|
||||
func GuessFuzzinessByKeyword(s string) int {
|
||||
tokenizer := unicode.NewUnicodeTokenizer()
|
||||
tokenizer := unicode_tokenizer.NewUnicodeTokenizer()
|
||||
tokens := tokenizer.Tokenize([]byte(s))
|
||||
|
||||
if len(tokens) > 0 {
|
||||
|
@ -77,8 +78,10 @@ func guessFuzzinessByKeyword(s string) int {
|
|||
// according to https://github.com/blevesearch/bleve/issues/1563, the supported max fuzziness is 2
|
||||
// magic number 4 was chosen to determine the levenshtein distance per each character of a keyword
|
||||
// BUT, when using CJK (eg: `갃갃갃` `啊啊啊`), it mismatches a lot.
|
||||
// Likewise, queries whose terms contains characters that are *not* letters should not use fuzziness
|
||||
|
||||
for _, r := range s {
|
||||
if r >= 128 {
|
||||
if r >= 128 || !unicode.IsLetter(r) {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,14 @@ func TestBleveGuessFuzzinessByKeyword(t *testing.T) {
|
|||
Input: "갃갃갃",
|
||||
Fuzziness: 0,
|
||||
},
|
||||
{
|
||||
Input: "repo1",
|
||||
Fuzziness: 0,
|
||||
},
|
||||
{
|
||||
Input: "avocado.md",
|
||||
Fuzziness: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, scenario := range scenarios {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
|
||||
// Indexer represents a basic meilisearch indexer implementation
|
||||
type Indexer struct {
|
||||
Client *meilisearch.Client
|
||||
Client meilisearch.ServiceManager
|
||||
|
||||
url, apiKey string
|
||||
indexName string
|
||||
|
@ -40,11 +40,7 @@ func (i *Indexer) Init(_ context.Context) (bool, error) {
|
|||
return false, fmt.Errorf("indexer is already initialized")
|
||||
}
|
||||
|
||||
i.Client = meilisearch.NewClient(meilisearch.ClientConfig{
|
||||
Host: i.url,
|
||||
APIKey: i.apiKey,
|
||||
})
|
||||
|
||||
i.Client = meilisearch.New(i.url, meilisearch.WithAPIKey(i.apiKey))
|
||||
_, err := i.Client.GetIndex(i.VersionedIndexName())
|
||||
if err == nil {
|
||||
return true, nil
|
||||
|
|
|
@ -16,9 +16,10 @@ import (
|
|||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/proxy"
|
||||
)
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
const httpBatchSize = 20
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
// HTTPClient is used to communicate with the LFS server
|
||||
// https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md
|
||||
|
@ -30,7 +31,7 @@ type HTTPClient struct {
|
|||
|
||||
// BatchSize returns the preferred size of batchs to process
|
||||
func (c *HTTPClient) BatchSize() int {
|
||||
return httpBatchSize
|
||||
return setting.LFSClient.BatchSize
|
||||
}
|
||||
|
||||
func newHTTPClient(endpoint *url.URL, httpTransport *http.Transport) *HTTPClient {
|
||||
|
@ -114,6 +115,7 @@ func (c *HTTPClient) Upload(ctx context.Context, objects []Pointer, callback Upl
|
|||
return c.performOperation(ctx, objects, nil, callback)
|
||||
}
|
||||
|
||||
// performOperation takes a slice of LFS object pointers, batches them, and performs the upload/download operations concurrently in each batch
|
||||
func (c *HTTPClient) performOperation(ctx context.Context, objects []Pointer, dc DownloadCallback, uc UploadCallback) error {
|
||||
if len(objects) == 0 {
|
||||
return nil
|
||||
|
@ -134,71 +136,90 @@ func (c *HTTPClient) performOperation(ctx context.Context, objects []Pointer, dc
|
|||
return fmt.Errorf("TransferAdapter not found: %s", result.Transfer)
|
||||
}
|
||||
|
||||
if setting.LFSClient.BatchOperationConcurrency <= 0 {
|
||||
panic("BatchOperationConcurrency must be greater than 0, forgot to init?")
|
||||
}
|
||||
errGroup, groupCtx := errgroup.WithContext(ctx)
|
||||
errGroup.SetLimit(setting.LFSClient.BatchOperationConcurrency)
|
||||
for _, object := range result.Objects {
|
||||
if object.Error != nil {
|
||||
log.Trace("Error on object %v: %v", object.Pointer, object.Error)
|
||||
if uc != nil {
|
||||
if _, err := uc(object.Pointer, object.Error); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := dc(object.Pointer, nil, object.Error); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if uc != nil {
|
||||
if len(object.Actions) == 0 {
|
||||
log.Trace("%v already present on server", object.Pointer)
|
||||
continue
|
||||
}
|
||||
|
||||
link, ok := object.Actions["upload"]
|
||||
if !ok {
|
||||
log.Debug("%+v", object)
|
||||
return errors.New("missing action 'upload'")
|
||||
}
|
||||
|
||||
content, err := uc(object.Pointer, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = transferAdapter.Upload(ctx, link, object.Pointer, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
link, ok = object.Actions["verify"]
|
||||
if ok {
|
||||
if err := transferAdapter.Verify(ctx, link, object.Pointer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
link, ok := object.Actions["download"]
|
||||
if !ok {
|
||||
// no actions block in response, try legacy response schema
|
||||
link, ok = object.Links["download"]
|
||||
}
|
||||
if !ok {
|
||||
log.Debug("%+v", object)
|
||||
return errors.New("missing action 'download'")
|
||||
}
|
||||
|
||||
content, err := transferAdapter.Download(ctx, link)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dc(object.Pointer, content, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
errGroup.Go(func() error {
|
||||
return performSingleOperation(groupCtx, object, dc, uc, transferAdapter)
|
||||
})
|
||||
}
|
||||
|
||||
// only the first error is returned, preserving legacy behavior before concurrency
|
||||
return errGroup.Wait()
|
||||
}
|
||||
|
||||
// performSingleOperation performs an LFS upload or download operation on a single object
|
||||
func performSingleOperation(ctx context.Context, object *ObjectResponse, dc DownloadCallback, uc UploadCallback, transferAdapter TransferAdapter) error {
|
||||
// the response from a lfs batch api request for this specific object id contained an error
|
||||
if object.Error != nil {
|
||||
log.Trace("Error on object %v: %v", object.Pointer, object.Error)
|
||||
|
||||
// this was an 'upload' request inside the batch request
|
||||
if uc != nil {
|
||||
if _, err := uc(object.Pointer, object.Error); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// this was NOT an 'upload' request inside the batch request, meaning it must be a 'download' request
|
||||
if err := dc(object.Pointer, nil, object.Error); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// if the callback returns no err, then the error could be ignored, and the operations should continue
|
||||
return nil
|
||||
}
|
||||
|
||||
// the response from an lfs batch api request contained necessary upload/download fields to act upon
|
||||
if uc != nil {
|
||||
if len(object.Actions) == 0 {
|
||||
log.Trace("%v already present on server", object.Pointer)
|
||||
return nil
|
||||
}
|
||||
|
||||
link, ok := object.Actions["upload"]
|
||||
if !ok {
|
||||
return errors.New("missing action 'upload'")
|
||||
}
|
||||
|
||||
content, err := uc(object.Pointer, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = transferAdapter.Upload(ctx, link, object.Pointer, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
link, ok = object.Actions["verify"]
|
||||
if ok {
|
||||
if err := transferAdapter.Verify(ctx, link, object.Pointer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
link, ok := object.Actions["download"]
|
||||
if !ok {
|
||||
// no actions block in response, try legacy response schema
|
||||
link, ok = object.Links["download"]
|
||||
}
|
||||
if !ok {
|
||||
log.Debug("%+v", object)
|
||||
return errors.New("missing action 'download'")
|
||||
}
|
||||
|
||||
content, err := transferAdapter.Download(ctx, link)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := dc(object.Pointer, content, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
@ -183,93 +185,84 @@ func TestHTTPClientDownload(t *testing.T) {
|
|||
|
||||
cases := []struct {
|
||||
endpoint string
|
||||
expectederror string
|
||||
expectedError string
|
||||
}{
|
||||
// case 0
|
||||
{
|
||||
endpoint: "https://status-not-ok.io",
|
||||
expectederror: io.ErrUnexpectedEOF.Error(),
|
||||
expectedError: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
// case 1
|
||||
{
|
||||
endpoint: "https://invalid-json-response.io",
|
||||
expectederror: "invalid json",
|
||||
expectedError: "invalid json",
|
||||
},
|
||||
// case 2
|
||||
{
|
||||
endpoint: "https://valid-batch-request-download.io",
|
||||
expectederror: "",
|
||||
expectedError: "",
|
||||
},
|
||||
// case 3
|
||||
{
|
||||
endpoint: "https://response-no-objects.io",
|
||||
expectederror: "",
|
||||
expectedError: "",
|
||||
},
|
||||
// case 4
|
||||
{
|
||||
endpoint: "https://unknown-transfer-adapter.io",
|
||||
expectederror: "TransferAdapter not found: ",
|
||||
expectedError: "TransferAdapter not found: ",
|
||||
},
|
||||
// case 5
|
||||
{
|
||||
endpoint: "https://error-in-response-objects.io",
|
||||
expectederror: "Object not found",
|
||||
expectedError: "Object not found",
|
||||
},
|
||||
// case 6
|
||||
{
|
||||
endpoint: "https://empty-actions-map.io",
|
||||
expectederror: "missing action 'download'",
|
||||
expectedError: "missing action 'download'",
|
||||
},
|
||||
// case 7
|
||||
{
|
||||
endpoint: "https://download-actions-map.io",
|
||||
expectederror: "",
|
||||
expectedError: "",
|
||||
},
|
||||
// case 8
|
||||
{
|
||||
endpoint: "https://upload-actions-map.io",
|
||||
expectederror: "missing action 'download'",
|
||||
expectedError: "missing action 'download'",
|
||||
},
|
||||
// case 9
|
||||
{
|
||||
endpoint: "https://verify-actions-map.io",
|
||||
expectederror: "missing action 'download'",
|
||||
expectedError: "missing action 'download'",
|
||||
},
|
||||
// case 10
|
||||
{
|
||||
endpoint: "https://unknown-actions-map.io",
|
||||
expectederror: "missing action 'download'",
|
||||
expectedError: "missing action 'download'",
|
||||
},
|
||||
// case 11
|
||||
{
|
||||
endpoint: "https://legacy-batch-request-download.io",
|
||||
expectederror: "",
|
||||
expectedError: "",
|
||||
},
|
||||
}
|
||||
|
||||
for n, c := range cases {
|
||||
client := &HTTPClient{
|
||||
client: hc,
|
||||
endpoint: c.endpoint,
|
||||
transfers: map[string]TransferAdapter{
|
||||
"dummy": dummy,
|
||||
},
|
||||
}
|
||||
|
||||
err := client.Download(context.Background(), []Pointer{p}, func(p Pointer, content io.ReadCloser, objectError error) error {
|
||||
if objectError != nil {
|
||||
return objectError
|
||||
defer test.MockVariableValue(&setting.LFSClient.BatchOperationConcurrency, 8)()
|
||||
for _, c := range cases {
|
||||
t.Run(c.endpoint, func(t *testing.T) {
|
||||
client := &HTTPClient{
|
||||
client: hc,
|
||||
endpoint: c.endpoint,
|
||||
transfers: map[string]TransferAdapter{
|
||||
"dummy": dummy,
|
||||
},
|
||||
}
|
||||
|
||||
err := client.Download(context.Background(), []Pointer{p}, func(p Pointer, content io.ReadCloser, objectError error) error {
|
||||
if objectError != nil {
|
||||
return objectError
|
||||
}
|
||||
b, err := io.ReadAll(content)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("dummy"), b)
|
||||
return nil
|
||||
})
|
||||
if c.expectedError != "" {
|
||||
assert.ErrorContains(t, err, c.expectedError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
b, err := io.ReadAll(content)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("dummy"), b)
|
||||
return nil
|
||||
})
|
||||
if len(c.expectederror) > 0 {
|
||||
assert.True(t, strings.Contains(err.Error(), c.expectederror), "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||
} else {
|
||||
assert.NoError(t, err, "case %d", n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,81 +289,73 @@ func TestHTTPClientUpload(t *testing.T) {
|
|||
|
||||
cases := []struct {
|
||||
endpoint string
|
||||
expectederror string
|
||||
expectedError string
|
||||
}{
|
||||
// case 0
|
||||
{
|
||||
endpoint: "https://status-not-ok.io",
|
||||
expectederror: io.ErrUnexpectedEOF.Error(),
|
||||
expectedError: io.ErrUnexpectedEOF.Error(),
|
||||
},
|
||||
// case 1
|
||||
{
|
||||
endpoint: "https://invalid-json-response.io",
|
||||
expectederror: "invalid json",
|
||||
expectedError: "invalid json",
|
||||
},
|
||||
// case 2
|
||||
{
|
||||
endpoint: "https://valid-batch-request-upload.io",
|
||||
expectederror: "",
|
||||
expectedError: "",
|
||||
},
|
||||
// case 3
|
||||
{
|
||||
endpoint: "https://response-no-objects.io",
|
||||
expectederror: "",
|
||||
expectedError: "",
|
||||
},
|
||||
// case 4
|
||||
{
|
||||
endpoint: "https://unknown-transfer-adapter.io",
|
||||
expectederror: "TransferAdapter not found: ",
|
||||
expectedError: "TransferAdapter not found: ",
|
||||
},
|
||||
// case 5
|
||||
{
|
||||
endpoint: "https://error-in-response-objects.io",
|
||||
expectederror: "Object not found",
|
||||
expectedError: "Object not found",
|
||||
},
|
||||
// case 6
|
||||
{
|
||||
endpoint: "https://empty-actions-map.io",
|
||||
expectederror: "",
|
||||
expectedError: "",
|
||||
},
|
||||
// case 7
|
||||
{
|
||||
endpoint: "https://download-actions-map.io",
|
||||
expectederror: "missing action 'upload'",
|
||||
expectedError: "missing action 'upload'",
|
||||
},
|
||||
// case 8
|
||||
{
|
||||
endpoint: "https://upload-actions-map.io",
|
||||
expectederror: "",
|
||||
expectedError: "",
|
||||
},
|
||||
// case 9
|
||||
{
|
||||
endpoint: "https://verify-actions-map.io",
|
||||
expectederror: "missing action 'upload'",
|
||||
expectedError: "missing action 'upload'",
|
||||
},
|
||||
// case 10
|
||||
{
|
||||
endpoint: "https://unknown-actions-map.io",
|
||||
expectederror: "missing action 'upload'",
|
||||
expectedError: "missing action 'upload'",
|
||||
},
|
||||
}
|
||||
|
||||
for n, c := range cases {
|
||||
client := &HTTPClient{
|
||||
client: hc,
|
||||
endpoint: c.endpoint,
|
||||
transfers: map[string]TransferAdapter{
|
||||
"dummy": dummy,
|
||||
},
|
||||
}
|
||||
defer test.MockVariableValue(&setting.LFSClient.BatchOperationConcurrency, 8)()
|
||||
for _, c := range cases {
|
||||
t.Run(c.endpoint, func(t *testing.T) {
|
||||
client := &HTTPClient{
|
||||
client: hc,
|
||||
endpoint: c.endpoint,
|
||||
transfers: map[string]TransferAdapter{
|
||||
"dummy": dummy,
|
||||
},
|
||||
}
|
||||
|
||||
err := client.Upload(context.Background(), []Pointer{p}, func(p Pointer, objectError error) (io.ReadCloser, error) {
|
||||
return io.NopCloser(new(bytes.Buffer)), objectError
|
||||
err := client.Upload(context.Background(), []Pointer{p}, func(p Pointer, objectError error) (io.ReadCloser, error) {
|
||||
return io.NopCloser(new(bytes.Buffer)), objectError
|
||||
})
|
||||
if c.expectedError != "" {
|
||||
assert.ErrorContains(t, err, c.expectedError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
})
|
||||
if len(c.expectederror) > 0 {
|
||||
assert.True(t, strings.Contains(err.Error(), c.expectederror), "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||
} else {
|
||||
assert.NoError(t, err, "case %d", n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
type WriterConsoleOption struct {
|
||||
|
@ -18,19 +19,13 @@ type eventWriterConsole struct {
|
|||
|
||||
var _ EventWriter = (*eventWriterConsole)(nil)
|
||||
|
||||
type nopCloser struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (nopCloser) Close() error { return nil }
|
||||
|
||||
func NewEventWriterConsole(name string, mode WriterMode) EventWriter {
|
||||
w := &eventWriterConsole{EventWriterBaseImpl: NewEventWriterBase(name, "console", mode)}
|
||||
opt := mode.WriterOption.(WriterConsoleOption)
|
||||
if opt.Stderr {
|
||||
w.OutputWriteCloser = nopCloser{os.Stderr}
|
||||
w.OutputWriteCloser = util.NopCloser{Writer: os.Stderr}
|
||||
} else {
|
||||
w.OutputWriteCloser = nopCloser{os.Stdout}
|
||||
w.OutputWriteCloser = util.NopCloser{Writer: os.Stdout}
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package log
|
|||
import (
|
||||
"io"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/util/rotatingfilewriter"
|
||||
)
|
||||
|
||||
|
@ -42,7 +43,7 @@ func NewEventWriterFile(name string, mode WriterMode) EventWriter {
|
|||
// if the log file can't be opened, what should it do? panic/exit? ignore logs? fallback to stderr?
|
||||
// it seems that "fallback to stderr" is slightly better than others ....
|
||||
FallbackErrorf("unable to open log file %q: %v", opt.FileName, err)
|
||||
w.fileWriter = nopCloser{Writer: LoggerToWriter(FallbackErrorf)}
|
||||
w.fileWriter = util.NopCloser{Writer: LoggerToWriter(FallbackErrorf)}
|
||||
}
|
||||
w.OutputWriteCloser = w.fileWriter
|
||||
return w
|
||||
|
|
|
@ -6,25 +6,12 @@ package markup
|
|||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/emoji"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markup/common"
|
||||
"code.gitea.io/gitea/modules/references"
|
||||
"code.gitea.io/gitea/modules/regexplru"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates/vars"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
"golang.org/x/net/html/atom"
|
||||
|
@ -451,55 +438,14 @@ func createKeyword(content string) *html.Node {
|
|||
return span
|
||||
}
|
||||
|
||||
func createEmoji(content, class, name string) *html.Node {
|
||||
span := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.Span.String(),
|
||||
Attr: []html.Attribute{},
|
||||
}
|
||||
if class != "" {
|
||||
span.Attr = append(span.Attr, html.Attribute{Key: "class", Val: class})
|
||||
}
|
||||
if name != "" {
|
||||
span.Attr = append(span.Attr, html.Attribute{Key: "aria-label", Val: name})
|
||||
}
|
||||
|
||||
text := &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: content,
|
||||
}
|
||||
|
||||
span.AppendChild(text)
|
||||
return span
|
||||
}
|
||||
|
||||
func createCustomEmoji(alias string) *html.Node {
|
||||
span := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.Span.String(),
|
||||
Attr: []html.Attribute{},
|
||||
}
|
||||
span.Attr = append(span.Attr, html.Attribute{Key: "class", Val: "emoji"})
|
||||
span.Attr = append(span.Attr, html.Attribute{Key: "aria-label", Val: alias})
|
||||
|
||||
img := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
DataAtom: atom.Img,
|
||||
Data: "img",
|
||||
Attr: []html.Attribute{},
|
||||
}
|
||||
img.Attr = append(img.Attr, html.Attribute{Key: "alt", Val: ":" + alias + ":"})
|
||||
img.Attr = append(img.Attr, html.Attribute{Key: "src", Val: setting.StaticURLPrefix + "/assets/img/emoji/" + alias + ".png"})
|
||||
|
||||
span.AppendChild(img)
|
||||
return span
|
||||
}
|
||||
|
||||
func createLink(href, content, class string) *html.Node {
|
||||
a := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.A.String(),
|
||||
Attr: []html.Attribute{{Key: "href", Val: href}},
|
||||
Attr: []html.Attribute{
|
||||
{Key: "href", Val: href},
|
||||
{Key: "data-markdown-generated-content"},
|
||||
},
|
||||
}
|
||||
|
||||
if class != "" {
|
||||
|
@ -515,33 +461,6 @@ func createLink(href, content, class string) *html.Node {
|
|||
return a
|
||||
}
|
||||
|
||||
func createCodeLink(href, content, class string) *html.Node {
|
||||
a := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.A.String(),
|
||||
Attr: []html.Attribute{{Key: "href", Val: href}},
|
||||
}
|
||||
|
||||
if class != "" {
|
||||
a.Attr = append(a.Attr, html.Attribute{Key: "class", Val: class})
|
||||
}
|
||||
|
||||
text := &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: content,
|
||||
}
|
||||
|
||||
code := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.Code.String(),
|
||||
Attr: []html.Attribute{{Key: "class", Val: "nohighlight"}},
|
||||
}
|
||||
|
||||
code.AppendChild(text)
|
||||
a.AppendChild(code)
|
||||
return a
|
||||
}
|
||||
|
||||
// replaceContent takes text node, and in its content it replaces a section of
|
||||
// it with the specified newNode.
|
||||
func replaceContent(node *html.Node, i, j int, newNode *html.Node) {
|
||||
|
@ -573,676 +492,3 @@ func replaceContentList(node *html.Node, i, j int, newNodes []*html.Node) {
|
|||
}, nextSibling)
|
||||
}
|
||||
}
|
||||
|
||||
func mentionProcessor(ctx *RenderContext, node *html.Node) {
|
||||
start := 0
|
||||
nodeStop := node.NextSibling
|
||||
for node != nodeStop {
|
||||
found, loc := references.FindFirstMentionBytes(util.UnsafeStringToBytes(node.Data[start:]))
|
||||
if !found {
|
||||
node = node.NextSibling
|
||||
start = 0
|
||||
continue
|
||||
}
|
||||
loc.Start += start
|
||||
loc.End += start
|
||||
mention := node.Data[loc.Start:loc.End]
|
||||
teams, ok := ctx.Metas["teams"]
|
||||
// FIXME: util.URLJoin may not be necessary here:
|
||||
// - setting.AppURL is defined to have a terminal '/' so unless mention[1:]
|
||||
// is an AppSubURL link we can probably fallback to concatenation.
|
||||
// team mention should follow @orgName/teamName style
|
||||
if ok && strings.Contains(mention, "/") {
|
||||
mentionOrgAndTeam := strings.Split(mention, "/")
|
||||
if mentionOrgAndTeam[0][1:] == ctx.Metas["org"] && strings.Contains(teams, ","+strings.ToLower(mentionOrgAndTeam[1])+",") {
|
||||
replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(ctx.Links.Prefix(), "org", ctx.Metas["org"], "teams", mentionOrgAndTeam[1]), mention, "mention"))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
continue
|
||||
}
|
||||
start = loc.End
|
||||
continue
|
||||
}
|
||||
mentionedUsername := mention[1:]
|
||||
|
||||
if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) {
|
||||
replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(ctx.Links.Prefix(), mentionedUsername), mention, "mention"))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
} else {
|
||||
start = loc.End
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := shortLinkPattern.FindStringSubmatchIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
content := node.Data[m[2]:m[3]]
|
||||
tail := node.Data[m[4]:m[5]]
|
||||
props := make(map[string]string)
|
||||
|
||||
// MediaWiki uses [[link|text]], while GitHub uses [[text|link]]
|
||||
// It makes page handling terrible, but we prefer GitHub syntax
|
||||
// And fall back to MediaWiki only when it is obvious from the look
|
||||
// Of text and link contents
|
||||
sl := strings.Split(content, "|")
|
||||
for _, v := range sl {
|
||||
if equalPos := strings.IndexByte(v, '='); equalPos == -1 {
|
||||
// There is no equal in this argument; this is a mandatory arg
|
||||
if props["name"] == "" {
|
||||
if IsFullURLString(v) {
|
||||
// If we clearly see it is a link, we save it so
|
||||
|
||||
// But first we need to ensure, that if both mandatory args provided
|
||||
// look like links, we stick to GitHub syntax
|
||||
if props["link"] != "" {
|
||||
props["name"] = props["link"]
|
||||
}
|
||||
|
||||
props["link"] = strings.TrimSpace(v)
|
||||
} else {
|
||||
props["name"] = v
|
||||
}
|
||||
} else {
|
||||
props["link"] = strings.TrimSpace(v)
|
||||
}
|
||||
} else {
|
||||
// There is an equal; optional argument.
|
||||
|
||||
sep := strings.IndexByte(v, '=')
|
||||
key, val := v[:sep], html.UnescapeString(v[sep+1:])
|
||||
|
||||
// When parsing HTML, x/net/html will change all quotes which are
|
||||
// not used for syntax into UTF-8 quotes. So checking val[0] won't
|
||||
// be enough, since that only checks a single byte.
|
||||
if len(val) > 1 {
|
||||
if (strings.HasPrefix(val, "“") && strings.HasSuffix(val, "”")) ||
|
||||
(strings.HasPrefix(val, "‘") && strings.HasSuffix(val, "’")) {
|
||||
const lenQuote = len("‘")
|
||||
val = val[lenQuote : len(val)-lenQuote]
|
||||
} else if (strings.HasPrefix(val, "\"") && strings.HasSuffix(val, "\"")) ||
|
||||
(strings.HasPrefix(val, "'") && strings.HasSuffix(val, "'")) {
|
||||
val = val[1 : len(val)-1]
|
||||
} else if strings.HasPrefix(val, "'") && strings.HasSuffix(val, "’") {
|
||||
const lenQuote = len("‘")
|
||||
val = val[1 : len(val)-lenQuote]
|
||||
}
|
||||
}
|
||||
props[key] = val
|
||||
}
|
||||
}
|
||||
|
||||
var name, link string
|
||||
if props["link"] != "" {
|
||||
link = props["link"]
|
||||
} else if props["name"] != "" {
|
||||
link = props["name"]
|
||||
}
|
||||
if props["title"] != "" {
|
||||
name = props["title"]
|
||||
} else if props["name"] != "" {
|
||||
name = props["name"]
|
||||
} else {
|
||||
name = link
|
||||
}
|
||||
|
||||
name += tail
|
||||
image := false
|
||||
ext := filepath.Ext(link)
|
||||
switch ext {
|
||||
// fast path: empty string, ignore
|
||||
case "":
|
||||
// leave image as false
|
||||
case ".jpg", ".jpeg", ".png", ".tif", ".tiff", ".webp", ".gif", ".bmp", ".ico", ".svg":
|
||||
image = true
|
||||
}
|
||||
|
||||
childNode := &html.Node{}
|
||||
linkNode := &html.Node{
|
||||
FirstChild: childNode,
|
||||
LastChild: childNode,
|
||||
Type: html.ElementNode,
|
||||
Data: "a",
|
||||
DataAtom: atom.A,
|
||||
}
|
||||
childNode.Parent = linkNode
|
||||
absoluteLink := IsFullURLString(link)
|
||||
if !absoluteLink {
|
||||
if image {
|
||||
link = strings.ReplaceAll(link, " ", "+")
|
||||
} else {
|
||||
link = strings.ReplaceAll(link, " ", "-") // FIXME: it should support dashes in the link, eg: "the-dash-support.-"
|
||||
}
|
||||
if !strings.Contains(link, "/") {
|
||||
link = url.PathEscape(link) // FIXME: it doesn't seem right and it might cause double-escaping
|
||||
}
|
||||
}
|
||||
if image {
|
||||
if !absoluteLink {
|
||||
link = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsWiki), link)
|
||||
}
|
||||
title := props["title"]
|
||||
if title == "" {
|
||||
title = props["alt"]
|
||||
}
|
||||
if title == "" {
|
||||
title = path.Base(name)
|
||||
}
|
||||
alt := props["alt"]
|
||||
if alt == "" {
|
||||
alt = name
|
||||
}
|
||||
|
||||
// make the childNode an image - if we can, we also place the alt
|
||||
childNode.Type = html.ElementNode
|
||||
childNode.Data = "img"
|
||||
childNode.DataAtom = atom.Img
|
||||
childNode.Attr = []html.Attribute{
|
||||
{Key: "src", Val: link},
|
||||
{Key: "title", Val: title},
|
||||
{Key: "alt", Val: alt},
|
||||
}
|
||||
if alt == "" {
|
||||
childNode.Attr = childNode.Attr[:2]
|
||||
}
|
||||
} else {
|
||||
link, _ = ResolveLink(ctx, link, "")
|
||||
childNode.Type = html.TextNode
|
||||
childNode.Data = name
|
||||
}
|
||||
linkNode.Attr = []html.Attribute{{Key: "href", Val: link}}
|
||||
replaceContent(node, m[0], m[1], linkNode)
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := getIssueFullPattern().FindStringSubmatchIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
mDiffView := getFilesChangedFullPattern().FindStringSubmatchIndex(node.Data)
|
||||
// leave it as it is if the link is from "Files Changed" tab in PR Diff View https://domain/org/repo/pulls/27/files
|
||||
if mDiffView != nil {
|
||||
return
|
||||
}
|
||||
|
||||
link := node.Data[m[0]:m[1]]
|
||||
text := "#" + node.Data[m[2]:m[3]]
|
||||
// if m[4] and m[5] is not -1, then link is to a comment
|
||||
// indicate that in the text by appending (comment)
|
||||
if m[4] != -1 && m[5] != -1 {
|
||||
if locale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale); ok {
|
||||
text += " " + locale.TrString("repo.from_comment")
|
||||
} else {
|
||||
text += " (comment)"
|
||||
}
|
||||
}
|
||||
|
||||
// extract repo and org name from matched link like
|
||||
// http://localhost:3000/gituser/myrepo/issues/1
|
||||
linkParts := strings.Split(link, "/")
|
||||
matchOrg := linkParts[len(linkParts)-4]
|
||||
matchRepo := linkParts[len(linkParts)-3]
|
||||
|
||||
if matchOrg == ctx.Metas["user"] && matchRepo == ctx.Metas["repo"] {
|
||||
replaceContent(node, m[0], m[1], createLink(link, text, "ref-issue"))
|
||||
} else {
|
||||
text = matchOrg + "/" + matchRepo + text
|
||||
replaceContent(node, m[0], m[1], createLink(link, text, "ref-issue"))
|
||||
}
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: the use of "mode" is quite dirty and hacky, for example: what is a "document"? how should it be rendered?
|
||||
// The "mode" approach should be refactored to some other more clear&reliable way.
|
||||
crossLinkOnly := ctx.Metas["mode"] == "document" && !ctx.IsWiki
|
||||
|
||||
var (
|
||||
found bool
|
||||
ref *references.RenderizableReference
|
||||
)
|
||||
|
||||
next := node.NextSibling
|
||||
|
||||
for node != nil && node != next {
|
||||
_, hasExtTrackFormat := ctx.Metas["format"]
|
||||
|
||||
// Repos with external issue trackers might still need to reference local PRs
|
||||
// We need to concern with the first one that shows up in the text, whichever it is
|
||||
isNumericStyle := ctx.Metas["style"] == "" || ctx.Metas["style"] == IssueNameStyleNumeric
|
||||
foundNumeric, refNumeric := references.FindRenderizableReferenceNumeric(node.Data, hasExtTrackFormat && !isNumericStyle, crossLinkOnly)
|
||||
|
||||
switch ctx.Metas["style"] {
|
||||
case "", IssueNameStyleNumeric:
|
||||
found, ref = foundNumeric, refNumeric
|
||||
case IssueNameStyleAlphanumeric:
|
||||
found, ref = references.FindRenderizableReferenceAlphanumeric(node.Data)
|
||||
case IssueNameStyleRegexp:
|
||||
pattern, err := regexplru.GetCompiled(ctx.Metas["regexp"])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
found, ref = references.FindRenderizableReferenceRegexp(node.Data, pattern)
|
||||
}
|
||||
|
||||
// Repos with external issue trackers might still need to reference local PRs
|
||||
// We need to concern with the first one that shows up in the text, whichever it is
|
||||
if hasExtTrackFormat && !isNumericStyle && refNumeric != nil {
|
||||
// If numeric (PR) was found, and it was BEFORE the non-numeric pattern, use that
|
||||
// Allow a free-pass when non-numeric pattern wasn't found.
|
||||
if found && (ref == nil || refNumeric.RefLocation.Start < ref.RefLocation.Start) {
|
||||
found = foundNumeric
|
||||
ref = refNumeric
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
|
||||
var link *html.Node
|
||||
reftext := node.Data[ref.RefLocation.Start:ref.RefLocation.End]
|
||||
if hasExtTrackFormat && !ref.IsPull {
|
||||
ctx.Metas["index"] = ref.Issue
|
||||
|
||||
res, err := vars.Expand(ctx.Metas["format"], ctx.Metas)
|
||||
if err != nil {
|
||||
// here we could just log the error and continue the rendering
|
||||
log.Error("unable to expand template vars for ref %s, err: %v", ref.Issue, err)
|
||||
}
|
||||
|
||||
link = createLink(res, reftext, "ref-issue ref-external-issue")
|
||||
} else {
|
||||
// Path determines the type of link that will be rendered. It's unknown at this point whether
|
||||
// the linked item is actually a PR or an issue. Luckily it's of no real consequence because
|
||||
// Gitea will redirect on click as appropriate.
|
||||
issuePath := util.Iif(ref.IsPull, "pulls", "issues")
|
||||
if ref.Owner == "" {
|
||||
link = createLink(util.URLJoin(ctx.Links.Prefix(), ctx.Metas["user"], ctx.Metas["repo"], issuePath, ref.Issue), reftext, "ref-issue")
|
||||
} else {
|
||||
link = createLink(util.URLJoin(ctx.Links.Prefix(), ref.Owner, ref.Name, issuePath, ref.Issue), reftext, "ref-issue")
|
||||
}
|
||||
}
|
||||
|
||||
if ref.Action == references.XRefActionNone {
|
||||
replaceContent(node, ref.RefLocation.Start, ref.RefLocation.End, link)
|
||||
node = node.NextSibling.NextSibling
|
||||
continue
|
||||
}
|
||||
|
||||
// Decorate action keywords if actionable
|
||||
var keyword *html.Node
|
||||
if references.IsXrefActionable(ref, hasExtTrackFormat) {
|
||||
keyword = createKeyword(node.Data[ref.ActionLocation.Start:ref.ActionLocation.End])
|
||||
} else {
|
||||
keyword = &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: node.Data[ref.ActionLocation.Start:ref.ActionLocation.End],
|
||||
}
|
||||
}
|
||||
spaces := &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: node.Data[ref.ActionLocation.End:ref.RefLocation.Start],
|
||||
}
|
||||
replaceContentList(node, ref.ActionLocation.Start, ref.RefLocation.End, []*html.Node{keyword, spaces, link})
|
||||
node = node.NextSibling.NextSibling.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func commitCrossReferencePatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
|
||||
for node != nil && node != next {
|
||||
found, ref := references.FindRenderizableCommitCrossReference(node.Data)
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
|
||||
reftext := ref.Owner + "/" + ref.Name + "@" + base.ShortSha(ref.CommitSha)
|
||||
link := createLink(util.URLJoin(ctx.Links.Prefix(), ref.Owner, ref.Name, "commit", ref.CommitSha), reftext, "commit")
|
||||
|
||||
replaceContent(node, ref.RefLocation.Start, ref.RefLocation.End, link)
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
type anyHashPatternResult struct {
|
||||
PosStart int
|
||||
PosEnd int
|
||||
FullURL string
|
||||
CommitID string
|
||||
SubPath string
|
||||
QueryHash string
|
||||
}
|
||||
|
||||
func anyHashPatternExtract(s string) (ret anyHashPatternResult, ok bool) {
|
||||
m := anyHashPattern.FindStringSubmatchIndex(s)
|
||||
if m == nil {
|
||||
return ret, false
|
||||
}
|
||||
|
||||
ret.PosStart, ret.PosEnd = m[0], m[1]
|
||||
ret.FullURL = s[ret.PosStart:ret.PosEnd]
|
||||
if strings.HasSuffix(ret.FullURL, ".") {
|
||||
// if url ends in '.', it's very likely that it is not part of the actual url but used to finish a sentence.
|
||||
ret.PosEnd--
|
||||
ret.FullURL = ret.FullURL[:len(ret.FullURL)-1]
|
||||
for i := 0; i < len(m); i++ {
|
||||
m[i] = min(m[i], ret.PosEnd)
|
||||
}
|
||||
}
|
||||
|
||||
ret.CommitID = s[m[2]:m[3]]
|
||||
if m[5] > 0 {
|
||||
ret.SubPath = s[m[4]:m[5]]
|
||||
}
|
||||
|
||||
lastStart, lastEnd := m[len(m)-2], m[len(m)-1]
|
||||
if lastEnd > 0 {
|
||||
ret.QueryHash = s[lastStart:lastEnd][1:]
|
||||
}
|
||||
return ret, true
|
||||
}
|
||||
|
||||
// fullHashPatternProcessor renders SHA containing URLs
|
||||
func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
nodeStop := node.NextSibling
|
||||
for node != nodeStop {
|
||||
if node.Type != html.TextNode {
|
||||
node = node.NextSibling
|
||||
continue
|
||||
}
|
||||
ret, ok := anyHashPatternExtract(node.Data)
|
||||
if !ok {
|
||||
node = node.NextSibling
|
||||
continue
|
||||
}
|
||||
text := base.ShortSha(ret.CommitID)
|
||||
if ret.SubPath != "" {
|
||||
text += ret.SubPath
|
||||
}
|
||||
if ret.QueryHash != "" {
|
||||
text += " (" + ret.QueryHash + ")"
|
||||
}
|
||||
replaceContent(node, ret.PosStart, ret.PosEnd, createCodeLink(ret.FullURL, text, "commit"))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func comparePatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
nodeStop := node.NextSibling
|
||||
for node != nodeStop {
|
||||
if node.Type != html.TextNode {
|
||||
node = node.NextSibling
|
||||
continue
|
||||
}
|
||||
m := comparePattern.FindStringSubmatchIndex(node.Data)
|
||||
if m == nil || slices.Contains(m[:8], -1) { // ensure that every group (m[0]...m[7]) has a match
|
||||
node = node.NextSibling
|
||||
continue
|
||||
}
|
||||
|
||||
urlFull := node.Data[m[0]:m[1]]
|
||||
text1 := base.ShortSha(node.Data[m[2]:m[3]])
|
||||
textDots := base.ShortSha(node.Data[m[4]:m[5]])
|
||||
text2 := base.ShortSha(node.Data[m[6]:m[7]])
|
||||
|
||||
hash := ""
|
||||
if m[9] > 0 {
|
||||
hash = node.Data[m[8]:m[9]][1:]
|
||||
}
|
||||
|
||||
start := m[0]
|
||||
end := m[1]
|
||||
|
||||
// If url ends in '.', it's very likely that it is not part of the
|
||||
// actual url but used to finish a sentence.
|
||||
if strings.HasSuffix(urlFull, ".") {
|
||||
end--
|
||||
urlFull = urlFull[:len(urlFull)-1]
|
||||
if hash != "" {
|
||||
hash = hash[:len(hash)-1]
|
||||
} else if text2 != "" {
|
||||
text2 = text2[:len(text2)-1]
|
||||
}
|
||||
}
|
||||
|
||||
text := text1 + textDots + text2
|
||||
if hash != "" {
|
||||
text += " (" + hash + ")"
|
||||
}
|
||||
replaceContent(node, start, end, createCodeLink(urlFull, text, "compare"))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
// emojiShortCodeProcessor for rendering text like :smile: into emoji
|
||||
func emojiShortCodeProcessor(ctx *RenderContext, node *html.Node) {
|
||||
start := 0
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next && start < len(node.Data) {
|
||||
m := emojiShortCodeRegex.FindStringSubmatchIndex(node.Data[start:])
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
m[0] += start
|
||||
m[1] += start
|
||||
|
||||
start = m[1]
|
||||
|
||||
alias := node.Data[m[0]:m[1]]
|
||||
alias = strings.ReplaceAll(alias, ":", "")
|
||||
converted := emoji.FromAlias(alias)
|
||||
if converted == nil {
|
||||
// check if this is a custom reaction
|
||||
if _, exist := setting.UI.CustomEmojisMap[alias]; exist {
|
||||
replaceContent(node, m[0], m[1], createCustomEmoji(alias))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
replaceContent(node, m[0], m[1], createEmoji(converted.Emoji, "emoji", converted.Description))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
}
|
||||
}
|
||||
|
||||
// emoji processor to match emoji and add emoji class
|
||||
func emojiProcessor(ctx *RenderContext, node *html.Node) {
|
||||
start := 0
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next && start < len(node.Data) {
|
||||
m := emoji.FindEmojiSubmatchIndex(node.Data[start:])
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
m[0] += start
|
||||
m[1] += start
|
||||
|
||||
codepoint := node.Data[m[0]:m[1]]
|
||||
start = m[1]
|
||||
val := emoji.FromCode(codepoint)
|
||||
if val != nil {
|
||||
replaceContent(node, m[0], m[1], createEmoji(codepoint, "emoji", val.Description))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// hashCurrentPatternProcessor renders SHA1 strings to corresponding links that
|
||||
// are assumed to be in the same repository.
|
||||
func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil || ctx.Metas["user"] == "" || ctx.Metas["repo"] == "" || (ctx.Repo == nil && ctx.GitRepo == nil) {
|
||||
return
|
||||
}
|
||||
|
||||
start := 0
|
||||
next := node.NextSibling
|
||||
if ctx.ShaExistCache == nil {
|
||||
ctx.ShaExistCache = make(map[string]bool)
|
||||
}
|
||||
for node != nil && node != next && start < len(node.Data) {
|
||||
m := hashCurrentPattern.FindStringSubmatchIndex(node.Data[start:])
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
m[2] += start
|
||||
m[3] += start
|
||||
|
||||
hash := node.Data[m[2]:m[3]]
|
||||
// The regex does not lie, it matches the hash pattern.
|
||||
// However, a regex cannot know if a hash actually exists or not.
|
||||
// We could assume that a SHA1 hash should probably contain alphas AND numerics
|
||||
// but that is not always the case.
|
||||
// Although unlikely, deadbeef and 1234567 are valid short forms of SHA1 hash
|
||||
// as used by git and github for linking and thus we have to do similar.
|
||||
// Because of this, we check to make sure that a matched hash is actually
|
||||
// a commit in the repository before making it a link.
|
||||
|
||||
// check cache first
|
||||
exist, inCache := ctx.ShaExistCache[hash]
|
||||
if !inCache {
|
||||
if ctx.GitRepo == nil {
|
||||
var err error
|
||||
var closer io.Closer
|
||||
ctx.GitRepo, closer, err = gitrepo.RepositoryFromContextOrOpen(ctx.Ctx, ctx.Repo)
|
||||
if err != nil {
|
||||
log.Error("unable to open repository: %s Error: %v", gitrepo.RepoGitURL(ctx.Repo), err)
|
||||
return
|
||||
}
|
||||
ctx.AddCancel(func() {
|
||||
_ = closer.Close()
|
||||
ctx.GitRepo = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Don't use IsObjectExist since it doesn't support short hashs with gogit edition.
|
||||
exist = ctx.GitRepo.IsReferenceExist(hash)
|
||||
ctx.ShaExistCache[hash] = exist
|
||||
}
|
||||
|
||||
if !exist {
|
||||
start = m[3]
|
||||
continue
|
||||
}
|
||||
|
||||
link := util.URLJoin(ctx.Links.Prefix(), ctx.Metas["user"], ctx.Metas["repo"], "commit", hash)
|
||||
replaceContent(node, m[2], m[3], createCodeLink(link, base.ShortSha(hash), "commit"))
|
||||
start = 0
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
// emailAddressProcessor replaces raw email addresses with a mailto: link.
|
||||
func emailAddressProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := emailRegex.FindStringSubmatchIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
mail := node.Data[m[2]:m[3]]
|
||||
replaceContent(node, m[2], m[3], createLink("mailto:"+mail, mail, "mailto"))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
// linkProcessor creates links for any HTTP or HTTPS URL not captured by
|
||||
// markdown.
|
||||
func linkProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := common.LinkRegex.FindStringIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
uri := node.Data[m[0]:m[1]]
|
||||
replaceContent(node, m[0], m[1], createLink(uri, uri, "link"))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func genDefaultLinkProcessor(defaultLink string) processor {
|
||||
return func(ctx *RenderContext, node *html.Node) {
|
||||
ch := &html.Node{
|
||||
Parent: node,
|
||||
Type: html.TextNode,
|
||||
Data: node.Data,
|
||||
}
|
||||
|
||||
node.Type = html.ElementNode
|
||||
node.Data = "a"
|
||||
node.DataAtom = atom.A
|
||||
node.Attr = []html.Attribute{
|
||||
{Key: "href", Val: defaultLink},
|
||||
{Key: "class", Val: "default-link muted"},
|
||||
}
|
||||
node.FirstChild, node.LastChild = ch, ch
|
||||
}
|
||||
}
|
||||
|
||||
// descriptionLinkProcessor creates links for DescriptionHTML
|
||||
func descriptionLinkProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := common.LinkRegex.FindStringIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
uri := node.Data[m[0]:m[1]]
|
||||
replaceContent(node, m[0], m[1], createDescriptionLink(uri, uri))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func createDescriptionLink(href, content string) *html.Node {
|
||||
textNode := &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: content,
|
||||
}
|
||||
linkNode := &html.Node{
|
||||
FirstChild: textNode,
|
||||
LastChild: textNode,
|
||||
Type: html.ElementNode,
|
||||
Data: "a",
|
||||
DataAtom: atom.A,
|
||||
Attr: []html.Attribute{
|
||||
{Key: "href", Val: href},
|
||||
{Key: "target", Val: "_blank"},
|
||||
{Key: "rel", Val: "noopener noreferrer"},
|
||||
},
|
||||
}
|
||||
textNode.Parent = linkNode
|
||||
return linkNode
|
||||
}
|
||||
|
|
|
@ -30,5 +30,5 @@ func TestRenderCodePreview(t *testing.T) {
|
|||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
|
||||
}
|
||||
test("http://localhost:3000/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20", "<p><div>code preview</div></p>")
|
||||
test("http://other/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20", `<p><a href="http://other/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20" rel="nofollow">http://other/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20</a></p>`)
|
||||
test("http://other/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20", `<p><a href="http://other/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20" data-markdown-generated-content="" rel="nofollow">http://other/owner/repo/src/commit/0123456789/foo/bar.md#L10-L20</a></p>`)
|
||||
}
|
||||
|
|
225
modules/markup/html_commit.go
Normal file
225
modules/markup/html_commit.go
Normal file
|
@ -0,0 +1,225 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"io"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
"golang.org/x/net/html/atom"
|
||||
)
|
||||
|
||||
type anyHashPatternResult struct {
|
||||
PosStart int
|
||||
PosEnd int
|
||||
FullURL string
|
||||
CommitID string
|
||||
SubPath string
|
||||
QueryHash string
|
||||
}
|
||||
|
||||
func createCodeLink(href, content, class string) *html.Node {
|
||||
a := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.A.String(),
|
||||
Attr: []html.Attribute{{Key: "href", Val: href}},
|
||||
}
|
||||
|
||||
if class != "" {
|
||||
a.Attr = append(a.Attr, html.Attribute{Key: "class", Val: class})
|
||||
}
|
||||
|
||||
text := &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: content,
|
||||
}
|
||||
|
||||
code := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.Code.String(),
|
||||
Attr: []html.Attribute{{Key: "class", Val: "nohighlight"}},
|
||||
}
|
||||
|
||||
code.AppendChild(text)
|
||||
a.AppendChild(code)
|
||||
return a
|
||||
}
|
||||
|
||||
func anyHashPatternExtract(s string) (ret anyHashPatternResult, ok bool) {
|
||||
m := anyHashPattern.FindStringSubmatchIndex(s)
|
||||
if m == nil {
|
||||
return ret, false
|
||||
}
|
||||
|
||||
ret.PosStart, ret.PosEnd = m[0], m[1]
|
||||
ret.FullURL = s[ret.PosStart:ret.PosEnd]
|
||||
if strings.HasSuffix(ret.FullURL, ".") {
|
||||
// if url ends in '.', it's very likely that it is not part of the actual url but used to finish a sentence.
|
||||
ret.PosEnd--
|
||||
ret.FullURL = ret.FullURL[:len(ret.FullURL)-1]
|
||||
for i := 0; i < len(m); i++ {
|
||||
m[i] = min(m[i], ret.PosEnd)
|
||||
}
|
||||
}
|
||||
|
||||
ret.CommitID = s[m[2]:m[3]]
|
||||
if m[5] > 0 {
|
||||
ret.SubPath = s[m[4]:m[5]]
|
||||
}
|
||||
|
||||
lastStart, lastEnd := m[len(m)-2], m[len(m)-1]
|
||||
if lastEnd > 0 {
|
||||
ret.QueryHash = s[lastStart:lastEnd][1:]
|
||||
}
|
||||
return ret, true
|
||||
}
|
||||
|
||||
// fullHashPatternProcessor renders SHA containing URLs
|
||||
func fullHashPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
nodeStop := node.NextSibling
|
||||
for node != nodeStop {
|
||||
if node.Type != html.TextNode {
|
||||
node = node.NextSibling
|
||||
continue
|
||||
}
|
||||
ret, ok := anyHashPatternExtract(node.Data)
|
||||
if !ok {
|
||||
node = node.NextSibling
|
||||
continue
|
||||
}
|
||||
text := base.ShortSha(ret.CommitID)
|
||||
if ret.SubPath != "" {
|
||||
text += ret.SubPath
|
||||
}
|
||||
if ret.QueryHash != "" {
|
||||
text += " (" + ret.QueryHash + ")"
|
||||
}
|
||||
replaceContent(node, ret.PosStart, ret.PosEnd, createCodeLink(ret.FullURL, text, "commit"))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func comparePatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
nodeStop := node.NextSibling
|
||||
for node != nodeStop {
|
||||
if node.Type != html.TextNode {
|
||||
node = node.NextSibling
|
||||
continue
|
||||
}
|
||||
m := comparePattern.FindStringSubmatchIndex(node.Data)
|
||||
if m == nil || slices.Contains(m[:8], -1) { // ensure that every group (m[0]...m[7]) has a match
|
||||
node = node.NextSibling
|
||||
continue
|
||||
}
|
||||
|
||||
urlFull := node.Data[m[0]:m[1]]
|
||||
text1 := base.ShortSha(node.Data[m[2]:m[3]])
|
||||
textDots := base.ShortSha(node.Data[m[4]:m[5]])
|
||||
text2 := base.ShortSha(node.Data[m[6]:m[7]])
|
||||
|
||||
hash := ""
|
||||
if m[9] > 0 {
|
||||
hash = node.Data[m[8]:m[9]][1:]
|
||||
}
|
||||
|
||||
start := m[0]
|
||||
end := m[1]
|
||||
|
||||
// If url ends in '.', it's very likely that it is not part of the
|
||||
// actual url but used to finish a sentence.
|
||||
if strings.HasSuffix(urlFull, ".") {
|
||||
end--
|
||||
urlFull = urlFull[:len(urlFull)-1]
|
||||
if hash != "" {
|
||||
hash = hash[:len(hash)-1]
|
||||
} else if text2 != "" {
|
||||
text2 = text2[:len(text2)-1]
|
||||
}
|
||||
}
|
||||
|
||||
text := text1 + textDots + text2
|
||||
if hash != "" {
|
||||
text += " (" + hash + ")"
|
||||
}
|
||||
replaceContent(node, start, end, createCodeLink(urlFull, text, "compare"))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
// hashCurrentPatternProcessor renders SHA1 strings to corresponding links that
|
||||
// are assumed to be in the same repository.
|
||||
func hashCurrentPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil || ctx.Metas["user"] == "" || ctx.Metas["repo"] == "" || (ctx.Repo == nil && ctx.GitRepo == nil) {
|
||||
return
|
||||
}
|
||||
|
||||
start := 0
|
||||
next := node.NextSibling
|
||||
if ctx.ShaExistCache == nil {
|
||||
ctx.ShaExistCache = make(map[string]bool)
|
||||
}
|
||||
for node != nil && node != next && start < len(node.Data) {
|
||||
m := hashCurrentPattern.FindStringSubmatchIndex(node.Data[start:])
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
m[2] += start
|
||||
m[3] += start
|
||||
|
||||
hash := node.Data[m[2]:m[3]]
|
||||
// The regex does not lie, it matches the hash pattern.
|
||||
// However, a regex cannot know if a hash actually exists or not.
|
||||
// We could assume that a SHA1 hash should probably contain alphas AND numerics
|
||||
// but that is not always the case.
|
||||
// Although unlikely, deadbeef and 1234567 are valid short forms of SHA1 hash
|
||||
// as used by git and github for linking and thus we have to do similar.
|
||||
// Because of this, we check to make sure that a matched hash is actually
|
||||
// a commit in the repository before making it a link.
|
||||
|
||||
// check cache first
|
||||
exist, inCache := ctx.ShaExistCache[hash]
|
||||
if !inCache {
|
||||
if ctx.GitRepo == nil {
|
||||
var err error
|
||||
var closer io.Closer
|
||||
ctx.GitRepo, closer, err = gitrepo.RepositoryFromContextOrOpen(ctx.Ctx, ctx.Repo)
|
||||
if err != nil {
|
||||
log.Error("unable to open repository: %s Error: %v", gitrepo.RepoGitURL(ctx.Repo), err)
|
||||
return
|
||||
}
|
||||
ctx.AddCancel(func() {
|
||||
_ = closer.Close()
|
||||
ctx.GitRepo = nil
|
||||
})
|
||||
}
|
||||
|
||||
// Don't use IsObjectExist since it doesn't support short hashs with gogit edition.
|
||||
exist = ctx.GitRepo.IsReferenceExist(hash)
|
||||
ctx.ShaExistCache[hash] = exist
|
||||
}
|
||||
|
||||
if !exist {
|
||||
start = m[3]
|
||||
continue
|
||||
}
|
||||
|
||||
link := util.URLJoin(ctx.Links.Prefix(), ctx.Metas["user"], ctx.Metas["repo"], "commit", hash)
|
||||
replaceContent(node, m[2], m[3], createCodeLink(link, base.ShortSha(hash), "commit"))
|
||||
start = 0
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
21
modules/markup/html_email.go
Normal file
21
modules/markup/html_email.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package markup
|
||||
|
||||
import "golang.org/x/net/html"
|
||||
|
||||
// emailAddressProcessor replaces raw email addresses with a mailto: link.
|
||||
func emailAddressProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := emailRegex.FindStringSubmatchIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
mail := node.Data[m[2]:m[3]]
|
||||
replaceContent(node, m[2], m[3], createLink("mailto:"+mail, mail, "mailto"))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
115
modules/markup/html_emoji.go
Normal file
115
modules/markup/html_emoji.go
Normal file
|
@ -0,0 +1,115 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/emoji"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
"golang.org/x/net/html/atom"
|
||||
)
|
||||
|
||||
func createEmoji(content, class, name string) *html.Node {
|
||||
span := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.Span.String(),
|
||||
Attr: []html.Attribute{},
|
||||
}
|
||||
if class != "" {
|
||||
span.Attr = append(span.Attr, html.Attribute{Key: "class", Val: class})
|
||||
}
|
||||
if name != "" {
|
||||
span.Attr = append(span.Attr, html.Attribute{Key: "aria-label", Val: name})
|
||||
}
|
||||
|
||||
text := &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: content,
|
||||
}
|
||||
|
||||
span.AppendChild(text)
|
||||
return span
|
||||
}
|
||||
|
||||
func createCustomEmoji(alias string) *html.Node {
|
||||
span := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
Data: atom.Span.String(),
|
||||
Attr: []html.Attribute{},
|
||||
}
|
||||
span.Attr = append(span.Attr, html.Attribute{Key: "class", Val: "emoji"})
|
||||
span.Attr = append(span.Attr, html.Attribute{Key: "aria-label", Val: alias})
|
||||
|
||||
img := &html.Node{
|
||||
Type: html.ElementNode,
|
||||
DataAtom: atom.Img,
|
||||
Data: "img",
|
||||
Attr: []html.Attribute{},
|
||||
}
|
||||
img.Attr = append(img.Attr, html.Attribute{Key: "alt", Val: ":" + alias + ":"})
|
||||
img.Attr = append(img.Attr, html.Attribute{Key: "src", Val: setting.StaticURLPrefix + "/assets/img/emoji/" + alias + ".png"})
|
||||
|
||||
span.AppendChild(img)
|
||||
return span
|
||||
}
|
||||
|
||||
// emojiShortCodeProcessor for rendering text like :smile: into emoji
|
||||
func emojiShortCodeProcessor(ctx *RenderContext, node *html.Node) {
|
||||
start := 0
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next && start < len(node.Data) {
|
||||
m := emojiShortCodeRegex.FindStringSubmatchIndex(node.Data[start:])
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
m[0] += start
|
||||
m[1] += start
|
||||
|
||||
start = m[1]
|
||||
|
||||
alias := node.Data[m[0]:m[1]]
|
||||
alias = strings.ReplaceAll(alias, ":", "")
|
||||
converted := emoji.FromAlias(alias)
|
||||
if converted == nil {
|
||||
// check if this is a custom reaction
|
||||
if _, exist := setting.UI.CustomEmojisMap[alias]; exist {
|
||||
replaceContent(node, m[0], m[1], createCustomEmoji(alias))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
replaceContent(node, m[0], m[1], createEmoji(converted.Emoji, "emoji", converted.Description))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
}
|
||||
}
|
||||
|
||||
// emoji processor to match emoji and add emoji class
|
||||
func emojiProcessor(ctx *RenderContext, node *html.Node) {
|
||||
start := 0
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next && start < len(node.Data) {
|
||||
m := emoji.FindEmojiSubmatchIndex(node.Data[start:])
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
m[0] += start
|
||||
m[1] += start
|
||||
|
||||
codepoint := node.Data[m[0]:m[1]]
|
||||
start = m[1]
|
||||
val := emoji.FromCode(codepoint)
|
||||
if val != nil {
|
||||
replaceContent(node, m[0], m[1], createEmoji(codepoint, "emoji", val.Description))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,11 +33,9 @@ func numericIssueLink(baseURL, class string, index int, marker string) string {
|
|||
|
||||
// link an HTML link
|
||||
func link(href, class, contents string) string {
|
||||
if class != "" {
|
||||
class = " class=\"" + class + "\""
|
||||
}
|
||||
|
||||
return fmt.Sprintf("<a href=\"%s\"%s>%s</a>", href, class, contents)
|
||||
extra := ` data-markdown-generated-content=""`
|
||||
extra += util.Iif(class != "", ` class="`+class+`"`, "")
|
||||
return fmt.Sprintf(`<a href="%s"%s>%s</a>`, href, extra, contents)
|
||||
}
|
||||
|
||||
var numericMetas = map[string]string{
|
||||
|
@ -353,7 +351,9 @@ func TestRender_FullIssueURLs(t *testing.T) {
|
|||
Metas: localMetas,
|
||||
}, []processor{fullIssuePatternProcessor}, strings.NewReader(input), &result)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, result.String())
|
||||
actual := result.String()
|
||||
actual = strings.ReplaceAll(actual, ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
test("Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6",
|
||||
"Here is a link https://git.osgeo.org/gogs/postgis/postgis/pulls/6")
|
||||
|
|
180
modules/markup/html_issue.go
Normal file
180
modules/markup/html_issue.go
Normal file
|
@ -0,0 +1,180 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/references"
|
||||
"code.gitea.io/gitea/modules/regexplru"
|
||||
"code.gitea.io/gitea/modules/templates/vars"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
func fullIssuePatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := getIssueFullPattern().FindStringSubmatchIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
mDiffView := getFilesChangedFullPattern().FindStringSubmatchIndex(node.Data)
|
||||
// leave it as it is if the link is from "Files Changed" tab in PR Diff View https://domain/org/repo/pulls/27/files
|
||||
if mDiffView != nil {
|
||||
return
|
||||
}
|
||||
|
||||
link := node.Data[m[0]:m[1]]
|
||||
text := "#" + node.Data[m[2]:m[3]]
|
||||
// if m[4] and m[5] is not -1, then link is to a comment
|
||||
// indicate that in the text by appending (comment)
|
||||
if m[4] != -1 && m[5] != -1 {
|
||||
if locale, ok := ctx.Ctx.Value(translation.ContextKey).(translation.Locale); ok {
|
||||
text += " " + locale.TrString("repo.from_comment")
|
||||
} else {
|
||||
text += " (comment)"
|
||||
}
|
||||
}
|
||||
|
||||
// extract repo and org name from matched link like
|
||||
// http://localhost:3000/gituser/myrepo/issues/1
|
||||
linkParts := strings.Split(link, "/")
|
||||
matchOrg := linkParts[len(linkParts)-4]
|
||||
matchRepo := linkParts[len(linkParts)-3]
|
||||
|
||||
if matchOrg == ctx.Metas["user"] && matchRepo == ctx.Metas["repo"] {
|
||||
replaceContent(node, m[0], m[1], createLink(link, text, "ref-issue"))
|
||||
} else {
|
||||
text = matchOrg + "/" + matchRepo + text
|
||||
replaceContent(node, m[0], m[1], createLink(link, text, "ref-issue"))
|
||||
}
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func issueIndexPatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
if ctx.Metas == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: the use of "mode" is quite dirty and hacky, for example: what is a "document"? how should it be rendered?
|
||||
// The "mode" approach should be refactored to some other more clear&reliable way.
|
||||
crossLinkOnly := ctx.Metas["mode"] == "document" && !ctx.IsWiki
|
||||
|
||||
var (
|
||||
found bool
|
||||
ref *references.RenderizableReference
|
||||
)
|
||||
|
||||
next := node.NextSibling
|
||||
|
||||
for node != nil && node != next {
|
||||
_, hasExtTrackFormat := ctx.Metas["format"]
|
||||
|
||||
// Repos with external issue trackers might still need to reference local PRs
|
||||
// We need to concern with the first one that shows up in the text, whichever it is
|
||||
isNumericStyle := ctx.Metas["style"] == "" || ctx.Metas["style"] == IssueNameStyleNumeric
|
||||
foundNumeric, refNumeric := references.FindRenderizableReferenceNumeric(node.Data, hasExtTrackFormat && !isNumericStyle, crossLinkOnly)
|
||||
|
||||
switch ctx.Metas["style"] {
|
||||
case "", IssueNameStyleNumeric:
|
||||
found, ref = foundNumeric, refNumeric
|
||||
case IssueNameStyleAlphanumeric:
|
||||
found, ref = references.FindRenderizableReferenceAlphanumeric(node.Data)
|
||||
case IssueNameStyleRegexp:
|
||||
pattern, err := regexplru.GetCompiled(ctx.Metas["regexp"])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
found, ref = references.FindRenderizableReferenceRegexp(node.Data, pattern)
|
||||
}
|
||||
|
||||
// Repos with external issue trackers might still need to reference local PRs
|
||||
// We need to concern with the first one that shows up in the text, whichever it is
|
||||
if hasExtTrackFormat && !isNumericStyle && refNumeric != nil {
|
||||
// If numeric (PR) was found, and it was BEFORE the non-numeric pattern, use that
|
||||
// Allow a free-pass when non-numeric pattern wasn't found.
|
||||
if found && (ref == nil || refNumeric.RefLocation.Start < ref.RefLocation.Start) {
|
||||
found = foundNumeric
|
||||
ref = refNumeric
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
|
||||
var link *html.Node
|
||||
reftext := node.Data[ref.RefLocation.Start:ref.RefLocation.End]
|
||||
if hasExtTrackFormat && !ref.IsPull {
|
||||
ctx.Metas["index"] = ref.Issue
|
||||
|
||||
res, err := vars.Expand(ctx.Metas["format"], ctx.Metas)
|
||||
if err != nil {
|
||||
// here we could just log the error and continue the rendering
|
||||
log.Error("unable to expand template vars for ref %s, err: %v", ref.Issue, err)
|
||||
}
|
||||
|
||||
link = createLink(res, reftext, "ref-issue ref-external-issue")
|
||||
} else {
|
||||
// Path determines the type of link that will be rendered. It's unknown at this point whether
|
||||
// the linked item is actually a PR or an issue. Luckily it's of no real consequence because
|
||||
// Gitea will redirect on click as appropriate.
|
||||
issuePath := util.Iif(ref.IsPull, "pulls", "issues")
|
||||
if ref.Owner == "" {
|
||||
link = createLink(util.URLJoin(ctx.Links.Prefix(), ctx.Metas["user"], ctx.Metas["repo"], issuePath, ref.Issue), reftext, "ref-issue")
|
||||
} else {
|
||||
link = createLink(util.URLJoin(ctx.Links.Prefix(), ref.Owner, ref.Name, issuePath, ref.Issue), reftext, "ref-issue")
|
||||
}
|
||||
}
|
||||
|
||||
if ref.Action == references.XRefActionNone {
|
||||
replaceContent(node, ref.RefLocation.Start, ref.RefLocation.End, link)
|
||||
node = node.NextSibling.NextSibling
|
||||
continue
|
||||
}
|
||||
|
||||
// Decorate action keywords if actionable
|
||||
var keyword *html.Node
|
||||
if references.IsXrefActionable(ref, hasExtTrackFormat) {
|
||||
keyword = createKeyword(node.Data[ref.ActionLocation.Start:ref.ActionLocation.End])
|
||||
} else {
|
||||
keyword = &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: node.Data[ref.ActionLocation.Start:ref.ActionLocation.End],
|
||||
}
|
||||
}
|
||||
spaces := &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: node.Data[ref.ActionLocation.End:ref.RefLocation.Start],
|
||||
}
|
||||
replaceContentList(node, ref.ActionLocation.Start, ref.RefLocation.End, []*html.Node{keyword, spaces, link})
|
||||
node = node.NextSibling.NextSibling.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func commitCrossReferencePatternProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
|
||||
for node != nil && node != next {
|
||||
found, ref := references.FindRenderizableCommitCrossReference(node.Data)
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
|
||||
reftext := ref.Owner + "/" + ref.Name + "@" + base.ShortSha(ref.CommitSha)
|
||||
link := createLink(util.URLJoin(ctx.Links.Prefix(), ref.Owner, ref.Name, "commit", ref.CommitSha), reftext, "commit")
|
||||
|
||||
replaceContent(node, ref.RefLocation.Start, ref.RefLocation.End, link)
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
|
@ -4,7 +4,16 @@
|
|||
package markup
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/markup/common"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
"golang.org/x/net/html/atom"
|
||||
)
|
||||
|
||||
func ResolveLink(ctx *RenderContext, link, userContentAnchorPrefix string) (result string, resolved bool) {
|
||||
|
@ -27,3 +36,221 @@ func ResolveLink(ctx *RenderContext, link, userContentAnchorPrefix string) (resu
|
|||
}
|
||||
return link, resolved
|
||||
}
|
||||
|
||||
func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := shortLinkPattern.FindStringSubmatchIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
content := node.Data[m[2]:m[3]]
|
||||
tail := node.Data[m[4]:m[5]]
|
||||
props := make(map[string]string)
|
||||
|
||||
// MediaWiki uses [[link|text]], while GitHub uses [[text|link]]
|
||||
// It makes page handling terrible, but we prefer GitHub syntax
|
||||
// And fall back to MediaWiki only when it is obvious from the look
|
||||
// Of text and link contents
|
||||
sl := strings.Split(content, "|")
|
||||
for _, v := range sl {
|
||||
if equalPos := strings.IndexByte(v, '='); equalPos == -1 {
|
||||
// There is no equal in this argument; this is a mandatory arg
|
||||
if props["name"] == "" {
|
||||
if IsFullURLString(v) {
|
||||
// If we clearly see it is a link, we save it so
|
||||
|
||||
// But first we need to ensure, that if both mandatory args provided
|
||||
// look like links, we stick to GitHub syntax
|
||||
if props["link"] != "" {
|
||||
props["name"] = props["link"]
|
||||
}
|
||||
|
||||
props["link"] = strings.TrimSpace(v)
|
||||
} else {
|
||||
props["name"] = v
|
||||
}
|
||||
} else {
|
||||
props["link"] = strings.TrimSpace(v)
|
||||
}
|
||||
} else {
|
||||
// There is an equal; optional argument.
|
||||
|
||||
sep := strings.IndexByte(v, '=')
|
||||
key, val := v[:sep], html.UnescapeString(v[sep+1:])
|
||||
|
||||
// When parsing HTML, x/net/html will change all quotes which are
|
||||
// not used for syntax into UTF-8 quotes. So checking val[0] won't
|
||||
// be enough, since that only checks a single byte.
|
||||
if len(val) > 1 {
|
||||
if (strings.HasPrefix(val, "“") && strings.HasSuffix(val, "”")) ||
|
||||
(strings.HasPrefix(val, "‘") && strings.HasSuffix(val, "’")) {
|
||||
const lenQuote = len("‘")
|
||||
val = val[lenQuote : len(val)-lenQuote]
|
||||
} else if (strings.HasPrefix(val, "\"") && strings.HasSuffix(val, "\"")) ||
|
||||
(strings.HasPrefix(val, "'") && strings.HasSuffix(val, "'")) {
|
||||
val = val[1 : len(val)-1]
|
||||
} else if strings.HasPrefix(val, "'") && strings.HasSuffix(val, "’") {
|
||||
const lenQuote = len("‘")
|
||||
val = val[1 : len(val)-lenQuote]
|
||||
}
|
||||
}
|
||||
props[key] = val
|
||||
}
|
||||
}
|
||||
|
||||
var name, link string
|
||||
if props["link"] != "" {
|
||||
link = props["link"]
|
||||
} else if props["name"] != "" {
|
||||
link = props["name"]
|
||||
}
|
||||
if props["title"] != "" {
|
||||
name = props["title"]
|
||||
} else if props["name"] != "" {
|
||||
name = props["name"]
|
||||
} else {
|
||||
name = link
|
||||
}
|
||||
|
||||
name += tail
|
||||
image := false
|
||||
ext := filepath.Ext(link)
|
||||
switch ext {
|
||||
// fast path: empty string, ignore
|
||||
case "":
|
||||
// leave image as false
|
||||
case ".jpg", ".jpeg", ".png", ".tif", ".tiff", ".webp", ".gif", ".bmp", ".ico", ".svg":
|
||||
image = true
|
||||
}
|
||||
|
||||
childNode := &html.Node{}
|
||||
linkNode := &html.Node{
|
||||
FirstChild: childNode,
|
||||
LastChild: childNode,
|
||||
Type: html.ElementNode,
|
||||
Data: "a",
|
||||
DataAtom: atom.A,
|
||||
}
|
||||
childNode.Parent = linkNode
|
||||
absoluteLink := IsFullURLString(link)
|
||||
if !absoluteLink {
|
||||
if image {
|
||||
link = strings.ReplaceAll(link, " ", "+")
|
||||
} else {
|
||||
link = strings.ReplaceAll(link, " ", "-") // FIXME: it should support dashes in the link, eg: "the-dash-support.-"
|
||||
}
|
||||
if !strings.Contains(link, "/") {
|
||||
link = url.PathEscape(link) // FIXME: it doesn't seem right and it might cause double-escaping
|
||||
}
|
||||
}
|
||||
if image {
|
||||
if !absoluteLink {
|
||||
link = util.URLJoin(ctx.Links.ResolveMediaLink(ctx.IsWiki), link)
|
||||
}
|
||||
title := props["title"]
|
||||
if title == "" {
|
||||
title = props["alt"]
|
||||
}
|
||||
if title == "" {
|
||||
title = path.Base(name)
|
||||
}
|
||||
alt := props["alt"]
|
||||
if alt == "" {
|
||||
alt = name
|
||||
}
|
||||
|
||||
// make the childNode an image - if we can, we also place the alt
|
||||
childNode.Type = html.ElementNode
|
||||
childNode.Data = "img"
|
||||
childNode.DataAtom = atom.Img
|
||||
childNode.Attr = []html.Attribute{
|
||||
{Key: "src", Val: link},
|
||||
{Key: "title", Val: title},
|
||||
{Key: "alt", Val: alt},
|
||||
}
|
||||
if alt == "" {
|
||||
childNode.Attr = childNode.Attr[:2]
|
||||
}
|
||||
} else {
|
||||
link, _ = ResolveLink(ctx, link, "")
|
||||
childNode.Type = html.TextNode
|
||||
childNode.Data = name
|
||||
}
|
||||
linkNode.Attr = []html.Attribute{{Key: "href", Val: link}}
|
||||
replaceContent(node, m[0], m[1], linkNode)
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
// linkProcessor creates links for any HTTP or HTTPS URL not captured by
|
||||
// markdown.
|
||||
func linkProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := common.LinkRegex.FindStringIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
uri := node.Data[m[0]:m[1]]
|
||||
replaceContent(node, m[0], m[1], createLink(uri, uri, "link"))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func genDefaultLinkProcessor(defaultLink string) processor {
|
||||
return func(ctx *RenderContext, node *html.Node) {
|
||||
ch := &html.Node{
|
||||
Parent: node,
|
||||
Type: html.TextNode,
|
||||
Data: node.Data,
|
||||
}
|
||||
|
||||
node.Type = html.ElementNode
|
||||
node.Data = "a"
|
||||
node.DataAtom = atom.A
|
||||
node.Attr = []html.Attribute{
|
||||
{Key: "href", Val: defaultLink},
|
||||
{Key: "class", Val: "default-link muted"},
|
||||
}
|
||||
node.FirstChild, node.LastChild = ch, ch
|
||||
}
|
||||
}
|
||||
|
||||
// descriptionLinkProcessor creates links for DescriptionHTML
|
||||
func descriptionLinkProcessor(ctx *RenderContext, node *html.Node) {
|
||||
next := node.NextSibling
|
||||
for node != nil && node != next {
|
||||
m := common.LinkRegex.FindStringIndex(node.Data)
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
uri := node.Data[m[0]:m[1]]
|
||||
replaceContent(node, m[0], m[1], createDescriptionLink(uri, uri))
|
||||
node = node.NextSibling.NextSibling
|
||||
}
|
||||
}
|
||||
|
||||
func createDescriptionLink(href, content string) *html.Node {
|
||||
textNode := &html.Node{
|
||||
Type: html.TextNode,
|
||||
Data: content,
|
||||
}
|
||||
linkNode := &html.Node{
|
||||
FirstChild: textNode,
|
||||
LastChild: textNode,
|
||||
Type: html.ElementNode,
|
||||
Data: "a",
|
||||
DataAtom: atom.A,
|
||||
Attr: []html.Attribute{
|
||||
{Key: "href", Val: href},
|
||||
{Key: "target", Val: "_blank"},
|
||||
{Key: "rel", Val: "noopener noreferrer"},
|
||||
},
|
||||
}
|
||||
textNode.Parent = linkNode
|
||||
return linkNode
|
||||
}
|
||||
|
|
54
modules/markup/html_mention.go
Normal file
54
modules/markup/html_mention.go
Normal file
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/references"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"golang.org/x/net/html"
|
||||
)
|
||||
|
||||
func mentionProcessor(ctx *RenderContext, node *html.Node) {
|
||||
start := 0
|
||||
nodeStop := node.NextSibling
|
||||
for node != nodeStop {
|
||||
found, loc := references.FindFirstMentionBytes(util.UnsafeStringToBytes(node.Data[start:]))
|
||||
if !found {
|
||||
node = node.NextSibling
|
||||
start = 0
|
||||
continue
|
||||
}
|
||||
loc.Start += start
|
||||
loc.End += start
|
||||
mention := node.Data[loc.Start:loc.End]
|
||||
teams, ok := ctx.Metas["teams"]
|
||||
// FIXME: util.URLJoin may not be necessary here:
|
||||
// - setting.AppURL is defined to have a terminal '/' so unless mention[1:]
|
||||
// is an AppSubURL link we can probably fallback to concatenation.
|
||||
// team mention should follow @orgName/teamName style
|
||||
if ok && strings.Contains(mention, "/") {
|
||||
mentionOrgAndTeam := strings.Split(mention, "/")
|
||||
if mentionOrgAndTeam[0][1:] == ctx.Metas["org"] && strings.Contains(teams, ","+strings.ToLower(mentionOrgAndTeam[1])+",") {
|
||||
replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(ctx.Links.Prefix(), "org", ctx.Metas["org"], "teams", mentionOrgAndTeam[1]), mention, "mention"))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
continue
|
||||
}
|
||||
start = loc.End
|
||||
continue
|
||||
}
|
||||
mentionedUsername := mention[1:]
|
||||
|
||||
if DefaultProcessorHelper.IsUsernameMentionable != nil && DefaultProcessorHelper.IsUsernameMentionable(ctx.Ctx, mentionedUsername) {
|
||||
replaceContent(node, loc.Start, loc.End, createLink(util.URLJoin(ctx.Links.Prefix(), mentionedUsername), mention, "mention"))
|
||||
node = node.NextSibling.NextSibling
|
||||
start = 0
|
||||
} else {
|
||||
start = loc.End
|
||||
}
|
||||
}
|
||||
}
|
|
@ -116,7 +116,9 @@ func TestRender_CrossReferences(t *testing.T) {
|
|||
Metas: localMetas,
|
||||
}, input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
|
||||
actual := strings.TrimSpace(buffer)
|
||||
actual = strings.ReplaceAll(actual, ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, strings.TrimSpace(expected), actual)
|
||||
}
|
||||
|
||||
test(
|
||||
|
@ -156,7 +158,9 @@ func TestRender_links(t *testing.T) {
|
|||
},
|
||||
}, input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(buffer))
|
||||
actual := strings.TrimSpace(buffer)
|
||||
actual = strings.ReplaceAll(actual, ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, strings.TrimSpace(expected), actual)
|
||||
}
|
||||
|
||||
oldCustomURLSchemes := setting.Markdown.CustomURLSchemes
|
||||
|
@ -267,7 +271,9 @@ func TestRender_email(t *testing.T) {
|
|||
},
|
||||
}, input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res))
|
||||
actual := strings.TrimSpace(res)
|
||||
actual = strings.ReplaceAll(actual, ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, strings.TrimSpace(expected), actual)
|
||||
}
|
||||
// Text that should be turned into email link
|
||||
|
||||
|
@ -616,7 +622,9 @@ func TestPostProcess_RenderDocument(t *testing.T) {
|
|||
Metas: localMetas,
|
||||
}, strings.NewReader(input), &res)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(expected), strings.TrimSpace(res.String()))
|
||||
actual := strings.TrimSpace(res.String())
|
||||
actual = strings.ReplaceAll(actual, ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, strings.TrimSpace(expected), actual)
|
||||
}
|
||||
|
||||
// Issue index shouldn't be post processing in a document.
|
||||
|
|
|
@ -45,7 +45,7 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
|
|||
ctx := pc.Get(renderContextKey).(*markup.RenderContext)
|
||||
rc := pc.Get(renderConfigKey).(*RenderConfig)
|
||||
|
||||
tocList := make([]markup.Header, 0, 20)
|
||||
tocList := make([]Header, 0, 20)
|
||||
if rc.yamlNode != nil {
|
||||
metaNode := rc.toMetaNode()
|
||||
if metaNode != nil {
|
||||
|
@ -213,8 +213,7 @@ func (r *HTMLRenderer) renderIcon(w util.BufWriter, source []byte, node ast.Node
|
|||
return ast.WalkContinue, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
_, err = w.WriteString(fmt.Sprintf(`<i class="icon %s"></i>`, name))
|
||||
_, err := w.WriteString(fmt.Sprintf(`<i class="icon %s"></i>`, name))
|
||||
if err != nil {
|
||||
return ast.WalkStop, err
|
||||
}
|
||||
|
|
|
@ -311,7 +311,8 @@ func TestTotal_RenderWiki(t *testing.T) {
|
|||
IsWiki: true,
|
||||
}, sameCases[i])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, template.HTML(answers[i]), line)
|
||||
actual := strings.ReplaceAll(string(line), ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, answers[i], actual)
|
||||
}
|
||||
|
||||
testCases := []string{
|
||||
|
@ -336,7 +337,8 @@ func TestTotal_RenderWiki(t *testing.T) {
|
|||
IsWiki: true,
|
||||
}, testCases[i])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, template.HTML(testCases[i+1]), line)
|
||||
actual := strings.ReplaceAll(string(line), ` data-markdown-generated-content=""`, "")
|
||||
assert.EqualValues(t, testCases[i+1], actual)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,7 +358,8 @@ func TestTotal_RenderString(t *testing.T) {
|
|||
Metas: localMetas,
|
||||
}, sameCases[i])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, template.HTML(answers[i]), line)
|
||||
actual := strings.ReplaceAll(string(line), ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, answers[i], actual)
|
||||
}
|
||||
|
||||
testCases := []string{}
|
||||
|
@ -996,7 +999,8 @@ space</p>
|
|||
for i, c := range cases {
|
||||
result, err := markdown.RenderString(&markup.RenderContext{Ctx: context.Background(), Links: c.Links, IsWiki: c.IsWiki}, input)
|
||||
assert.NoError(t, err, "Unexpected error in testcase: %v", i)
|
||||
assert.Equal(t, c.Expected, string(result), "Unexpected result in testcase %v", i)
|
||||
actual := strings.ReplaceAll(string(result), ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, c.Expected, actual, "Unexpected result in testcase %v", i)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,19 @@ import (
|
|||
"fmt"
|
||||
"net/url"
|
||||
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
|
||||
"github.com/yuin/goldmark/ast"
|
||||
)
|
||||
|
||||
func createTOCNode(toc []markup.Header, lang string, detailsAttrs map[string]string) ast.Node {
|
||||
// Header holds the data about a header.
|
||||
type Header struct {
|
||||
Level int
|
||||
Text string
|
||||
ID string
|
||||
}
|
||||
|
||||
func createTOCNode(toc []Header, lang string, detailsAttrs map[string]string) ast.Node {
|
||||
details := NewDetails()
|
||||
summary := NewSummary()
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ func (g *ASTTransformer) extractBlockquoteAttentionEmphasis(firstParagraph ast.N
|
|||
if !ok {
|
||||
return "", nil
|
||||
}
|
||||
val1 := string(node1.Text(reader.Source()))
|
||||
val1 := string(node1.Text(reader.Source())) //nolint:staticcheck
|
||||
attentionType := strings.ToLower(val1)
|
||||
if g.attentionTypes.Contains(attentionType) {
|
||||
return attentionType, []ast.Node{node1}
|
||||
|
|
|
@ -69,7 +69,7 @@ func cssColorHandler(value string) bool {
|
|||
}
|
||||
|
||||
func (g *ASTTransformer) transformCodeSpan(_ *markup.RenderContext, v *ast.CodeSpan, reader text.Reader) {
|
||||
colorContent := v.Text(reader.Source())
|
||||
colorContent := v.Text(reader.Source()) //nolint:staticcheck
|
||||
if cssColorHandler(string(colorContent)) {
|
||||
v.AppendChild(v, NewColorPreview(colorContent))
|
||||
}
|
||||
|
|
|
@ -13,14 +13,14 @@ import (
|
|||
"github.com/yuin/goldmark/text"
|
||||
)
|
||||
|
||||
func (g *ASTTransformer) transformHeading(_ *markup.RenderContext, v *ast.Heading, reader text.Reader, tocList *[]markup.Header) {
|
||||
func (g *ASTTransformer) transformHeading(_ *markup.RenderContext, v *ast.Heading, reader text.Reader, tocList *[]Header) {
|
||||
for _, attr := range v.Attributes() {
|
||||
if _, ok := attr.Value.([]byte); !ok {
|
||||
v.SetAttribute(attr.Name, []byte(fmt.Sprintf("%v", attr.Value)))
|
||||
}
|
||||
}
|
||||
txt := v.Text(reader.Source())
|
||||
header := markup.Header{
|
||||
txt := v.Text(reader.Source()) //nolint:staticcheck
|
||||
header := Header{
|
||||
Text: util.UnsafeBytesToString(txt),
|
||||
Level: v.Level,
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ func (r *stripRenderer) Render(w io.Writer, source []byte, doc ast.Node) error {
|
|||
coalesce := prevSibIsText
|
||||
r.processString(
|
||||
w,
|
||||
v.Text(source),
|
||||
v.Text(source), //nolint:staticcheck
|
||||
coalesce)
|
||||
if v.SoftLineBreak() {
|
||||
r.doubleSpace(w)
|
||||
|
|
226
modules/markup/render.go
Normal file
226
modules/markup/render.go
Normal file
|
@ -0,0 +1,226 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/yuin/goldmark/ast"
|
||||
)
|
||||
|
||||
type RenderMetaMode string
|
||||
|
||||
const (
|
||||
RenderMetaAsDetails RenderMetaMode = "details" // default
|
||||
RenderMetaAsNone RenderMetaMode = "none"
|
||||
RenderMetaAsTable RenderMetaMode = "table"
|
||||
)
|
||||
|
||||
// RenderContext represents a render context
|
||||
type RenderContext struct {
|
||||
Ctx context.Context
|
||||
RelativePath string // relative path from tree root of the branch
|
||||
Type string
|
||||
IsWiki bool
|
||||
Links Links
|
||||
Metas map[string]string // user, repo, mode(comment/document)
|
||||
DefaultLink string
|
||||
GitRepo *git.Repository
|
||||
Repo gitrepo.Repository
|
||||
ShaExistCache map[string]bool
|
||||
cancelFn func()
|
||||
SidebarTocNode ast.Node
|
||||
RenderMetaAs RenderMetaMode
|
||||
InStandalonePage bool // used by external render. the router "/org/repo/render/..." will output the rendered content in a standalone page
|
||||
}
|
||||
|
||||
// Cancel runs any cleanup functions that have been registered for this Ctx
|
||||
func (ctx *RenderContext) Cancel() {
|
||||
if ctx == nil {
|
||||
return
|
||||
}
|
||||
ctx.ShaExistCache = map[string]bool{}
|
||||
if ctx.cancelFn == nil {
|
||||
return
|
||||
}
|
||||
ctx.cancelFn()
|
||||
}
|
||||
|
||||
// AddCancel adds the provided fn as a Cleanup for this Ctx
|
||||
func (ctx *RenderContext) AddCancel(fn func()) {
|
||||
if ctx == nil {
|
||||
return
|
||||
}
|
||||
oldCancelFn := ctx.cancelFn
|
||||
if oldCancelFn == nil {
|
||||
ctx.cancelFn = fn
|
||||
return
|
||||
}
|
||||
ctx.cancelFn = func() {
|
||||
defer oldCancelFn()
|
||||
fn()
|
||||
}
|
||||
}
|
||||
|
||||
// Render renders markup file to HTML with all specific handling stuff.
|
||||
func Render(ctx *RenderContext, input io.Reader, output io.Writer) error {
|
||||
if ctx.Type != "" {
|
||||
return renderByType(ctx, input, output)
|
||||
} else if ctx.RelativePath != "" {
|
||||
return renderFile(ctx, input, output)
|
||||
}
|
||||
return errors.New("render options both filename and type missing")
|
||||
}
|
||||
|
||||
// RenderString renders Markup string to HTML with all specific handling stuff and return string
|
||||
func RenderString(ctx *RenderContext, content string) (string, error) {
|
||||
var buf strings.Builder
|
||||
if err := Render(ctx, strings.NewReader(content), &buf); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func renderIFrame(ctx *RenderContext, output io.Writer) error {
|
||||
// set height="0" ahead, otherwise the scrollHeight would be max(150, realHeight)
|
||||
// at the moment, only "allow-scripts" is allowed for sandbox mode.
|
||||
// "allow-same-origin" should never be used, it leads to XSS attack, and it makes the JS in iframe can access parent window's config and CSRF token
|
||||
// TODO: when using dark theme, if the rendered content doesn't have proper style, the default text color is black, which is not easy to read
|
||||
_, err := io.WriteString(output, fmt.Sprintf(`
|
||||
<iframe src="%s/%s/%s/render/%s/%s"
|
||||
name="giteaExternalRender"
|
||||
onload="this.height=giteaExternalRender.document.documentElement.scrollHeight"
|
||||
width="100%%" height="0" scrolling="no" frameborder="0" style="overflow: hidden"
|
||||
sandbox="allow-scripts"
|
||||
></iframe>`,
|
||||
setting.AppSubURL,
|
||||
url.PathEscape(ctx.Metas["user"]),
|
||||
url.PathEscape(ctx.Metas["repo"]),
|
||||
ctx.Metas["BranchNameSubURL"],
|
||||
url.PathEscape(ctx.RelativePath),
|
||||
))
|
||||
return err
|
||||
}
|
||||
|
||||
func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Writer) error {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
pr, pw := io.Pipe()
|
||||
defer func() {
|
||||
_ = pr.Close()
|
||||
_ = pw.Close()
|
||||
}()
|
||||
|
||||
var pr2 io.ReadCloser
|
||||
var pw2 io.WriteCloser
|
||||
|
||||
var sanitizerDisabled bool
|
||||
if r, ok := renderer.(ExternalRenderer); ok {
|
||||
sanitizerDisabled = r.SanitizerDisabled()
|
||||
}
|
||||
|
||||
if !sanitizerDisabled {
|
||||
pr2, pw2 = io.Pipe()
|
||||
defer func() {
|
||||
_ = pr2.Close()
|
||||
_ = pw2.Close()
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
err = SanitizeReader(pr2, renderer.Name(), output)
|
||||
_ = pr2.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
} else {
|
||||
pw2 = util.NopCloser{Writer: output}
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
if r, ok := renderer.(PostProcessRenderer); ok && r.NeedPostProcess() {
|
||||
err = PostProcess(ctx, pr, pw2)
|
||||
} else {
|
||||
_, err = io.Copy(pw2, pr)
|
||||
}
|
||||
_ = pr.Close()
|
||||
_ = pw2.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
if err1 := renderer.Render(ctx, input, pw); err1 != nil {
|
||||
return err1
|
||||
}
|
||||
_ = pw.Close()
|
||||
|
||||
wg.Wait()
|
||||
return err
|
||||
}
|
||||
|
||||
func renderByType(ctx *RenderContext, input io.Reader, output io.Writer) error {
|
||||
if renderer, ok := renderers[ctx.Type]; ok {
|
||||
return render(ctx, renderer, input, output)
|
||||
}
|
||||
return fmt.Errorf("unsupported render type: %s", ctx.Type)
|
||||
}
|
||||
|
||||
// ErrUnsupportedRenderExtension represents the error when extension doesn't supported to render
|
||||
type ErrUnsupportedRenderExtension struct {
|
||||
Extension string
|
||||
}
|
||||
|
||||
func IsErrUnsupportedRenderExtension(err error) bool {
|
||||
_, ok := err.(ErrUnsupportedRenderExtension)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUnsupportedRenderExtension) Error() string {
|
||||
return fmt.Sprintf("Unsupported render extension: %s", err.Extension)
|
||||
}
|
||||
|
||||
func renderFile(ctx *RenderContext, input io.Reader, output io.Writer) error {
|
||||
extension := strings.ToLower(filepath.Ext(ctx.RelativePath))
|
||||
if renderer, ok := extRenderers[extension]; ok {
|
||||
if r, ok := renderer.(ExternalRenderer); ok && r.DisplayInIFrame() {
|
||||
if !ctx.InStandalonePage {
|
||||
// for an external render, it could only output its content in a standalone page
|
||||
// otherwise, a <iframe> should be outputted to embed the external rendered page
|
||||
return renderIFrame(ctx, output)
|
||||
}
|
||||
}
|
||||
return render(ctx, renderer, input, output)
|
||||
}
|
||||
return ErrUnsupportedRenderExtension{extension}
|
||||
}
|
||||
|
||||
// Init initializes the render global variables
|
||||
func Init(ph *ProcessorHelper) {
|
||||
if ph != nil {
|
||||
DefaultProcessorHelper = *ph
|
||||
}
|
||||
|
||||
if len(setting.Markdown.CustomURLSchemes) > 0 {
|
||||
CustomLinkURLSchemes(setting.Markdown.CustomURLSchemes)
|
||||
}
|
||||
|
||||
// since setting maybe changed extensions, this will reload all renderer extensions mapping
|
||||
extRenderers = make(map[string]Renderer)
|
||||
for _, renderer := range renderers {
|
||||
for _, ext := range renderer.Extensions() {
|
||||
extRenderers[strings.ToLower(ext)] = renderer
|
||||
}
|
||||
}
|
||||
}
|
21
modules/markup/render_helper.go
Normal file
21
modules/markup/render_helper.go
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"context"
|
||||
"html/template"
|
||||
)
|
||||
|
||||
// ProcessorHelper is a helper for the rendering processors (it could be renamed to RenderHelper in the future).
|
||||
// The main purpose of this helper is to decouple some functions which are not directly available in this package.
|
||||
type ProcessorHelper struct {
|
||||
IsUsernameMentionable func(ctx context.Context, username string) bool
|
||||
|
||||
ElementDir string // the direction of the elements, eg: "ltr", "rtl", "auto", default to no direction attribute
|
||||
|
||||
RenderRepoFileCodePreview func(ctx context.Context, options RenderCodePreviewOptions) (template.HTML, error)
|
||||
}
|
||||
|
||||
var DefaultProcessorHelper ProcessorHelper
|
56
modules/markup/render_links.go
Normal file
56
modules/markup/render_links.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package markup
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
type Links struct {
|
||||
AbsolutePrefix bool // add absolute URL prefix to auto-resolved links like "#issue", but not for pre-provided links and medias
|
||||
Base string // base prefix for pre-provided links and medias (images, videos)
|
||||
BranchPath string // actually it is the ref path, eg: "branch/features/feat-12", "tag/v1.0"
|
||||
TreePath string // the dir of the file, eg: "doc" if the file "doc/CHANGE.md" is being rendered
|
||||
}
|
||||
|
||||
func (l *Links) Prefix() string {
|
||||
if l.AbsolutePrefix {
|
||||
return setting.AppURL
|
||||
}
|
||||
return setting.AppSubURL
|
||||
}
|
||||
|
||||
func (l *Links) HasBranchInfo() bool {
|
||||
return l.BranchPath != ""
|
||||
}
|
||||
|
||||
func (l *Links) SrcLink() string {
|
||||
return util.URLJoin(l.Base, "src", l.BranchPath, l.TreePath)
|
||||
}
|
||||
|
||||
func (l *Links) MediaLink() string {
|
||||
return util.URLJoin(l.Base, "media", l.BranchPath, l.TreePath)
|
||||
}
|
||||
|
||||
func (l *Links) RawLink() string {
|
||||
return util.URLJoin(l.Base, "raw", l.BranchPath, l.TreePath)
|
||||
}
|
||||
|
||||
func (l *Links) WikiLink() string {
|
||||
return util.URLJoin(l.Base, "wiki")
|
||||
}
|
||||
|
||||
func (l *Links) WikiRawLink() string {
|
||||
return util.URLJoin(l.Base, "wiki/raw")
|
||||
}
|
||||
|
||||
func (l *Links) ResolveMediaLink(isWiki bool) string {
|
||||
if isWiki {
|
||||
return l.WikiRawLink()
|
||||
} else if l.HasBranchInfo() {
|
||||
return l.MediaLink()
|
||||
}
|
||||
return l.Base
|
||||
}
|
|
@ -5,161 +5,13 @@ package markup
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/yuin/goldmark/ast"
|
||||
)
|
||||
|
||||
type RenderMetaMode string
|
||||
|
||||
const (
|
||||
RenderMetaAsDetails RenderMetaMode = "details" // default
|
||||
RenderMetaAsNone RenderMetaMode = "none"
|
||||
RenderMetaAsTable RenderMetaMode = "table"
|
||||
)
|
||||
|
||||
type ProcessorHelper struct {
|
||||
IsUsernameMentionable func(ctx context.Context, username string) bool
|
||||
|
||||
ElementDir string // the direction of the elements, eg: "ltr", "rtl", "auto", default to no direction attribute
|
||||
|
||||
RenderRepoFileCodePreview func(ctx context.Context, options RenderCodePreviewOptions) (template.HTML, error)
|
||||
}
|
||||
|
||||
var DefaultProcessorHelper ProcessorHelper
|
||||
|
||||
// Init initialize regexps for markdown parsing
|
||||
func Init(ph *ProcessorHelper) {
|
||||
if ph != nil {
|
||||
DefaultProcessorHelper = *ph
|
||||
}
|
||||
|
||||
if len(setting.Markdown.CustomURLSchemes) > 0 {
|
||||
CustomLinkURLSchemes(setting.Markdown.CustomURLSchemes)
|
||||
}
|
||||
|
||||
// since setting maybe changed extensions, this will reload all renderer extensions mapping
|
||||
extRenderers = make(map[string]Renderer)
|
||||
for _, renderer := range renderers {
|
||||
for _, ext := range renderer.Extensions() {
|
||||
extRenderers[strings.ToLower(ext)] = renderer
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Header holds the data about a header.
|
||||
type Header struct {
|
||||
Level int
|
||||
Text string
|
||||
ID string
|
||||
}
|
||||
|
||||
// RenderContext represents a render context
|
||||
type RenderContext struct {
|
||||
Ctx context.Context
|
||||
RelativePath string // relative path from tree root of the branch
|
||||
Type string
|
||||
IsWiki bool
|
||||
Links Links
|
||||
Metas map[string]string // user, repo, mode(comment/document)
|
||||
DefaultLink string
|
||||
GitRepo *git.Repository
|
||||
Repo gitrepo.Repository
|
||||
ShaExistCache map[string]bool
|
||||
cancelFn func()
|
||||
SidebarTocNode ast.Node
|
||||
RenderMetaAs RenderMetaMode
|
||||
InStandalonePage bool // used by external render. the router "/org/repo/render/..." will output the rendered content in a standalone page
|
||||
}
|
||||
|
||||
type Links struct {
|
||||
AbsolutePrefix bool // add absolute URL prefix to auto-resolved links like "#issue", but not for pre-provided links and medias
|
||||
Base string // base prefix for pre-provided links and medias (images, videos)
|
||||
BranchPath string // actually it is the ref path, eg: "branch/features/feat-12", "tag/v1.0"
|
||||
TreePath string // the dir of the file, eg: "doc" if the file "doc/CHANGE.md" is being rendered
|
||||
}
|
||||
|
||||
func (l *Links) Prefix() string {
|
||||
if l.AbsolutePrefix {
|
||||
return setting.AppURL
|
||||
}
|
||||
return setting.AppSubURL
|
||||
}
|
||||
|
||||
func (l *Links) HasBranchInfo() bool {
|
||||
return l.BranchPath != ""
|
||||
}
|
||||
|
||||
func (l *Links) SrcLink() string {
|
||||
return util.URLJoin(l.Base, "src", l.BranchPath, l.TreePath)
|
||||
}
|
||||
|
||||
func (l *Links) MediaLink() string {
|
||||
return util.URLJoin(l.Base, "media", l.BranchPath, l.TreePath)
|
||||
}
|
||||
|
||||
func (l *Links) RawLink() string {
|
||||
return util.URLJoin(l.Base, "raw", l.BranchPath, l.TreePath)
|
||||
}
|
||||
|
||||
func (l *Links) WikiLink() string {
|
||||
return util.URLJoin(l.Base, "wiki")
|
||||
}
|
||||
|
||||
func (l *Links) WikiRawLink() string {
|
||||
return util.URLJoin(l.Base, "wiki/raw")
|
||||
}
|
||||
|
||||
func (l *Links) ResolveMediaLink(isWiki bool) string {
|
||||
if isWiki {
|
||||
return l.WikiRawLink()
|
||||
} else if l.HasBranchInfo() {
|
||||
return l.MediaLink()
|
||||
}
|
||||
return l.Base
|
||||
}
|
||||
|
||||
// Cancel runs any cleanup functions that have been registered for this Ctx
|
||||
func (ctx *RenderContext) Cancel() {
|
||||
if ctx == nil {
|
||||
return
|
||||
}
|
||||
ctx.ShaExistCache = map[string]bool{}
|
||||
if ctx.cancelFn == nil {
|
||||
return
|
||||
}
|
||||
ctx.cancelFn()
|
||||
}
|
||||
|
||||
// AddCancel adds the provided fn as a Cleanup for this Ctx
|
||||
func (ctx *RenderContext) AddCancel(fn func()) {
|
||||
if ctx == nil {
|
||||
return
|
||||
}
|
||||
oldCancelFn := ctx.cancelFn
|
||||
if oldCancelFn == nil {
|
||||
ctx.cancelFn = fn
|
||||
return
|
||||
}
|
||||
ctx.cancelFn = func() {
|
||||
defer oldCancelFn()
|
||||
fn()
|
||||
}
|
||||
}
|
||||
|
||||
// Renderer defines an interface for rendering markup file to HTML
|
||||
type Renderer interface {
|
||||
Name() string // markup format name
|
||||
|
@ -173,7 +25,7 @@ type PostProcessRenderer interface {
|
|||
NeedPostProcess() bool
|
||||
}
|
||||
|
||||
// PostProcessRenderer defines an interface for external renderers
|
||||
// ExternalRenderer defines an interface for external renderers
|
||||
type ExternalRenderer interface {
|
||||
// SanitizerDisabled disabled sanitize if return true
|
||||
SanitizerDisabled() bool
|
||||
|
@ -207,11 +59,6 @@ func GetRendererByFileName(filename string) Renderer {
|
|||
return extRenderers[extension]
|
||||
}
|
||||
|
||||
// GetRendererByType returns a renderer according type
|
||||
func GetRendererByType(tp string) Renderer {
|
||||
return renderers[tp]
|
||||
}
|
||||
|
||||
// DetectRendererType detects the markup type of the content
|
||||
func DetectRendererType(filename string, input io.Reader) string {
|
||||
buf, err := io.ReadAll(input)
|
||||
|
@ -226,152 +73,6 @@ func DetectRendererType(filename string, input io.Reader) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// Render renders markup file to HTML with all specific handling stuff.
|
||||
func Render(ctx *RenderContext, input io.Reader, output io.Writer) error {
|
||||
if ctx.Type != "" {
|
||||
return renderByType(ctx, input, output)
|
||||
} else if ctx.RelativePath != "" {
|
||||
return renderFile(ctx, input, output)
|
||||
}
|
||||
return errors.New("Render options both filename and type missing")
|
||||
}
|
||||
|
||||
// RenderString renders Markup string to HTML with all specific handling stuff and return string
|
||||
func RenderString(ctx *RenderContext, content string) (string, error) {
|
||||
var buf strings.Builder
|
||||
if err := Render(ctx, strings.NewReader(content), &buf); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
type nopCloser struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (nopCloser) Close() error { return nil }
|
||||
|
||||
func renderIFrame(ctx *RenderContext, output io.Writer) error {
|
||||
// set height="0" ahead, otherwise the scrollHeight would be max(150, realHeight)
|
||||
// at the moment, only "allow-scripts" is allowed for sandbox mode.
|
||||
// "allow-same-origin" should never be used, it leads to XSS attack, and it makes the JS in iframe can access parent window's config and CSRF token
|
||||
// TODO: when using dark theme, if the rendered content doesn't have proper style, the default text color is black, which is not easy to read
|
||||
_, err := io.WriteString(output, fmt.Sprintf(`
|
||||
<iframe src="%s/%s/%s/render/%s/%s"
|
||||
name="giteaExternalRender"
|
||||
onload="this.height=giteaExternalRender.document.documentElement.scrollHeight"
|
||||
width="100%%" height="0" scrolling="no" frameborder="0" style="overflow: hidden"
|
||||
sandbox="allow-scripts"
|
||||
></iframe>`,
|
||||
setting.AppSubURL,
|
||||
url.PathEscape(ctx.Metas["user"]),
|
||||
url.PathEscape(ctx.Metas["repo"]),
|
||||
ctx.Metas["BranchNameSubURL"],
|
||||
url.PathEscape(ctx.RelativePath),
|
||||
))
|
||||
return err
|
||||
}
|
||||
|
||||
func render(ctx *RenderContext, renderer Renderer, input io.Reader, output io.Writer) error {
|
||||
var wg sync.WaitGroup
|
||||
var err error
|
||||
pr, pw := io.Pipe()
|
||||
defer func() {
|
||||
_ = pr.Close()
|
||||
_ = pw.Close()
|
||||
}()
|
||||
|
||||
var pr2 io.ReadCloser
|
||||
var pw2 io.WriteCloser
|
||||
|
||||
var sanitizerDisabled bool
|
||||
if r, ok := renderer.(ExternalRenderer); ok {
|
||||
sanitizerDisabled = r.SanitizerDisabled()
|
||||
}
|
||||
|
||||
if !sanitizerDisabled {
|
||||
pr2, pw2 = io.Pipe()
|
||||
defer func() {
|
||||
_ = pr2.Close()
|
||||
_ = pw2.Close()
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
err = SanitizeReader(pr2, renderer.Name(), output)
|
||||
_ = pr2.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
} else {
|
||||
pw2 = nopCloser{output}
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
if r, ok := renderer.(PostProcessRenderer); ok && r.NeedPostProcess() {
|
||||
err = PostProcess(ctx, pr, pw2)
|
||||
} else {
|
||||
_, err = io.Copy(pw2, pr)
|
||||
}
|
||||
_ = pr.Close()
|
||||
_ = pw2.Close()
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
if err1 := renderer.Render(ctx, input, pw); err1 != nil {
|
||||
return err1
|
||||
}
|
||||
_ = pw.Close()
|
||||
|
||||
wg.Wait()
|
||||
return err
|
||||
}
|
||||
|
||||
// ErrUnsupportedRenderType represents
|
||||
type ErrUnsupportedRenderType struct {
|
||||
Type string
|
||||
}
|
||||
|
||||
func (err ErrUnsupportedRenderType) Error() string {
|
||||
return fmt.Sprintf("Unsupported render type: %s", err.Type)
|
||||
}
|
||||
|
||||
func renderByType(ctx *RenderContext, input io.Reader, output io.Writer) error {
|
||||
if renderer, ok := renderers[ctx.Type]; ok {
|
||||
return render(ctx, renderer, input, output)
|
||||
}
|
||||
return ErrUnsupportedRenderType{ctx.Type}
|
||||
}
|
||||
|
||||
// ErrUnsupportedRenderExtension represents the error when extension doesn't supported to render
|
||||
type ErrUnsupportedRenderExtension struct {
|
||||
Extension string
|
||||
}
|
||||
|
||||
func IsErrUnsupportedRenderExtension(err error) bool {
|
||||
_, ok := err.(ErrUnsupportedRenderExtension)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrUnsupportedRenderExtension) Error() string {
|
||||
return fmt.Sprintf("Unsupported render extension: %s", err.Extension)
|
||||
}
|
||||
|
||||
func renderFile(ctx *RenderContext, input io.Reader, output io.Writer) error {
|
||||
extension := strings.ToLower(filepath.Ext(ctx.RelativePath))
|
||||
if renderer, ok := extRenderers[extension]; ok {
|
||||
if r, ok := renderer.(ExternalRenderer); ok && r.DisplayInIFrame() {
|
||||
if !ctx.InStandalonePage {
|
||||
// for an external render, it could only output its content in a standalone page
|
||||
// otherwise, a <iframe> should be outputted to embed the external rendered page
|
||||
return renderIFrame(ctx, output)
|
||||
}
|
||||
}
|
||||
return render(ctx, renderer, input, output)
|
||||
}
|
||||
return ErrUnsupportedRenderExtension{extension}
|
||||
}
|
||||
|
||||
// DetectMarkupTypeByFileName returns the possible markup format type via the filename
|
||||
func DetectMarkupTypeByFileName(filename string) string {
|
||||
if parser := GetRendererByFileName(filename); parser != nil {
|
||||
|
|
|
@ -107,6 +107,7 @@ func (st *Sanitizer) createDefaultPolicy() *bluemonday.Policy {
|
|||
"start", "summary", "tabindex", "target",
|
||||
"title", "type", "usemap", "valign", "value",
|
||||
"vspace", "width", "itemprop",
|
||||
"data-markdown-generated-content",
|
||||
}
|
||||
|
||||
generalSafeElements := []string{
|
||||
|
|
|
@ -37,8 +37,8 @@ func (s *ContentStore) ShouldServeDirect() bool {
|
|||
return setting.Packages.Storage.ServeDirect()
|
||||
}
|
||||
|
||||
func (s *ContentStore) GetServeDirectURL(key BlobHash256Key, filename string) (*url.URL, error) {
|
||||
return s.store.URL(KeyToRelativePath(key), filename)
|
||||
func (s *ContentStore) GetServeDirectURL(key BlobHash256Key, filename string, reqParams url.Values) (*url.URL, error) {
|
||||
return s.store.URL(KeyToRelativePath(key), filename, reqParams)
|
||||
}
|
||||
|
||||
// FIXME: Workaround to be removed in v1.20
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"io"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/zstd"
|
||||
|
||||
"github.com/blakesmith/ar"
|
||||
|
@ -77,7 +78,7 @@ func TestParsePackage(t *testing.T) {
|
|||
{
|
||||
Extension: "",
|
||||
WriterFactory: func(w io.Writer) io.WriteCloser {
|
||||
return nopCloser{w}
|
||||
return util.NopCloser{Writer: w}
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -129,14 +130,6 @@ func TestParsePackage(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
type nopCloser struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (nopCloser) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestParseControlFile(t *testing.T) {
|
||||
buildContent := func(name, version, architecture string) *bytes.Buffer {
|
||||
var buf bytes.Buffer
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
func AddCollaborator(ctx context.Context, repo *repo_model.Repository, u *user_model.User) error {
|
||||
if err := repo.LoadOwner(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if user_model.IsUserBlockedBy(ctx, u, repo.OwnerID) || user_model.IsUserBlockedBy(ctx, repo.Owner, u.ID) {
|
||||
return user_model.ErrBlockedUser
|
||||
}
|
||||
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
has, err := db.Exist[repo_model.Collaboration](ctx, builder.Eq{
|
||||
"repo_id": repo.ID,
|
||||
"user_id": u.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = db.Insert(ctx, &repo_model.Collaboration{
|
||||
RepoID: repo.ID,
|
||||
UserID: u.ID,
|
||||
Mode: perm.AccessModeWrite,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return access_model.RecalculateUserAccess(ctx, repo, u.ID)
|
||||
})
|
||||
}
|
|
@ -1,280 +0,0 @@
|
|||
// Copyright 2019 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package repository
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
perm_model "code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRepository_AddCollaborator(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
testSuccess := func(repoID, userID int64) {
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
|
||||
assert.NoError(t, repo.LoadOwner(db.DefaultContext))
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID})
|
||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repoID}, &user_model.User{ID: userID})
|
||||
}
|
||||
testSuccess(1, 4)
|
||||
testSuccess(1, 4)
|
||||
testSuccess(3, 4)
|
||||
}
|
||||
|
||||
func TestRepoPermissionPublicNonOrgRepo(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// public non-organization repo
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
|
||||
|
||||
// plain user
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.False(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// change to collaborator
|
||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// collaborator
|
||||
collaborator := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, collaborator)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// owner
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// admin
|
||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepoPermissionPrivateNonOrgRepo(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// private non-organization repo
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
|
||||
|
||||
// plain user
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.False(t, perm.CanRead(unit.Type))
|
||||
assert.False(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// change to collaborator to default write access
|
||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.False(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// owner
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// admin
|
||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepoPermissionPublicOrgRepo(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// public organization repo
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 32})
|
||||
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
|
||||
|
||||
// plain user
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.False(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// change to collaborator to default write access
|
||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.False(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// org member team owner
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// org member team tester
|
||||
member := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, member)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
}
|
||||
assert.True(t, perm.CanWrite(unit.TypeIssues))
|
||||
assert.False(t, perm.CanWrite(unit.TypeCode))
|
||||
|
||||
// admin
|
||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepoPermissionPrivateOrgRepo(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// private organization repo
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 24})
|
||||
assert.NoError(t, repo.LoadUnits(db.DefaultContext))
|
||||
|
||||
// plain user
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 5})
|
||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.False(t, perm.CanRead(unit.Type))
|
||||
assert.False(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// change to collaborator to default write access
|
||||
assert.NoError(t, AddCollaborator(db.DefaultContext, repo, user))
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, user.ID, perm_model.AccessModeRead))
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.False(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// org member team owner
|
||||
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 15})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// update team information and then check permission
|
||||
team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5})
|
||||
err = organization.UpdateTeamUnits(db.DefaultContext, team, nil)
|
||||
assert.NoError(t, err)
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
|
||||
// org member team tester
|
||||
tester := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, tester)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, perm.CanWrite(unit.TypeIssues))
|
||||
assert.False(t, perm.CanWrite(unit.TypeCode))
|
||||
assert.False(t, perm.CanRead(unit.TypeCode))
|
||||
|
||||
// org member team reviewer
|
||||
reviewer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 20})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, reviewer)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, perm.CanRead(unit.TypeIssues))
|
||||
assert.False(t, perm.CanWrite(unit.TypeCode))
|
||||
assert.True(t, perm.CanRead(unit.TypeCode))
|
||||
|
||||
// admin
|
||||
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, admin)
|
||||
assert.NoError(t, err)
|
||||
for _, unit := range repo.Units {
|
||||
assert.True(t, perm.CanRead(unit.Type))
|
||||
assert.True(t, perm.CanWrite(unit.Type))
|
||||
}
|
||||
}
|
|
@ -42,8 +42,8 @@ func NewPushCommits() *PushCommits {
|
|||
return &PushCommits{}
|
||||
}
|
||||
|
||||
// toAPIPayloadCommit converts a single PushCommit to an api.PayloadCommit object.
|
||||
func (pc *PushCommits) toAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repoPath, repoLink string, commit *PushCommit) (*api.PayloadCommit, error) {
|
||||
// ToAPIPayloadCommit converts a single PushCommit to an api.PayloadCommit object.
|
||||
func ToAPIPayloadCommit(ctx context.Context, emailUsers map[string]*user_model.User, repoPath, repoLink string, commit *PushCommit) (*api.PayloadCommit, error) {
|
||||
var err error
|
||||
authorUsername := ""
|
||||
author, ok := emailUsers[commit.AuthorEmail]
|
||||
|
@ -105,7 +105,7 @@ func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLi
|
|||
emailUsers := make(map[string]*user_model.User)
|
||||
|
||||
for i, commit := range pc.Commits {
|
||||
apiCommit, err := pc.toAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, commit)
|
||||
apiCommit, err := ToAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, commit)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ func (pc *PushCommits) ToAPIPayloadCommits(ctx context.Context, repoPath, repoLi
|
|||
}
|
||||
if pc.HeadCommit != nil && headCommit == nil {
|
||||
var err error
|
||||
headCommit, err = pc.toAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, pc.HeadCommit)
|
||||
headCommit, err = ToAPIPayloadCommit(ctx, emailUsers, repoPath, repoLink, pc.HeadCommit)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
|
@ -11,160 +11,17 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
"code.gitea.io/gitea/models/organization"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/models/webhook"
|
||||
issue_indexer "code.gitea.io/gitea/modules/indexer/issues"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// CreateRepositoryByExample creates a repository for the user/organization.
|
||||
func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository, overwriteOrAdopt, isFork bool) (err error) {
|
||||
if err = repo_model.IsUsableRepoName(repo.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
has, err := repo_model.IsRepositoryModelExist(ctx, u, repo.Name)
|
||||
if err != nil {
|
||||
return fmt.Errorf("IsRepositoryExist: %w", err)
|
||||
} else if has {
|
||||
return repo_model.ErrRepoAlreadyExist{
|
||||
Uname: u.Name,
|
||||
Name: repo.Name,
|
||||
}
|
||||
}
|
||||
|
||||
repoPath := repo_model.RepoPath(u.Name, repo.Name)
|
||||
isExist, err := util.IsExist(repoPath)
|
||||
if err != nil {
|
||||
log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
|
||||
return err
|
||||
}
|
||||
if !overwriteOrAdopt && isExist {
|
||||
log.Error("Files already exist in %s and we are not going to adopt or delete.", repoPath)
|
||||
return repo_model.ErrRepoFilesAlreadyExist{
|
||||
Uname: u.Name,
|
||||
Name: repo.Name,
|
||||
}
|
||||
}
|
||||
|
||||
if err = db.Insert(ctx, repo); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = repo_model.DeleteRedirect(ctx, u.ID, repo.Name); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// insert units for repo
|
||||
defaultUnits := unit.DefaultRepoUnits
|
||||
if isFork {
|
||||
defaultUnits = unit.DefaultForkRepoUnits
|
||||
}
|
||||
units := make([]repo_model.RepoUnit, 0, len(defaultUnits))
|
||||
for _, tp := range defaultUnits {
|
||||
if tp == unit.TypeIssues {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: tp,
|
||||
Config: &repo_model.IssuesConfig{
|
||||
EnableTimetracker: setting.Service.DefaultEnableTimetracking,
|
||||
AllowOnlyContributorsToTrackTime: setting.Service.DefaultAllowOnlyContributorsToTrackTime,
|
||||
EnableDependencies: setting.Service.DefaultEnableDependencies,
|
||||
},
|
||||
})
|
||||
} else if tp == unit.TypePullRequests {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: tp,
|
||||
Config: &repo_model.PullRequestsConfig{
|
||||
AllowMerge: true, AllowRebase: true, AllowRebaseMerge: true, AllowSquash: true, AllowFastForwardOnly: true,
|
||||
DefaultMergeStyle: repo_model.MergeStyle(setting.Repository.PullRequest.DefaultMergeStyle),
|
||||
AllowRebaseUpdate: true,
|
||||
},
|
||||
})
|
||||
} else if tp == unit.TypeProjects {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: tp,
|
||||
Config: &repo_model.ProjectsConfig{ProjectsMode: repo_model.ProjectsModeAll},
|
||||
})
|
||||
} else {
|
||||
units = append(units, repo_model.RepoUnit{
|
||||
RepoID: repo.ID,
|
||||
Type: tp,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if err = db.Insert(ctx, units); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Remember visibility preference.
|
||||
u.LastRepoVisibility = repo.IsPrivate
|
||||
if err = user_model.UpdateUserCols(ctx, u, "last_repo_visibility"); err != nil {
|
||||
return fmt.Errorf("UpdateUserCols: %w", err)
|
||||
}
|
||||
|
||||
if err = user_model.IncrUserRepoNum(ctx, u.ID); err != nil {
|
||||
return fmt.Errorf("IncrUserRepoNum: %w", err)
|
||||
}
|
||||
u.NumRepos++
|
||||
|
||||
// Give access to all members in teams with access to all repositories.
|
||||
if u.IsOrganization() {
|
||||
teams, err := organization.FindOrgTeams(ctx, u.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("FindOrgTeams: %w", err)
|
||||
}
|
||||
for _, t := range teams {
|
||||
if t.IncludesAllRepositories {
|
||||
if err := models.AddRepository(ctx, t, repo); err != nil {
|
||||
return fmt.Errorf("AddRepository: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isAdmin, err := access_model.IsUserRepoAdmin(ctx, repo, doer); err != nil {
|
||||
return fmt.Errorf("IsUserRepoAdmin: %w", err)
|
||||
} else if !isAdmin {
|
||||
// Make creator repo admin if it wasn't assigned automatically
|
||||
if err = AddCollaborator(ctx, repo, doer); err != nil {
|
||||
return fmt.Errorf("AddCollaborator: %w", err)
|
||||
}
|
||||
if err = repo_model.ChangeCollaborationAccessMode(ctx, repo, doer.ID, perm.AccessModeAdmin); err != nil {
|
||||
return fmt.Errorf("ChangeCollaborationAccessModeCtx: %w", err)
|
||||
}
|
||||
}
|
||||
} else if err = access_model.RecalculateAccesses(ctx, repo); err != nil {
|
||||
// Organization automatically called this in AddRepository method.
|
||||
return fmt.Errorf("RecalculateAccesses: %w", err)
|
||||
}
|
||||
|
||||
if setting.Service.AutoWatchNewRepos {
|
||||
if err = repo_model.WatchRepo(ctx, doer, repo, true); err != nil {
|
||||
return fmt.Errorf("WatchRepo: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = webhook.CopyDefaultWebhooksToRepo(ctx, repo.ID); err != nil {
|
||||
return fmt.Errorf("CopyDefaultWebhooksToRepo: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const notRegularFileMode = os.ModeSymlink | os.ModeNamedPipe | os.ModeSocket | os.ModeDevice | os.ModeCharDevice | os.ModeIrregular
|
||||
|
||||
// getDirectorySize returns the disk consumption for a given path
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
_ "code.gitea.io/gitea/models"
|
||||
_ "code.gitea.io/gitea/models/actions"
|
||||
)
|
||||
|
||||
|
|
|
@ -181,11 +181,12 @@ func StoreMissingLfsObjectsInRepository(ctx context.Context, repo *repo_model.Re
|
|||
|
||||
downloadObjects := func(pointers []lfs.Pointer) error {
|
||||
err := lfsClient.Download(ctx, pointers, func(p lfs.Pointer, content io.ReadCloser, objectError error) error {
|
||||
if errors.Is(objectError, lfs.ErrObjectNotExist) {
|
||||
log.Warn("Ignoring missing upstream LFS object %-v: %v", p, objectError)
|
||||
return nil
|
||||
}
|
||||
|
||||
if objectError != nil {
|
||||
if errors.Is(objectError, lfs.ErrObjectNotExist) {
|
||||
log.Warn("Repo[%-v]: Ignore missing LFS object %-v: %v", repo, p, objectError)
|
||||
return nil
|
||||
}
|
||||
return objectError
|
||||
}
|
||||
|
||||
|
@ -340,9 +341,10 @@ func pullMirrorReleaseSync(ctx context.Context, repo *repo_model.Repository, git
|
|||
|
||||
for _, tag := range updates {
|
||||
if _, err := db.GetEngine(ctx).Where("repo_id = ? AND lower_tag_name = ?", repo.ID, strings.ToLower(tag.Name)).
|
||||
Cols("sha1").
|
||||
Cols("sha1", "created_unix").
|
||||
Update(&repo_model.Release{
|
||||
Sha1: tag.Object.String(),
|
||||
Sha1: tag.Object.String(),
|
||||
CreatedUnix: timeutil.TimeStamp(tag.Tagger.When.Unix()),
|
||||
}); err != nil {
|
||||
return fmt.Errorf("unable to update tag %s for pull-mirror Repo[%d:%s/%s]: %w", tag.Name, repo.ID, repo.OwnerName, repo.Name, err)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,10 @@ import (
|
|||
"code.gitea.io/gitea/modules/generate"
|
||||
)
|
||||
|
||||
// LFS represents the configuration for Git LFS
|
||||
// LFS represents the server-side configuration for Git LFS.
|
||||
// Ideally these options should be in a section like "[lfs_server]",
|
||||
// but they are in "[server]" section due to historical reasons.
|
||||
// Could be refactored in the future while keeping backwards compatibility.
|
||||
var LFS = struct {
|
||||
StartServer bool `ini:"LFS_START_SERVER"`
|
||||
AllowPureSSH bool `ini:"LFS_ALLOW_PURE_SSH"`
|
||||
|
@ -18,15 +21,22 @@ var LFS = struct {
|
|||
HTTPAuthExpiry time.Duration `ini:"LFS_HTTP_AUTH_EXPIRY"`
|
||||
MaxFileSize int64 `ini:"LFS_MAX_FILE_SIZE"`
|
||||
LocksPagingNum int `ini:"LFS_LOCKS_PAGING_NUM"`
|
||||
MaxBatchSize int `ini:"LFS_MAX_BATCH_SIZE"`
|
||||
|
||||
Storage *Storage
|
||||
}{}
|
||||
|
||||
// LFSClient represents configuration for Gitea's LFS clients, for example: mirroring upstream Git LFS
|
||||
var LFSClient = struct {
|
||||
BatchSize int `ini:"BATCH_SIZE"`
|
||||
BatchOperationConcurrency int `ini:"BATCH_OPERATION_CONCURRENCY"`
|
||||
}{}
|
||||
|
||||
func loadLFSFrom(rootCfg ConfigProvider) error {
|
||||
mustMapSetting(rootCfg, "lfs_client", &LFSClient)
|
||||
|
||||
mustMapSetting(rootCfg, "server", &LFS)
|
||||
sec := rootCfg.Section("server")
|
||||
if err := sec.MapTo(&LFS); err != nil {
|
||||
return fmt.Errorf("failed to map LFS settings: %v", err)
|
||||
}
|
||||
|
||||
lfsSec, _ := rootCfg.GetSection("lfs")
|
||||
|
||||
|
@ -53,6 +63,15 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
|
|||
LFS.LocksPagingNum = 50
|
||||
}
|
||||
|
||||
if LFSClient.BatchSize < 1 {
|
||||
LFSClient.BatchSize = 20
|
||||
}
|
||||
|
||||
if LFSClient.BatchOperationConcurrency < 1 {
|
||||
// match the default git-lfs's `lfs.concurrenttransfers` https://github.com/git-lfs/git-lfs/blob/main/docs/man/git-lfs-config.adoc#upload-and-download-transfer-settings
|
||||
LFSClient.BatchOperationConcurrency = 8
|
||||
}
|
||||
|
||||
LFS.HTTPAuthExpiry = sec.Key("LFS_HTTP_AUTH_EXPIRY").MustDuration(24 * time.Hour)
|
||||
|
||||
if !LFS.StartServer || !InstallLock {
|
||||
|
|
|
@ -99,3 +99,32 @@ STORAGE_TYPE = minio
|
|||
assert.EqualValues(t, "gitea", LFS.Storage.MinioConfig.Bucket)
|
||||
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
|
||||
func Test_LFSClientServerConfigs(t *testing.T) {
|
||||
iniStr := `
|
||||
[server]
|
||||
LFS_MAX_BATCH_SIZE = 100
|
||||
[lfs_client]
|
||||
# will default to 20
|
||||
BATCH_SIZE = 0
|
||||
`
|
||||
cfg, err := NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
assert.EqualValues(t, 100, LFS.MaxBatchSize)
|
||||
assert.EqualValues(t, 20, LFSClient.BatchSize)
|
||||
assert.EqualValues(t, 8, LFSClient.BatchOperationConcurrency)
|
||||
|
||||
iniStr = `
|
||||
[lfs_client]
|
||||
BATCH_SIZE = 50
|
||||
BATCH_OPERATION_CONCURRENCY = 10
|
||||
`
|
||||
cfg, err = NewConfigProviderFromData(iniStr)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
assert.EqualValues(t, 50, LFSClient.BatchSize)
|
||||
assert.EqualValues(t, 10, LFSClient.BatchOperationConcurrency)
|
||||
}
|
||||
|
|
|
@ -247,7 +247,7 @@ func (a *AzureBlobStorage) Delete(path string) error {
|
|||
}
|
||||
|
||||
// URL gets the redirect URL to a file. The presigned link is valid for 5 minutes.
|
||||
func (a *AzureBlobStorage) URL(path, name string) (*url.URL, error) {
|
||||
func (a *AzureBlobStorage) URL(path, name string, reqParams url.Values) (*url.URL, error) {
|
||||
blobClient := a.getBlobClient(path)
|
||||
|
||||
startTime := time.Now()
|
||||
|
|
|
@ -30,7 +30,7 @@ func (s discardStorage) Delete(_ string) error {
|
|||
return fmt.Errorf("%s", s)
|
||||
}
|
||||
|
||||
func (s discardStorage) URL(_, _ string) (*url.URL, error) {
|
||||
func (s discardStorage) URL(_, _ string, _ url.Values) (*url.URL, error) {
|
||||
return nil, fmt.Errorf("%s", s)
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ func Test_discardStorage(t *testing.T) {
|
|||
assert.Error(t, err, string(tt))
|
||||
}
|
||||
{
|
||||
got, err := tt.URL("path", "name")
|
||||
got, err := tt.URL("path", "name", nil)
|
||||
assert.Nil(t, got)
|
||||
assert.Errorf(t, err, string(tt))
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ func (l *LocalStorage) Delete(path string) error {
|
|||
}
|
||||
|
||||
// URL gets the redirect URL to a file
|
||||
func (l *LocalStorage) URL(path, name string) (*url.URL, error) {
|
||||
func (l *LocalStorage) URL(path, name string, reqParams url.Values) (*url.URL, error) {
|
||||
return nil, ErrURLNotSupported
|
||||
}
|
||||
|
||||
|
|
|
@ -276,8 +276,12 @@ func (m *MinioStorage) Delete(path string) error {
|
|||
}
|
||||
|
||||
// URL gets the redirect URL to a file. The presigned link is valid for 5 minutes.
|
||||
func (m *MinioStorage) URL(path, name string) (*url.URL, error) {
|
||||
reqParams := make(url.Values)
|
||||
func (m *MinioStorage) URL(path, name string, serveDirectReqParams url.Values) (*url.URL, error) {
|
||||
// copy serveDirectReqParams
|
||||
reqParams, err := url.ParseQuery(serveDirectReqParams.Encode())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO it may be good to embed images with 'inline' like ServeData does, but we don't want to have to read the file, do we?
|
||||
reqParams.Set("response-content-disposition", "attachment; filename=\""+quoteEscaper.Replace(name)+"\"")
|
||||
u, err := m.client.PresignedGetObject(m.ctx, m.bucket, m.buildMinioPath(path), 5*time.Minute, reqParams)
|
||||
|
|
|
@ -63,7 +63,7 @@ type ObjectStorage interface {
|
|||
Save(path string, r io.Reader, size int64) (int64, error)
|
||||
Stat(path string) (os.FileInfo, error)
|
||||
Delete(path string) error
|
||||
URL(path, name string) (*url.URL, error)
|
||||
URL(path, name string, reqParams url.Values) (*url.URL, error)
|
||||
IterateObjects(path string, iterator func(path string, obj Object) error) error
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ var (
|
|||
ActionsArtifacts ObjectStorage = uninitializedStorage
|
||||
)
|
||||
|
||||
// Init init the stoarge
|
||||
// Init init the storage
|
||||
func Init() error {
|
||||
for _, f := range []func() error{
|
||||
initAttachments,
|
||||
|
|
|
@ -262,13 +262,6 @@ func (p *ReleasePayload) JSONPayload() ([]byte, error) {
|
|||
return json.MarshalIndent(p, "", " ")
|
||||
}
|
||||
|
||||
// __________ .__
|
||||
// \______ \__ __ _____| |__
|
||||
// | ___/ | \/ ___/ | \
|
||||
// | | | | /\___ \| Y \
|
||||
// |____| |____//____ >___| /
|
||||
// \/ \/
|
||||
|
||||
// PushPayload represents a payload information of push event.
|
||||
type PushPayload struct {
|
||||
Ref string `json:"ref"`
|
||||
|
@ -509,3 +502,26 @@ type WorkflowDispatchPayload struct {
|
|||
func (p *WorkflowDispatchPayload) JSONPayload() ([]byte, error) {
|
||||
return json.MarshalIndent(p, "", " ")
|
||||
}
|
||||
|
||||
// CommitStatusPayload represents a payload information of commit status event.
|
||||
type CommitStatusPayload struct {
|
||||
// TODO: add Branches per https://docs.github.com/en/webhooks/webhook-events-and-payloads#status
|
||||
Commit *PayloadCommit `json:"commit"`
|
||||
Context string `json:"context"`
|
||||
// swagger:strfmt date-time
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Description string `json:"description"`
|
||||
ID int64 `json:"id"`
|
||||
Repo *Repository `json:"repository"`
|
||||
Sender *User `json:"sender"`
|
||||
SHA string `json:"sha"`
|
||||
State string `json:"state"`
|
||||
TargetURL string `json:"target_url"`
|
||||
// swagger:strfmt date-time
|
||||
UpdatedAt *time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// JSONPayload implements Payload
|
||||
func (p *CommitStatusPayload) JSONPayload() ([]byte, error) {
|
||||
return json.MarshalIndent(p, "", " ")
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/svg"
|
||||
"code.gitea.io/gitea/modules/templates/eval"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/gitdiff"
|
||||
"code.gitea.io/gitea/services/webtheme"
|
||||
|
@ -54,6 +53,7 @@ func NewFuncMap() template.FuncMap {
|
|||
"StringUtils": NewStringUtils,
|
||||
"SliceUtils": NewSliceUtils,
|
||||
"JsonUtils": NewJsonUtils,
|
||||
"DateUtils": NewDateUtils,
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// svg / avatar / icon / color
|
||||
|
@ -66,12 +66,9 @@ func NewFuncMap() template.FuncMap {
|
|||
|
||||
// -----------------------------------------------------------------
|
||||
// time / number / format
|
||||
"FileSize": base.FileSize,
|
||||
"CountFmt": base.FormatNumberSI,
|
||||
"TimeSince": timeutil.TimeSince,
|
||||
"TimeSinceUnix": timeutil.TimeSinceUnix,
|
||||
"DateTime": timeutil.DateTime,
|
||||
"Sec2Time": util.SecToTime,
|
||||
"FileSize": base.FileSize,
|
||||
"CountFmt": base.FormatNumberSI,
|
||||
"Sec2Time": util.SecToTime,
|
||||
"LoadTimes": func(startTime time.Time) string {
|
||||
return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
|
||||
},
|
||||
|
@ -154,18 +151,8 @@ func NewFuncMap() template.FuncMap {
|
|||
|
||||
// -----------------------------------------------------------------
|
||||
// render
|
||||
"RenderCommitMessage": RenderCommitMessage,
|
||||
"RenderCommitMessageLinkSubject": renderCommitMessageLinkSubject,
|
||||
|
||||
"RenderCommitBody": renderCommitBody,
|
||||
"RenderCodeBlock": renderCodeBlock,
|
||||
"RenderIssueTitle": renderIssueTitle,
|
||||
"RenderEmoji": renderEmoji,
|
||||
"ReactionToEmoji": reactionToEmoji,
|
||||
|
||||
"RenderMarkdownToHtml": RenderMarkdownToHtml,
|
||||
"RenderLabel": renderLabel,
|
||||
"RenderLabels": RenderLabels,
|
||||
"RenderCodeBlock": renderCodeBlock,
|
||||
"ReactionToEmoji": reactionToEmoji,
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// misc
|
||||
|
@ -177,6 +164,22 @@ func NewFuncMap() template.FuncMap {
|
|||
|
||||
"FilenameIsImage": filenameIsImage,
|
||||
"TabSizeClass": tabSizeClass,
|
||||
|
||||
// for backward compatibility only, do not use them anymore
|
||||
"TimeSince": timeSinceLegacy,
|
||||
"TimeSinceUnix": timeSinceLegacy,
|
||||
"DateTime": dateTimeLegacy,
|
||||
|
||||
"RenderEmoji": renderEmojiLegacy,
|
||||
"RenderLabel": renderLabelLegacy,
|
||||
"RenderLabels": renderLabelsLegacy,
|
||||
"RenderIssueTitle": renderIssueTitleLegacy,
|
||||
|
||||
"RenderMarkdownToHtml": renderMarkdownToHtmlLegacy,
|
||||
|
||||
"RenderCommitMessage": renderCommitMessageLegacy,
|
||||
"RenderCommitMessageLinkSubject": renderCommitMessageLinkSubjectLegacy,
|
||||
"RenderCommitBody": renderCommitBodyLegacy,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -294,3 +297,9 @@ func userThemeName(user *user_model.User) string {
|
|||
}
|
||||
return setting.UI.DefaultTheme
|
||||
}
|
||||
|
||||
func panicIfDevOrTesting() {
|
||||
if !setting.IsProd || setting.IsInTesting {
|
||||
panic("legacy template functions are for backward compatibility only, do not use them in new code")
|
||||
}
|
||||
}
|
||||
|
|
133
modules/templates/util_date.go
Normal file
133
modules/templates/util_date.go
Normal file
|
@ -0,0 +1,133 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
)
|
||||
|
||||
type DateUtils struct{}
|
||||
|
||||
func NewDateUtils() *DateUtils {
|
||||
return (*DateUtils)(nil) // the util is stateless, and we do not need to create an instance
|
||||
}
|
||||
|
||||
// AbsoluteShort renders in "Jan 01, 2006" format
|
||||
func (du *DateUtils) AbsoluteShort(time any) template.HTML {
|
||||
return dateTimeFormat("short", time)
|
||||
}
|
||||
|
||||
// AbsoluteLong renders in "January 01, 2006" format
|
||||
func (du *DateUtils) AbsoluteLong(time any) template.HTML {
|
||||
return dateTimeFormat("long", time)
|
||||
}
|
||||
|
||||
// FullTime renders in "Jan 01, 2006 20:33:44" format
|
||||
func (du *DateUtils) FullTime(time any) template.HTML {
|
||||
return dateTimeFormat("full", time)
|
||||
}
|
||||
|
||||
func (du *DateUtils) TimeSince(time any) template.HTML {
|
||||
return TimeSince(time)
|
||||
}
|
||||
|
||||
// ParseLegacy parses the datetime in legacy format, eg: "2016-01-02" in server's timezone.
|
||||
// It shouldn't be used in new code. New code should use Time or TimeStamp as much as possible.
|
||||
func (du *DateUtils) ParseLegacy(datetime string) time.Time {
|
||||
return parseLegacy(datetime)
|
||||
}
|
||||
|
||||
func parseLegacy(datetime string) time.Time {
|
||||
t, err := time.Parse(time.RFC3339, datetime)
|
||||
if err != nil {
|
||||
t, _ = time.ParseInLocation(time.DateOnly, datetime, setting.DefaultUILocation)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func anyToTime(any any) (t time.Time, isZero bool) {
|
||||
switch v := any.(type) {
|
||||
case nil:
|
||||
// it is zero
|
||||
case *time.Time:
|
||||
if v != nil {
|
||||
t = *v
|
||||
}
|
||||
case time.Time:
|
||||
t = v
|
||||
case timeutil.TimeStamp:
|
||||
t = v.AsTime()
|
||||
case timeutil.TimeStampNano:
|
||||
t = v.AsTime()
|
||||
case int:
|
||||
t = timeutil.TimeStamp(v).AsTime()
|
||||
case int64:
|
||||
t = timeutil.TimeStamp(v).AsTime()
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported time type %T", any))
|
||||
}
|
||||
return t, t.IsZero() || t.Unix() == 0
|
||||
}
|
||||
|
||||
func dateTimeFormat(format string, datetime any) template.HTML {
|
||||
t, isZero := anyToTime(datetime)
|
||||
if isZero {
|
||||
return "-"
|
||||
}
|
||||
var textEscaped string
|
||||
datetimeEscaped := html.EscapeString(t.Format(time.RFC3339))
|
||||
if format == "full" {
|
||||
textEscaped = html.EscapeString(t.Format("2006-01-02 15:04:05 -07:00"))
|
||||
} else {
|
||||
textEscaped = html.EscapeString(t.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
attrs := []string{`weekday=""`, `year="numeric"`}
|
||||
switch format {
|
||||
case "short", "long": // date only
|
||||
attrs = append(attrs, `month="`+format+`"`, `day="numeric"`)
|
||||
return template.HTML(fmt.Sprintf(`<absolute-date %s date="%s">%s</absolute-date>`, strings.Join(attrs, " "), datetimeEscaped, textEscaped))
|
||||
case "full": // full date including time
|
||||
attrs = append(attrs, `format="datetime"`, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`, `data-tooltip-content`, `data-tooltip-interactive="true"`)
|
||||
return template.HTML(fmt.Sprintf(`<relative-time %s datetime="%s">%s</relative-time>`, strings.Join(attrs, " "), datetimeEscaped, textEscaped))
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported format %s", format))
|
||||
}
|
||||
}
|
||||
|
||||
func timeSinceTo(then any, now time.Time) template.HTML {
|
||||
thenTime, isZero := anyToTime(then)
|
||||
if isZero {
|
||||
return "-"
|
||||
}
|
||||
|
||||
friendlyText := thenTime.Format("2006-01-02 15:04:05 -07:00")
|
||||
|
||||
// document: https://github.com/github/relative-time-element
|
||||
attrs := `tense="past"`
|
||||
isFuture := now.Before(thenTime)
|
||||
if isFuture {
|
||||
attrs = `tense="future"`
|
||||
}
|
||||
|
||||
// declare data-tooltip-content attribute to switch from "title" tooltip to "tippy" tooltip
|
||||
htm := fmt.Sprintf(`<relative-time prefix="" %s datetime="%s" data-tooltip-content data-tooltip-interactive="true">%s</relative-time>`,
|
||||
attrs, thenTime.Format(time.RFC3339), friendlyText)
|
||||
return template.HTML(htm)
|
||||
}
|
||||
|
||||
// TimeSince renders relative time HTML given a time
|
||||
func TimeSince(then any) template.HTML {
|
||||
if setting.UI.PreferredTimestampTense == "absolute" {
|
||||
return dateTimeFormat("full", then)
|
||||
}
|
||||
return timeSinceTo(then, time.Now())
|
||||
}
|
23
modules/templates/util_date_legacy.go
Normal file
23
modules/templates/util_date_legacy.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
)
|
||||
|
||||
func dateTimeLegacy(format string, datetime any, _ ...string) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
if s, ok := datetime.(string); ok {
|
||||
datetime = parseLegacy(s)
|
||||
}
|
||||
return dateTimeFormat(format, datetime)
|
||||
}
|
||||
|
||||
func timeSinceLegacy(time any, _ translation.Locale) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
return TimeSince(time)
|
||||
}
|
72
modules/templates/util_date_test.go
Normal file
72
modules/templates/util_date_test.go
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDateTime(t *testing.T) {
|
||||
testTz, _ := time.LoadLocation("America/New_York")
|
||||
defer test.MockVariableValue(&setting.DefaultUILocation, testTz)()
|
||||
defer test.MockVariableValue(&setting.IsInTesting, false)()
|
||||
|
||||
du := NewDateUtils()
|
||||
|
||||
refTimeStr := "2018-01-01T00:00:00Z"
|
||||
refDateStr := "2018-01-01"
|
||||
refTime, _ := time.Parse(time.RFC3339, refTimeStr)
|
||||
refTimeStamp := timeutil.TimeStamp(refTime.Unix())
|
||||
|
||||
assert.EqualValues(t, "-", du.AbsoluteShort(nil))
|
||||
assert.EqualValues(t, "-", du.AbsoluteShort(0))
|
||||
assert.EqualValues(t, "-", du.AbsoluteShort(time.Time{}))
|
||||
assert.EqualValues(t, "-", du.AbsoluteShort(timeutil.TimeStamp(0)))
|
||||
|
||||
actual := dateTimeLegacy("short", "invalid")
|
||||
assert.EqualValues(t, `-`, actual)
|
||||
|
||||
actual = dateTimeLegacy("short", refTimeStr)
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01</absolute-date>`, actual)
|
||||
|
||||
actual = du.AbsoluteShort(refTime)
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01</absolute-date>`, actual)
|
||||
|
||||
actual = dateTimeLegacy("short", refDateStr)
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00-05:00">2018-01-01</absolute-date>`, actual)
|
||||
|
||||
actual = du.AbsoluteShort(refTimeStamp)
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2017-12-31T19:00:00-05:00">2017-12-31</absolute-date>`, actual)
|
||||
|
||||
actual = du.FullTime(refTimeStamp)
|
||||
assert.EqualValues(t, `<relative-time weekday="" year="numeric" format="datetime" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" data-tooltip-content data-tooltip-interactive="true" datetime="2017-12-31T19:00:00-05:00">2017-12-31 19:00:00 -05:00</relative-time>`, actual)
|
||||
}
|
||||
|
||||
func TestTimeSince(t *testing.T) {
|
||||
testTz, _ := time.LoadLocation("America/New_York")
|
||||
defer test.MockVariableValue(&setting.DefaultUILocation, testTz)()
|
||||
defer test.MockVariableValue(&setting.IsInTesting, false)()
|
||||
|
||||
du := NewDateUtils()
|
||||
assert.EqualValues(t, "-", du.TimeSince(nil))
|
||||
|
||||
refTimeStr := "2018-01-01T00:00:00Z"
|
||||
refTime, _ := time.Parse(time.RFC3339, refTimeStr)
|
||||
|
||||
actual := du.TimeSince(refTime)
|
||||
assert.EqualValues(t, `<relative-time prefix="" tense="past" datetime="2018-01-01T00:00:00Z" data-tooltip-content data-tooltip-interactive="true">2018-01-01 00:00:00 +00:00</relative-time>`, actual)
|
||||
|
||||
actual = timeSinceTo(&refTime, time.Time{})
|
||||
assert.EqualValues(t, `<relative-time prefix="" tense="future" datetime="2018-01-01T00:00:00Z" data-tooltip-content data-tooltip-interactive="true">2018-01-01 00:00:00 +00:00</relative-time>`, actual)
|
||||
|
||||
actual = timeSinceLegacy(timeutil.TimeStampNano(refTime.UnixNano()), nil)
|
||||
assert.EqualValues(t, `<relative-time prefix="" tense="past" datetime="2017-12-31T19:00:00-05:00" data-tooltip-content data-tooltip-interactive="true">2017-12-31 19:00:00 -05:00</relative-time>`, actual)
|
||||
}
|
|
@ -24,13 +24,21 @@ import (
|
|||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
type RenderUtils struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func NewRenderUtils(ctx context.Context) *RenderUtils {
|
||||
return &RenderUtils{ctx: ctx}
|
||||
}
|
||||
|
||||
// RenderCommitMessage renders commit message with XSS-safe and special links.
|
||||
func RenderCommitMessage(ctx context.Context, msg string, metas map[string]string) template.HTML {
|
||||
func (ut *RenderUtils) RenderCommitMessage(msg string, metas map[string]string) template.HTML {
|
||||
cleanMsg := template.HTMLEscapeString(msg)
|
||||
// we can safely assume that it will not return any error, since there
|
||||
// shouldn't be any special HTML.
|
||||
fullMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
|
||||
Ctx: ctx,
|
||||
Ctx: ut.ctx,
|
||||
Metas: metas,
|
||||
}, cleanMsg)
|
||||
if err != nil {
|
||||
|
@ -44,9 +52,9 @@ func RenderCommitMessage(ctx context.Context, msg string, metas map[string]strin
|
|||
return renderCodeBlock(template.HTML(msgLines[0]))
|
||||
}
|
||||
|
||||
// renderCommitMessageLinkSubject renders commit message as a XSS-safe link to
|
||||
// RenderCommitMessageLinkSubject renders commit message as a XSS-safe link to
|
||||
// the provided default url, handling for special links without email to links.
|
||||
func renderCommitMessageLinkSubject(ctx context.Context, msg, urlDefault string, metas map[string]string) template.HTML {
|
||||
func (ut *RenderUtils) RenderCommitMessageLinkSubject(msg, urlDefault string, metas map[string]string) template.HTML {
|
||||
msgLine := strings.TrimLeftFunc(msg, unicode.IsSpace)
|
||||
lineEnd := strings.IndexByte(msgLine, '\n')
|
||||
if lineEnd > 0 {
|
||||
|
@ -60,7 +68,7 @@ func renderCommitMessageLinkSubject(ctx context.Context, msg, urlDefault string,
|
|||
// we can safely assume that it will not return any error, since there
|
||||
// shouldn't be any special HTML.
|
||||
renderedMessage, err := markup.RenderCommitMessageSubject(&markup.RenderContext{
|
||||
Ctx: ctx,
|
||||
Ctx: ut.ctx,
|
||||
DefaultLink: urlDefault,
|
||||
Metas: metas,
|
||||
}, template.HTMLEscapeString(msgLine))
|
||||
|
@ -71,8 +79,8 @@ func renderCommitMessageLinkSubject(ctx context.Context, msg, urlDefault string,
|
|||
return renderCodeBlock(template.HTML(renderedMessage))
|
||||
}
|
||||
|
||||
// renderCommitBody extracts the body of a commit message without its title.
|
||||
func renderCommitBody(ctx context.Context, msg string, metas map[string]string) template.HTML {
|
||||
// RenderCommitBody extracts the body of a commit message without its title.
|
||||
func (ut *RenderUtils) RenderCommitBody(msg string, metas map[string]string) template.HTML {
|
||||
msgLine := strings.TrimSpace(msg)
|
||||
lineEnd := strings.IndexByte(msgLine, '\n')
|
||||
if lineEnd > 0 {
|
||||
|
@ -86,7 +94,7 @@ func renderCommitBody(ctx context.Context, msg string, metas map[string]string)
|
|||
}
|
||||
|
||||
renderedMessage, err := markup.RenderCommitMessage(&markup.RenderContext{
|
||||
Ctx: ctx,
|
||||
Ctx: ut.ctx,
|
||||
Metas: metas,
|
||||
}, template.HTMLEscapeString(msgLine))
|
||||
if err != nil {
|
||||
|
@ -105,22 +113,22 @@ func renderCodeBlock(htmlEscapedTextToRender template.HTML) template.HTML {
|
|||
return template.HTML(htmlWithCodeTags)
|
||||
}
|
||||
|
||||
// renderIssueTitle renders issue/pull title with defined post processors
|
||||
func renderIssueTitle(ctx context.Context, text string, metas map[string]string) template.HTML {
|
||||
// RenderIssueTitle renders issue/pull title with defined post processors
|
||||
func (ut *RenderUtils) RenderIssueTitle(text string, metas map[string]string) template.HTML {
|
||||
renderedText, err := markup.RenderIssueTitle(&markup.RenderContext{
|
||||
Ctx: ctx,
|
||||
Ctx: ut.ctx,
|
||||
Metas: metas,
|
||||
}, template.HTMLEscapeString(text))
|
||||
if err != nil {
|
||||
log.Error("RenderIssueTitle: %v", err)
|
||||
return template.HTML("")
|
||||
return ""
|
||||
}
|
||||
return template.HTML(renderedText)
|
||||
}
|
||||
|
||||
// renderLabel renders a label
|
||||
// locale is needed due to an import cycle with our context providing the `Tr` function
|
||||
func renderLabel(ctx context.Context, locale translation.Locale, label *issues_model.Label) template.HTML {
|
||||
// RenderLabel renders a label
|
||||
func (ut *RenderUtils) RenderLabel(label *issues_model.Label) template.HTML {
|
||||
locale := ut.ctx.Value(translation.ContextKey).(translation.Locale)
|
||||
var extraCSSClasses string
|
||||
textColor := util.ContrastColor(label.Color)
|
||||
labelScope := label.ExclusiveScope()
|
||||
|
@ -134,12 +142,12 @@ func renderLabel(ctx context.Context, locale translation.Locale, label *issues_m
|
|||
if labelScope == "" {
|
||||
// Regular label
|
||||
return HTMLFormat(`<div class="ui label %s" style="color: %s !important; background-color: %s !important;" data-tooltip-content title="%s">%s</div>`,
|
||||
extraCSSClasses, textColor, label.Color, descriptionText, renderEmoji(ctx, label.Name))
|
||||
extraCSSClasses, textColor, label.Color, descriptionText, ut.RenderEmoji(label.Name))
|
||||
}
|
||||
|
||||
// Scoped label
|
||||
scopeHTML := renderEmoji(ctx, labelScope)
|
||||
itemHTML := renderEmoji(ctx, label.Name[len(labelScope)+1:])
|
||||
scopeHTML := ut.RenderEmoji(labelScope)
|
||||
itemHTML := ut.RenderEmoji(label.Name[len(labelScope)+1:])
|
||||
|
||||
// Make scope and item background colors slightly darker and lighter respectively.
|
||||
// More contrast needed with higher luminance, empirically tweaked.
|
||||
|
@ -176,13 +184,12 @@ func renderLabel(ctx context.Context, locale translation.Locale, label *issues_m
|
|||
textColor, itemColor, itemHTML)
|
||||
}
|
||||
|
||||
// renderEmoji renders html text with emoji post processors
|
||||
func renderEmoji(ctx context.Context, text string) template.HTML {
|
||||
renderedText, err := markup.RenderEmoji(&markup.RenderContext{Ctx: ctx},
|
||||
template.HTMLEscapeString(text))
|
||||
// RenderEmoji renders html text with emoji post processors
|
||||
func (ut *RenderUtils) RenderEmoji(text string) template.HTML {
|
||||
renderedText, err := markup.RenderEmoji(&markup.RenderContext{Ctx: ut.ctx}, template.HTMLEscapeString(text))
|
||||
if err != nil {
|
||||
log.Error("RenderEmoji: %v", err)
|
||||
return template.HTML("")
|
||||
return ""
|
||||
}
|
||||
return template.HTML(renderedText)
|
||||
}
|
||||
|
@ -200,9 +207,9 @@ func reactionToEmoji(reaction string) template.HTML {
|
|||
return template.HTML(fmt.Sprintf(`<img alt=":%s:" src="%s/assets/img/emoji/%s.png"></img>`, reaction, setting.StaticURLPrefix, url.PathEscape(reaction)))
|
||||
}
|
||||
|
||||
func RenderMarkdownToHtml(ctx context.Context, input string) template.HTML { //nolint:revive
|
||||
func (ut *RenderUtils) MarkdownToHtml(input string) template.HTML { //nolint:revive
|
||||
output, err := markdown.RenderString(&markup.RenderContext{
|
||||
Ctx: ctx,
|
||||
Ctx: ut.ctx,
|
||||
Metas: map[string]string{"mode": "document"},
|
||||
}, input)
|
||||
if err != nil {
|
||||
|
@ -211,7 +218,7 @@ func RenderMarkdownToHtml(ctx context.Context, input string) template.HTML { //n
|
|||
return output
|
||||
}
|
||||
|
||||
func RenderLabels(ctx context.Context, locale translation.Locale, labels []*issues_model.Label, repoLink string, issue *issues_model.Issue) template.HTML {
|
||||
func (ut *RenderUtils) RenderLabels(labels []*issues_model.Label, repoLink string, issue *issues_model.Issue) template.HTML {
|
||||
isPullRequest := issue != nil && issue.IsPull
|
||||
baseLink := fmt.Sprintf("%s/%s", repoLink, util.Iif(isPullRequest, "pulls", "issues"))
|
||||
htmlCode := `<span class="labels-list">`
|
||||
|
@ -220,7 +227,7 @@ func RenderLabels(ctx context.Context, locale translation.Locale, labels []*issu
|
|||
if label == nil {
|
||||
continue
|
||||
}
|
||||
htmlCode += fmt.Sprintf(`<a href="%s?labels=%d">%s</a>`, baseLink, label.ID, renderLabel(ctx, locale, label))
|
||||
htmlCode += fmt.Sprintf(`<a href="%s?labels=%d">%s</a>`, baseLink, label.ID, ut.RenderLabel(label))
|
||||
}
|
||||
htmlCode += "</span>"
|
||||
return template.HTML(htmlCode)
|
||||
|
|
52
modules/templates/util_render_legacy.go
Normal file
52
modules/templates/util_render_legacy.go
Normal file
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package templates
|
||||
|
||||
import (
|
||||
"context"
|
||||
"html/template"
|
||||
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
)
|
||||
|
||||
func renderEmojiLegacy(ctx context.Context, text string) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
return NewRenderUtils(ctx).RenderEmoji(text)
|
||||
}
|
||||
|
||||
func renderLabelLegacy(ctx context.Context, locale translation.Locale, label *issues_model.Label) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
return NewRenderUtils(ctx).RenderLabel(label)
|
||||
}
|
||||
|
||||
func renderLabelsLegacy(ctx context.Context, locale translation.Locale, labels []*issues_model.Label, repoLink string, issue *issues_model.Issue) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
return NewRenderUtils(ctx).RenderLabels(labels, repoLink, issue)
|
||||
}
|
||||
|
||||
func renderMarkdownToHtmlLegacy(ctx context.Context, input string) template.HTML { //nolint:revive
|
||||
panicIfDevOrTesting()
|
||||
return NewRenderUtils(ctx).MarkdownToHtml(input)
|
||||
}
|
||||
|
||||
func renderCommitMessageLegacy(ctx context.Context, msg string, metas map[string]string) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
return NewRenderUtils(ctx).RenderCommitMessage(msg, metas)
|
||||
}
|
||||
|
||||
func renderCommitMessageLinkSubjectLegacy(ctx context.Context, msg, urlDefault string, metas map[string]string) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
return NewRenderUtils(ctx).RenderCommitMessageLinkSubject(msg, urlDefault, metas)
|
||||
}
|
||||
|
||||
func renderIssueTitleLegacy(ctx context.Context, text string, metas map[string]string) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
return NewRenderUtils(ctx).RenderIssueTitle(text, metas)
|
||||
}
|
||||
|
||||
func renderCommitBodyLegacy(ctx context.Context, msg string, metas map[string]string) template.HTML {
|
||||
panicIfDevOrTesting()
|
||||
return NewRenderUtils(ctx).RenderCommitBody(msg, metas)
|
||||
}
|
|
@ -65,9 +65,14 @@ func TestMain(m *testing.M) {
|
|||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func newTestRenderUtils() *RenderUtils {
|
||||
ctx := context.Background()
|
||||
ctx = context.WithValue(ctx, translation.ContextKey, &translation.MockLocale{})
|
||||
return NewRenderUtils(ctx)
|
||||
}
|
||||
|
||||
func TestRenderCommitBody(t *testing.T) {
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
msg string
|
||||
metas map[string]string
|
||||
}
|
||||
|
@ -79,7 +84,6 @@ func TestRenderCommitBody(t *testing.T) {
|
|||
{
|
||||
name: "multiple lines",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
msg: "first line\nsecond line",
|
||||
},
|
||||
want: "second line",
|
||||
|
@ -87,7 +91,6 @@ func TestRenderCommitBody(t *testing.T) {
|
|||
{
|
||||
name: "multiple lines with leading newlines",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
msg: "\n\n\n\nfirst line\nsecond line",
|
||||
},
|
||||
want: "second line",
|
||||
|
@ -95,15 +98,15 @@ func TestRenderCommitBody(t *testing.T) {
|
|||
{
|
||||
name: "multiple lines with trailing newlines",
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
msg: "first line\nsecond line\n\n\n",
|
||||
},
|
||||
want: "second line",
|
||||
},
|
||||
}
|
||||
ut := newTestRenderUtils()
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equalf(t, tt.want, renderCommitBody(tt.args.ctx, tt.args.msg, tt.args.metas), "RenderCommitBody(%v, %v, %v)", tt.args.ctx, tt.args.msg, tt.args.metas)
|
||||
assert.Equalf(t, tt.want, ut.RenderCommitBody(tt.args.msg, tt.args.metas), "RenderCommitBody(%v, %v)", tt.args.msg, tt.args.metas)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -126,20 +129,20 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
|
|||
<a href="/mention-user" class="mention">@mention-user</a> test
|
||||
<a href="/user13/repo11/issues/123" class="ref-issue">#123</a>
|
||||
space`
|
||||
|
||||
assert.EqualValues(t, expected, renderCommitBody(context.Background(), testInput(), testMetas))
|
||||
actual := strings.ReplaceAll(string(newTestRenderUtils().RenderCommitBody(testInput(), testMetas)), ` data-markdown-generated-content=""`, "")
|
||||
assert.EqualValues(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestRenderCommitMessage(t *testing.T) {
|
||||
expected := `space <a href="/mention-user" class="mention">@mention-user</a> `
|
||||
expected := `space <a href="/mention-user" data-markdown-generated-content="" class="mention">@mention-user</a> `
|
||||
|
||||
assert.EqualValues(t, expected, RenderCommitMessage(context.Background(), testInput(), testMetas))
|
||||
assert.EqualValues(t, expected, newTestRenderUtils().RenderCommitMessage(testInput(), testMetas))
|
||||
}
|
||||
|
||||
func TestRenderCommitMessageLinkSubject(t *testing.T) {
|
||||
expected := `<a href="https://example.com/link" class="default-link muted">space </a><a href="/mention-user" class="mention">@mention-user</a>`
|
||||
expected := `<a href="https://example.com/link" class="default-link muted">space </a><a href="/mention-user" data-markdown-generated-content="" class="mention">@mention-user</a>`
|
||||
|
||||
assert.EqualValues(t, expected, renderCommitMessageLinkSubject(context.Background(), testInput(), "https://example.com/link", testMetas))
|
||||
assert.EqualValues(t, expected, newTestRenderUtils().RenderCommitMessageLinkSubject(testInput(), "https://example.com/link", testMetas))
|
||||
}
|
||||
|
||||
func TestRenderIssueTitle(t *testing.T) {
|
||||
|
@ -165,7 +168,8 @@ mail@domain.com
|
|||
space<SPACE><SPACE>
|
||||
`
|
||||
expected = strings.ReplaceAll(expected, "<SPACE>", " ")
|
||||
assert.EqualValues(t, expected, renderIssueTitle(context.Background(), testInput(), testMetas))
|
||||
actual := strings.ReplaceAll(string(newTestRenderUtils().RenderIssueTitle(testInput(), testMetas)), ` data-markdown-generated-content=""`, "")
|
||||
assert.EqualValues(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestRenderMarkdownToHtml(t *testing.T) {
|
||||
|
@ -190,25 +194,24 @@ com 88fc37a3c0a4dda553bdcfc80c178a58247f42fb mit
|
|||
#123
|
||||
space</p>
|
||||
`
|
||||
assert.Equal(t, expected, string(RenderMarkdownToHtml(context.Background(), testInput())))
|
||||
actual := strings.ReplaceAll(string(newTestRenderUtils().MarkdownToHtml(testInput())), ` data-markdown-generated-content=""`, "")
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestRenderLabels(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
locale := &translation.MockLocale{}
|
||||
|
||||
ut := newTestRenderUtils()
|
||||
label := &issues.Label{ID: 123, Name: "label-name", Color: "label-color"}
|
||||
issue := &issues.Issue{}
|
||||
expected := `/owner/repo/issues?labels=123`
|
||||
assert.Contains(t, RenderLabels(ctx, locale, []*issues.Label{label}, "/owner/repo", issue), expected)
|
||||
assert.Contains(t, ut.RenderLabels([]*issues.Label{label}, "/owner/repo", issue), expected)
|
||||
|
||||
label = &issues.Label{ID: 123, Name: "label-name", Color: "label-color"}
|
||||
issue = &issues.Issue{IsPull: true}
|
||||
expected = `/owner/repo/pulls?labels=123`
|
||||
assert.Contains(t, RenderLabels(ctx, locale, []*issues.Label{label}, "/owner/repo", issue), expected)
|
||||
assert.Contains(t, ut.RenderLabels([]*issues.Label{label}, "/owner/repo", issue), expected)
|
||||
}
|
||||
|
||||
func TestUserMention(t *testing.T) {
|
||||
rendered := RenderMarkdownToHtml(context.Background(), "@no-such-user @mention-user @mention-user")
|
||||
assert.EqualValues(t, `<p>@no-such-user <a href="/mention-user" rel="nofollow">@mention-user</a> <a href="/mention-user" rel="nofollow">@mention-user</a></p>`, strings.TrimSpace(string(rendered)))
|
||||
rendered := newTestRenderUtils().MarkdownToHtml("@no-such-user @mention-user @mention-user")
|
||||
assert.EqualValues(t, `<p>@no-such-user <a href="/mention-user" data-markdown-generated-content="" rel="nofollow">@mention-user</a> <a href="/mention-user" data-markdown-generated-content="" rel="nofollow">@mention-user</a></p>`, strings.TrimSpace(string(rendered)))
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/queue"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -92,10 +93,7 @@ func (w *testLoggerWriterCloser) Reset() {
|
|||
func PrintCurrentTest(t testing.TB, skip ...int) func() {
|
||||
t.Helper()
|
||||
start := time.Now()
|
||||
actualSkip := 1
|
||||
if len(skip) > 0 {
|
||||
actualSkip = skip[0] + 1
|
||||
}
|
||||
actualSkip := util.OptionalArg(skip) + 1
|
||||
_, filename, line, _ := runtime.Caller(actualSkip)
|
||||
|
||||
if log.CanColorStdout {
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package timeutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"html/template"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DateTime renders an absolute time HTML element by datetime.
|
||||
func DateTime(format string, datetime any, extraAttrs ...string) template.HTML {
|
||||
// TODO: remove the extraAttrs argument, it's not used in any call to DateTime
|
||||
|
||||
if p, ok := datetime.(*time.Time); ok {
|
||||
datetime = *p
|
||||
}
|
||||
if p, ok := datetime.(*TimeStamp); ok {
|
||||
datetime = *p
|
||||
}
|
||||
switch v := datetime.(type) {
|
||||
case TimeStamp:
|
||||
datetime = v.AsTime()
|
||||
case int:
|
||||
datetime = TimeStamp(v).AsTime()
|
||||
case int64:
|
||||
datetime = TimeStamp(v).AsTime()
|
||||
}
|
||||
|
||||
var datetimeEscaped, textEscaped string
|
||||
switch v := datetime.(type) {
|
||||
case nil:
|
||||
return "-"
|
||||
case string:
|
||||
datetimeEscaped = html.EscapeString(v)
|
||||
textEscaped = datetimeEscaped
|
||||
case time.Time:
|
||||
if v.IsZero() || v.Unix() == 0 {
|
||||
return "-"
|
||||
}
|
||||
datetimeEscaped = html.EscapeString(v.Format(time.RFC3339))
|
||||
if format == "full" {
|
||||
textEscaped = html.EscapeString(v.Format("2006-01-02 15:04:05 -07:00"))
|
||||
} else {
|
||||
textEscaped = html.EscapeString(v.Format("2006-01-02"))
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported time type %T", datetime))
|
||||
}
|
||||
|
||||
attrs := make([]string, 0, 10+len(extraAttrs))
|
||||
attrs = append(attrs, extraAttrs...)
|
||||
attrs = append(attrs, `weekday=""`, `year="numeric"`)
|
||||
|
||||
switch format {
|
||||
case "short", "long": // date only
|
||||
attrs = append(attrs, `month="`+format+`"`, `day="numeric"`)
|
||||
return template.HTML(fmt.Sprintf(`<absolute-date %s date="%s">%s</absolute-date>`, strings.Join(attrs, " "), datetimeEscaped, textEscaped))
|
||||
case "full": // full date including time
|
||||
attrs = append(attrs, `format="datetime"`, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`, `data-tooltip-content`, `data-tooltip-interactive="true"`)
|
||||
return template.HTML(fmt.Sprintf(`<relative-time %s datetime="%s">%s</relative-time>`, strings.Join(attrs, " "), datetimeEscaped, textEscaped))
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported format %s", format))
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package timeutil
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDateTime(t *testing.T) {
|
||||
testTz, _ := time.LoadLocation("America/New_York")
|
||||
defer test.MockVariableValue(&setting.DefaultUILocation, testTz)()
|
||||
|
||||
refTimeStr := "2018-01-01T00:00:00Z"
|
||||
refDateStr := "2018-01-01"
|
||||
refTime, _ := time.Parse(time.RFC3339, refTimeStr)
|
||||
refTimeStamp := TimeStamp(refTime.Unix())
|
||||
|
||||
assert.EqualValues(t, "-", DateTime("short", nil))
|
||||
assert.EqualValues(t, "-", DateTime("short", 0))
|
||||
assert.EqualValues(t, "-", DateTime("short", time.Time{}))
|
||||
assert.EqualValues(t, "-", DateTime("short", TimeStamp(0)))
|
||||
|
||||
actual := DateTime("short", "invalid")
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="invalid">invalid</absolute-date>`, actual)
|
||||
|
||||
actual = DateTime("short", refTimeStr)
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01T00:00:00Z</absolute-date>`, actual)
|
||||
|
||||
actual = DateTime("short", refTime)
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01T00:00:00Z">2018-01-01</absolute-date>`, actual)
|
||||
|
||||
actual = DateTime("short", refDateStr)
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2018-01-01">2018-01-01</absolute-date>`, actual)
|
||||
|
||||
actual = DateTime("short", refTimeStamp)
|
||||
assert.EqualValues(t, `<absolute-date weekday="" year="numeric" month="short" day="numeric" date="2017-12-31T19:00:00-05:00">2017-12-31</absolute-date>`, actual)
|
||||
|
||||
actual = DateTime("full", refTimeStamp)
|
||||
assert.EqualValues(t, `<relative-time weekday="" year="numeric" format="datetime" month="short" day="numeric" hour="numeric" minute="numeric" second="numeric" data-tooltip-content data-tooltip-interactive="true" datetime="2017-12-31T19:00:00-05:00">2017-12-31 19:00:00 -05:00</relative-time>`, actual)
|
||||
}
|
|
@ -4,12 +4,9 @@
|
|||
package timeutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
)
|
||||
|
||||
|
@ -81,16 +78,11 @@ func computeTimeDiffFloor(diff int64, lang translation.Locale) (int64, string) {
|
|||
return diff, diffStr
|
||||
}
|
||||
|
||||
// MinutesToFriendly returns a user friendly string with number of minutes
|
||||
// MinutesToFriendly returns a user-friendly string with number of minutes
|
||||
// converted to hours and minutes.
|
||||
func MinutesToFriendly(minutes int, lang translation.Locale) string {
|
||||
duration := time.Duration(minutes) * time.Minute
|
||||
return TimeSincePro(time.Now().Add(-duration), lang)
|
||||
}
|
||||
|
||||
// TimeSincePro calculates the time interval and generate full user-friendly string.
|
||||
func TimeSincePro(then time.Time, lang translation.Locale) string {
|
||||
return timeSincePro(then, time.Now(), lang)
|
||||
return timeSincePro(time.Now().Add(-duration), time.Now(), lang)
|
||||
}
|
||||
|
||||
func timeSincePro(then, now time.Time, lang translation.Locale) string {
|
||||
|
@ -114,32 +106,3 @@ func timeSincePro(then, now time.Time, lang translation.Locale) string {
|
|||
}
|
||||
return strings.TrimPrefix(timeStr, ", ")
|
||||
}
|
||||
|
||||
func timeSinceUnix(then, now time.Time, _ translation.Locale) template.HTML {
|
||||
friendlyText := then.Format("2006-01-02 15:04:05 -07:00")
|
||||
|
||||
// document: https://github.com/github/relative-time-element
|
||||
attrs := `tense="past"`
|
||||
isFuture := now.Before(then)
|
||||
if isFuture {
|
||||
attrs = `tense="future"`
|
||||
}
|
||||
|
||||
// declare data-tooltip-content attribute to switch from "title" tooltip to "tippy" tooltip
|
||||
htm := fmt.Sprintf(`<relative-time prefix="" %s datetime="%s" data-tooltip-content data-tooltip-interactive="true">%s</relative-time>`,
|
||||
attrs, then.Format(time.RFC3339), friendlyText)
|
||||
return template.HTML(htm)
|
||||
}
|
||||
|
||||
// TimeSince renders relative time HTML given a time.Time
|
||||
func TimeSince(then time.Time, lang translation.Locale) template.HTML {
|
||||
if setting.UI.PreferredTimestampTense == "absolute" {
|
||||
return DateTime("full", then)
|
||||
}
|
||||
return timeSinceUnix(then, time.Now(), lang)
|
||||
}
|
||||
|
||||
// TimeSinceUnix renders relative time HTML given a TimeStamp
|
||||
func TimeSinceUnix(then TimeStamp, lang translation.Locale) template.HTML {
|
||||
return TimeSince(then.AsLocalTime(), lang)
|
||||
}
|
||||
|
|
|
@ -9,6 +9,12 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
type NopCloser struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (NopCloser) Close() error { return nil }
|
||||
|
||||
// ReadAtMost reads at most len(buf) bytes from r into buf.
|
||||
// It returns the number of bytes copied. n is only less than len(buf) if r provides fewer bytes.
|
||||
// If EOF or ErrUnexpectedEOF occurs while reading, err will be nil.
|
||||
|
|
|
@ -230,6 +230,25 @@ func IfZero[T comparable](v, def T) T {
|
|||
return v
|
||||
}
|
||||
|
||||
// OptionalArg helps the "optional argument" in Golang:
|
||||
//
|
||||
// func foo(optArg ...int) { return OptionalArg(optArg) }
|
||||
// calling `foo()` gets zero value 0, calling `foo(100)` gets 100
|
||||
// func bar(optArg ...int) { return OptionalArg(optArg, 42) }
|
||||
// calling `bar()` gets default value 42, calling `bar(100)` gets 100
|
||||
//
|
||||
// Passing more than 1 item to `optArg` or `defaultValue` is undefined behavior.
|
||||
// At the moment only the first item is used.
|
||||
func OptionalArg[T any](optArg []T, defaultValue ...T) (ret T) {
|
||||
if len(optArg) >= 1 {
|
||||
return optArg[0]
|
||||
}
|
||||
if len(defaultValue) >= 1 {
|
||||
return defaultValue[0]
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func ReserveLineBreakForTextarea(input string) string {
|
||||
// Since the content is from a form which is a textarea, the line endings are \r\n.
|
||||
// It's a standard behavior of HTML.
|
||||
|
|
|
@ -240,3 +240,16 @@ func TestReserveLineBreakForTextarea(t *testing.T) {
|
|||
assert.Equal(t, ReserveLineBreakForTextarea("test\r\ndata"), "test\ndata")
|
||||
assert.Equal(t, ReserveLineBreakForTextarea("test\r\ndata\r\n"), "test\ndata\n")
|
||||
}
|
||||
|
||||
func TestOptionalArg(t *testing.T) {
|
||||
foo := func(other any, optArg ...int) int {
|
||||
return OptionalArg(optArg)
|
||||
}
|
||||
bar := func(other any, optArg ...int) int {
|
||||
return OptionalArg(optArg, 42)
|
||||
}
|
||||
assert.Equal(t, 0, foo(nil))
|
||||
assert.Equal(t, 100, foo(nil, 100))
|
||||
assert.Equal(t, 42, bar(nil))
|
||||
assert.Equal(t, 100, bar(nil, 100))
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ const (
|
|||
HookEventRelease HookEventType = "release"
|
||||
HookEventPackage HookEventType = "package"
|
||||
HookEventSchedule HookEventType = "schedule"
|
||||
HookEventStatus HookEventType = "status"
|
||||
)
|
||||
|
||||
// Event returns the HookEventType as an event string
|
||||
|
|
|
@ -209,6 +209,10 @@ buttons.link.tooltip = Add a link
|
|||
buttons.list.unordered.tooltip = Add a bullet list
|
||||
buttons.list.ordered.tooltip = Add a numbered list
|
||||
buttons.list.task.tooltip = Add a list of tasks
|
||||
buttons.table.add.tooltip = Add a table
|
||||
buttons.table.add.insert = Add
|
||||
buttons.table.rows = Rows
|
||||
buttons.table.cols = Columns
|
||||
buttons.mention.tooltip = Mention a user or team
|
||||
buttons.ref.tooltip = Reference an issue or pull request
|
||||
buttons.switch_to_legacy.tooltip = Use the legacy editor instead
|
||||
|
|
4659
package-lock.json
generated
4659
package-lock.json
generated
File diff suppressed because it is too large
Load diff
74
package.json
74
package.json
|
@ -5,19 +5,19 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"@citation-js/core": "0.7.14",
|
||||
"@citation-js/plugin-bibtex": "0.7.14",
|
||||
"@citation-js/plugin-bibtex": "0.7.16",
|
||||
"@citation-js/plugin-csl": "0.7.14",
|
||||
"@citation-js/plugin-software-formats": "0.6.1",
|
||||
"@github/markdown-toolbar-element": "2.2.3",
|
||||
"@github/relative-time-element": "4.4.3",
|
||||
"@github/text-expander-element": "2.7.1",
|
||||
"@github/text-expander-element": "2.8.0",
|
||||
"@mcaptcha/vanilla-glue": "0.1.0-alpha-3",
|
||||
"@primer/octicons": "19.11.0",
|
||||
"@primer/octicons": "19.12.0",
|
||||
"@silverwind/vue3-calendar-heatmap": "2.0.6",
|
||||
"add-asset-webpack-plugin": "3.0.0",
|
||||
"ansi_up": "6.0.2",
|
||||
"asciinema-player": "3.8.0",
|
||||
"chart.js": "4.4.4",
|
||||
"asciinema-player": "3.8.1",
|
||||
"chart.js": "4.4.6",
|
||||
"chartjs-adapter-dayjs-4": "1.0.4",
|
||||
"chartjs-plugin-zoom": "2.0.1",
|
||||
"clippie": "4.1.3",
|
||||
|
@ -33,43 +33,43 @@
|
|||
"jquery": "3.7.1",
|
||||
"katex": "0.16.11",
|
||||
"license-checker-webpack-plugin": "0.2.1",
|
||||
"mermaid": "11.0.2",
|
||||
"mermaid": "11.4.0",
|
||||
"mini-css-extract-plugin": "2.9.1",
|
||||
"minimatch": "10.0.1",
|
||||
"monaco-editor": "0.51.0",
|
||||
"monaco-editor": "0.52.0",
|
||||
"monaco-editor-webpack-plugin": "7.1.0",
|
||||
"pdfobject": "2.3.0",
|
||||
"postcss": "8.4.41",
|
||||
"perfect-debounce": "1.0.0",
|
||||
"postcss": "8.4.47",
|
||||
"postcss-loader": "8.1.1",
|
||||
"postcss-nesting": "13.0.0",
|
||||
"sortablejs": "1.15.2",
|
||||
"postcss-nesting": "13.0.1",
|
||||
"sortablejs": "1.15.3",
|
||||
"swagger-ui-dist": "5.17.14",
|
||||
"tailwindcss": "3.4.10",
|
||||
"temporal-polyfill": "0.2.5",
|
||||
"tailwindcss": "3.4.14",
|
||||
"throttle-debounce": "5.0.2",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tippy.js": "6.3.7",
|
||||
"toastify-js": "1.12.0",
|
||||
"tributejs": "5.1.3",
|
||||
"typescript": "5.5.4",
|
||||
"typescript": "5.6.3",
|
||||
"uint8-to-base64": "0.2.0",
|
||||
"vanilla-colorful": "0.7.2",
|
||||
"vue": "3.5.12",
|
||||
"vue-bar-graph": "2.1.0",
|
||||
"vue-chartjs": "5.3.1",
|
||||
"vue-loader": "17.4.2",
|
||||
"webpack": "5.94.0",
|
||||
"webpack": "5.95.0",
|
||||
"webpack-cli": "5.1.4",
|
||||
"wrap-ansi": "9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "4.4.0",
|
||||
"@playwright/test": "1.46.1",
|
||||
"@stoplight/spectral-cli": "6.11.1",
|
||||
"@stylistic/eslint-plugin-js": "2.6.5",
|
||||
"@stylistic/stylelint-plugin": "3.0.1",
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "4.4.1",
|
||||
"@playwright/test": "1.48.2",
|
||||
"@stoplight/spectral-cli": "6.13.1",
|
||||
"@stylistic/eslint-plugin-js": "2.9.0",
|
||||
"@stylistic/stylelint-plugin": "3.1.1",
|
||||
"@types/dropzone": "5.7.8",
|
||||
"@types/jquery": "3.5.30",
|
||||
"@types/jquery": "3.5.32",
|
||||
"@types/katex": "0.16.7",
|
||||
"@types/license-checker-webpack-plugin": "0.2.4",
|
||||
"@types/pdfobject": "2.2.5",
|
||||
|
@ -78,39 +78,38 @@
|
|||
"@types/throttle-debounce": "5.0.2",
|
||||
"@types/tinycolor2": "1.4.6",
|
||||
"@types/toastify-js": "1.12.3",
|
||||
"@typescript-eslint/eslint-plugin": "8.3.0",
|
||||
"@typescript-eslint/parser": "8.3.0",
|
||||
"@vitejs/plugin-vue": "5.1.2",
|
||||
"@typescript-eslint/eslint-plugin": "8.12.2",
|
||||
"@typescript-eslint/parser": "8.12.2",
|
||||
"@vitejs/plugin-vue": "5.1.4",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-import-resolver-typescript": "3.6.3",
|
||||
"eslint-plugin-array-func": "4.0.0",
|
||||
"eslint-plugin-deprecation": "3.0.0",
|
||||
"eslint-plugin-github": "5.0.1",
|
||||
"eslint-plugin-github": "5.0.2",
|
||||
"eslint-plugin-i": "2.29.1",
|
||||
"eslint-plugin-no-jquery": "3.0.2",
|
||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||
"eslint-plugin-playwright": "1.6.2",
|
||||
"eslint-plugin-playwright": "2.0.0",
|
||||
"eslint-plugin-regexp": "2.6.0",
|
||||
"eslint-plugin-sonarjs": "2.0.1",
|
||||
"eslint-plugin-unicorn": "55.0.0",
|
||||
"eslint-plugin-sonarjs": "2.0.4",
|
||||
"eslint-plugin-unicorn": "56.0.0",
|
||||
"eslint-plugin-vitest": "0.4.1",
|
||||
"eslint-plugin-vitest-globals": "1.5.0",
|
||||
"eslint-plugin-vue": "9.27.0",
|
||||
"eslint-plugin-vue": "9.30.0",
|
||||
"eslint-plugin-vue-scoped-css": "2.8.1",
|
||||
"eslint-plugin-wc": "2.1.1",
|
||||
"happy-dom": "15.3.1",
|
||||
"markdownlint-cli": "0.41.0",
|
||||
"nolyfill": "1.0.39",
|
||||
"eslint-plugin-wc": "2.2.0",
|
||||
"happy-dom": "15.7.4",
|
||||
"markdownlint-cli": "0.42.0",
|
||||
"nolyfill": "1.0.42",
|
||||
"postcss-html": "1.7.0",
|
||||
"stylelint": "16.8.1",
|
||||
"stylelint-declaration-block-no-ignored-properties": "2.8.0",
|
||||
"stylelint-declaration-strict-value": "1.10.6",
|
||||
"stylelint-value-no-unknown-custom-properties": "6.0.1",
|
||||
"svgo": "3.3.2",
|
||||
"type-fest": "4.26.0",
|
||||
"type-fest": "4.26.1",
|
||||
"updates": "16.4.0",
|
||||
"vite-string-plugin": "1.3.4",
|
||||
"vitest": "2.0.5"
|
||||
"vitest": "2.1.4"
|
||||
},
|
||||
"browserslist": [
|
||||
"defaults"
|
||||
|
@ -135,6 +134,9 @@
|
|||
"array.prototype.findlast": "npm:@nolyfill/array.prototype.findlast@^1",
|
||||
"array.prototype.tosorted": "npm:@nolyfill/array.prototype.tosorted@^1",
|
||||
"string.prototype.matchall": "npm:@nolyfill/string.prototype.matchall@^1",
|
||||
"string.prototype.repeat": "npm:@nolyfill/string.prototype.repeat@^1"
|
||||
"string.prototype.repeat": "npm:@nolyfill/string.prototype.repeat@^1",
|
||||
"safe-buffer": "npm:@nolyfill/safe-buffer@^1",
|
||||
"safer-buffer": "npm:@nolyfill/safer-buffer@^1",
|
||||
"string.prototype.trimend": "npm:@nolyfill/string.prototype.trimend@^1"
|
||||
}
|
||||
}
|
||||
|
|
348
poetry.lock
generated
348
poetry.lock
generated
|
@ -1,4 +1,4 @@
|
|||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
|
@ -42,28 +42,28 @@ six = ">=1.13.0"
|
|||
|
||||
[[package]]
|
||||
name = "djlint"
|
||||
version = "1.34.2"
|
||||
version = "1.35.3"
|
||||
description = "HTML Template Linter and Formatter"
|
||||
optional = false
|
||||
python-versions = "<4.0.0,>=3.8.0"
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "djlint-1.34.2-py3-none-any.whl", hash = "sha256:4825389e395eb77371857c77f547fa5ebd1a644b1bc4fe9fed19d49a2786b9e5"},
|
||||
{file = "djlint-1.34.2.tar.gz", hash = "sha256:db9b2e59203a452b83532499bc243c749279090b905cc1f657973f78e7a31ddd"},
|
||||
{file = "djlint-1.35.3-py3-none-any.whl", hash = "sha256:bf2f23798909f9c5a110925c369538383de0141f9a2be37ee0d26422d41b7543"},
|
||||
{file = "djlint-1.35.3.tar.gz", hash = "sha256:780ea3e25662fca89033fa96ecf656099954d6f81dce039eac90f4bba3cbe850"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=8.0.1,<9.0.0"
|
||||
colorama = ">=0.4.4,<0.5.0"
|
||||
cssbeautifier = ">=1.14.4,<2.0.0"
|
||||
html-tag-names = ">=0.1.2,<0.2.0"
|
||||
html-void-elements = ">=0.1.0,<0.2.0"
|
||||
jsbeautifier = ">=1.14.4,<2.0.0"
|
||||
json5 = ">=0.9.11,<0.10.0"
|
||||
pathspec = ">=0.12.0,<0.13.0"
|
||||
PyYAML = ">=6.0,<7.0"
|
||||
regex = ">=2023.0.0,<2024.0.0"
|
||||
tomli = {version = ">=2.0.1,<3.0.0", markers = "python_version < \"3.11\""}
|
||||
tqdm = ">=4.62.2,<5.0.0"
|
||||
click = ">=8.0.1"
|
||||
colorama = ">=0.4.4"
|
||||
cssbeautifier = ">=1.14.4"
|
||||
html-tag-names = ">=0.1.2"
|
||||
html-void-elements = ">=0.1"
|
||||
jsbeautifier = ">=1.14.4"
|
||||
json5 = ">=0.9.11"
|
||||
pathspec = ">=0.12"
|
||||
pyyaml = ">=6"
|
||||
regex = ">=2023"
|
||||
tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""}
|
||||
tqdm = ">=4.62.2"
|
||||
|
||||
[[package]]
|
||||
name = "editorconfig"
|
||||
|
@ -135,163 +135,167 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.1"
|
||||
version = "6.0.2"
|
||||
description = "YAML parser and emitter for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"},
|
||||
{file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"},
|
||||
{file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"},
|
||||
{file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"},
|
||||
{file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"},
|
||||
{file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"},
|
||||
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"},
|
||||
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"},
|
||||
{file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"},
|
||||
{file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"},
|
||||
{file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"},
|
||||
{file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"},
|
||||
{file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"},
|
||||
{file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "2023.12.25"
|
||||
version = "2024.9.11"
|
||||
description = "Alternative regular expression module, to replace re."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "regex-2023.12.25-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0694219a1d54336fd0445ea382d49d36882415c0134ee1e8332afd1529f0baa5"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b014333bd0217ad3d54c143de9d4b9a3ca1c5a29a6d0d554952ea071cff0f1f8"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d865984b3f71f6d0af64d0d88f5733521698f6c16f445bb09ce746c92c97c586"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e0eabac536b4cc7f57a5f3d095bfa557860ab912f25965e08fe1545e2ed8b4c"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c25a8ad70e716f96e13a637802813f65d8a6760ef48672aa3502f4c24ea8b400"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9b6d73353f777630626f403b0652055ebfe8ff142a44ec2cf18ae470395766e"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9cc99d6946d750eb75827cb53c4371b8b0fe89c733a94b1573c9dd16ea6c9e4"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88d1f7bef20c721359d8675f7d9f8e414ec5003d8f642fdfd8087777ff7f94b5"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cb3fe77aec8f1995611f966d0c656fdce398317f850d0e6e7aebdfe61f40e1cd"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7aa47c2e9ea33a4a2a05f40fcd3ea36d73853a2aae7b4feab6fc85f8bf2c9704"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:df26481f0c7a3f8739fecb3e81bc9da3fcfae34d6c094563b9d4670b047312e1"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c40281f7d70baf6e0db0c2f7472b31609f5bc2748fe7275ea65a0b4601d9b392"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:d94a1db462d5690ebf6ae86d11c5e420042b9898af5dcf278bd97d6bda065423"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ba1b30765a55acf15dce3f364e4928b80858fa8f979ad41f862358939bdd1f2f"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-win32.whl", hash = "sha256:150c39f5b964e4d7dba46a7962a088fbc91f06e606f023ce57bb347a3b2d4630"},
|
||||
{file = "regex-2023.12.25-cp310-cp310-win_amd64.whl", hash = "sha256:09da66917262d9481c719599116c7dc0c321ffcec4b1f510c4f8a066f8768105"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1b9d811f72210fa9306aeb88385b8f8bcef0dfbf3873410413c00aa94c56c2b6"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d902a43085a308cef32c0d3aea962524b725403fd9373dea18110904003bac97"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d166eafc19f4718df38887b2bbe1467a4f74a9830e8605089ea7a30dd4da8887"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7ad32824b7f02bb3c9f80306d405a1d9b7bb89362d68b3c5a9be53836caebdb"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:636ba0a77de609d6510235b7f0e77ec494d2657108f777e8765efc060094c98c"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fda75704357805eb953a3ee15a2b240694a9a514548cd49b3c5124b4e2ad01b"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f72cbae7f6b01591f90814250e636065850c5926751af02bb48da94dfced7baa"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db2a0b1857f18b11e3b0e54ddfefc96af46b0896fb678c85f63fb8c37518b3e7"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:7502534e55c7c36c0978c91ba6f61703faf7ce733715ca48f499d3dbbd7657e0"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e8c7e08bb566de4faaf11984af13f6bcf6a08f327b13631d41d62592681d24fe"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:283fc8eed679758de38fe493b7d7d84a198b558942b03f017b1f94dda8efae80"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:f44dd4d68697559d007462b0a3a1d9acd61d97072b71f6d1968daef26bc744bd"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:67d3ccfc590e5e7197750fcb3a2915b416a53e2de847a728cfa60141054123d4"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-win32.whl", hash = "sha256:68191f80a9bad283432385961d9efe09d783bcd36ed35a60fb1ff3f1ec2efe87"},
|
||||
{file = "regex-2023.12.25-cp311-cp311-win_amd64.whl", hash = "sha256:7d2af3f6b8419661a0c421584cfe8aaec1c0e435ce7e47ee2a97e344b98f794f"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8a0ccf52bb37d1a700375a6b395bff5dd15c50acb745f7db30415bae3c2b0715"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c3c4a78615b7762740531c27cf46e2f388d8d727d0c0c739e72048beb26c8a9d"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad83e7545b4ab69216cef4cc47e344d19622e28aabec61574b20257c65466d6a"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7a635871143661feccce3979e1727c4e094f2bdfd3ec4b90dfd4f16f571a87a"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d498eea3f581fbe1b34b59c697512a8baef88212f92e4c7830fcc1499f5b45a5"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:43f7cd5754d02a56ae4ebb91b33461dc67be8e3e0153f593c509e21d219c5060"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51f4b32f793812714fd5307222a7f77e739b9bc566dc94a18126aba3b92b98a3"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba99d8077424501b9616b43a2d208095746fb1284fc5ba490139651f971d39d9"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4bfc2b16e3ba8850e0e262467275dd4d62f0d045e0e9eda2bc65078c0110a11f"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8c2c19dae8a3eb0ea45a8448356ed561be843b13cbc34b840922ddf565498c1c"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:60080bb3d8617d96f0fb7e19796384cc2467447ef1c491694850ebd3670bc457"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b77e27b79448e34c2c51c09836033056a0547aa360c45eeeb67803da7b0eedaf"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:518440c991f514331f4850a63560321f833979d145d7d81186dbe2f19e27ae3d"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-win32.whl", hash = "sha256:e2610e9406d3b0073636a3a2e80db05a02f0c3169b5632022b4e81c0364bcda5"},
|
||||
{file = "regex-2023.12.25-cp312-cp312-win_amd64.whl", hash = "sha256:cc37b9aeebab425f11f27e5e9e6cf580be7206c6582a64467a14dda211abc232"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:da695d75ac97cb1cd725adac136d25ca687da4536154cdc2815f576e4da11c69"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d126361607b33c4eb7b36debc173bf25d7805847346dd4d99b5499e1fef52bc7"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4719bb05094d7d8563a450cf8738d2e1061420f79cfcc1fa7f0a44744c4d8f73"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5dd58946bce44b53b06d94aa95560d0b243eb2fe64227cba50017a8d8b3cd3e2"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22a86d9fff2009302c440b9d799ef2fe322416d2d58fc124b926aa89365ec482"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2aae8101919e8aa05ecfe6322b278f41ce2994c4a430303c4cd163fef746e04f"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e692296c4cc2873967771345a876bcfc1c547e8dd695c6b89342488b0ea55cd8"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:263ef5cc10979837f243950637fffb06e8daed7f1ac1e39d5910fd29929e489a"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:d6f7e255e5fa94642a0724e35406e6cb7001c09d476ab5fce002f652b36d0c39"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:88ad44e220e22b63b0f8f81f007e8abbb92874d8ced66f32571ef8beb0643b2b"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3a17d3ede18f9cedcbe23d2daa8a2cd6f59fe2bf082c567e43083bba3fb00347"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d15b274f9e15b1a0b7a45d2ac86d1f634d983ca40d6b886721626c47a400bf39"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-win32.whl", hash = "sha256:ed19b3a05ae0c97dd8f75a5d8f21f7723a8c33bbc555da6bbe1f96c470139d3c"},
|
||||
{file = "regex-2023.12.25-cp37-cp37m-win_amd64.whl", hash = "sha256:a6d1047952c0b8104a1d371f88f4ab62e6275567d4458c1e26e9627ad489b445"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:b43523d7bc2abd757119dbfb38af91b5735eea45537ec6ec3a5ec3f9562a1c53"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:efb2d82f33b2212898f1659fb1c2e9ac30493ac41e4d53123da374c3b5541e64"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b7fca9205b59c1a3d5031f7e64ed627a1074730a51c2a80e97653e3e9fa0d415"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:086dd15e9435b393ae06f96ab69ab2d333f5d65cbe65ca5a3ef0ec9564dfe770"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e81469f7d01efed9b53740aedd26085f20d49da65f9c1f41e822a33992cb1590"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:34e4af5b27232f68042aa40a91c3b9bb4da0eeb31b7632e0091afc4310afe6cb"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9852b76ab558e45b20bf1893b59af64a28bd3820b0c2efc80e0a70a4a3ea51c1"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ff100b203092af77d1a5a7abe085b3506b7eaaf9abf65b73b7d6905b6cb76988"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cc038b2d8b1470364b1888a98fd22d616fba2b6309c5b5f181ad4483e0017861"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:094ba386bb5c01e54e14434d4caabf6583334090865b23ef58e0424a6286d3dc"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5cd05d0f57846d8ba4b71d9c00f6f37d6b97d5e5ef8b3c3840426a475c8f70f4"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:9aa1a67bbf0f957bbe096375887b2505f5d8ae16bf04488e8b0f334c36e31360"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:98a2636994f943b871786c9e82bfe7883ecdaba2ef5df54e1450fa9869d1f756"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37f8e93a81fc5e5bd8db7e10e62dc64261bcd88f8d7e6640aaebe9bc180d9ce2"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-win32.whl", hash = "sha256:d78bd484930c1da2b9679290a41cdb25cc127d783768a0369d6b449e72f88beb"},
|
||||
{file = "regex-2023.12.25-cp38-cp38-win_amd64.whl", hash = "sha256:b521dcecebc5b978b447f0f69b5b7f3840eac454862270406a39837ffae4e697"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f7bc09bc9c29ebead055bcba136a67378f03d66bf359e87d0f7c759d6d4ffa31"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e14b73607d6231f3cc4622809c196b540a6a44e903bcfad940779c80dffa7be7"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9eda5f7a50141291beda3edd00abc2d4a5b16c29c92daf8d5bd76934150f3edc"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cc6bb9aa69aacf0f6032c307da718f61a40cf970849e471254e0e91c56ffca95"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:298dc6354d414bc921581be85695d18912bea163a8b23cac9a2562bbcd5088b1"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2f4e475a80ecbd15896a976aa0b386c5525d0ed34d5c600b6d3ebac0a67c7ddf"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:531ac6cf22b53e0696f8e1d56ce2396311254eb806111ddd3922c9d937151dae"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22f3470f7524b6da61e2020672df2f3063676aff444db1daa283c2ea4ed259d6"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:89723d2112697feaa320c9d351e5f5e7b841e83f8b143dba8e2d2b5f04e10923"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0ecf44ddf9171cd7566ef1768047f6e66975788258b1c6c6ca78098b95cf9a3d"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:905466ad1702ed4acfd67a902af50b8db1feeb9781436372261808df7a2a7bca"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:4558410b7a5607a645e9804a3e9dd509af12fb72b9825b13791a37cd417d73a5"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7e316026cc1095f2a3e8cc012822c99f413b702eaa2ca5408a513609488cb62f"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3b1de218d5375cd6ac4b5493e0b9f3df2be331e86520f23382f216c137913d20"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-win32.whl", hash = "sha256:11a963f8e25ab5c61348d090bf1b07f1953929c13bd2309a0662e9ff680763c9"},
|
||||
{file = "regex-2023.12.25-cp39-cp39-win_amd64.whl", hash = "sha256:e693e233ac92ba83a87024e1d32b5f9ab15ca55ddd916d878146f4e3406b5c91"},
|
||||
{file = "regex-2023.12.25.tar.gz", hash = "sha256:29171aa128da69afdf4bde412d5bedc335f2ca8fcfe4489038577d05f16181e5"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1494fa8725c285a81d01dc8c06b55287a1ee5e0e382d8413adc0a9197aac6408"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0e12c481ad92d129c78f13a2a3662317e46ee7ef96c94fd332e1c29131875b7d"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:16e13a7929791ac1216afde26f712802e3df7bf0360b32e4914dca3ab8baeea5"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46989629904bad940bbec2106528140a218b4a36bb3042d8406980be1941429c"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a906ed5e47a0ce5f04b2c981af1c9acf9e8696066900bf03b9d7879a6f679fc8"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9a091b0550b3b0207784a7d6d0f1a00d1d1c8a11699c1a4d93db3fbefc3ad35"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ddcd9a179c0a6fa8add279a4444015acddcd7f232a49071ae57fa6e278f1f71"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6b41e1adc61fa347662b09398e31ad446afadff932a24807d3ceb955ed865cc8"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ced479f601cd2f8ca1fd7b23925a7e0ad512a56d6e9476f79b8f381d9d37090a"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:635a1d96665f84b292e401c3d62775851aedc31d4f8784117b3c68c4fcd4118d"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0256beda696edcf7d97ef16b2a33a8e5a875affd6fa6567b54f7c577b30a137"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3ce4f1185db3fbde8ed8aa223fc9620f276c58de8b0d4f8cc86fd1360829edb6"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:09d77559e80dcc9d24570da3745ab859a9cf91953062e4ab126ba9d5993688ca"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7a22ccefd4db3f12b526eccb129390942fe874a3a9fdbdd24cf55773a1faab1a"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-win32.whl", hash = "sha256:f745ec09bc1b0bd15cfc73df6fa4f726dcc26bb16c23a03f9e3367d357eeedd0"},
|
||||
{file = "regex-2024.9.11-cp310-cp310-win_amd64.whl", hash = "sha256:01c2acb51f8a7d6494c8c5eafe3d8e06d76563d8a8a4643b37e9b2dd8a2ff623"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2cce2449e5927a0bf084d346da6cd5eb016b2beca10d0013ab50e3c226ffc0df"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3b37fa423beefa44919e009745ccbf353d8c981516e807995b2bd11c2c77d268"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:64ce2799bd75039b480cc0360907c4fb2f50022f030bf9e7a8705b636e408fad"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a4cc92bb6db56ab0c1cbd17294e14f5e9224f0cc6521167ef388332604e92679"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d05ac6fa06959c4172eccd99a222e1fbf17b5670c4d596cb1e5cde99600674c4"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:040562757795eeea356394a7fb13076ad4f99d3c62ab0f8bdfb21f99a1f85664"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6113c008a7780792efc80f9dfe10ba0cd043cbf8dc9a76ef757850f51b4edc50"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e5fb5f77c8745a60105403a774fe2c1759b71d3e7b4ca237a5e67ad066c7199"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:54d9ff35d4515debf14bc27f1e3b38bfc453eff3220f5bce159642fa762fe5d4"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:df5cbb1fbc74a8305b6065d4ade43b993be03dbe0f8b30032cced0d7740994bd"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:7fb89ee5d106e4a7a51bce305ac4efb981536301895f7bdcf93ec92ae0d91c7f"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:a738b937d512b30bf75995c0159c0ddf9eec0775c9d72ac0202076c72f24aa96"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e28f9faeb14b6f23ac55bfbbfd3643f5c7c18ede093977f1df249f73fd22c7b1"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-win32.whl", hash = "sha256:18e707ce6c92d7282dfce370cd205098384b8ee21544e7cb29b8aab955b66fa9"},
|
||||
{file = "regex-2024.9.11-cp311-cp311-win_amd64.whl", hash = "sha256:313ea15e5ff2a8cbbad96ccef6be638393041b0a7863183c2d31e0c6116688cf"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b0d0a6c64fcc4ef9c69bd5b3b3626cc3776520a1637d8abaa62b9edc147a58f7"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:49b0e06786ea663f933f3710a51e9385ce0cba0ea56b67107fd841a55d56a231"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5b513b6997a0b2f10e4fd3a1313568e373926e8c252bd76c960f96fd039cd28d"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee439691d8c23e76f9802c42a95cfeebf9d47cf4ffd06f18489122dbb0a7ad64"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8f877c89719d759e52783f7fe6e1c67121076b87b40542966c02de5503ace42"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:23b30c62d0f16827f2ae9f2bb87619bc4fba2044911e2e6c2eb1af0161cdb766"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ab7824093d8f10d44330fe1e6493f756f252d145323dd17ab6b48733ff6c0a"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dee5b4810a89447151999428fe096977346cf2f29f4d5e29609d2e19e0199c9"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:98eeee2f2e63edae2181c886d7911ce502e1292794f4c5ee71e60e23e8d26b5d"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:57fdd2e0b2694ce6fc2e5ccf189789c3e2962916fb38779d3e3521ff8fe7a822"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d552c78411f60b1fdaafd117a1fca2f02e562e309223b9d44b7de8be451ec5e0"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a0b2b80321c2ed3fcf0385ec9e51a12253c50f146fddb2abbb10f033fe3d049a"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:18406efb2f5a0e57e3a5881cd9354c1512d3bb4f5c45d96d110a66114d84d23a"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-win32.whl", hash = "sha256:e464b467f1588e2c42d26814231edecbcfe77f5ac414d92cbf4e7b55b2c2a776"},
|
||||
{file = "regex-2024.9.11-cp312-cp312-win_amd64.whl", hash = "sha256:9e8719792ca63c6b8340380352c24dcb8cd7ec49dae36e963742a275dfae6009"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c157bb447303070f256e084668b702073db99bbb61d44f85d811025fcf38f784"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4db21ece84dfeefc5d8a3863f101995de646c6cb0536952c321a2650aa202c36"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:220e92a30b426daf23bb67a7962900ed4613589bab80382be09b48896d211e92"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eb1ae19e64c14c7ec1995f40bd932448713d3c73509e82d8cd7744dc00e29e86"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f47cd43a5bfa48f86925fe26fbdd0a488ff15b62468abb5d2a1e092a4fb10e85"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9d4a76b96f398697fe01117093613166e6aa8195d63f1b4ec3f21ab637632963"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ea51dcc0835eea2ea31d66456210a4e01a076d820e9039b04ae8d17ac11dee6"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7aaa315101c6567a9a45d2839322c51c8d6e81f67683d529512f5bcfb99c802"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c57d08ad67aba97af57a7263c2d9006d5c404d721c5f7542f077f109ec2a4a29"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8404bf61298bb6f8224bb9176c1424548ee1181130818fcd2cbffddc768bed8"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:dd4490a33eb909ef5078ab20f5f000087afa2a4daa27b4c072ccb3cb3050ad84"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:eee9130eaad130649fd73e5cd92f60e55708952260ede70da64de420cdcad554"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6a2644a93da36c784e546de579ec1806bfd2763ef47babc1b03d765fe560c9f8"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-win32.whl", hash = "sha256:e997fd30430c57138adc06bba4c7c2968fb13d101e57dd5bb9355bf8ce3fa7e8"},
|
||||
{file = "regex-2024.9.11-cp313-cp313-win_amd64.whl", hash = "sha256:042c55879cfeb21a8adacc84ea347721d3d83a159da6acdf1116859e2427c43f"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:35f4a6f96aa6cb3f2f7247027b07b15a374f0d5b912c0001418d1d55024d5cb4"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:55b96e7ce3a69a8449a66984c268062fbaa0d8ae437b285428e12797baefce7e"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb130fccd1a37ed894824b8c046321540263013da72745d755f2d35114b81a60"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:323c1f04be6b2968944d730e5c2091c8c89767903ecaa135203eec4565ed2b2b"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be1c8ed48c4c4065ecb19d882a0ce1afe0745dfad8ce48c49586b90a55f02366"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5b029322e6e7b94fff16cd120ab35a253236a5f99a79fb04fda7ae71ca20ae8"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6fff13ef6b5f29221d6904aa816c34701462956aa72a77f1f151a8ec4f56aeb"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:587d4af3979376652010e400accc30404e6c16b7df574048ab1f581af82065e4"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:079400a8269544b955ffa9e31f186f01d96829110a3bf79dc338e9910f794fca"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f9268774428ec173654985ce55fc6caf4c6d11ade0f6f914d48ef4719eb05ebb"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:23f9985c8784e544d53fc2930fc1ac1a7319f5d5332d228437acc9f418f2f168"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:ae2941333154baff9838e88aa71c1d84f4438189ecc6021a12c7573728b5838e"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e93f1c331ca8e86fe877a48ad64e77882c0c4da0097f2212873a69bbfea95d0c"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:846bc79ee753acf93aef4184c040d709940c9d001029ceb7b7a52747b80ed2dd"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-win32.whl", hash = "sha256:c94bb0a9f1db10a1d16c00880bdebd5f9faf267273b8f5bd1878126e0fbde771"},
|
||||
{file = "regex-2024.9.11-cp38-cp38-win_amd64.whl", hash = "sha256:2b08fce89fbd45664d3df6ad93e554b6c16933ffa9d55cb7e01182baaf971508"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:07f45f287469039ffc2c53caf6803cd506eb5f5f637f1d4acb37a738f71dd066"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4838e24ee015101d9f901988001038f7f0d90dc0c3b115541a1365fb439add62"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6edd623bae6a737f10ce853ea076f56f507fd7726bee96a41ee3d68d347e4d16"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c69ada171c2d0e97a4b5aa78fbb835e0ffbb6b13fc5da968c09811346564f0d3"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02087ea0a03b4af1ed6ebab2c54d7118127fee8d71b26398e8e4b05b78963199"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69dee6a020693d12a3cf892aba4808fe168d2a4cef368eb9bf74f5398bfd4ee8"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:297f54910247508e6e5cae669f2bc308985c60540a4edd1c77203ef19bfa63ca"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ecea58b43a67b1b79805f1a0255730edaf5191ecef84dbc4cc85eb30bc8b63b9"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:eab4bb380f15e189d1313195b062a6aa908f5bd687a0ceccd47c8211e9cf0d4a"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0cbff728659ce4bbf4c30b2a1be040faafaa9eca6ecde40aaff86f7889f4ab39"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:54c4a097b8bc5bb0dfc83ae498061d53ad7b5762e00f4adaa23bee22b012e6ba"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:73d6d2f64f4d894c96626a75578b0bf7d9e56dcda8c3d037a2118fdfe9b1c664"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:e53b5fbab5d675aec9f0c501274c467c0f9a5d23696cfc94247e1fb56501ed89"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ffbcf9221e04502fc35e54d1ce9567541979c3fdfb93d2c554f0ca583a19b35"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-win32.whl", hash = "sha256:e4c22e1ac1f1ec1e09f72e6c44d8f2244173db7eb9629cc3a346a8d7ccc31142"},
|
||||
{file = "regex-2024.9.11-cp39-cp39-win_amd64.whl", hash = "sha256:faa3c142464efec496967359ca99696c896c591c56c53506bac1ad465f66e919"},
|
||||
{file = "regex-2024.9.11.tar.gz", hash = "sha256:6c188c307e8433bcb63dc1915022deb553b4203a70722fc542c363bf120a01fd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -307,24 +311,24 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
version = "2.0.2"
|
||||
description = "A lil' TOML parser"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||
{file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"},
|
||||
{file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tqdm"
|
||||
version = "4.66.4"
|
||||
version = "4.66.6"
|
||||
description = "Fast, Extensible Progress Meter"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"},
|
||||
{file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"},
|
||||
{file = "tqdm-4.66.6-py3-none-any.whl", hash = "sha256:223e8b5359c2efc4b30555531f09e9f2f3589bcd7fdd389271191031b49b7a63"},
|
||||
{file = "tqdm-4.66.6.tar.gz", hash = "sha256:4bdd694238bef1485ce839d67967ab50af8f9272aab687c0d7702a01da0be090"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -357,4 +361,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "af89bce0c442463621b6e536f9b94c31e188e1662c2caa84372c0858a2ee7d5c"
|
||||
content-hash = "180bc880a782085c502016f7cdc112a7d24f1de7ca9a95edc0448bb8cd1afe3b"
|
||||
|
|
2
public/assets/img/svg/octicon-thumbsdown.svg
generated
2
public/assets/img/svg/octicon-thumbsdown.svg
generated
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg octicon-thumbsdown" width="16" height="16" aria-hidden="true"><path d="M7.083 15.986c-.763-.087-1.499-.295-2.011-.884-.504-.581-.655-1.378-.655-2.299 0-.468.087-1.12.157-1.638l.015-.112H3.167c-.603 0-1.174-.086-1.669-.334a2.4 2.4 0 0 1-1.136-1.2c-.454-.998-.438-2.447-.188-4.316l.04-.306C.32 4.108.41 3.424.526 2.864c.132-.63.316-1.209.669-1.672C1.947.205 3.211.053 4.917.053c1.848 0 3.234.332 4.388.652l.474.133c.658.187 1.201.341 1.726.415a1.75 1.75 0 0 1 1.662-1.2h1c.966 0 1.75.784 1.75 1.75v7.5a1.75 1.75 0 0 1-1.75 1.75h-1a1.75 1.75 0 0 1-1.514-.872c-.259.105-.59.268-.919.508-.671.491-1.317 1.285-1.317 2.614v.5c0 1.201-.994 2.336-2.334 2.183m4.334-13.232c-.706-.089-1.39-.284-2.072-.479l-.441-.125c-1.096-.304-2.335-.597-3.987-.597-1.794 0-2.28.222-2.529.548-.147.193-.275.505-.393 1.07-.105.502-.188 1.124-.295 1.93l-.04.3c-.25 1.882-.19 2.933.067 3.497a.92.92 0 0 0 .443.48c.208.104.52.175.997.175h1.75c.685 0 1.295.577 1.205 1.335q-.034.29-.075.586c-.066.488-.13.97-.13 1.329 0 .808.144 1.15.288 1.316.137.157.401.303 1.048.377.307.035.664-.237.664-.693v-.5c0-1.922.978-3.127 1.932-3.825a5.9 5.9 0 0 1 1.568-.809Zm1.75 6.798h1a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25h-1a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg octicon-thumbsdown" width="16" height="16" aria-hidden="true"><path d="M7.653 15.369a.75.75 0 0 1-.776.371l-.238-.04a3.25 3.25 0 0 1-2.591-4.099L4.506 10h-.665A3.25 3.25 0 0 1 .723 5.833l1.135-3.859A2.75 2.75 0 0 1 4.482 0H9.43c.78.003 1.538.25 2.168.702A1.75 1.75 0 0 1 12.989 0h1.272A1.75 1.75 0 0 1 16 1.75v6.5A1.75 1.75 0 0 1 14.25 10h-3.417a.25.25 0 0 0-.217.127ZM11.25 2.351l-.396-.33a2.25 2.25 0 0 0-1.44-.521H4.496a1.25 1.25 0 0 0-1.199.897L2.162 6.256A1.75 1.75 0 0 0 3.841 8.5H5.5a.75.75 0 0 1 .721.956l-.731 2.558a1.75 1.75 0 0 0 1.127 2.14L9.31 9.389a1.75 1.75 0 0 1 1.523-.889h.417Zm1.5 6.149h1.5a.25.25 0 0 0 .25-.25v-6.5a.25.25 0 0 0-.25-.25H13a.25.25 0 0 0-.25.25Z"/></svg>
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 760 B |
2
public/assets/img/svg/octicon-thumbsup.svg
generated
2
public/assets/img/svg/octicon-thumbsup.svg
generated
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg octicon-thumbsup" width="16" height="16" aria-hidden="true"><path d="M8.834.066c.763.087 1.5.295 2.01.884.505.581.656 1.378.656 2.3 0 .467-.087 1.119-.157 1.637L11.328 5h1.422c.603 0 1.174.085 1.668.333.508.254.911.679 1.137 1.2.453.998.438 2.447.188 4.316l-.04.306c-.105.79-.195 1.473-.313 2.033-.131.63-.315 1.209-.668 1.672C13.97 15.847 12.706 16 11 16c-1.848 0-3.234-.333-4.388-.653q-.247-.068-.475-.133c-.658-.186-1.2-.34-1.725-.415A1.75 1.75 0 0 1 2.75 16h-1A1.75 1.75 0 0 1 0 14.25v-7.5C0 5.784.784 5 1.75 5h1a1.75 1.75 0 0 1 1.514.872c.258-.105.59-.268.918-.508C5.853 4.874 6.5 4.079 6.5 2.75v-.5c0-1.202.994-2.337 2.334-2.184M4.5 13.3c.705.088 1.39.284 2.072.478l.441.125c1.096.305 2.334.598 3.987.598 1.794 0 2.28-.223 2.528-.549.147-.193.276-.505.394-1.07.105-.502.188-1.124.295-1.93l.04-.3c.25-1.882.189-2.933-.068-3.497a.92.92 0 0 0-.442-.48c-.208-.104-.52-.174-.997-.174H11c-.686 0-1.295-.577-1.206-1.336q.036-.29.076-.586c.065-.488.13-.97.13-1.328 0-.809-.144-1.15-.288-1.316-.137-.158-.402-.304-1.048-.378C8.357 1.521 8 1.793 8 2.25v.5c0 1.922-.978 3.128-1.933 3.825a5.8 5.8 0 0 1-1.567.81ZM2.75 6.5h-1a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h1a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" class="svg octicon-thumbsup" width="16" height="16" aria-hidden="true"><path d="M8.347.631A.75.75 0 0 1 9.123.26l.238.04a3.25 3.25 0 0 1 2.591 4.098L11.494 6h.665a3.25 3.25 0 0 1 3.118 4.167l-1.135 3.859A2.75 2.75 0 0 1 11.503 16H6.586a3.75 3.75 0 0 1-2.184-.702A1.75 1.75 0 0 1 3 16H1.75A1.75 1.75 0 0 1 0 14.25v-6.5C0 6.784.784 6 1.75 6h3.417a.25.25 0 0 0 .217-.127ZM4.75 13.649l.396.33c.404.337.914.521 1.44.521h4.917a1.25 1.25 0 0 0 1.2-.897l1.135-3.859A1.75 1.75 0 0 0 12.159 7.5H10.5a.75.75 0 0 1-.721-.956l.731-2.558a1.75 1.75 0 0 0-1.127-2.14L6.69 6.611a1.75 1.75 0 0 1-1.523.889H4.75ZM3.25 7.5h-1.5a.25.25 0 0 0-.25.25v6.5c0 .138.112.25.25.25H3a.25.25 0 0 0 .25-.25Z"/></svg>
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 744 B |
|
@ -5,7 +5,7 @@ package-mode = false
|
|||
python = "^3.10"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
djlint = "1.34.2"
|
||||
djlint = "1.35.3"
|
||||
yamllint = "1.35.1"
|
||||
|
||||
[tool.djlint]
|
||||
|
|
|
@ -425,7 +425,7 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) {
|
|||
for _, artifact := range artifacts {
|
||||
var downloadURL string
|
||||
if setting.Actions.ArtifactStorage.ServeDirect() {
|
||||
u, err := ar.fs.URL(artifact.StoragePath, artifact.ArtifactName)
|
||||
u, err := ar.fs.URL(artifact.StoragePath, artifact.ArtifactName, nil)
|
||||
if err != nil && !errors.Is(err, storage.ErrURLNotSupported) {
|
||||
log.Error("Error getting serve direct url: %v", err)
|
||||
}
|
||||
|
|
|
@ -517,7 +517,7 @@ func (r *artifactV4Routes) getSignedArtifactURL(ctx *ArtifactContext) {
|
|||
respData := GetSignedArtifactURLResponse{}
|
||||
|
||||
if setting.Actions.ArtifactStorage.ServeDirect() {
|
||||
u, err := storage.ActionsArtifacts.URL(artifact.StoragePath, artifact.ArtifactPath)
|
||||
u, err := storage.ActionsArtifacts.URL(artifact.StoragePath, artifact.ArtifactPath, nil)
|
||||
if u != nil && err == nil {
|
||||
respData.SignedUrl = u.String()
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue