You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

repository.go 12KB

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