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  }