backport #26094 Temporily resolve #25915 Related #25994 This PR includes #26007 's changes but have a UI to prompt administrator about the deprecated settings as well as the log or console warning. Then users will have enough time to notice the problem and don't have surprise like before. <img width="1293" alt="图片" src="https://github.com/go-gitea/gitea/assets/81045/c33355f0-1ea7-4fb3-ad43-cd23cd15391d">tags/v1.20.2
} | } | ||||
} | } | ||||
func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) { | |||||
if rootCfg.Section(oldSection).HasKey(oldKey) { | |||||
log.Error("Deprecated fallback `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version) | |||||
} | |||||
} | |||||
// DeprecatedWarnings contains the warning message for various deprecations, including: setting option, file/folder, etc | |||||
var DeprecatedWarnings []string | |||||
func deprecatedSettingFatal(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) { | |||||
func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) { | |||||
if rootCfg.Section(oldSection).HasKey(oldKey) { | if rootCfg.Section(oldSection).HasKey(oldKey) { | ||||
log.Fatal("Deprecated fallback `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be/has been removed in %s. Shutting down", oldSection, oldKey, newSection, newKey, version) | |||||
msg := fmt.Sprintf("Deprecated config option `[%s]` `%s` present. Use `[%s]` `%s` instead. This fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version) | |||||
log.Error("%v", msg) | |||||
DeprecatedWarnings = append(DeprecatedWarnings, msg) | |||||
} | } | ||||
} | } | ||||
// Specifically default PATH to LFS_CONTENT_PATH | // Specifically default PATH to LFS_CONTENT_PATH | ||||
// DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version | // DEPRECATED should not be removed because users maybe upgrade from lower version to the latest version | ||||
// if these are removed, the warning will not be shown | // if these are removed, the warning will not be shown | ||||
deprecatedSettingFatal(rootCfg, "server", "LFS_CONTENT_PATH", "lfs", "PATH", "v1.19.0") | |||||
deprecatedSetting(rootCfg, "server", "LFS_CONTENT_PATH", "lfs", "PATH", "v1.19.0") | |||||
if val := sec.Key("LFS_CONTENT_PATH").String(); val != "" { | |||||
if lfsSec == nil { | |||||
lfsSec = rootCfg.Section("lfs") | |||||
} | |||||
lfsSec.Key("PATH").MustString(val) | |||||
} | |||||
var err error | var err error | ||||
LFS.Storage, err = getStorage(rootCfg, "lfs", "", lfsSec) | LFS.Storage, err = getStorage(rootCfg, "lfs", "", lfsSec) |
assert.EqualValues(t, "minio", LFS.Storage.Type) | assert.EqualValues(t, "minio", LFS.Storage.Type) | ||||
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath) | assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath) | ||||
iniStr = ` | |||||
[server] | |||||
LFS_CONTENT_PATH = path_ignored | |||||
[lfs] | |||||
PATH = path_used | |||||
` | |||||
cfg, err = NewConfigProviderFromData(iniStr) | |||||
assert.NoError(t, err) | |||||
assert.NoError(t, loadLFSFrom(cfg)) | |||||
assert.EqualValues(t, "local", LFS.Storage.Type) | |||||
assert.Contains(t, LFS.Storage.Path, "path_used") | |||||
iniStr = ` | |||||
[server] | |||||
LFS_CONTENT_PATH = deprecatedpath | |||||
` | |||||
cfg, err = NewConfigProviderFromData(iniStr) | |||||
assert.NoError(t, err) | |||||
assert.NoError(t, loadLFSFrom(cfg)) | |||||
assert.EqualValues(t, "local", LFS.Storage.Type) | |||||
assert.Contains(t, LFS.Storage.Path, "deprecatedpath") | |||||
iniStr = ` | iniStr = ` | ||||
[storage.lfs] | [storage.lfs] | ||||
STORAGE_TYPE = minio | STORAGE_TYPE = minio |
sysStatus.NumGC = m.NumGC | sysStatus.NumGC = m.NumGC | ||||
} | } | ||||
func prepareDeprecatedWarningsAlert(ctx *context.Context) { | |||||
if len(setting.DeprecatedWarnings) > 0 { | |||||
content := setting.DeprecatedWarnings[0] | |||||
if len(setting.DeprecatedWarnings) > 1 { | |||||
content += fmt.Sprintf(" (and %d more)", len(setting.DeprecatedWarnings)-1) | |||||
} | |||||
ctx.Flash.Error(content, true) | |||||
} | |||||
} | |||||
// Dashboard show admin panel dashboard | // Dashboard show admin panel dashboard | ||||
func Dashboard(ctx *context.Context) { | func Dashboard(ctx *context.Context) { | ||||
ctx.Data["Title"] = ctx.Tr("admin.dashboard") | ctx.Data["Title"] = ctx.Tr("admin.dashboard") | ||||
updateSystemStatus() | updateSystemStatus() | ||||
ctx.Data["SysStatus"] = sysStatus | ctx.Data["SysStatus"] = sysStatus | ||||
ctx.Data["SSH"] = setting.SSH | ctx.Data["SSH"] = setting.SSH | ||||
prepareDeprecatedWarningsAlert(ctx) | |||||
ctx.HTML(http.StatusOK, tplDashboard) | ctx.HTML(http.StatusOK, tplDashboard) | ||||
} | } | ||||
ctx.Data["Loggers"] = log.GetManager().DumpLoggers() | ctx.Data["Loggers"] = log.GetManager().DumpLoggers() | ||||
prepareDeprecatedWarningsAlert(ctx) | |||||
ctx.HTML(http.StatusOK, tplConfig) | ctx.HTML(http.StatusOK, tplConfig) | ||||
} | } | ||||
{{template "base/head" .ctxData}} | {{template "base/head" .ctxData}} | ||||
<div role="main" aria-label="{{.ctxData.Title}}" class="page-content {{.pageClass}}"> | <div role="main" aria-label="{{.ctxData.Title}}" class="page-content {{.pageClass}}"> | ||||
<div class="ui container stackable grid"> | |||||
<div class="ui container"> | |||||
{{template "base/alert" .ctxData}} | |||||
</div> | |||||
<div class="ui container admin-container"> | |||||
{{template "admin/navbar" .ctxData}} | {{template "admin/navbar" .ctxData}} | ||||
<div class="twelve wide column"> | |||||
{{template "base/alert" .ctxData}} | |||||
<div class="admin-main"> | |||||
{{/* block: admin-setting-content */}} | {{/* block: admin-setting-content */}} | ||||
{{if false}}{{/* to make html structure "likely" complete to prevent IDE warnings */}} | {{if false}}{{/* to make html structure "likely" complete to prevent IDE warnings */}} |
<div class="four wide column"> | |||||
<div class="admin-nav"> | |||||
<div class="ui fluid vertical menu"> | <div class="ui fluid vertical menu"> | ||||
<div class="header item">{{.locale.Tr "settings"}}</div> | <div class="header item">{{.locale.Tr "settings"}}</div> | ||||
<a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/admin"> | <a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/admin"> |
.admin-container { | |||||
margin-top: 15px; | |||||
display: flex !important; | |||||
gap: 16px; | |||||
} | |||||
.admin-nav { | |||||
width: 240px; | |||||
} | |||||
.admin-main { | |||||
flex: 1; | |||||
} | |||||
@media (max-width: 767.98px) { | |||||
.admin-container { | |||||
flex-direction: column; | |||||
} | |||||
.admin-nav { | |||||
width: auto; | |||||
} | |||||
} | |||||
.admin.hooks .list > .item:not(:first-child) { | .admin.hooks .list > .item:not(:first-child) { | ||||
border-top: 1px solid var(--color-secondary); | border-top: 1px solid var(--color-secondary); | ||||
padding: 0.25rem 1rem; | padding: 0.25rem 1rem; |