forked from forgejo/forgejo
Backport #26441 by @lunny
This PR rewrites the function `getStorage` and make it more clear.
Include tests from #26435, thanks @earl-warren
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: Earl Warren <contact@earl-warren.org>
(cherry picked from commit f1c5d33d3e
)
This commit is contained in:
parent
d297a87f75
commit
b683b93d16
2 changed files with 306 additions and 105 deletions
|
@ -91,134 +91,172 @@ func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*S
|
|||
return nil, errors.New("no name for storage")
|
||||
}
|
||||
|
||||
var targetSec ConfigSection
|
||||
// check typ first
|
||||
if typ != "" {
|
||||
var err error
|
||||
targetSec, err = rootCfg.GetSection(storageSectionName + "." + typ)
|
||||
if err != nil {
|
||||
if !IsValidStorageType(StorageType(typ)) {
|
||||
return nil, fmt.Errorf("get section via storage type %q failed: %v", typ, err)
|
||||
}
|
||||
}
|
||||
if targetSec != nil {
|
||||
targetType := targetSec.Key("STORAGE_TYPE").String()
|
||||
if targetType == "" {
|
||||
if !IsValidStorageType(StorageType(typ)) {
|
||||
return nil, fmt.Errorf("unknow storage type %q", typ)
|
||||
}
|
||||
targetSec.Key("STORAGE_TYPE").SetValue(typ)
|
||||
} else if !IsValidStorageType(StorageType(targetType)) {
|
||||
return nil, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ)
|
||||
}
|
||||
}
|
||||
targetSec, tp, err := getStorageTargetSection(rootCfg, name, typ, sec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if targetSec == nil && sec != nil {
|
||||
secTyp := sec.Key("STORAGE_TYPE").String()
|
||||
if IsValidStorageType(StorageType(secTyp)) {
|
||||
targetSec = sec
|
||||
} else if secTyp != "" {
|
||||
targetSec, _ = rootCfg.GetSection(storageSectionName + "." + secTyp)
|
||||
}
|
||||
}
|
||||
overrideSec := getStorageOverrideSection(rootCfg, targetSec, sec, tp, name)
|
||||
|
||||
targetSecIsStoragename := false
|
||||
storageNameSec, _ := rootCfg.GetSection(storageSectionName + "." + name)
|
||||
if targetSec == nil {
|
||||
targetSec = storageNameSec
|
||||
targetSecIsStoragename = storageNameSec != nil
|
||||
targetType := targetSec.Key("STORAGE_TYPE").String()
|
||||
switch targetType {
|
||||
case string(LocalStorageType):
|
||||
return getStorageForLocal(targetSec, overrideSec, tp, name)
|
||||
case string(MinioStorageType):
|
||||
return getStorageForMinio(targetSec, overrideSec, tp, name)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported storage type %q", targetType)
|
||||
}
|
||||
}
|
||||
|
||||
if targetSec == nil {
|
||||
targetSec = getDefaultStorageSection(rootCfg)
|
||||
} else {
|
||||
targetType := targetSec.Key("STORAGE_TYPE").String()
|
||||
switch {
|
||||
case targetType == "":
|
||||
if targetSec != storageNameSec && storageNameSec != nil {
|
||||
targetSec = storageNameSec
|
||||
targetSecIsStoragename = true
|
||||
if targetSec.Key("STORAGE_TYPE").String() == "" {
|
||||
return nil, fmt.Errorf("storage section %s.%s has no STORAGE_TYPE", storageSectionName, name)
|
||||
}
|
||||
} else {
|
||||
if targetSec.Key("PATH").String() == "" {
|
||||
targetSec = getDefaultStorageSection(rootCfg)
|
||||
} else {
|
||||
targetSec.Key("STORAGE_TYPE").SetValue("local")
|
||||
}
|
||||
}
|
||||
default:
|
||||
newTargetSec, _ := rootCfg.GetSection(storageSectionName + "." + targetType)
|
||||
if newTargetSec == nil {
|
||||
if !IsValidStorageType(StorageType(targetType)) {
|
||||
return nil, fmt.Errorf("invalid storage section %s.%q", storageSectionName, targetType)
|
||||
}
|
||||
} else {
|
||||
targetSec = newTargetSec
|
||||
if IsValidStorageType(StorageType(targetType)) {
|
||||
tp := targetSec.Key("STORAGE_TYPE").String()
|
||||
if tp == "" {
|
||||
targetSec.Key("STORAGE_TYPE").SetValue(targetType)
|
||||
}
|
||||
}
|
||||
}
|
||||
type targetSecType int
|
||||
|
||||
const (
|
||||
targetSecIsTyp targetSecType = iota // target section is [storage.type] which the type from parameter
|
||||
targetSecIsStorage // target section is [storage]
|
||||
targetSecIsDefault // target section is the default value
|
||||
targetSecIsStorageWithName // target section is [storage.name]
|
||||
targetSecIsSec // target section is from the name seciont [name]
|
||||
)
|
||||
|
||||
func getStorageSectionByType(rootCfg ConfigProvider, typ string) (ConfigSection, targetSecType, error) {
|
||||
targetSec, err := rootCfg.GetSection(storageSectionName + "." + typ)
|
||||
if err != nil {
|
||||
if !IsValidStorageType(StorageType(typ)) {
|
||||
return nil, 0, fmt.Errorf("get section via storage type %q failed: %v", typ, err)
|
||||
}
|
||||
// if typ is a valid storage type, but there is no [storage.local] or [storage.minio] section
|
||||
// it's not an error
|
||||
return nil, 0, nil
|
||||
}
|
||||
|
||||
targetType := targetSec.Key("STORAGE_TYPE").String()
|
||||
if !IsValidStorageType(StorageType(targetType)) {
|
||||
return nil, fmt.Errorf("invalid storage type %q", targetType)
|
||||
if targetType == "" {
|
||||
if !IsValidStorageType(StorageType(typ)) {
|
||||
return nil, 0, fmt.Errorf("unknow storage type %q", typ)
|
||||
}
|
||||
targetSec.Key("STORAGE_TYPE").SetValue(typ)
|
||||
} else if !IsValidStorageType(StorageType(targetType)) {
|
||||
return nil, 0, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ)
|
||||
}
|
||||
|
||||
// extra config section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH, MINIO_BUCKET to override the targetsec when possible
|
||||
extraConfigSec := sec
|
||||
if extraConfigSec == nil {
|
||||
extraConfigSec = storageNameSec
|
||||
return targetSec, targetSecIsTyp, nil
|
||||
}
|
||||
|
||||
func getStorageTargetSection(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (ConfigSection, targetSecType, error) {
|
||||
// check typ first
|
||||
if typ == "" {
|
||||
if sec != nil { // check sec's type secondly
|
||||
typ = sec.Key("STORAGE_TYPE").String()
|
||||
if IsValidStorageType(StorageType(typ)) {
|
||||
if targetSec, _ := rootCfg.GetSection(storageSectionName + "." + typ); targetSec == nil {
|
||||
return sec, targetSecIsSec, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var storage Storage
|
||||
storage.Type = StorageType(targetType)
|
||||
|
||||
switch targetType {
|
||||
case string(LocalStorageType):
|
||||
targetPath := ConfigSectionKeyString(targetSec, "PATH", "")
|
||||
if targetPath == "" {
|
||||
targetPath = AppDataPath
|
||||
} else if !filepath.IsAbs(targetPath) {
|
||||
targetPath = filepath.Join(AppDataPath, targetPath)
|
||||
if typ != "" {
|
||||
targetSec, tp, err := getStorageSectionByType(rootCfg, typ)
|
||||
if targetSec != nil || err != nil {
|
||||
return targetSec, tp, err
|
||||
}
|
||||
}
|
||||
|
||||
var fallbackPath string
|
||||
if targetSecIsStoragename {
|
||||
fallbackPath = targetPath
|
||||
} else {
|
||||
fallbackPath = filepath.Join(targetPath, name)
|
||||
}
|
||||
// check stoarge name thirdly
|
||||
targetSec, _ := rootCfg.GetSection(storageSectionName + "." + name)
|
||||
if targetSec != nil {
|
||||
targetType := targetSec.Key("STORAGE_TYPE").String()
|
||||
switch {
|
||||
case targetType == "":
|
||||
if targetSec.Key("PATH").String() == "" { // both storage type and path are empty, use default
|
||||
return getDefaultStorageSection(rootCfg), targetSecIsDefault, nil
|
||||
}
|
||||
|
||||
if extraConfigSec == nil {
|
||||
storage.Path = fallbackPath
|
||||
} else {
|
||||
storage.Path = ConfigSectionKeyString(extraConfigSec, "PATH", fallbackPath)
|
||||
if !filepath.IsAbs(storage.Path) {
|
||||
storage.Path = filepath.Join(targetPath, storage.Path)
|
||||
targetSec.Key("STORAGE_TYPE").SetValue("local")
|
||||
default:
|
||||
targetSec, tp, err := getStorageSectionByType(rootCfg, targetType)
|
||||
if targetSec != nil || err != nil {
|
||||
return targetSec, tp, err
|
||||
}
|
||||
}
|
||||
|
||||
case string(MinioStorageType):
|
||||
if err := targetSec.MapTo(&storage.MinioConfig); err != nil {
|
||||
return nil, fmt.Errorf("map minio config failed: %v", err)
|
||||
return targetSec, targetSecIsStorageWithName, nil
|
||||
}
|
||||
|
||||
return getDefaultStorageSection(rootCfg), targetSecIsDefault, nil
|
||||
}
|
||||
|
||||
// getStorageOverrideSection override section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH, MINIO_BUCKET to override the targetsec when possible
|
||||
func getStorageOverrideSection(rootConfig ConfigProvider, targetSec, sec ConfigSection, targetSecType targetSecType, name string) ConfigSection {
|
||||
if targetSecType == targetSecIsSec {
|
||||
return nil
|
||||
}
|
||||
|
||||
if sec != nil {
|
||||
return sec
|
||||
}
|
||||
|
||||
if targetSecType != targetSecIsStorageWithName {
|
||||
nameSec, _ := rootConfig.GetSection(storageSectionName + "." + name)
|
||||
return nameSec
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getStorageForLocal(targetSec, overrideSec ConfigSection, tp targetSecType, name string) (*Storage, error) {
|
||||
storage := Storage{
|
||||
Type: StorageType(targetSec.Key("STORAGE_TYPE").String()),
|
||||
}
|
||||
|
||||
targetPath := ConfigSectionKeyString(targetSec, "PATH", "")
|
||||
var fallbackPath string
|
||||
if targetPath == "" { // no path
|
||||
fallbackPath = filepath.Join(AppDataPath, name)
|
||||
} else {
|
||||
if tp == targetSecIsStorage || tp == targetSecIsDefault {
|
||||
fallbackPath = filepath.Join(targetPath, name)
|
||||
} else {
|
||||
fallbackPath = targetPath
|
||||
}
|
||||
if !filepath.IsAbs(fallbackPath) {
|
||||
fallbackPath = filepath.Join(AppDataPath, fallbackPath)
|
||||
}
|
||||
}
|
||||
|
||||
storage.MinioConfig.BasePath = name + "/"
|
||||
|
||||
if extraConfigSec != nil {
|
||||
storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(extraConfigSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect)
|
||||
storage.MinioConfig.BasePath = ConfigSectionKeyString(extraConfigSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath)
|
||||
storage.MinioConfig.Bucket = ConfigSectionKeyString(extraConfigSec, "MINIO_BUCKET", storage.MinioConfig.Bucket)
|
||||
if overrideSec == nil { // no override section
|
||||
storage.Path = fallbackPath
|
||||
} else {
|
||||
storage.Path = ConfigSectionKeyString(overrideSec, "PATH", "")
|
||||
if storage.Path == "" { // overrideSec has no path
|
||||
storage.Path = fallbackPath
|
||||
} else if !filepath.IsAbs(storage.Path) {
|
||||
if targetPath == "" {
|
||||
storage.Path = filepath.Join(AppDataPath, storage.Path)
|
||||
} else {
|
||||
storage.Path = filepath.Join(targetPath, storage.Path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &storage, nil
|
||||
}
|
||||
|
||||
func getStorageForMinio(targetSec, overrideSec ConfigSection, tp targetSecType, name string) (*Storage, error) {
|
||||
var storage Storage
|
||||
storage.Type = StorageType(targetSec.Key("STORAGE_TYPE").String())
|
||||
if err := targetSec.MapTo(&storage.MinioConfig); err != nil {
|
||||
return nil, fmt.Errorf("map minio config failed: %v", err)
|
||||
}
|
||||
|
||||
if storage.MinioConfig.BasePath == "" {
|
||||
storage.MinioConfig.BasePath = name + "/"
|
||||
}
|
||||
|
||||
if overrideSec != nil {
|
||||
storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(overrideSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect)
|
||||
storage.MinioConfig.BasePath = ConfigSectionKeyString(overrideSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath)
|
||||
storage.MinioConfig.Bucket = ConfigSectionKeyString(overrideSec, "MINIO_BUCKET", storage.MinioConfig.Bucket)
|
||||
}
|
||||
return &storage, nil
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue