Skip to content

Commit c09ad7c

Browse files
lunnyearl-warren
authored andcommitted
Fix storage path logic especially for relative paths (go-gitea#26441)
This PR rewrites the function `getStorage` and make it more clear. Include tests from go-gitea#26435, thanks @earl-warren --------- Co-authored-by: Earl Warren <[email protected]>
1 parent fe1b11b commit c09ad7c

File tree

2 files changed

+294
-93
lines changed

2 files changed

+294
-93
lines changed

modules/setting/storage.go

Lines changed: 131 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -91,134 +91,172 @@ func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*S
9191
return nil, errors.New("no name for storage")
9292
}
9393

94-
var targetSec ConfigSection
95-
// check typ first
96-
if typ != "" {
97-
var err error
98-
targetSec, err = rootCfg.GetSection(storageSectionName + "." + typ)
99-
if err != nil {
100-
if !IsValidStorageType(StorageType(typ)) {
101-
return nil, fmt.Errorf("get section via storage type %q failed: %v", typ, err)
102-
}
94+
targetSec, tp, err := getStorageTargetSection(rootCfg, name, typ, sec)
95+
if err != nil {
96+
return nil, err
97+
}
98+
99+
overrideSec := getStorageOverrideSection(rootCfg, targetSec, sec, tp, name)
100+
101+
targetType := targetSec.Key("STORAGE_TYPE").String()
102+
switch targetType {
103+
case string(LocalStorageType):
104+
return getStorageForLocal(targetSec, overrideSec, tp, name)
105+
case string(MinioStorageType):
106+
return getStorageForMinio(targetSec, overrideSec, tp, name)
107+
default:
108+
return nil, fmt.Errorf("unsupported storage type %q", targetType)
109+
}
110+
}
111+
112+
type targetSecType int
113+
114+
const (
115+
targetSecIsTyp targetSecType = iota // target section is [storage.type] which the type from parameter
116+
targetSecIsStorage // target section is [storage]
117+
targetSecIsDefault // target section is the default value
118+
targetSecIsStorageWithName // target section is [storage.name]
119+
targetSecIsSec // target section is from the name seciont [name]
120+
)
121+
122+
func getStorageSectionByType(rootCfg ConfigProvider, typ string) (ConfigSection, targetSecType, error) {
123+
targetSec, err := rootCfg.GetSection(storageSectionName + "." + typ)
124+
if err != nil {
125+
if !IsValidStorageType(StorageType(typ)) {
126+
return nil, 0, fmt.Errorf("get section via storage type %q failed: %v", typ, err)
103127
}
104-
if targetSec != nil {
105-
targetType := targetSec.Key("STORAGE_TYPE").String()
106-
if targetType == "" {
107-
if !IsValidStorageType(StorageType(typ)) {
108-
return nil, fmt.Errorf("unknow storage type %q", typ)
109-
}
110-
targetSec.Key("STORAGE_TYPE").SetValue(typ)
111-
} else if !IsValidStorageType(StorageType(targetType)) {
112-
return nil, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ)
113-
}
128+
// if typ is a valid storage type, but there is no [storage.local] or [storage.minio] section
129+
// it's not an error
130+
return nil, 0, nil
131+
}
132+
133+
targetType := targetSec.Key("STORAGE_TYPE").String()
134+
if targetType == "" {
135+
if !IsValidStorageType(StorageType(typ)) {
136+
return nil, 0, fmt.Errorf("unknow storage type %q", typ)
114137
}
138+
targetSec.Key("STORAGE_TYPE").SetValue(typ)
139+
} else if !IsValidStorageType(StorageType(targetType)) {
140+
return nil, 0, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ)
115141
}
116142

117-
if targetSec == nil && sec != nil {
118-
secTyp := sec.Key("STORAGE_TYPE").String()
119-
if IsValidStorageType(StorageType(secTyp)) {
120-
targetSec = sec
121-
} else if secTyp != "" {
122-
targetSec, _ = rootCfg.GetSection(storageSectionName + "." + secTyp)
143+
return targetSec, targetSecIsTyp, nil
144+
}
145+
146+
func getStorageTargetSection(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (ConfigSection, targetSecType, error) {
147+
// check typ first
148+
if typ == "" {
149+
if sec != nil { // check sec's type secondly
150+
typ = sec.Key("STORAGE_TYPE").String()
151+
if IsValidStorageType(StorageType(typ)) {
152+
if targetSec, _ := rootCfg.GetSection(storageSectionName + "." + typ); targetSec == nil {
153+
return sec, targetSecIsSec, nil
154+
}
155+
}
123156
}
124157
}
125158

126-
targetSecIsStoragename := false
127-
storageNameSec, _ := rootCfg.GetSection(storageSectionName + "." + name)
128-
if targetSec == nil {
129-
targetSec = storageNameSec
130-
targetSecIsStoragename = storageNameSec != nil
159+
if typ != "" {
160+
targetSec, tp, err := getStorageSectionByType(rootCfg, typ)
161+
if targetSec != nil || err != nil {
162+
return targetSec, tp, err
163+
}
131164
}
132165

133-
if targetSec == nil {
134-
targetSec = getDefaultStorageSection(rootCfg)
135-
} else {
166+
// check stoarge name thirdly
167+
targetSec, _ := rootCfg.GetSection(storageSectionName + "." + name)
168+
if targetSec != nil {
136169
targetType := targetSec.Key("STORAGE_TYPE").String()
137170
switch {
138171
case targetType == "":
139-
if targetSec != storageNameSec && storageNameSec != nil {
140-
targetSec = storageNameSec
141-
targetSecIsStoragename = true
142-
if targetSec.Key("STORAGE_TYPE").String() == "" {
143-
return nil, fmt.Errorf("storage section %s.%s has no STORAGE_TYPE", storageSectionName, name)
144-
}
145-
} else {
146-
if targetSec.Key("PATH").String() == "" {
147-
targetSec = getDefaultStorageSection(rootCfg)
148-
} else {
149-
targetSec.Key("STORAGE_TYPE").SetValue("local")
150-
}
172+
if targetSec.Key("PATH").String() == "" { // both storage type and path are empty, use default
173+
return getDefaultStorageSection(rootCfg), targetSecIsDefault, nil
151174
}
175+
176+
targetSec.Key("STORAGE_TYPE").SetValue("local")
152177
default:
153-
newTargetSec, _ := rootCfg.GetSection(storageSectionName + "." + targetType)
154-
if newTargetSec == nil {
155-
if !IsValidStorageType(StorageType(targetType)) {
156-
return nil, fmt.Errorf("invalid storage section %s.%q", storageSectionName, targetType)
157-
}
158-
} else {
159-
targetSec = newTargetSec
160-
if IsValidStorageType(StorageType(targetType)) {
161-
tp := targetSec.Key("STORAGE_TYPE").String()
162-
if tp == "" {
163-
targetSec.Key("STORAGE_TYPE").SetValue(targetType)
164-
}
165-
}
178+
targetSec, tp, err := getStorageSectionByType(rootCfg, targetType)
179+
if targetSec != nil || err != nil {
180+
return targetSec, tp, err
166181
}
167182
}
183+
184+
return targetSec, targetSecIsStorageWithName, nil
168185
}
169186

170-
targetType := targetSec.Key("STORAGE_TYPE").String()
171-
if !IsValidStorageType(StorageType(targetType)) {
172-
return nil, fmt.Errorf("invalid storage type %q", targetType)
187+
return getDefaultStorageSection(rootCfg), targetSecIsDefault, nil
188+
}
189+
190+
// getStorageOverrideSection override section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH, MINIO_BUCKET to override the targetsec when possible
191+
func getStorageOverrideSection(rootConfig ConfigProvider, targetSec, sec ConfigSection, targetSecType targetSecType, name string) ConfigSection {
192+
if targetSecType == targetSecIsSec {
193+
return nil
173194
}
174195

175-
// extra config section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH, MINIO_BUCKET to override the targetsec when possible
176-
extraConfigSec := sec
177-
if extraConfigSec == nil {
178-
extraConfigSec = storageNameSec
196+
if sec != nil {
197+
return sec
179198
}
180199

181-
var storage Storage
182-
storage.Type = StorageType(targetType)
200+
if targetSecType != targetSecIsStorageWithName {
201+
nameSec, _ := rootConfig.GetSection(storageSectionName + "." + name)
202+
return nameSec
203+
}
204+
return nil
205+
}
183206

184-
switch targetType {
185-
case string(LocalStorageType):
186-
targetPath := ConfigSectionKeyString(targetSec, "PATH", "")
187-
if targetPath == "" {
188-
targetPath = AppDataPath
189-
} else if !filepath.IsAbs(targetPath) {
190-
targetPath = filepath.Join(AppDataPath, targetPath)
191-
}
207+
func getStorageForLocal(targetSec, overrideSec ConfigSection, tp targetSecType, name string) (*Storage, error) {
208+
storage := Storage{
209+
Type: StorageType(targetSec.Key("STORAGE_TYPE").String()),
210+
}
192211

193-
var fallbackPath string
194-
if targetSecIsStoragename {
195-
fallbackPath = targetPath
196-
} else {
212+
targetPath := ConfigSectionKeyString(targetSec, "PATH", "")
213+
var fallbackPath string
214+
if targetPath == "" { // no path
215+
fallbackPath = filepath.Join(AppDataPath, name)
216+
} else {
217+
if tp == targetSecIsStorage || tp == targetSecIsDefault {
197218
fallbackPath = filepath.Join(targetPath, name)
219+
} else {
220+
fallbackPath = targetPath
221+
}
222+
if !filepath.IsAbs(fallbackPath) {
223+
fallbackPath = filepath.Join(AppDataPath, fallbackPath)
198224
}
225+
}
199226

200-
if extraConfigSec == nil {
227+
if overrideSec == nil { // no override section
228+
storage.Path = fallbackPath
229+
} else {
230+
storage.Path = ConfigSectionKeyString(overrideSec, "PATH", "")
231+
if storage.Path == "" { // overrideSec has no path
201232
storage.Path = fallbackPath
202-
} else {
203-
storage.Path = ConfigSectionKeyString(extraConfigSec, "PATH", fallbackPath)
204-
if !filepath.IsAbs(storage.Path) {
233+
} else if !filepath.IsAbs(storage.Path) {
234+
if targetPath == "" {
235+
storage.Path = filepath.Join(AppDataPath, storage.Path)
236+
} else {
205237
storage.Path = filepath.Join(targetPath, storage.Path)
206238
}
207239
}
240+
}
208241

209-
case string(MinioStorageType):
210-
if err := targetSec.MapTo(&storage.MinioConfig); err != nil {
211-
return nil, fmt.Errorf("map minio config failed: %v", err)
212-
}
242+
return &storage, nil
243+
}
213244

214-
storage.MinioConfig.BasePath = name + "/"
245+
func getStorageForMinio(targetSec, overrideSec ConfigSection, tp targetSecType, name string) (*Storage, error) {
246+
var storage Storage
247+
storage.Type = StorageType(targetSec.Key("STORAGE_TYPE").String())
248+
if err := targetSec.MapTo(&storage.MinioConfig); err != nil {
249+
return nil, fmt.Errorf("map minio config failed: %v", err)
250+
}
215251

216-
if extraConfigSec != nil {
217-
storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(extraConfigSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect)
218-
storage.MinioConfig.BasePath = ConfigSectionKeyString(extraConfigSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath)
219-
storage.MinioConfig.Bucket = ConfigSectionKeyString(extraConfigSec, "MINIO_BUCKET", storage.MinioConfig.Bucket)
220-
}
252+
if storage.MinioConfig.BasePath == "" {
253+
storage.MinioConfig.BasePath = name + "/"
221254
}
222255

256+
if overrideSec != nil {
257+
storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(overrideSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect)
258+
storage.MinioConfig.BasePath = ConfigSectionKeyString(overrideSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath)
259+
storage.MinioConfig.Bucket = ConfigSectionKeyString(overrideSec, "MINIO_BUCKET", storage.MinioConfig.Bucket)
260+
}
223261
return &storage, nil
224262
}

0 commit comments

Comments
 (0)