code.gitea.io/gitea@v1.22.3/modules/setting/repository.go (about) 1 // Copyright 2019 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package setting 5 6 import ( 7 "os/exec" 8 "path" 9 "path/filepath" 10 "strings" 11 12 "code.gitea.io/gitea/modules/log" 13 ) 14 15 // enumerates all the policy repository creating 16 const ( 17 RepoCreatingLastUserVisibility = "last" 18 RepoCreatingPrivate = "private" 19 RepoCreatingPublic = "public" 20 ) 21 22 // ItemsPerPage maximum items per page in forks, watchers and stars of a repo 23 const ItemsPerPage = 40 24 25 // Repository settings 26 var ( 27 Repository = struct { 28 DetectedCharsetsOrder []string 29 DetectedCharsetScore map[string]int `ini:"-"` 30 AnsiCharset string 31 ForcePrivate bool 32 DefaultPrivate string 33 DefaultPushCreatePrivate bool 34 MaxCreationLimit int 35 PreferredLicenses []string 36 DisableHTTPGit bool 37 AccessControlAllowOrigin string 38 UseCompatSSHURI bool 39 GoGetCloneURLProtocol string 40 DefaultCloseIssuesViaCommitsInAnyBranch bool 41 EnablePushCreateUser bool 42 EnablePushCreateOrg bool 43 DisabledRepoUnits []string 44 DefaultRepoUnits []string 45 DefaultForkRepoUnits []string 46 PrefixArchiveFiles bool 47 DisableMigrations bool 48 DisableStars bool `ini:"DISABLE_STARS"` 49 DefaultBranch string 50 AllowAdoptionOfUnadoptedRepositories bool 51 AllowDeleteOfUnadoptedRepositories bool 52 DisableDownloadSourceArchives bool 53 AllowForkWithoutMaximumLimit bool 54 55 // Repository editor settings 56 Editor struct { 57 LineWrapExtensions []string 58 } `ini:"-"` 59 60 // Repository upload settings 61 Upload struct { 62 Enabled bool 63 TempPath string 64 AllowedTypes string 65 FileMaxSize int64 66 MaxFiles int 67 } `ini:"-"` 68 69 // Repository local settings 70 Local struct { 71 LocalCopyPath string 72 } `ini:"-"` 73 74 // Pull request settings 75 PullRequest struct { 76 WorkInProgressPrefixes []string 77 CloseKeywords []string 78 ReopenKeywords []string 79 DefaultMergeStyle string 80 DefaultMergeMessageCommitsLimit int 81 DefaultMergeMessageSize int 82 DefaultMergeMessageAllAuthors bool 83 DefaultMergeMessageMaxApprovers int 84 DefaultMergeMessageOfficialApproversOnly bool 85 PopulateSquashCommentWithCommitMessages bool 86 AddCoCommitterTrailers bool 87 TestConflictingPatchesWithGitApply bool 88 RetargetChildrenOnMerge bool 89 } `ini:"repository.pull-request"` 90 91 // Issue Setting 92 Issue struct { 93 LockReasons []string 94 MaxPinned int 95 } `ini:"repository.issue"` 96 97 Release struct { 98 AllowedTypes string 99 DefaultPagingNum int 100 } `ini:"repository.release"` 101 102 Signing struct { 103 SigningKey string 104 SigningName string 105 SigningEmail string 106 InitialCommit []string 107 CRUDActions []string `ini:"CRUD_ACTIONS"` 108 Merges []string 109 Wiki []string 110 DefaultTrustModel string 111 } `ini:"repository.signing"` 112 }{ 113 DetectedCharsetsOrder: []string{ 114 "UTF-8", 115 "UTF-16BE", 116 "UTF-16LE", 117 "UTF-32BE", 118 "UTF-32LE", 119 "ISO-8859-1", 120 "windows-1252", 121 "ISO-8859-2", 122 "windows-1250", 123 "ISO-8859-5", 124 "ISO-8859-6", 125 "ISO-8859-7", 126 "windows-1253", 127 "ISO-8859-8-I", 128 "windows-1255", 129 "ISO-8859-8", 130 "windows-1251", 131 "windows-1256", 132 "KOI8-R", 133 "ISO-8859-9", 134 "windows-1254", 135 "Shift_JIS", 136 "GB18030", 137 "EUC-JP", 138 "EUC-KR", 139 "Big5", 140 "ISO-2022-JP", 141 "ISO-2022-KR", 142 "ISO-2022-CN", 143 "IBM424_rtl", 144 "IBM424_ltr", 145 "IBM420_rtl", 146 "IBM420_ltr", 147 }, 148 DetectedCharsetScore: map[string]int{}, 149 AnsiCharset: "", 150 ForcePrivate: false, 151 DefaultPrivate: RepoCreatingLastUserVisibility, 152 DefaultPushCreatePrivate: true, 153 MaxCreationLimit: -1, 154 PreferredLicenses: []string{"Apache License 2.0", "MIT License"}, 155 DisableHTTPGit: false, 156 AccessControlAllowOrigin: "", 157 UseCompatSSHURI: false, 158 DefaultCloseIssuesViaCommitsInAnyBranch: false, 159 EnablePushCreateUser: false, 160 EnablePushCreateOrg: false, 161 DisabledRepoUnits: []string{}, 162 DefaultRepoUnits: []string{}, 163 DefaultForkRepoUnits: []string{}, 164 PrefixArchiveFiles: true, 165 DisableMigrations: false, 166 DisableStars: false, 167 DefaultBranch: "main", 168 AllowForkWithoutMaximumLimit: true, 169 170 // Repository editor settings 171 Editor: struct { 172 LineWrapExtensions []string 173 }{ 174 LineWrapExtensions: strings.Split(".txt,.md,.markdown,.mdown,.mkd,.livemd,", ","), 175 }, 176 177 // Repository upload settings 178 Upload: struct { 179 Enabled bool 180 TempPath string 181 AllowedTypes string 182 FileMaxSize int64 183 MaxFiles int 184 }{ 185 Enabled: true, 186 TempPath: "data/tmp/uploads", 187 AllowedTypes: "", 188 FileMaxSize: 50, 189 MaxFiles: 5, 190 }, 191 192 // Repository local settings 193 Local: struct { 194 LocalCopyPath string 195 }{ 196 LocalCopyPath: "tmp/local-repo", 197 }, 198 199 // Pull request settings 200 PullRequest: struct { 201 WorkInProgressPrefixes []string 202 CloseKeywords []string 203 ReopenKeywords []string 204 DefaultMergeStyle string 205 DefaultMergeMessageCommitsLimit int 206 DefaultMergeMessageSize int 207 DefaultMergeMessageAllAuthors bool 208 DefaultMergeMessageMaxApprovers int 209 DefaultMergeMessageOfficialApproversOnly bool 210 PopulateSquashCommentWithCommitMessages bool 211 AddCoCommitterTrailers bool 212 TestConflictingPatchesWithGitApply bool 213 RetargetChildrenOnMerge bool 214 }{ 215 WorkInProgressPrefixes: []string{"WIP:", "[WIP]"}, 216 // Same as GitHub. See 217 // https://help.github.com/articles/closing-issues-via-commit-messages 218 CloseKeywords: strings.Split("close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved", ","), 219 ReopenKeywords: strings.Split("reopen,reopens,reopened", ","), 220 DefaultMergeStyle: "merge", 221 DefaultMergeMessageCommitsLimit: 50, 222 DefaultMergeMessageSize: 5 * 1024, 223 DefaultMergeMessageAllAuthors: false, 224 DefaultMergeMessageMaxApprovers: 10, 225 DefaultMergeMessageOfficialApproversOnly: true, 226 PopulateSquashCommentWithCommitMessages: false, 227 AddCoCommitterTrailers: true, 228 RetargetChildrenOnMerge: true, 229 }, 230 231 // Issue settings 232 Issue: struct { 233 LockReasons []string 234 MaxPinned int 235 }{ 236 LockReasons: strings.Split("Too heated,Off-topic,Spam,Resolved", ","), 237 MaxPinned: 3, 238 }, 239 240 Release: struct { 241 AllowedTypes string 242 DefaultPagingNum int 243 }{ 244 AllowedTypes: "", 245 DefaultPagingNum: 10, 246 }, 247 248 // Signing settings 249 Signing: struct { 250 SigningKey string 251 SigningName string 252 SigningEmail string 253 InitialCommit []string 254 CRUDActions []string `ini:"CRUD_ACTIONS"` 255 Merges []string 256 Wiki []string 257 DefaultTrustModel string 258 }{ 259 SigningKey: "default", 260 SigningName: "", 261 SigningEmail: "", 262 InitialCommit: []string{"always"}, 263 CRUDActions: []string{"pubkey", "twofa", "parentsigned"}, 264 Merges: []string{"pubkey", "twofa", "basesigned", "commitssigned"}, 265 Wiki: []string{"never"}, 266 DefaultTrustModel: "collaborator", 267 }, 268 } 269 RepoRootPath string 270 ScriptType = "bash" 271 ) 272 273 func loadRepositoryFrom(rootCfg ConfigProvider) { 274 var err error 275 // Determine and create root git repository path. 276 sec := rootCfg.Section("repository") 277 Repository.DisableHTTPGit = sec.Key("DISABLE_HTTP_GIT").MustBool() 278 Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool() 279 Repository.GoGetCloneURLProtocol = sec.Key("GO_GET_CLONE_URL_PROTOCOL").MustString("https") 280 Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1) 281 Repository.DefaultBranch = sec.Key("DEFAULT_BRANCH").MustString(Repository.DefaultBranch) 282 RepoRootPath = sec.Key("ROOT").MustString(path.Join(AppDataPath, "gitea-repositories")) 283 if !filepath.IsAbs(RepoRootPath) { 284 RepoRootPath = filepath.Join(AppWorkPath, RepoRootPath) 285 } else { 286 RepoRootPath = filepath.Clean(RepoRootPath) 287 } 288 289 checkOverlappedPath("[repository].ROOT", RepoRootPath) 290 291 defaultDetectedCharsetsOrder := make([]string, 0, len(Repository.DetectedCharsetsOrder)) 292 for _, charset := range Repository.DetectedCharsetsOrder { 293 defaultDetectedCharsetsOrder = append(defaultDetectedCharsetsOrder, strings.ToLower(strings.TrimSpace(charset))) 294 } 295 ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash") 296 297 if _, err := exec.LookPath(ScriptType); err != nil { 298 log.Warn("SCRIPT_TYPE %q is not on the current PATH. Are you sure that this is the correct SCRIPT_TYPE?", ScriptType) 299 } 300 301 if err = sec.MapTo(&Repository); err != nil { 302 log.Fatal("Failed to map Repository settings: %v", err) 303 } else if err = rootCfg.Section("repository.editor").MapTo(&Repository.Editor); err != nil { 304 log.Fatal("Failed to map Repository.Editor settings: %v", err) 305 } else if err = rootCfg.Section("repository.upload").MapTo(&Repository.Upload); err != nil { 306 log.Fatal("Failed to map Repository.Upload settings: %v", err) 307 } else if err = rootCfg.Section("repository.local").MapTo(&Repository.Local); err != nil { 308 log.Fatal("Failed to map Repository.Local settings: %v", err) 309 } else if err = rootCfg.Section("repository.pull-request").MapTo(&Repository.PullRequest); err != nil { 310 log.Fatal("Failed to map Repository.PullRequest settings: %v", err) 311 } 312 313 if !rootCfg.Section("packages").Key("ENABLED").MustBool(Packages.Enabled) { 314 Repository.DisabledRepoUnits = append(Repository.DisabledRepoUnits, "repo.packages") 315 } 316 317 if !rootCfg.Section("actions").Key("ENABLED").MustBool(Actions.Enabled) { 318 Repository.DisabledRepoUnits = append(Repository.DisabledRepoUnits, "repo.actions") 319 } 320 321 // Handle default trustmodel settings 322 Repository.Signing.DefaultTrustModel = strings.ToLower(strings.TrimSpace(Repository.Signing.DefaultTrustModel)) 323 if Repository.Signing.DefaultTrustModel == "default" { 324 Repository.Signing.DefaultTrustModel = "collaborator" 325 } 326 327 // Handle preferred charset orders 328 preferred := make([]string, 0, len(Repository.DetectedCharsetsOrder)) 329 for _, charset := range Repository.DetectedCharsetsOrder { 330 canonicalCharset := strings.ToLower(strings.TrimSpace(charset)) 331 preferred = append(preferred, canonicalCharset) 332 // remove it from the defaults 333 for i, charset := range defaultDetectedCharsetsOrder { 334 if charset == canonicalCharset { 335 defaultDetectedCharsetsOrder = append(defaultDetectedCharsetsOrder[:i], defaultDetectedCharsetsOrder[i+1:]...) 336 break 337 } 338 } 339 } 340 341 i := 0 342 for _, charset := range preferred { 343 // Add the defaults 344 if charset == "defaults" { 345 for _, charset := range defaultDetectedCharsetsOrder { 346 canonicalCharset := strings.ToLower(strings.TrimSpace(charset)) 347 if _, has := Repository.DetectedCharsetScore[canonicalCharset]; !has { 348 Repository.DetectedCharsetScore[canonicalCharset] = i 349 i++ 350 } 351 } 352 continue 353 } 354 if _, has := Repository.DetectedCharsetScore[charset]; !has { 355 Repository.DetectedCharsetScore[charset] = i 356 i++ 357 } 358 } 359 360 if !filepath.IsAbs(Repository.Upload.TempPath) { 361 Repository.Upload.TempPath = path.Join(AppWorkPath, Repository.Upload.TempPath) 362 } 363 364 if err := loadRepoArchiveFrom(rootCfg); err != nil { 365 log.Fatal("loadRepoArchiveFrom: %v", err) 366 } 367 }