mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 02:46:04 +01:00 
			
		
		
		
	Do not allow different storage configurations to point to the same directory (#30169)
Replace #29171
This commit is contained in:
		| @@ -58,7 +58,7 @@ func loadIndexerFrom(rootCfg ConfigProvider) { | ||||
| 		if !filepath.IsAbs(Indexer.IssuePath) { | ||||
| 			Indexer.IssuePath = filepath.ToSlash(filepath.Join(AppWorkPath, Indexer.IssuePath)) | ||||
| 		} | ||||
| 		fatalDuplicatedPath("issue_indexer", Indexer.IssuePath) | ||||
| 		checkOverlappedPath("indexer.ISSUE_INDEXER_PATH", Indexer.IssuePath) | ||||
| 	} else { | ||||
| 		Indexer.IssueConnStr = sec.Key("ISSUE_INDEXER_CONN_STR").MustString(Indexer.IssueConnStr) | ||||
| 		if Indexer.IssueType == "meilisearch" { | ||||
|   | ||||
| @@ -66,12 +66,8 @@ func init() { | ||||
| 		AppWorkPath = filepath.Dir(AppPath) | ||||
| 	} | ||||
|  | ||||
| 	fatalDuplicatedPath("app_work_path", AppWorkPath) | ||||
|  | ||||
| 	appWorkPathBuiltin = AppWorkPath | ||||
| 	customPathBuiltin = CustomPath | ||||
|  | ||||
| 	fatalDuplicatedPath("custom_path", CustomPath) | ||||
| 	customConfBuiltin = CustomConf | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -286,7 +286,7 @@ func loadRepositoryFrom(rootCfg ConfigProvider) { | ||||
| 		RepoRootPath = filepath.Clean(RepoRootPath) | ||||
| 	} | ||||
|  | ||||
| 	fatalDuplicatedPath("repository.ROOT", RepoRootPath) | ||||
| 	checkOverlappedPath("repository.ROOT", RepoRootPath) | ||||
|  | ||||
| 	defaultDetectedCharsetsOrder := make([]string, 0, len(Repository.DetectedCharsetsOrder)) | ||||
| 	for _, charset := range Repository.DetectedCharsetsOrder { | ||||
|   | ||||
| @@ -324,7 +324,6 @@ func loadServerFrom(rootCfg ConfigProvider) { | ||||
| 	if !filepath.IsAbs(AppDataPath) { | ||||
| 		AppDataPath = filepath.ToSlash(filepath.Join(AppWorkPath, AppDataPath)) | ||||
| 	} | ||||
| 	fatalDuplicatedPath("app_data_path", AppDataPath) | ||||
|  | ||||
| 	EnableGzip = sec.Key("ENABLE_GZIP").MustBool() | ||||
| 	EnablePprof = sec.Key("ENABLE_PPROF").MustBool(false) | ||||
| @@ -332,7 +331,7 @@ func loadServerFrom(rootCfg ConfigProvider) { | ||||
| 	if !filepath.IsAbs(PprofDataPath) { | ||||
| 		PprofDataPath = filepath.Join(AppWorkPath, PprofDataPath) | ||||
| 	} | ||||
| 	fatalDuplicatedPath("pprof_data_path", PprofDataPath) | ||||
| 	checkOverlappedPath("server.PPROF_DATA_PATH", PprofDataPath) | ||||
|  | ||||
| 	landingPage := sec.Key("LANDING_PAGE").MustString("home") | ||||
| 	switch landingPage { | ||||
|   | ||||
| @@ -46,7 +46,7 @@ func loadSessionFrom(rootCfg ConfigProvider) { | ||||
| 	SessionConfig.ProviderConfig = strings.Trim(sec.Key("PROVIDER_CONFIG").MustString(filepath.Join(AppDataPath, "sessions")), "\" ") | ||||
| 	if SessionConfig.Provider == "file" && !filepath.IsAbs(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.CookiePath = AppSubURL | ||||
|   | ||||
| @@ -230,11 +230,14 @@ func LoadSettingsForInstall() { | ||||
| 	loadMailerFrom(CfgProvider) | ||||
| } | ||||
|  | ||||
| var uniquePaths = make(map[string]string) | ||||
| var configuredPaths = make(map[string]string) | ||||
|  | ||||
| func fatalDuplicatedPath(name, p string) { | ||||
| 	if targetName, ok := uniquePaths[p]; ok && targetName != name { | ||||
| 		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) | ||||
| func checkOverlappedPath(name, path string) { | ||||
| 	// TODO: some paths shouldn't overlap (storage.xxx.path), while some could (data path is the base path for storage path) | ||||
| 	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 | ||||
| } | ||||
|   | ||||
| @@ -2775,6 +2775,7 @@ teams.invite.by = Invited by %s | ||||
| teams.invite.description = Please click the button below to join the team. | ||||
|  | ||||
| [admin] | ||||
| maintenance = Maintenance | ||||
| dashboard = Dashboard | ||||
| self_check = Self Check | ||||
| 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.statistic = Summary | ||||
| dashboard.operations = Maintenance Operations | ||||
| dashboard.maintenance_operations = Maintenance Operations | ||||
| dashboard.system_status = System Status | ||||
| dashboard.operation_name = Operation Name | ||||
| dashboard.operation_switch = Switch | ||||
| @@ -3305,6 +3306,7 @@ notices.op = Op. | ||||
| notices.delete_success = The system notices have been deleted. | ||||
|  | ||||
| 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_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. | ||||
|   | ||||
| @@ -190,6 +190,14 @@ func DashboardPost(ctx *context.Context) { | ||||
|  | ||||
| func SelfCheck(ctx *context.Context) { | ||||
| 	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() | ||||
| 	if err != nil { | ||||
| 		ctx.Flash.Error(fmt.Sprintf("CheckCollationsDefaultEngine: %v", err), true) | ||||
|   | ||||
| @@ -6,7 +6,7 @@ | ||||
| 			</div> | ||||
| 		{{end}} | ||||
| 		<h4 class="ui top attached header"> | ||||
| 			{{ctx.Locale.Tr "admin.dashboard.operations"}} | ||||
| 			{{ctx.Locale.Tr "admin.dashboard.maintenance_operations"}} | ||||
| 		</h4> | ||||
| 		<div class="ui attached table segment"> | ||||
| 			<form method="post" action="{{AppSubUrl}}/admin"> | ||||
|   | ||||
| @@ -1,12 +1,18 @@ | ||||
| <div class="flex-container-nav"> | ||||
| 	<div class="ui fluid vertical menu"> | ||||
| 		<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"> | ||||
| 					{{ctx.Locale.Tr "admin.dashboard"}} | ||||
| 				</a> | ||||
| 				<a class="{{if .PageIsAdminSelfCheck}}active {{end}}item" href="{{AppSubUrl}}/admin/self_check"> | ||||
| 					{{ctx.Locale.Tr "admin.self_check"}} | ||||
| 				</a> | ||||
| 			</div> | ||||
| 		</details> | ||||
| 		<details class="item toggleable-item" {{if or .PageIsAdminUsers .PageIsAdminEmails .PageIsAdminOrganizations .PageIsAdminAuthentications}}open{{end}}> | ||||
| 			<summary>{{ctx.Locale.Tr "admin.identity_access"}}</summary> | ||||
| 			<div class="menu"> | ||||
|   | ||||
| @@ -4,8 +4,18 @@ | ||||
| 	<h4 class="ui top attached header"> | ||||
| 		{{ctx.Locale.Tr "admin.self_check"}} | ||||
| 	</h4> | ||||
|  | ||||
| 	{{if .DeprecatedWarnings}} | ||||
| 	<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}} | ||||
| 	<div class="ui attached segment"> | ||||
| 		{{if .DatabaseType.IsMySQL}} | ||||
| 			<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mysql"}}</div> | ||||
| 		{{else if .DatabaseType.IsMSSQL}} | ||||
| @@ -27,10 +37,14 @@ | ||||
| 				</ul> | ||||
| 			</div> | ||||
| 		{{end}} | ||||
| 		{{else}} | ||||
| 			<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.no_problem_found"}}</div> | ||||
| 		{{end}} | ||||
| 	</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> | ||||
|  | ||||
| {{template "admin/layout_footer" .}} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user