first-commit

This commit is contained in:
2025-08-25 15:46:12 +08:00
commit f4d95dfff4
5665 changed files with 705359 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package config
import (
"context"
"sync"
)
var getterMu sync.RWMutex
type CfgSecKeyGetter interface {
GetValue(sec, key string) (v string, has bool)
}
var cfgSecKeyGetterInternal CfgSecKeyGetter
func SetCfgSecKeyGetter(p CfgSecKeyGetter) {
getterMu.Lock()
cfgSecKeyGetterInternal = p
getterMu.Unlock()
}
func GetCfgSecKeyGetter() CfgSecKeyGetter {
getterMu.RLock()
defer getterMu.RUnlock()
return cfgSecKeyGetterInternal
}
type DynKeyGetter interface {
GetValue(ctx context.Context, key string) (v string, has bool)
GetRevision(ctx context.Context) int
InvalidateCache()
}
var dynKeyGetterInternal DynKeyGetter
func SetDynGetter(p DynKeyGetter) {
getterMu.Lock()
dynKeyGetterInternal = p
getterMu.Unlock()
}
func GetDynGetter() DynKeyGetter {
getterMu.RLock()
defer getterMu.RUnlock()
return dynKeyGetterInternal
}

View File

@@ -0,0 +1,94 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package config
import (
"context"
"sync"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
)
type CfgSecKey struct {
Sec, Key string
}
type Value[T any] struct {
mu sync.RWMutex
cfgSecKey CfgSecKey
dynKey string
def, value T
revision int
}
func (value *Value[T]) parse(key, valStr string) (v T) {
v = value.def
if valStr != "" {
if err := json.Unmarshal(util.UnsafeStringToBytes(valStr), &v); err != nil {
log.Error("Unable to unmarshal json config for key %q, err: %v", key, err)
}
}
return v
}
func (value *Value[T]) Value(ctx context.Context) (v T) {
dg := GetDynGetter()
if dg == nil {
// this is an edge case: the database is not initialized but the system setting is going to be used
// it should panic to avoid inconsistent config values (from config / system setting) and fix the code
panic("no config dyn value getter")
}
rev := dg.GetRevision(ctx)
// if the revision in database doesn't change, use the last value
value.mu.RLock()
if rev == value.revision {
v = value.value
value.mu.RUnlock()
return v
}
value.mu.RUnlock()
// try to parse the config and cache it
var valStr *string
if dynVal, has := dg.GetValue(ctx, value.dynKey); has {
valStr = &dynVal
} else if cfgVal, has := GetCfgSecKeyGetter().GetValue(value.cfgSecKey.Sec, value.cfgSecKey.Key); has {
valStr = &cfgVal
}
if valStr == nil {
v = value.def
} else {
v = value.parse(value.dynKey, *valStr)
}
value.mu.Lock()
value.value = v
value.revision = rev
value.mu.Unlock()
return v
}
func (value *Value[T]) DynKey() string {
return value.dynKey
}
func (value *Value[T]) WithDefault(def T) *Value[T] {
value.def = def
return value
}
func (value *Value[T]) WithFileConfig(cfgSecKey CfgSecKey) *Value[T] {
value.cfgSecKey = cfgSecKey
return value
}
func ValueJSON[T any](dynKey string) *Value[T] {
return &Value[T]{dynKey: dynKey}
}