Do not allow different storage configurations to point to the same directory (#30169)
Replace #29171
This commit is contained in:
parent
82ffd91607
commit
6d34ce25b1
@ -58,7 +58,7 @@ func loadIndexerFrom(rootCfg ConfigProvider) {
|
|||||||
if !filepath.IsAbs(Indexer.IssuePath) {
|
if !filepath.IsAbs(Indexer.IssuePath) {
|
||||||
Indexer.IssuePath = filepath.ToSlash(filepath.Join(AppWorkPath, Indexer.IssuePath))
|
Indexer.IssuePath = filepath.ToSlash(filepath.Join(AppWorkPath, Indexer.IssuePath))
|
||||||
}
|
}
|
||||||
fatalDuplicatedPath("issue_indexer", Indexer.IssuePath)
|
checkOverlappedPath("indexer.ISSUE_INDEXER_PATH", Indexer.IssuePath)
|
||||||
} else {
|
} else {
|
||||||
Indexer.IssueConnStr = sec.Key("ISSUE_INDEXER_CONN_STR").MustString(Indexer.IssueConnStr)
|
Indexer.IssueConnStr = sec.Key("ISSUE_INDEXER_CONN_STR").MustString(Indexer.IssueConnStr)
|
||||||
if Indexer.IssueType == "meilisearch" {
|
if Indexer.IssueType == "meilisearch" {
|
||||||
|
@ -66,12 +66,8 @@ func init() {
|
|||||||
AppWorkPath = filepath.Dir(AppPath)
|
AppWorkPath = filepath.Dir(AppPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
fatalDuplicatedPath("app_work_path", AppWorkPath)
|
|
||||||
|
|
||||||
appWorkPathBuiltin = AppWorkPath
|
appWorkPathBuiltin = AppWorkPath
|
||||||
customPathBuiltin = CustomPath
|
customPathBuiltin = CustomPath
|
||||||
|
|
||||||
fatalDuplicatedPath("custom_path", CustomPath)
|
|
||||||
customConfBuiltin = CustomConf
|
customConfBuiltin = CustomConf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +286,7 @@ func loadRepositoryFrom(rootCfg ConfigProvider) {
|
|||||||
RepoRootPath = filepath.Clean(RepoRootPath)
|
RepoRootPath = filepath.Clean(RepoRootPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
fatalDuplicatedPath("repository.ROOT", RepoRootPath)
|
checkOverlappedPath("repository.ROOT", RepoRootPath)
|
||||||
|
|
||||||
defaultDetectedCharsetsOrder := make([]string, 0, len(Repository.DetectedCharsetsOrder))
|
defaultDetectedCharsetsOrder := make([]string, 0, len(Repository.DetectedCharsetsOrder))
|
||||||
for _, charset := range Repository.DetectedCharsetsOrder {
|
for _, charset := range Repository.DetectedCharsetsOrder {
|
||||||
|
@ -324,7 +324,6 @@ func loadServerFrom(rootCfg ConfigProvider) {
|
|||||||
if !filepath.IsAbs(AppDataPath) {
|
if !filepath.IsAbs(AppDataPath) {
|
||||||
AppDataPath = filepath.ToSlash(filepath.Join(AppWorkPath, AppDataPath))
|
AppDataPath = filepath.ToSlash(filepath.Join(AppWorkPath, AppDataPath))
|
||||||
}
|
}
|
||||||
fatalDuplicatedPath("app_data_path", AppDataPath)
|
|
||||||
|
|
||||||
EnableGzip = sec.Key("ENABLE_GZIP").MustBool()
|
EnableGzip = sec.Key("ENABLE_GZIP").MustBool()
|
||||||
EnablePprof = sec.Key("ENABLE_PPROF").MustBool(false)
|
EnablePprof = sec.Key("ENABLE_PPROF").MustBool(false)
|
||||||
@ -332,7 +331,7 @@ func loadServerFrom(rootCfg ConfigProvider) {
|
|||||||
if !filepath.IsAbs(PprofDataPath) {
|
if !filepath.IsAbs(PprofDataPath) {
|
||||||
PprofDataPath = filepath.Join(AppWorkPath, PprofDataPath)
|
PprofDataPath = filepath.Join(AppWorkPath, PprofDataPath)
|
||||||
}
|
}
|
||||||
fatalDuplicatedPath("pprof_data_path", PprofDataPath)
|
checkOverlappedPath("server.PPROF_DATA_PATH", PprofDataPath)
|
||||||
|
|
||||||
landingPage := sec.Key("LANDING_PAGE").MustString("home")
|
landingPage := sec.Key("LANDING_PAGE").MustString("home")
|
||||||
switch landingPage {
|
switch landingPage {
|
||||||
|
@ -46,7 +46,7 @@ func loadSessionFrom(rootCfg ConfigProvider) {
|
|||||||
SessionConfig.ProviderConfig = strings.Trim(sec.Key("PROVIDER_CONFIG").MustString(filepath.Join(AppDataPath, "sessions")), "\" ")
|
SessionConfig.ProviderConfig = strings.Trim(sec.Key("PROVIDER_CONFIG").MustString(filepath.Join(AppDataPath, "sessions")), "\" ")
|
||||||
if SessionConfig.Provider == "file" && !filepath.IsAbs(SessionConfig.ProviderConfig) {
|
if SessionConfig.Provider == "file" && !filepath.IsAbs(SessionConfig.ProviderConfig) {
|
||||||
SessionConfig.ProviderConfig = filepath.Join(AppWorkPath, SessionConfig.ProviderConfig)
|
SessionConfig.ProviderConfig = filepath.Join(AppWorkPath, SessionConfig.ProviderConfig)
|
||||||
fatalDuplicatedPath("session", SessionConfig.ProviderConfig)
|
checkOverlappedPath("session.PROVIDER_CONFIG", SessionConfig.ProviderConfig)
|
||||||
}
|
}
|
||||||
SessionConfig.CookieName = sec.Key("COOKIE_NAME").MustString("i_like_gitea")
|
SessionConfig.CookieName = sec.Key("COOKIE_NAME").MustString("i_like_gitea")
|
||||||
SessionConfig.CookiePath = AppSubURL
|
SessionConfig.CookiePath = AppSubURL
|
||||||
|
@ -230,11 +230,14 @@ func LoadSettingsForInstall() {
|
|||||||
loadMailerFrom(CfgProvider)
|
loadMailerFrom(CfgProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
var uniquePaths = make(map[string]string)
|
var configuredPaths = make(map[string]string)
|
||||||
|
|
||||||
func fatalDuplicatedPath(name, p string) {
|
func checkOverlappedPath(name, path string) {
|
||||||
if targetName, ok := uniquePaths[p]; ok && targetName != name {
|
// TODO: some paths shouldn't overlap (storage.xxx.path), while some could (data path is the base path for storage path)
|
||||||
log.Fatal("storage path %q is being used by %q and %q and all storage paths must be unique to prevent data loss.", p, targetName, name)
|
if targetName, ok := configuredPaths[path]; ok && targetName != name {
|
||||||
|
msg := fmt.Sprintf("Configured path %q is used by %q and %q at the same time. The paths must be unique to prevent data loss.", path, targetName, name)
|
||||||
|
log.Error("%s", msg)
|
||||||
|
DeprecatedWarnings = append(DeprecatedWarnings, msg)
|
||||||
}
|
}
|
||||||
uniquePaths[p] = name
|
configuredPaths[path] = name
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ func getStorageForLocal(targetSec, overrideSec ConfigSection, tp targetSecType,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fatalDuplicatedPath("storage."+name, storage.Path)
|
checkOverlappedPath("storage."+name+".PATH", storage.Path)
|
||||||
|
|
||||||
return &storage, nil
|
return &storage, nil
|
||||||
}
|
}
|
||||||
|
@ -2775,6 +2775,7 @@ teams.invite.by = Invited by %s
|
|||||||
teams.invite.description = Please click the button below to join the team.
|
teams.invite.description = Please click the button below to join the team.
|
||||||
|
|
||||||
[admin]
|
[admin]
|
||||||
|
maintenance = Maintenance
|
||||||
dashboard = Dashboard
|
dashboard = Dashboard
|
||||||
self_check = Self Check
|
self_check = Self Check
|
||||||
identity_access = Identity & Access
|
identity_access = Identity & Access
|
||||||
@ -2798,7 +2799,7 @@ settings = Admin Settings
|
|||||||
|
|
||||||
dashboard.new_version_hint = Gitea %s is now available, you are running %s. Check <a target="_blank" rel="noreferrer" href="https://blog.gitea.io">the blog</a> for more details.
|
dashboard.new_version_hint = Gitea %s is now available, you are running %s. Check <a target="_blank" rel="noreferrer" href="https://blog.gitea.io">the blog</a> for more details.
|
||||||
dashboard.statistic = Summary
|
dashboard.statistic = Summary
|
||||||
dashboard.operations = Maintenance Operations
|
dashboard.maintenance_operations = Maintenance Operations
|
||||||
dashboard.system_status = System Status
|
dashboard.system_status = System Status
|
||||||
dashboard.operation_name = Operation Name
|
dashboard.operation_name = Operation Name
|
||||||
dashboard.operation_switch = Switch
|
dashboard.operation_switch = Switch
|
||||||
@ -3305,6 +3306,7 @@ notices.op = Op.
|
|||||||
notices.delete_success = The system notices have been deleted.
|
notices.delete_success = The system notices have been deleted.
|
||||||
|
|
||||||
self_check.no_problem_found = No problem found yet.
|
self_check.no_problem_found = No problem found yet.
|
||||||
|
self_check.startup_warnings = Startup warnings:
|
||||||
self_check.database_collation_mismatch = Expect database to use collation: %s
|
self_check.database_collation_mismatch = Expect database to use collation: %s
|
||||||
self_check.database_collation_case_insensitive = Database is using a collation %s, which is an insensitive collation. Although Gitea could work with it, there might be some rare cases which don't work as expected.
|
self_check.database_collation_case_insensitive = Database is using a collation %s, which is an insensitive collation. Although Gitea could work with it, there might be some rare cases which don't work as expected.
|
||||||
self_check.database_inconsistent_collation_columns = Database is using collation %s, but these columns are using mismatched collations. It might cause some unexpected problems.
|
self_check.database_inconsistent_collation_columns = Database is using collation %s, but these columns are using mismatched collations. It might cause some unexpected problems.
|
||||||
|
@ -190,6 +190,14 @@ func DashboardPost(ctx *context.Context) {
|
|||||||
|
|
||||||
func SelfCheck(ctx *context.Context) {
|
func SelfCheck(ctx *context.Context) {
|
||||||
ctx.Data["PageIsAdminSelfCheck"] = true
|
ctx.Data["PageIsAdminSelfCheck"] = true
|
||||||
|
|
||||||
|
ctx.Data["DeprecatedWarnings"] = setting.DeprecatedWarnings
|
||||||
|
if len(setting.DeprecatedWarnings) == 0 && !setting.IsProd {
|
||||||
|
if time.Now().Unix()%2 == 0 {
|
||||||
|
ctx.Data["DeprecatedWarnings"] = []string{"This is a test warning message in dev mode"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r, err := db.CheckCollationsDefaultEngine()
|
r, err := db.CheckCollationsDefaultEngine()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Flash.Error(fmt.Sprintf("CheckCollationsDefaultEngine: %v", err), true)
|
ctx.Flash.Error(fmt.Sprintf("CheckCollationsDefaultEngine: %v", err), true)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<h4 class="ui top attached header">
|
<h4 class="ui top attached header">
|
||||||
{{ctx.Locale.Tr "admin.dashboard.operations"}}
|
{{ctx.Locale.Tr "admin.dashboard.maintenance_operations"}}
|
||||||
</h4>
|
</h4>
|
||||||
<div class="ui attached table segment">
|
<div class="ui attached table segment">
|
||||||
<form method="post" action="{{AppSubUrl}}/admin">
|
<form method="post" action="{{AppSubUrl}}/admin">
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
<div class="flex-container-nav">
|
<div class="flex-container-nav">
|
||||||
<div class="ui fluid vertical menu">
|
<div class="ui fluid vertical menu">
|
||||||
<div class="header item">{{ctx.Locale.Tr "admin.settings"}}</div>
|
<div class="header item">{{ctx.Locale.Tr "admin.settings"}}</div>
|
||||||
|
|
||||||
|
<details class="item toggleable-item" {{if or .PageIsAdminDashboard .PageIsAdminSelfCheck}}open{{end}}>
|
||||||
|
<summary>{{ctx.Locale.Tr "admin.maintenance"}}</summary>
|
||||||
|
<div class="menu">
|
||||||
<a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/admin">
|
<a class="{{if .PageIsAdminDashboard}}active {{end}}item" href="{{AppSubUrl}}/admin">
|
||||||
{{ctx.Locale.Tr "admin.dashboard"}}
|
{{ctx.Locale.Tr "admin.dashboard"}}
|
||||||
</a>
|
</a>
|
||||||
<a class="{{if .PageIsAdminSelfCheck}}active {{end}}item" href="{{AppSubUrl}}/admin/self_check">
|
<a class="{{if .PageIsAdminSelfCheck}}active {{end}}item" href="{{AppSubUrl}}/admin/self_check">
|
||||||
{{ctx.Locale.Tr "admin.self_check"}}
|
{{ctx.Locale.Tr "admin.self_check"}}
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
<details class="item toggleable-item" {{if or .PageIsAdminUsers .PageIsAdminEmails .PageIsAdminOrganizations .PageIsAdminAuthentications}}open{{end}}>
|
<details class="item toggleable-item" {{if or .PageIsAdminUsers .PageIsAdminEmails .PageIsAdminOrganizations .PageIsAdminAuthentications}}open{{end}}>
|
||||||
<summary>{{ctx.Locale.Tr "admin.identity_access"}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.identity_access"}}</summary>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
|
@ -4,8 +4,18 @@
|
|||||||
<h4 class="ui top attached header">
|
<h4 class="ui top attached header">
|
||||||
{{ctx.Locale.Tr "admin.self_check"}}
|
{{ctx.Locale.Tr "admin.self_check"}}
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
|
{{if .DeprecatedWarnings}}
|
||||||
<div class="ui attached segment">
|
<div class="ui attached segment">
|
||||||
|
<div class="ui warning message">
|
||||||
|
<div>{{ctx.Locale.Tr "admin.self_check.startup_warnings"}}</div>
|
||||||
|
<ul class="tw-w-full">{{range .DeprecatedWarnings}}<li>{{.}}</li>{{end}}</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
{{if .DatabaseCheckHasProblems}}
|
{{if .DatabaseCheckHasProblems}}
|
||||||
|
<div class="ui attached segment">
|
||||||
{{if .DatabaseType.IsMySQL}}
|
{{if .DatabaseType.IsMySQL}}
|
||||||
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mysql"}}</div>
|
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mysql"}}</div>
|
||||||
{{else if .DatabaseType.IsMSSQL}}
|
{{else if .DatabaseType.IsMSSQL}}
|
||||||
@ -27,10 +37,14 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{else}}
|
|
||||||
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.no_problem_found"}}</div>
|
|
||||||
{{end}}
|
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if and (not .DeprecatedWarnings) (not .DatabaseCheckHasProblems)}}
|
||||||
|
<div class="ui attached segment">
|
||||||
|
{{ctx.Locale.Tr "admin.self_check.no_problem_found"}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{template "admin/layout_footer" .}}
|
{{template "admin/layout_footer" .}}
|
||||||
|
Loading…
Reference in New Issue
Block a user