Browse Source

conf: overhaul repository settings (#5932)

ᴜɴᴋɴᴡᴏɴ 4 years ago
parent
commit
c4a0a40473

+ 2 - 0
CHANGELOG.md

@@ -37,6 +37,8 @@ All notable changes to Gogs are documented in this file.
 
 - Configuration option `[other] SHOW_FOOTER_VERSION`
 - Configuration option `[server] STATIC_ROOT_PATH`
+- Configuration option `[repository] MIRROR_QUEUE_LENGTH`
+- Configuration option `[repository] PULL_REQUEST_QUEUE_LENGTH`
 
 ---
 

+ 24 - 29
conf/app.ini

@@ -89,53 +89,48 @@ RSA     = 2048
 DSA     = 1024
 
 [repository]
-; Root path for storing repositories's data, default is "~/gogs-repositories"
+; The root path for storing managed repositories, default is "~/gogs-repositories"
 ROOT =
-; The script type server supports, sometimes could be "sh"
+; The script type server supports, sometimes could be "sh".
 SCRIPT_TYPE = bash
-; Default ANSI charset for an unrecognized charset
+; Default ANSI charset for an unrecognized charset.
 ANSI_CHARSET =
-; Force every new repository to be private
+; Whether to force every new repository to be private.
 FORCE_PRIVATE = false
-; Global maximum creation limit of repository per user, -1 means no limit
+; The global limit of number of repositories a user can create, -1 means no limit.
 MAX_CREATION_LIMIT = -1
-; Mirror sync queue length, increase if mirror syncing starts hanging
-MIRROR_QUEUE_LENGTH = 1000
-; Patch test queue length, increase if pull request patch testing starts hanging
-PULL_REQUEST_QUEUE_LENGTH = 1000
-; Preferred Licenses to place at the top of the list
-; Name must match file name in conf/license or custom/conf/license
-PREFERRED_LICENSES = Apache License 2.0,MIT License
-; Disable ability to interact with repositories by HTTP protocol
+; Preferred Licenses to place at the top of the list.
+; Name must match file name in "conf/license" or "custom/conf/license".
+PREFERRED_LICENSES = Apache License 2.0, MIT License
+; Whether to disable Git interaction with repositories via HTTP/HTTPS protocol.
 DISABLE_HTTP_GIT = false
-; Enable ability to migrate repository by local path
+; Whether to enable ability to migrate repository by server local path.
 ENABLE_LOCAL_PATH_MIGRATION = false
-; Concurrency is used to retrieve commits information. This variable define
-; the maximum number of tasks that can be run at the same time. Usually, the
-; value depend of how many CPUs (cores) you have. If the value is set to zero
-; or under, Gogs will automatically detect the number of CPUs your system have
-COMMITS_FETCH_CONCURRENCY = 0
-; Enable render mode for raw file
+; Whether to enable render mode for raw file. There are potential security risks.
 ENABLE_RAW_FILE_RENDER_MODE = false
+; The maximum number of goroutines that can be run at the same time for a single
+; fetch request. Usually, the value depend of how many CPU (cores) you have. If
+; the value is non-positive, it matchs the number of CPUs available to the application.
+COMMITS_FETCH_CONCURRENCY = 0
 
 [repository.editor]
 ; List of file extensions that should have line wraps in the CodeMirror editor.
-; Separate extensions with a comma. To line wrap files without extension, just put a comma
-LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,
-; Valid file modes that have a preview API associated with them, such as api/v1/markdown.
-; Separate values by commas. Preview tab in edit mode won't show if the file extension doesn't match
+; Separate extensions with a comma.
+LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd
+; Valid file modes that have a preview API associated with them, such as "/api/v1/markdown".
+; Separate values by commas. Preview tab in edit mode won't show if the file extension doesn't match.
 PREVIEWABLE_FILE_MODES = markdown
 
 [repository.upload]
-; Enable repository file uploads.
+; Whether to enable repository file uploads.
 ENABLED = true
-; Path to temporarily store uploads (default path gets cleaned by Gogs in every start)
+; The path to temporarily store uploads (content under this path gets wiped out on every start).
 TEMP_PATH = data/tmp/uploads
-; File types that are allowed to be uploaded, e.g. image/jpeg|image/png. Leave empty means allow any file type
+; File types that are allowed to be uploaded, e.g. "image/jpeg|image/png". Leave empty to allow any file type.
 ALLOWED_TYPES =
-; Maximum size of each file in MB
+; The maximum size of each file in MB.
 FILE_MAX_SIZE = 3
-; Maximum number of files per upload
+; The maximum number of files per upload.
 MAX_FILES = 5
 
 ; Attachment settings for releases

+ 19 - 10
conf/locale/locale_en-US.ini

@@ -1197,19 +1197,28 @@ config.ssh.listen_host = Listen host
 config.ssh.listen_port = Listen port
 config.ssh.server_ciphers = Server ciphers
 
+config.repo_config = Repository configuration
+config.repo.root_path = Root path
+config.repo.script_type = Script type
+config.repo.ansi_chatset = ANSI charset
+config.repo.force_private = Force private
+config.repo.max_creation_limit = Max creation limit
+config.repo.preferred_licenses = Preferred licenses
+config.repo.disable_http_git = Disable HTTP Git
+config.repo.enable_local_path_migration = Enable local path migration
+config.repo.enable_raw_file_render_mode = Enable raw file render mode
+config.repo.commits_fetch_concurrency = Commits fetch concurrency
+config.repo.editor.line_wrap_extensions = Editor line wrap extensions
+config.repo.editor.previewable_file_modes = Editor previewable file modes
+config.repo.upload.enabled = Upload enabled
+config.repo.upload.temp_path = Upload temporary path
+config.repo.upload.allowed_types = Upload allowed types
+config.repo.upload.file_max_size = Upload file size limit
+config.repo.upload.max_files = Upload files limit
+
 config.log_file_root_path = Log File Root Path
 config.reverse_auth_user = Reverse Authentication User
 
-config.repo_config = Repository Configuration
-config.repo_root_path = Repository Root Path
-config.script_type = Script Type
-config.repo_force_private = Force Private
-config.max_creation_limit = Max Creation Limit
-config.preferred_licenses = Preferred Licenses
-config.disable_http_git = Disable HTTP Git
-config.enable_local_path_migration = Enable Local Path Migration
-config.commits_fetch_concurrency = Commits Fetch Concurrency
-
 config.http_config = HTTP Configuration
 config.http_access_control_allow_origin = Access Control Allow Origin
 

File diff suppressed because it is too large
+ 2 - 2
internal/assets/conf/conf_gen.go


File diff suppressed because it is too large
+ 0 - 1
internal/assets/public/public_gen.go


File diff suppressed because it is too large
+ 1 - 1
internal/assets/templates/templates_gen.go


+ 2 - 2
internal/cmd/backup.go

@@ -119,8 +119,8 @@ func runBackup(c *cli.Context) error {
 	// Repositories
 	if !c.Bool("exclude-repos") && !c.Bool("database-only") {
 		reposDump := filepath.Join(rootDir, "repositories.zip")
-		log.Info("Dumping repositories in '%s'", conf.RepoRootPath)
-		if err = zip.PackTo(conf.RepoRootPath, reposDump, true); err != nil {
+		log.Info("Dumping repositories in %q", conf.Repository.Root)
+		if err = zip.PackTo(conf.Repository.Root, reposDump, true); err != nil {
 			log.Fatal("Failed to dump repositories: %v", err)
 		}
 		log.Info("Repositories dumped to: %s", reposDump)

+ 1 - 1
internal/cmd/restore.go

@@ -145,7 +145,7 @@ func runRestore(c *cli.Context) error {
 	// Repositories
 	reposPath := filepath.Join(archivePath, "repositories.zip")
 	if !c.Bool("exclude-repos") && !c.Bool("database-only") && com.IsExist(reposPath) {
-		if err := zip.ExtractTo(reposPath, filepath.Dir(conf.RepoRootPath)); err != nil {
+		if err := zip.ExtractTo(reposPath, filepath.Dir(conf.Repository.Root)); err != nil {
 			log.Fatal("Failed to extract 'repositories.zip': %v", err)
 		}
 	}

+ 1 - 1
internal/cmd/serv.go

@@ -267,7 +267,7 @@ func runServ(c *cli.Context) error {
 			RepoPath:  repo.RepoPath(),
 		})...)
 	}
-	gitCmd.Dir = conf.RepoRootPath
+	gitCmd.Dir = conf.Repository.Root
 	gitCmd.Stdout = os.Stdout
 	gitCmd.Stdin = os.Stdin
 	gitCmd.Stderr = os.Stderr

+ 17 - 60
internal/conf/conf.go

@@ -100,6 +100,7 @@ func Init(customConf string) error {
 	if err = File.Section("server").MapTo(&Server); err != nil {
 		return errors.Wrap(err, "mapping [server] section")
 	}
+	Server.AppDataPath = ensureAbs(Server.AppDataPath)
 
 	if !strings.HasSuffix(Server.ExternalURL, "/") {
 		Server.ExternalURL += "/"
@@ -122,22 +123,19 @@ func Init(customConf string) error {
 	}
 	Server.UnixSocketMode = os.FileMode(unixSocketMode)
 
-	if !filepath.IsAbs(Server.AppDataPath) {
-		Server.AppDataPath = filepath.Join(WorkDir(), Server.AppDataPath)
-	}
-
 	// ************************
 	// ----- SSH settings -----
 	// ************************
 
+	SSH.RootPath = filepath.Join(HomeDir(), ".ssh")
+	SSH.KeyTestPath = os.TempDir()
 	if err = File.Section("server").MapTo(&SSH); err != nil {
 		return errors.Wrap(err, "mapping SSH settings from [server] section")
 	}
+	SSH.RootPath = ensureAbs(SSH.RootPath)
+	SSH.KeyTestPath = ensureAbs(SSH.KeyTestPath)
 
 	if !SSH.Disabled {
-		SSH.RootPath = filepath.Join(HomeDir(), ".ssh")
-		SSH.KeyTestPath = os.TempDir()
-
 		if !SSH.StartBuiltinServer {
 			if err := os.MkdirAll(SSH.RootPath, 0700); err != nil {
 				return errors.Wrap(err, "create SSH root directory")
@@ -173,7 +171,18 @@ func Init(customConf string) error {
 		}
 	}
 
-	transferDeprecated()
+	// *******************************
+	// ----- Repository settings -----
+	// *******************************
+
+	Repository.Root = filepath.Join(HomeDir(), "gogs-repositories")
+	if err = File.Section("repository").MapTo(&Repository); err != nil {
+		return errors.Wrap(err, "mapping [repository] section")
+	}
+	Repository.Root = ensureAbs(Repository.Root)
+	Repository.Upload.TempPath = ensureAbs(Repository.Upload.TempPath)
+
+	handleDeprecated()
 
 	// TODO
 
@@ -224,27 +233,6 @@ func Init(customConf string) error {
 		"StampNano":   time.StampNano,
 	}[File.Section("time").Key("FORMAT").MustString("RFC1123")]
 
-	// Determine and create root git repository path.
-	sec = File.Section("repository")
-	RepoRootPath = sec.Key("ROOT").MustString(filepath.Join(HomeDir(), "gogs-repositories"))
-	if !filepath.IsAbs(RepoRootPath) {
-		RepoRootPath = path.Join(workDir, RepoRootPath)
-	} else {
-		RepoRootPath = path.Clean(RepoRootPath)
-	}
-	ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
-	if err = File.Section("repository").MapTo(&Repository); err != nil {
-		log.Fatal("Failed to map Repository settings: %v", err)
-	} else if err = File.Section("repository.editor").MapTo(&Repository.Editor); err != nil {
-		log.Fatal("Failed to map Repository.Editor settings: %v", err)
-	} else if err = File.Section("repository.upload").MapTo(&Repository.Upload); err != nil {
-		log.Fatal("Failed to map Repository.Upload settings: %v", err)
-	}
-
-	if !filepath.IsAbs(Repository.Upload.TempPath) {
-		Repository.Upload.TempPath = path.Join(workDir, Repository.Upload.TempPath)
-	}
-
 	sec = File.Section("picture")
 	AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString(filepath.Join(Server.AppDataPath, "avatars"))
 	if !filepath.IsAbs(AvatarUploadPath) {
@@ -361,37 +349,6 @@ var (
 	UsePostgreSQL bool
 	UseMSSQL      bool
 
-	// Repository settings
-	Repository struct {
-		AnsiCharset              string
-		ForcePrivate             bool
-		MaxCreationLimit         int
-		MirrorQueueLength        int
-		PullRequestQueueLength   int
-		PreferredLicenses        []string
-		DisableHTTPGit           bool `ini:"DISABLE_HTTP_GIT"`
-		EnableLocalPathMigration bool
-		CommitsFetchConcurrency  int
-		EnableRawFileRenderMode  bool
-
-		// Repository editor settings
-		Editor struct {
-			LineWrapExtensions   []string
-			PreviewableFileModes []string
-		} `ini:"-"`
-
-		// Repository upload settings
-		Upload struct {
-			Enabled      bool
-			TempPath     string
-			AllowedTypes []string `delim:"|"`
-			FileMaxSize  int64
-			MaxFiles     int
-		} `ini:"-"`
-	}
-	RepoRootPath string
-	ScriptType   string
-
 	// Webhook settings
 	Webhook struct {
 		Types          []string

+ 37 - 4
internal/conf/static.go

@@ -12,9 +12,13 @@ import (
 // ℹ️ README: This file contains static values that should only be set at initialization time.
 
 // HasMinWinSvc is whether the application is built with Windows Service support.
+//
+// ⚠️ WARNING: should only be set by "static_minwinsvc.go".
 var HasMinWinSvc bool
 
-// Build information should only be set by -ldflags.
+// Build time and commit information.
+//
+// ⚠️ WARNING: should only be set by -ldflags.
 var (
 	BuildTime   string
 	BuildCommit string
@@ -28,7 +32,7 @@ var CustomConf string
 var (
 	// Application settings
 	App struct {
-		// ⚠️ WARNING: Should only be set by gogs.go.
+		// ⚠️ WARNING: Should only be set by main package (i.e. "gogs.go").
 		Version string `ini:"-"`
 
 		BrandName string
@@ -90,10 +94,39 @@ var (
 		ListenPort         int      `ini:"SSH_LISTEN_PORT"`
 		ServerCiphers      []string `ini:"SSH_SERVER_CIPHERS"`
 	}
+
+	// Repository settings
+	Repository struct {
+		Root                     string
+		ScriptType               string
+		ANSICharset              string `ini:"ANSI_CHARSET"`
+		ForcePrivate             bool
+		MaxCreationLimit         int
+		PreferredLicenses        []string
+		DisableHTTPGit           bool `ini:"DISABLE_HTTP_GIT"`
+		EnableLocalPathMigration bool
+		EnableRawFileRenderMode  bool
+		CommitsFetchConcurrency  int
+
+		// Repository editor settings
+		Editor struct {
+			LineWrapExtensions   []string
+			PreviewableFileModes []string
+		} `ini:"repository.editor"`
+
+		// Repository upload settings
+		Upload struct {
+			Enabled      bool
+			TempPath     string
+			AllowedTypes []string `delim:"|"`
+			FileMaxSize  int64
+			MaxFiles     int
+		} `ini:"repository.upload"`
+	}
 )
 
-// transferDeprecated transfers deprecated values to the new ones when set.
-func transferDeprecated() {
+// handleDeprecated transfers deprecated values to the new ones when set.
+func handleDeprecated() {
 	if App.AppName != "" {
 		App.BrandName = App.AppName
 		App.AppName = ""

+ 9 - 0
internal/conf/utils.go

@@ -5,6 +5,7 @@
 package conf
 
 import (
+	"path/filepath"
 	"strings"
 
 	"github.com/pkg/errors"
@@ -25,3 +26,11 @@ func openSSHVersion() (string, error) {
 	v = strings.TrimSuffix(strings.TrimPrefix(v, "OpenSSH_"), "p")
 	return v, nil
 }
+
+// ensureAbs prepends the WorkDir to the given path if it is not an absolute path.
+func ensureAbs(path string) string {
+	if filepath.IsAbs(path) {
+		return path
+	}
+	return filepath.Join(WorkDir(), path)
+}

+ 4 - 4
internal/db/migrations/v15.go

@@ -32,9 +32,9 @@ func generateAndMigrateGitHooks(x *xorm.Engine) (err error) {
 	var (
 		hookNames = []string{"pre-receive", "update", "post-receive"}
 		hookTpls  = []string{
-			fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' pre-receive\n", conf.ScriptType, conf.AppPath(), conf.CustomConf),
-			fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' update $1 $2 $3\n", conf.ScriptType, conf.AppPath(), conf.CustomConf),
-			fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' post-receive\n", conf.ScriptType, conf.AppPath(), conf.CustomConf),
+			fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' pre-receive\n", conf.Repository.ScriptType, conf.AppPath(), conf.CustomConf),
+			fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' update $1 $2 $3\n", conf.Repository.ScriptType, conf.AppPath(), conf.CustomConf),
+			fmt.Sprintf("#!/usr/bin/env %s\n\"%s\" hook --config='%s' post-receive\n", conf.Repository.ScriptType, conf.AppPath(), conf.CustomConf),
 		}
 	)
 
@@ -63,7 +63,7 @@ func generateAndMigrateGitHooks(x *xorm.Engine) (err error) {
 				return nil
 			}
 
-			repoBase := filepath.Join(conf.RepoRootPath, strings.ToLower(user.Name), strings.ToLower(repo.Name))
+			repoBase := filepath.Join(conf.Repository.Root, strings.ToLower(user.Name), strings.ToLower(repo.Name))
 			repoPath := repoBase + ".git"
 			wikiPath := repoBase + ".wiki.git"
 			log.Trace("[%04d]: %s", idx, repoPath)

+ 1 - 1
internal/db/migrations/v16.go

@@ -60,7 +60,7 @@ func updateRepositorySizes(x *xorm.Engine) (err error) {
 				continue
 			}
 
-			repoPath := filepath.Join(conf.RepoRootPath, strings.ToLower(user.Name), strings.ToLower(repo.Name)) + ".git"
+			repoPath := filepath.Join(conf.Repository.Root, strings.ToLower(user.Name), strings.ToLower(repo.Name)) + ".git"
 			countObject, err := git.GetRepoSize(repoPath)
 			if err != nil {
 				log.Warn("GetRepoSize: %v", err)

+ 2 - 2
internal/db/mirror.go

@@ -18,13 +18,13 @@ import (
 
 	"github.com/gogs/git-module"
 
+	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/process"
-	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/sync"
 )
 
-var MirrorQueue = sync.NewUniqueQueue(conf.Repository.MirrorQueueLength)
+var MirrorQueue = sync.NewUniqueQueue(1000)
 
 // Mirror represents mirror information of a repository.
 type Mirror struct {

+ 1 - 1
internal/db/pull.go

@@ -26,7 +26,7 @@ import (
 	"gogs.io/gogs/internal/sync"
 )
 
-var PullRequestQueue = sync.NewUniqueQueue(conf.Repository.PullRequestQueueLength)
+var PullRequestQueue = sync.NewUniqueQueue(1000)
 
 type PullRequestType int
 

+ 1 - 1
internal/db/repo.go

@@ -857,7 +857,7 @@ func createDelegateHooks(repoPath string) (err error) {
 	for _, name := range git.HookNames {
 		hookPath := filepath.Join(repoPath, "hooks", name)
 		if err = ioutil.WriteFile(hookPath,
-			[]byte(fmt.Sprintf(hooksTpls[name], conf.ScriptType, conf.AppPath(), conf.CustomConf)),
+			[]byte(fmt.Sprintf(hooksTpls[name], conf.Repository.ScriptType, conf.AppPath(), conf.CustomConf)),
 			os.ModePerm); err != nil {
 			return fmt.Errorf("create delegate hook '%s': %v", hookPath, err)
 		}

+ 1 - 1
internal/db/user.go

@@ -877,7 +877,7 @@ func DeleteInactivateUsers() (err error) {
 
 // UserPath returns the path absolute path of user repositories.
 func UserPath(userName string) string {
-	return filepath.Join(conf.RepoRootPath, strings.ToLower(userName))
+	return filepath.Join(conf.Repository.Root, strings.ToLower(userName))
 }
 
 func GetUserByKeyID(keyID int64) (*User, error) {

+ 1 - 3
internal/route/admin/admin.go

@@ -199,13 +199,11 @@ func Config(c *context.Context) {
 	c.Data["App"] = conf.App
 	c.Data["Server"] = conf.Server
 	c.Data["SSH"] = conf.SSH
+	c.Data["Repository"] = conf.Repository
 
 	c.Data["LogRootPath"] = conf.LogRootPath
 	c.Data["ReverseProxyAuthUser"] = conf.ReverseProxyAuthUser
 
-	c.Data["RepoRootPath"] = conf.RepoRootPath
-	c.Data["ScriptType"] = conf.ScriptType
-	c.Data["Repository"] = conf.Repository
 	c.Data["HTTP"] = conf.HTTP
 
 	c.Data["DbCfg"] = db.DbCfg

+ 1 - 1
internal/route/install.go

@@ -155,7 +155,7 @@ func Install(c *context.Context) {
 
 	// Application general settings
 	f.AppName = conf.App.BrandName
-	f.RepoRootPath = conf.RepoRootPath
+	f.RepoRootPath = conf.Repository.Root
 
 	// Note(unknwon): it's hard for Windows users change a running user,
 	// 	so just use current one if config says default.

+ 2 - 2
internal/route/repo/http.go

@@ -19,11 +19,11 @@ import (
 	"gopkg.in/macaron.v1"
 	log "unknwon.dev/clog/v2"
 
+	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/context"
 	"gogs.io/gogs/internal/db"
 	"gogs.io/gogs/internal/db/errors"
 	"gogs.io/gogs/internal/lazyregexp"
-	"gogs.io/gogs/internal/conf"
 	"gogs.io/gogs/internal/tool"
 )
 
@@ -368,7 +368,7 @@ func getGitRepoPath(dir string) (string, error) {
 		dir += ".git"
 	}
 
-	filename := path.Join(conf.RepoRootPath, dir)
+	filename := path.Join(conf.Repository.Root, dir)
 	if _, err := os.Stat(filename); os.IsNotExist(err) {
 		return "", err
 	}

+ 3 - 3
internal/tool/tool.go

@@ -62,9 +62,9 @@ func DetectEncoding(content []byte) (string, error) {
 	}
 
 	result, err := chardet.NewTextDetector().DetectBest(content)
-	if result.Charset != "UTF-8" && len(conf.Repository.AnsiCharset) > 0 {
-		log.Trace("Using default AnsiCharset: %s", conf.Repository.AnsiCharset)
-		return conf.Repository.AnsiCharset, err
+	if result.Charset != "UTF-8" && len(conf.Repository.ANSICharset) > 0 {
+		log.Trace("Using default ANSICharset: %s", conf.Repository.ANSICharset)
+		return conf.Repository.ANSICharset, err
 	}
 
 	log.Trace("Detected encoding: %s", result.Charset)

+ 38 - 11
templates/admin/config.tmpl

@@ -5,6 +5,8 @@
 			{{template "admin/navbar" .}}
 			<div class="twelve wide column content">
 				{{template "base/alert" .}}
+
+				{{/*	Server settings	*/}}
 				<h4 class="ui top attached header">
 					{{.i18n.Tr "admin.config.server_config"}}
 				</h4>
@@ -70,6 +72,7 @@
 					</dl>
 				</div>
 
+				{{/*	SSH settings	*/}}
 				<h4 class="ui top attached header">
 					{{.i18n.Tr "admin.config.ssh_config"}}
 				</h4>
@@ -109,28 +112,52 @@
 					</dl>
 				</div>
 
-				<!-- Repository Configuration -->
+				{{/*	Repository settings	*/}}
 				<h4 class="ui top attached header">
 					{{.i18n.Tr "admin.config.repo_config"}}
 				</h4>
 				<div class="ui attached table segment">
 					<dl class="dl-horizontal admin-dl-horizontal">
-						<dt>{{.i18n.Tr "admin.config.repo_root_path"}}</dt>
-						<dd><code>{{.RepoRootPath}}</code></dd>
-						<dt>{{.i18n.Tr "admin.config.script_type"}}</dt>
-						<dd>{{.ScriptType}}</dd>
-						<dt>{{.i18n.Tr "admin.config.repo_force_private"}}</dt>
+						<dt>{{.i18n.Tr "admin.config.repo.root_path"}}</dt>
+						<dd><code>{{.Repository.Root}}</code></dd>
+						<dt>{{.i18n.Tr "admin.config.repo.script_type"}}</dt>
+						<dd><code>{{.Repository.ScriptType}}</code></dd>
+						<dt>{{.i18n.Tr "admin.config.repo.ansi_chatset"}}</dt>
+						<dd>{{if .Repository.ANSICharset}}{{.Repository.AnsiCharset}}{{else}}{{.i18n.Tr "admin.config.not_set"}}{{end}}</dd>
+						<dt>{{.i18n.Tr "admin.config.repo.force_private"}}</dt>
 						<dd><i class="fa fa{{if .Repository.ForcePrivate}}-check{{end}}-square-o"></i></dd>
-						<dt>{{.i18n.Tr "admin.config.max_creation_limit"}}</dt>
+						<dt>{{.i18n.Tr "admin.config.repo.max_creation_limit"}}</dt>
 						<dd>{{.Repository.MaxCreationLimit}}</dd>
-						<dt>{{.i18n.Tr "admin.config.preferred_licenses"}}</dt>
+						<dt>{{.i18n.Tr "admin.config.repo.preferred_licenses"}}</dt>
 						<dd>{{Join .Repository.PreferredLicenses ", "}}</dd>
-						<dt>{{.i18n.Tr "admin.config.disable_http_git"}}</dt>
+						<dt>{{.i18n.Tr "admin.config.repo.disable_http_git"}}</dt>
 						<dd><i class="fa fa{{if .Repository.DisableHTTPGit}}-check{{end}}-square-o"></i></dd>
-						<dt>{{.i18n.Tr "admin.config.enable_local_path_migration"}}</dt>
+						<dt>{{.i18n.Tr "admin.config.repo.enable_local_path_migration"}}</dt>
 						<dd><i class="fa fa{{if .Repository.EnableLocalPathMigration}}-check{{end}}-square-o"></i></dd>
-						<dt>{{.i18n.Tr "admin.config.commits_fetch_concurrency"}}</dt>
+						<dt>{{.i18n.Tr "admin.config.repo.enable_raw_file_render_mode"}}</dt>
+						<dd><i class="fa fa{{if .Repository.EnableRawFileRenderMode}}-check{{end}}-square-o"></i></dd>
+						<dt>{{.i18n.Tr "admin.config.repo.commits_fetch_concurrency"}}</dt>
 						<dd>{{.Repository.CommitsFetchConcurrency}}</dd>
+
+						<div class="ui divider"></div>
+
+						<dt>{{.i18n.Tr "admin.config.repo.editor.line_wrap_extensions"}}</dt>
+						<dd><code>{{.Repository.Editor.LineWrapExtensions}}</code></dd>
+						<dt>{{.i18n.Tr "admin.config.repo.editor.previewable_file_modes"}}</dt>
+						<dd><code>{{.Repository.Editor.PreviewableFileModes}}</code></dd>
+
+						<div class="ui divider"></div>
+
+						<dt>{{.i18n.Tr "admin.config.repo.upload.enabled"}}</dt>
+						<dd><i class="fa fa{{if .Repository.Upload.Enabled}}-check{{end}}-square-o"></i></dd>
+						<dt>{{.i18n.Tr "admin.config.repo.upload.temp_path"}}</dt>
+						<dd><code>{{.Repository.Upload.TempPath}}</code></dd>
+						<dt>{{.i18n.Tr "admin.config.repo.upload.allowed_types"}}</dt>
+						<dd><code>{{.Repository.Upload.AllowedTypes}}</code></dd>
+						<dt>{{.i18n.Tr "admin.config.repo.upload.file_max_size"}}</dt>
+						<dd>{{.Repository.Upload.FileMaxSize}} MB</dd>
+						<dt>{{.i18n.Tr "admin.config.repo.upload.max_files"}}</dt>
+						<dd>{{.Repository.Upload.MaxFiles}}</dd>
 					</dl>
 				</div>
 

Some files were not shown because too many files changed in this diff