Fix the wrong derive path (#26271) (#26318)

Backport #26271 by @lunny

This PR will fix #26264, caused by #23911.

The package configuration derive is totally wrong when storage type is
local in that PR.

This PR fixed the inherit logic when storage type is local with some
unit tests.

Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Giteabot 2023-08-04 14:24:13 +08:00 committed by GitHub
parent fcd055c34a
commit 88f6f7579c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 215 additions and 17 deletions

View file

@ -84,12 +84,15 @@ func getDefaultStorageSection(rootCfg ConfigProvider) ConfigSection {
return storageSec return storageSec
} }
// getStorage will find target section and extra special section first and then read override
// items from extra section
func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*Storage, error) { func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*Storage, error) {
if name == "" { if name == "" {
return nil, errors.New("no name for storage") return nil, errors.New("no name for storage")
} }
var targetSec ConfigSection var targetSec ConfigSection
// check typ first
if typ != "" { if typ != "" {
var err error var err error
targetSec, err = rootCfg.GetSection(storageSectionName + "." + typ) targetSec, err = rootCfg.GetSection(storageSectionName + "." + typ)
@ -111,24 +114,40 @@ func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*S
} }
} }
storageNameSec, _ := rootCfg.GetSection(storageSectionName + "." + name) if targetSec == nil && sec != nil {
secTyp := sec.Key("STORAGE_TYPE").String()
if targetSec == nil { if IsValidStorageType(StorageType(secTyp)) {
targetSec = sec targetSec = sec
} else if secTyp != "" {
targetSec, _ = rootCfg.GetSection(storageSectionName + "." + secTyp)
}
} }
targetSecIsStoragename := false
storageNameSec, _ := rootCfg.GetSection(storageSectionName + "." + name)
if targetSec == nil { if targetSec == nil {
targetSec = storageNameSec targetSec = storageNameSec
targetSecIsStoragename = storageNameSec != nil
} }
if targetSec == nil { if targetSec == nil {
targetSec = getDefaultStorageSection(rootCfg) targetSec = getDefaultStorageSection(rootCfg)
} else { } else {
targetType := targetSec.Key("STORAGE_TYPE").String() targetType := targetSec.Key("STORAGE_TYPE").String()
switch { switch {
case targetType == "": case targetType == "":
if targetSec.Key("PATH").String() == "" { if targetSec != storageNameSec && storageNameSec != nil {
targetSec = getDefaultStorageSection(rootCfg) 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 { } else {
targetSec.Key("STORAGE_TYPE").SetValue("local") if targetSec.Key("PATH").String() == "" {
targetSec = getDefaultStorageSection(rootCfg)
} else {
targetSec.Key("STORAGE_TYPE").SetValue("local")
}
} }
default: default:
newTargetSec, _ := rootCfg.GetSection(storageSectionName + "." + targetType) newTargetSec, _ := rootCfg.GetSection(storageSectionName + "." + targetType)
@ -153,26 +172,46 @@ func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*S
return nil, fmt.Errorf("invalid storage type %q", targetType) return nil, fmt.Errorf("invalid storage type %q", targetType)
} }
// 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
}
var storage Storage var storage Storage
storage.Type = StorageType(targetType) storage.Type = StorageType(targetType)
switch targetType { switch targetType {
case string(LocalStorageType): case string(LocalStorageType):
storage.Path = ConfigSectionKeyString(targetSec, "PATH", filepath.Join(AppDataPath, name)) targetPath := ConfigSectionKeyString(targetSec, "PATH", "")
if !filepath.IsAbs(storage.Path) { if targetPath == "" {
storage.Path = filepath.Join(AppWorkPath, storage.Path) targetPath = AppDataPath
} else if !filepath.IsAbs(targetPath) {
targetPath = filepath.Join(AppDataPath, targetPath)
} }
case string(MinioStorageType):
storage.MinioConfig.BasePath = name + "/"
var fallbackPath string
if targetSecIsStoragename {
fallbackPath = targetPath
} else {
fallbackPath = filepath.Join(targetPath, name)
}
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)
}
}
case string(MinioStorageType):
if err := targetSec.MapTo(&storage.MinioConfig); err != nil { if err := targetSec.MapTo(&storage.MinioConfig); err != nil {
return nil, fmt.Errorf("map minio config failed: %v", err) return nil, fmt.Errorf("map minio config failed: %v", err)
} }
// extra config section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH to override the targetsec
extraConfigSec := sec storage.MinioConfig.BasePath = name + "/"
if extraConfigSec == nil {
extraConfigSec = storageNameSec
}
if extraConfigSec != nil { if extraConfigSec != nil {
storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(extraConfigSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect) storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(extraConfigSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect)

View file

@ -4,6 +4,7 @@
package setting package setting
import ( import (
"path/filepath"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -90,3 +91,161 @@ STORAGE_TYPE = minio
assert.EqualValues(t, "gitea", RepoAvatar.Storage.MinioConfig.Bucket) assert.EqualValues(t, "gitea", RepoAvatar.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "repo-avatars/", RepoAvatar.Storage.MinioConfig.BasePath) assert.EqualValues(t, "repo-avatars/", RepoAvatar.Storage.MinioConfig.BasePath)
} }
type testLocalStoragePathCase struct {
loader func(rootCfg ConfigProvider) error
storagePtr **Storage
expectedPath string
}
func testLocalStoragePath(t *testing.T, appDataPath, iniStr string, cases []testLocalStoragePathCase) {
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
AppDataPath = appDataPath
for _, c := range cases {
assert.NoError(t, c.loader(cfg))
storage := *c.storagePtr
assert.EqualValues(t, "local", storage.Type)
assert.True(t, filepath.IsAbs(storage.Path))
assert.EqualValues(t, filepath.Clean(c.expectedPath), filepath.Clean(storage.Path))
}
}
func Test_getStorageInheritStorageTypeLocal(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/repo-archive"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPath(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = /data/gitea
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/repo-archive"},
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalRelativePath(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = storages
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/appdata/storages/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/storages/repo-archive"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/storages/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/storages/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/storages/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = /data/gitea
[repo-archive]
PATH = /data/gitea/the-archives-dir
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/the-archives-dir"},
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverrideEmpty(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = /data/gitea
[repo-archive]
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/repo-archive"},
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalRelativePathOverride(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = /data/gitea
[repo-archive]
PATH = the-archives-dir
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/the-archives-dir"},
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride3(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
STORAGE_TYPE = local
PATH = /data/gitea/archives
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/archives"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride4(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
STORAGE_TYPE = local
PATH = /data/gitea/archives
[repo-archive]
PATH = /tmp/gitea/archives
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/tmp/gitea/archives"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride5(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
STORAGE_TYPE = local
PATH = /data/gitea/archives
[repo-archive]
`, []testLocalStoragePathCase{
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/archives"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}