forgejo/modules/setting/repository.go
Gergely Nagy dc39043cd6
Change the default SSH clone url to the ssh:// style
Rather than using an scp-style URI, use the same URL style for SSH
clones as for HTTP(S) ones. This is not only more consistent, but the
URL style allows one to specify a port, and makes it clear that it is an
SSH clone URL.

git itself favours the URL style, and mentions the scp-style in passing
only. Said style is prominently used by GitHub, and might be more
familiar for a lot of people, but other than familiarity, it has no
advantage over the URL style.

For the benefit of consistency, and flexibility, lets flip the default,
and make it the URL style. Instance admins who prefer to use the
scp-style, and are running SSH on its standard port, can change the
setting back to false.

This addresses #3193.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
2024-04-17 11:04:48 +02:00

376 lines
12 KiB
Go

// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"os/exec"
"path"
"path/filepath"
"strings"
"code.gitea.io/gitea/modules/log"
)
// enumerates all the policy repository creating
const (
RepoCreatingLastUserVisibility = "last"
RepoCreatingPrivate = "private"
RepoCreatingPublic = "public"
)
// MaxUserCardsPerPage sets maximum amount of watchers and stargazers shown per page
// those pages use 2 or 3 column layout, so the value should be divisible by 2 and 3
var MaxUserCardsPerPage = 36
// MaxForksPerPage sets maximum amount of forks shown per page
var MaxForksPerPage = 40
// Repository settings
var (
Repository = struct {
DetectedCharsetsOrder []string
DetectedCharsetScore map[string]int `ini:"-"`
AnsiCharset string
ForcePrivate bool
DefaultPrivate string
DefaultPushCreatePrivate bool
MaxCreationLimit int
PreferredLicenses []string
DisableHTTPGit bool
AccessControlAllowOrigin string
UseCompatSSHURI bool
GoGetCloneURLProtocol string
DefaultCloseIssuesViaCommitsInAnyBranch bool
EnablePushCreateUser bool
EnablePushCreateOrg bool
DisabledRepoUnits []string
DefaultRepoUnits []string
DefaultForkRepoUnits []string
PrefixArchiveFiles bool
DisableMigrations bool
DisableStars bool
DisableForks bool
DefaultBranch string
AllowAdoptionOfUnadoptedRepositories bool
AllowDeleteOfUnadoptedRepositories bool
DisableDownloadSourceArchives bool
AllowForkWithoutMaximumLimit bool
// Repository editor settings
Editor struct {
LineWrapExtensions []string
} `ini:"-"`
// Repository upload settings
Upload struct {
Enabled bool
TempPath string
AllowedTypes string
FileMaxSize int64
MaxFiles int
} `ini:"-"`
// Repository local settings
Local struct {
LocalCopyPath string
} `ini:"-"`
// Pull request settings
PullRequest struct {
WorkInProgressPrefixes []string
CloseKeywords []string
ReopenKeywords []string
DefaultMergeStyle string
DefaultMergeMessageCommitsLimit int
DefaultMergeMessageSize int
DefaultMergeMessageAllAuthors bool
DefaultMergeMessageMaxApprovers int
DefaultMergeMessageOfficialApproversOnly bool
PopulateSquashCommentWithCommitMessages bool
AddCoCommitterTrailers bool
TestConflictingPatchesWithGitApply bool
RetargetChildrenOnMerge bool
} `ini:"repository.pull-request"`
// Issue Setting
Issue struct {
LockReasons []string
MaxPinned int
} `ini:"repository.issue"`
Release struct {
AllowedTypes string
DefaultPagingNum int
} `ini:"repository.release"`
Signing struct {
SigningKey string
SigningName string
SigningEmail string
InitialCommit []string
CRUDActions []string `ini:"CRUD_ACTIONS"`
Merges []string
Wiki []string
DefaultTrustModel string
} `ini:"repository.signing"`
SettableFlags []string
EnableFlags bool
}{
DetectedCharsetsOrder: []string{
"UTF-8",
"UTF-16BE",
"UTF-16LE",
"UTF-32BE",
"UTF-32LE",
"ISO-8859-1",
"windows-1252",
"ISO-8859-2",
"windows-1250",
"ISO-8859-5",
"ISO-8859-6",
"ISO-8859-7",
"windows-1253",
"ISO-8859-8-I",
"windows-1255",
"ISO-8859-8",
"windows-1251",
"windows-1256",
"KOI8-R",
"ISO-8859-9",
"windows-1254",
"Shift_JIS",
"GB18030",
"EUC-JP",
"EUC-KR",
"Big5",
"ISO-2022-JP",
"ISO-2022-KR",
"ISO-2022-CN",
"IBM424_rtl",
"IBM424_ltr",
"IBM420_rtl",
"IBM420_ltr",
},
DetectedCharsetScore: map[string]int{},
AnsiCharset: "",
ForcePrivate: false,
DefaultPrivate: RepoCreatingLastUserVisibility,
DefaultPushCreatePrivate: true,
MaxCreationLimit: -1,
PreferredLicenses: []string{"Apache-2.0", "MIT"},
DisableHTTPGit: false,
AccessControlAllowOrigin: "",
UseCompatSSHURI: true,
DefaultCloseIssuesViaCommitsInAnyBranch: false,
EnablePushCreateUser: false,
EnablePushCreateOrg: false,
DisabledRepoUnits: []string{},
DefaultRepoUnits: []string{},
DefaultForkRepoUnits: []string{},
PrefixArchiveFiles: true,
DisableMigrations: false,
DisableStars: false,
DisableForks: false,
DefaultBranch: "main",
AllowForkWithoutMaximumLimit: true,
// Repository editor settings
Editor: struct {
LineWrapExtensions []string
}{
LineWrapExtensions: strings.Split(".txt,.md,.markdown,.mdown,.mkd,.livemd,", ","),
},
// Repository upload settings
Upload: struct {
Enabled bool
TempPath string
AllowedTypes string
FileMaxSize int64
MaxFiles int
}{
Enabled: true,
TempPath: "data/tmp/uploads",
AllowedTypes: "",
FileMaxSize: 50,
MaxFiles: 5,
},
// Repository local settings
Local: struct {
LocalCopyPath string
}{
LocalCopyPath: "tmp/local-repo",
},
// Pull request settings
PullRequest: struct {
WorkInProgressPrefixes []string
CloseKeywords []string
ReopenKeywords []string
DefaultMergeStyle string
DefaultMergeMessageCommitsLimit int
DefaultMergeMessageSize int
DefaultMergeMessageAllAuthors bool
DefaultMergeMessageMaxApprovers int
DefaultMergeMessageOfficialApproversOnly bool
PopulateSquashCommentWithCommitMessages bool
AddCoCommitterTrailers bool
TestConflictingPatchesWithGitApply bool
RetargetChildrenOnMerge bool
}{
WorkInProgressPrefixes: []string{"WIP:", "[WIP]"},
// Same as GitHub. See
// https://help.github.com/articles/closing-issues-via-commit-messages
CloseKeywords: strings.Split("close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved", ","),
ReopenKeywords: strings.Split("reopen,reopens,reopened", ","),
DefaultMergeStyle: "merge",
DefaultMergeMessageCommitsLimit: 50,
DefaultMergeMessageSize: 5 * 1024,
DefaultMergeMessageAllAuthors: false,
DefaultMergeMessageMaxApprovers: 10,
DefaultMergeMessageOfficialApproversOnly: true,
PopulateSquashCommentWithCommitMessages: false,
AddCoCommitterTrailers: true,
RetargetChildrenOnMerge: true,
},
// Issue settings
Issue: struct {
LockReasons []string
MaxPinned int
}{
LockReasons: strings.Split("Too heated,Off-topic,Spam,Resolved", ","),
MaxPinned: 3,
},
Release: struct {
AllowedTypes string
DefaultPagingNum int
}{
AllowedTypes: "",
DefaultPagingNum: 10,
},
// Signing settings
Signing: struct {
SigningKey string
SigningName string
SigningEmail string
InitialCommit []string
CRUDActions []string `ini:"CRUD_ACTIONS"`
Merges []string
Wiki []string
DefaultTrustModel string
}{
SigningKey: "default",
SigningName: "",
SigningEmail: "",
InitialCommit: []string{"always"},
CRUDActions: []string{"pubkey", "twofa", "parentsigned"},
Merges: []string{"pubkey", "twofa", "basesigned", "commitssigned"},
Wiki: []string{"never"},
DefaultTrustModel: "collaborator",
},
EnableFlags: false,
}
RepoRootPath string
ScriptType = "bash"
)
func loadRepositoryFrom(rootCfg ConfigProvider) {
var err error
// Determine and create root git repository path.
sec := rootCfg.Section("repository")
Repository.DisableHTTPGit = sec.Key("DISABLE_HTTP_GIT").MustBool()
Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool()
Repository.GoGetCloneURLProtocol = sec.Key("GO_GET_CLONE_URL_PROTOCOL").MustString("https")
Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1)
Repository.DefaultBranch = sec.Key("DEFAULT_BRANCH").MustString(Repository.DefaultBranch)
RepoRootPath = sec.Key("ROOT").MustString(path.Join(AppDataPath, "forgejo-repositories"))
if !filepath.IsAbs(RepoRootPath) {
RepoRootPath = filepath.Join(AppWorkPath, RepoRootPath)
} else {
RepoRootPath = filepath.Clean(RepoRootPath)
}
defaultDetectedCharsetsOrder := make([]string, 0, len(Repository.DetectedCharsetsOrder))
for _, charset := range Repository.DetectedCharsetsOrder {
defaultDetectedCharsetsOrder = append(defaultDetectedCharsetsOrder, strings.ToLower(strings.TrimSpace(charset)))
}
ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
if _, err := exec.LookPath(ScriptType); err != nil {
log.Warn("SCRIPT_TYPE %q is not on the current PATH. Are you sure that this is the correct SCRIPT_TYPE?", ScriptType)
}
if err = sec.MapTo(&Repository); err != nil {
log.Fatal("Failed to map Repository settings: %v", err)
} else if err = rootCfg.Section("repository.editor").MapTo(&Repository.Editor); err != nil {
log.Fatal("Failed to map Repository.Editor settings: %v", err)
} else if err = rootCfg.Section("repository.upload").MapTo(&Repository.Upload); err != nil {
log.Fatal("Failed to map Repository.Upload settings: %v", err)
} else if err = rootCfg.Section("repository.local").MapTo(&Repository.Local); err != nil {
log.Fatal("Failed to map Repository.Local settings: %v", err)
} else if err = rootCfg.Section("repository.pull-request").MapTo(&Repository.PullRequest); err != nil {
log.Fatal("Failed to map Repository.PullRequest settings: %v", err)
}
if !rootCfg.Section("packages").Key("ENABLED").MustBool(Packages.Enabled) {
Repository.DisabledRepoUnits = append(Repository.DisabledRepoUnits, "repo.packages")
}
if !rootCfg.Section("actions").Key("ENABLED").MustBool(Actions.Enabled) {
Repository.DisabledRepoUnits = append(Repository.DisabledRepoUnits, "repo.actions")
}
// Handle default trustmodel settings
Repository.Signing.DefaultTrustModel = strings.ToLower(strings.TrimSpace(Repository.Signing.DefaultTrustModel))
if Repository.Signing.DefaultTrustModel == "default" {
Repository.Signing.DefaultTrustModel = "collaborator"
}
// Handle preferred charset orders
preferred := make([]string, 0, len(Repository.DetectedCharsetsOrder))
for _, charset := range Repository.DetectedCharsetsOrder {
canonicalCharset := strings.ToLower(strings.TrimSpace(charset))
preferred = append(preferred, canonicalCharset)
// remove it from the defaults
for i, charset := range defaultDetectedCharsetsOrder {
if charset == canonicalCharset {
defaultDetectedCharsetsOrder = append(defaultDetectedCharsetsOrder[:i], defaultDetectedCharsetsOrder[i+1:]...)
break
}
}
}
i := 0
for _, charset := range preferred {
// Add the defaults
if charset == "defaults" {
for _, charset := range defaultDetectedCharsetsOrder {
canonicalCharset := strings.ToLower(strings.TrimSpace(charset))
if _, has := Repository.DetectedCharsetScore[canonicalCharset]; !has {
Repository.DetectedCharsetScore[canonicalCharset] = i
i++
}
}
continue
}
if _, has := Repository.DetectedCharsetScore[charset]; !has {
Repository.DetectedCharsetScore[charset] = i
i++
}
}
if !filepath.IsAbs(Repository.Upload.TempPath) {
Repository.Upload.TempPath = path.Join(AppWorkPath, Repository.Upload.TempPath)
}
if err := loadRepoArchiveFrom(rootCfg); err != nil {
log.Fatal("loadRepoArchiveFrom: %v", err)
}
Repository.EnableFlags = sec.Key("ENABLE_FLAGS").MustBool()
}