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>
(cherry picked from commit 88f6f7579c
)
This commit is contained in:
parent
9e4be39acb
commit
5aa6a8288d
2 changed files with 215 additions and 17 deletions
|
@ -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)
|
||||||
|
|
|
@ -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"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue