diff --git a/modules/setting/cron.go b/modules/setting/cron.go
new file mode 100644
index 0000000000..48298b453c
--- /dev/null
+++ b/modules/setting/cron.go
@@ -0,0 +1,124 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+	"time"
+
+	"code.gitea.io/gitea/modules/log"
+)
+
+var (
+
+	// Cron tasks
+	Cron = struct {
+		UpdateMirror struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+		} `ini:"cron.update_mirrors"`
+		RepoHealthCheck struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+			Timeout    time.Duration
+			Args       []string `delim:" "`
+		} `ini:"cron.repo_health_check"`
+		CheckRepoStats struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+		} `ini:"cron.check_repo_stats"`
+		ArchiveCleanup struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+			OlderThan  time.Duration
+		} `ini:"cron.archive_cleanup"`
+		SyncExternalUsers struct {
+			Enabled        bool
+			RunAtStart     bool
+			Schedule       string
+			UpdateExisting bool
+		} `ini:"cron.sync_external_users"`
+		DeletedBranchesCleanup struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+			OlderThan  time.Duration
+		} `ini:"cron.deleted_branches_cleanup"`
+	}{
+		UpdateMirror: struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+		}{
+			Enabled:    true,
+			RunAtStart: false,
+			Schedule:   "@every 10m",
+		},
+		RepoHealthCheck: struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+			Timeout    time.Duration
+			Args       []string `delim:" "`
+		}{
+			Enabled:    true,
+			RunAtStart: false,
+			Schedule:   "@every 24h",
+			Timeout:    60 * time.Second,
+			Args:       []string{},
+		},
+		CheckRepoStats: struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+		}{
+			Enabled:    true,
+			RunAtStart: true,
+			Schedule:   "@every 24h",
+		},
+		ArchiveCleanup: struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+			OlderThan  time.Duration
+		}{
+			Enabled:    true,
+			RunAtStart: true,
+			Schedule:   "@every 24h",
+			OlderThan:  24 * time.Hour,
+		},
+		SyncExternalUsers: struct {
+			Enabled        bool
+			RunAtStart     bool
+			Schedule       string
+			UpdateExisting bool
+		}{
+			Enabled:        true,
+			RunAtStart:     false,
+			Schedule:       "@every 24h",
+			UpdateExisting: true,
+		},
+		DeletedBranchesCleanup: struct {
+			Enabled    bool
+			RunAtStart bool
+			Schedule   string
+			OlderThan  time.Duration
+		}{
+			Enabled:    true,
+			RunAtStart: true,
+			Schedule:   "@every 24h",
+			OlderThan:  24 * time.Hour,
+		},
+	}
+)
+
+func newCron() {
+	if err := Cfg.Section("cron").MapTo(&Cron); err != nil {
+		log.Fatal(4, "Failed to map Cron settings: %v", err)
+	}
+}
diff --git a/modules/setting/git.go b/modules/setting/git.go
new file mode 100644
index 0000000000..59951fcb94
--- /dev/null
+++ b/modules/setting/git.go
@@ -0,0 +1,71 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+	"time"
+
+	"code.gitea.io/git"
+	"code.gitea.io/gitea/modules/log"
+	version "github.com/mcuadros/go-version"
+)
+
+var (
+	// Git settings
+	Git = struct {
+		Version                  string `ini:"-"`
+		DisableDiffHighlight     bool
+		MaxGitDiffLines          int
+		MaxGitDiffLineCharacters int
+		MaxGitDiffFiles          int
+		GCArgs                   []string `delim:" "`
+		Timeout                  struct {
+			Default int
+			Migrate int
+			Mirror  int
+			Clone   int
+			Pull    int
+			GC      int `ini:"GC"`
+		} `ini:"git.timeout"`
+	}{
+		DisableDiffHighlight:     false,
+		MaxGitDiffLines:          1000,
+		MaxGitDiffLineCharacters: 5000,
+		MaxGitDiffFiles:          100,
+		GCArgs:                   []string{},
+		Timeout: struct {
+			Default int
+			Migrate int
+			Mirror  int
+			Clone   int
+			Pull    int
+			GC      int `ini:"GC"`
+		}{
+			Default: int(git.DefaultCommandExecutionTimeout / time.Second),
+			Migrate: 600,
+			Mirror:  300,
+			Clone:   300,
+			Pull:    300,
+			GC:      60,
+		},
+	}
+)
+
+func newGit() {
+	if err := Cfg.Section("git").MapTo(&Git); err != nil {
+		log.Fatal(4, "Failed to map Git settings: %v", err)
+	}
+	git.DefaultCommandExecutionTimeout = time.Duration(Git.Timeout.Default) * time.Second
+
+	binVersion, err := git.BinVersion()
+	if err != nil {
+		log.Fatal(4, "Error retrieving git version: %v", err)
+	}
+
+	if version.Compare(binVersion, "2.9", ">=") {
+		// Explicitly disable credential helper, otherwise Git credentials might leak
+		git.GlobalCommandArgs = append(git.GlobalCommandArgs, "-c", "credential.helper=")
+	}
+}
diff --git a/modules/setting/markup.go b/modules/setting/markup.go
new file mode 100644
index 0000000000..41f3cdd3a1
--- /dev/null
+++ b/modules/setting/markup.go
@@ -0,0 +1,66 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+	"regexp"
+	"strings"
+
+	"code.gitea.io/gitea/modules/log"
+)
+
+// ExternalMarkupParsers represents the external markup parsers
+var (
+	ExternalMarkupParsers []MarkupParser
+)
+
+// MarkupParser defines the external parser configured in ini
+type MarkupParser struct {
+	Enabled        bool
+	MarkupName     string
+	Command        string
+	FileExtensions []string
+	IsInputFile    bool
+}
+
+func newMarkup() {
+	extensionReg := regexp.MustCompile(`\.\w`)
+	for _, sec := range Cfg.Section("markup").ChildSections() {
+		name := strings.TrimPrefix(sec.Name(), "markup.")
+		if name == "" {
+			log.Warn("name is empty, markup " + sec.Name() + "ignored")
+			continue
+		}
+
+		extensions := sec.Key("FILE_EXTENSIONS").Strings(",")
+		var exts = make([]string, 0, len(extensions))
+		for _, extension := range extensions {
+			if !extensionReg.MatchString(extension) {
+				log.Warn(sec.Name() + " file extension " + extension + " is invalid. Extension ignored")
+			} else {
+				exts = append(exts, extension)
+			}
+		}
+
+		if len(exts) == 0 {
+			log.Warn(sec.Name() + " file extension is empty, markup " + name + " ignored")
+			continue
+		}
+
+		command := sec.Key("RENDER_COMMAND").MustString("")
+		if command == "" {
+			log.Warn(" RENDER_COMMAND is empty, markup " + name + " ignored")
+			continue
+		}
+
+		ExternalMarkupParsers = append(ExternalMarkupParsers, MarkupParser{
+			Enabled:        sec.Key("ENABLED").MustBool(false),
+			MarkupName:     name,
+			FileExtensions: exts,
+			Command:        command,
+			IsInputFile:    sec.Key("IS_INPUT_FILE").MustBool(false),
+		})
+	}
+}
diff --git a/modules/setting/repository.go b/modules/setting/repository.go
new file mode 100644
index 0000000000..5880071286
--- /dev/null
+++ b/modules/setting/repository.go
@@ -0,0 +1,168 @@
+// Copyright 2019 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package setting
+
+import (
+	"path"
+	"path/filepath"
+	"strings"
+
+	"code.gitea.io/gitea/modules/log"
+	"github.com/Unknwon/com"
+)
+
+// enumerates all the policy repository creating
+const (
+	RepoCreatingLastUserVisibility = "last"
+	RepoCreatingPrivate            = "private"
+	RepoCreatingPublic             = "public"
+)
+
+// Repository settings
+var (
+	Repository = struct {
+		AnsiCharset                             string
+		ForcePrivate                            bool
+		DefaultPrivate                          string
+		MaxCreationLimit                        int
+		MirrorQueueLength                       int
+		PullRequestQueueLength                  int
+		PreferredLicenses                       []string
+		DisableHTTPGit                          bool
+		AccessControlAllowOrigin                string
+		UseCompatSSHURI                         bool
+		DefaultCloseIssuesViaCommitsInAnyBranch 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:"-"`
+
+		// Repository local settings
+		Local struct {
+			LocalCopyPath string
+			LocalWikiPath string
+		} `ini:"-"`
+
+		// Pull request settings
+		PullRequest struct {
+			WorkInProgressPrefixes []string
+		} `ini:"repository.pull-request"`
+
+		// Issue Setting
+		Issue struct {
+			LockReasons []string
+		} `ini:"repository.issue"`
+	}{
+		AnsiCharset:                             "",
+		ForcePrivate:                            false,
+		DefaultPrivate:                          RepoCreatingLastUserVisibility,
+		MaxCreationLimit:                        -1,
+		MirrorQueueLength:                       1000,
+		PullRequestQueueLength:                  1000,
+		PreferredLicenses:                       []string{"Apache License 2.0,MIT License"},
+		DisableHTTPGit:                          false,
+		AccessControlAllowOrigin:                "",
+		UseCompatSSHURI:                         false,
+		DefaultCloseIssuesViaCommitsInAnyBranch: false,
+
+		// Repository editor settings
+		Editor: struct {
+			LineWrapExtensions   []string
+			PreviewableFileModes []string
+		}{
+			LineWrapExtensions:   strings.Split(".txt,.md,.markdown,.mdown,.mkd,", ","),
+			PreviewableFileModes: []string{"markdown"},
+		},
+
+		// Repository upload settings
+		Upload: struct {
+			Enabled      bool
+			TempPath     string
+			AllowedTypes []string `delim:"|"`
+			FileMaxSize  int64
+			MaxFiles     int
+		}{
+			Enabled:      true,
+			TempPath:     "data/tmp/uploads",
+			AllowedTypes: []string{},
+			FileMaxSize:  3,
+			MaxFiles:     5,
+		},
+
+		// Repository local settings
+		Local: struct {
+			LocalCopyPath string
+			LocalWikiPath string
+		}{
+			LocalCopyPath: "tmp/local-repo",
+			LocalWikiPath: "tmp/local-wiki",
+		},
+
+		// Pull request settings
+		PullRequest: struct {
+			WorkInProgressPrefixes []string
+		}{
+			WorkInProgressPrefixes: []string{"WIP:", "[WIP]"},
+		},
+
+		// Issue settings
+		Issue: struct {
+			LockReasons []string
+		}{
+			LockReasons: strings.Split("Too heated,Off-topic,Spam,Resolved", ","),
+		},
+	}
+	RepoRootPath string
+	ScriptType   = "bash"
+)
+
+func newRepository() {
+	homeDir, err := com.HomeDir()
+	if err != nil {
+		log.Fatal(4, "Failed to get home directory: %v", err)
+	}
+	homeDir = strings.Replace(homeDir, "\\", "/", -1)
+
+	// Determine and create root git repository path.
+	sec := Cfg.Section("repository")
+	Repository.DisableHTTPGit = sec.Key("DISABLE_HTTP_GIT").MustBool()
+	Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool()
+	Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1)
+	RepoRootPath = sec.Key("ROOT").MustString(path.Join(homeDir, "gitea-repositories"))
+	forcePathSeparator(RepoRootPath)
+	if !filepath.IsAbs(RepoRootPath) {
+		RepoRootPath = filepath.Join(AppWorkPath, RepoRootPath)
+	} else {
+		RepoRootPath = filepath.Clean(RepoRootPath)
+	}
+	ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
+
+	if err = Cfg.Section("repository").MapTo(&Repository); err != nil {
+		log.Fatal(4, "Failed to map Repository settings: %v", err)
+	} else if err = Cfg.Section("repository.editor").MapTo(&Repository.Editor); err != nil {
+		log.Fatal(4, "Failed to map Repository.Editor settings: %v", err)
+	} else if err = Cfg.Section("repository.upload").MapTo(&Repository.Upload); err != nil {
+		log.Fatal(4, "Failed to map Repository.Upload settings: %v", err)
+	} else if err = Cfg.Section("repository.local").MapTo(&Repository.Local); err != nil {
+		log.Fatal(4, "Failed to map Repository.Local settings: %v", err)
+	} else if err = Cfg.Section("repository.pull-request").MapTo(&Repository.PullRequest); err != nil {
+		log.Fatal(4, "Failed to map Repository.PullRequest settings: %v", err)
+	}
+
+	if !filepath.IsAbs(Repository.Upload.TempPath) {
+		Repository.Upload.TempPath = path.Join(AppWorkPath, Repository.Upload.TempPath)
+	}
+}
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 0962c5d726..ac44f54f0a 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -15,7 +15,6 @@ import (
 	"os/exec"
 	"path"
 	"path/filepath"
-	"regexp"
 	"runtime"
 	"strconv"
 	"strings"
@@ -63,22 +62,6 @@ const (
 	LandingPageOrganizations LandingPage = "/explore/organizations"
 )
 
-// MarkupParser defines the external parser configured in ini
-type MarkupParser struct {
-	Enabled        bool
-	MarkupName     string
-	Command        string
-	FileExtensions []string
-	IsInputFile    bool
-}
-
-// enumerates all the policy repository creating
-const (
-	RepoCreatingLastUserVisibility = "last"
-	RepoCreatingPrivate            = "private"
-	RepoCreatingPublic             = "public"
-)
-
 // enumerates all the types of captchas
 const (
 	ImageCaptcha = "image"
@@ -181,113 +164,6 @@ var (
 	DBConnectRetries int
 	DBConnectBackoff time.Duration
 
-	// Repository settings
-	Repository = struct {
-		AnsiCharset                             string
-		ForcePrivate                            bool
-		DefaultPrivate                          string
-		MaxCreationLimit                        int
-		MirrorQueueLength                       int
-		PullRequestQueueLength                  int
-		PreferredLicenses                       []string
-		DisableHTTPGit                          bool
-		AccessControlAllowOrigin                string
-		UseCompatSSHURI                         bool
-		DefaultCloseIssuesViaCommitsInAnyBranch 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:"-"`
-
-		// Repository local settings
-		Local struct {
-			LocalCopyPath string
-			LocalWikiPath string
-		} `ini:"-"`
-
-		// Pull request settings
-		PullRequest struct {
-			WorkInProgressPrefixes []string
-		} `ini:"repository.pull-request"`
-
-		// Issue Setting
-		Issue struct {
-			LockReasons []string
-		} `ini:"repository.issue"`
-	}{
-		AnsiCharset:                             "",
-		ForcePrivate:                            false,
-		DefaultPrivate:                          RepoCreatingLastUserVisibility,
-		MaxCreationLimit:                        -1,
-		MirrorQueueLength:                       1000,
-		PullRequestQueueLength:                  1000,
-		PreferredLicenses:                       []string{"Apache License 2.0,MIT License"},
-		DisableHTTPGit:                          false,
-		AccessControlAllowOrigin:                "",
-		UseCompatSSHURI:                         false,
-		DefaultCloseIssuesViaCommitsInAnyBranch: false,
-
-		// Repository editor settings
-		Editor: struct {
-			LineWrapExtensions   []string
-			PreviewableFileModes []string
-		}{
-			LineWrapExtensions:   strings.Split(".txt,.md,.markdown,.mdown,.mkd,", ","),
-			PreviewableFileModes: []string{"markdown"},
-		},
-
-		// Repository upload settings
-		Upload: struct {
-			Enabled      bool
-			TempPath     string
-			AllowedTypes []string `delim:"|"`
-			FileMaxSize  int64
-			MaxFiles     int
-		}{
-			Enabled:      true,
-			TempPath:     "data/tmp/uploads",
-			AllowedTypes: []string{},
-			FileMaxSize:  3,
-			MaxFiles:     5,
-		},
-
-		// Repository local settings
-		Local: struct {
-			LocalCopyPath string
-			LocalWikiPath string
-		}{
-			LocalCopyPath: "tmp/local-repo",
-			LocalWikiPath: "tmp/local-wiki",
-		},
-
-		// Pull request settings
-		PullRequest: struct {
-			WorkInProgressPrefixes []string
-		}{
-			WorkInProgressPrefixes: []string{"WIP:", "[WIP]"},
-		},
-
-		// Issue settings
-		Issue: struct {
-			LockReasons []string
-		}{
-			LockReasons: strings.Split("Too heated,Off-topic,Spam,Resolved", ","),
-		},
-	}
-	RepoRootPath string
-	ScriptType   = "bash"
-
 	// UI settings
 	UI = struct {
 		ExplorePagingNum    int
@@ -400,149 +276,6 @@ var (
 
 	CSRFCookieName = "_csrf"
 
-	// Cron tasks
-	Cron = struct {
-		UpdateMirror struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-		} `ini:"cron.update_mirrors"`
-		RepoHealthCheck struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-			Timeout    time.Duration
-			Args       []string `delim:" "`
-		} `ini:"cron.repo_health_check"`
-		CheckRepoStats struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-		} `ini:"cron.check_repo_stats"`
-		ArchiveCleanup struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-			OlderThan  time.Duration
-		} `ini:"cron.archive_cleanup"`
-		SyncExternalUsers struct {
-			Enabled        bool
-			RunAtStart     bool
-			Schedule       string
-			UpdateExisting bool
-		} `ini:"cron.sync_external_users"`
-		DeletedBranchesCleanup struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-			OlderThan  time.Duration
-		} `ini:"cron.deleted_branches_cleanup"`
-	}{
-		UpdateMirror: struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-		}{
-			Enabled:    true,
-			RunAtStart: false,
-			Schedule:   "@every 10m",
-		},
-		RepoHealthCheck: struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-			Timeout    time.Duration
-			Args       []string `delim:" "`
-		}{
-			Enabled:    true,
-			RunAtStart: false,
-			Schedule:   "@every 24h",
-			Timeout:    60 * time.Second,
-			Args:       []string{},
-		},
-		CheckRepoStats: struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-		}{
-			Enabled:    true,
-			RunAtStart: true,
-			Schedule:   "@every 24h",
-		},
-		ArchiveCleanup: struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-			OlderThan  time.Duration
-		}{
-			Enabled:    true,
-			RunAtStart: true,
-			Schedule:   "@every 24h",
-			OlderThan:  24 * time.Hour,
-		},
-		SyncExternalUsers: struct {
-			Enabled        bool
-			RunAtStart     bool
-			Schedule       string
-			UpdateExisting bool
-		}{
-			Enabled:        true,
-			RunAtStart:     false,
-			Schedule:       "@every 24h",
-			UpdateExisting: true,
-		},
-		DeletedBranchesCleanup: struct {
-			Enabled    bool
-			RunAtStart bool
-			Schedule   string
-			OlderThan  time.Duration
-		}{
-			Enabled:    true,
-			RunAtStart: true,
-			Schedule:   "@every 24h",
-			OlderThan:  24 * time.Hour,
-		},
-	}
-
-	// Git settings
-	Git = struct {
-		Version                  string `ini:"-"`
-		DisableDiffHighlight     bool
-		MaxGitDiffLines          int
-		MaxGitDiffLineCharacters int
-		MaxGitDiffFiles          int
-		GCArgs                   []string `delim:" "`
-		Timeout                  struct {
-			Default int
-			Migrate int
-			Mirror  int
-			Clone   int
-			Pull    int
-			GC      int `ini:"GC"`
-		} `ini:"git.timeout"`
-	}{
-		DisableDiffHighlight:     false,
-		MaxGitDiffLines:          1000,
-		MaxGitDiffLineCharacters: 5000,
-		MaxGitDiffFiles:          100,
-		GCArgs:                   []string{},
-		Timeout: struct {
-			Default int
-			Migrate int
-			Mirror  int
-			Clone   int
-			Pull    int
-			GC      int `ini:"GC"`
-		}{
-			Default: int(git.DefaultCommandExecutionTimeout / time.Second),
-			Migrate: 600,
-			Mirror:  300,
-			Clone:   300,
-			Pull:    300,
-			GC:      60,
-		},
-	}
-
 	// Mirror settings
 	Mirror struct {
 		DefaultInterval time.Duration
@@ -612,7 +345,6 @@ var (
 	InternalToken     string // internal access token
 	IterateBufferSize int
 
-	ExternalMarkupParsers []MarkupParser
 	// UILocation is the location on the UI, so that we can display the time on UI.
 	// Currently only show the default time.Local, it could be added to app.ini after UI is ready
 	UILocation = time.Local
@@ -1064,34 +796,7 @@ func NewContext() {
 
 	SSH.BuiltinServerUser = Cfg.Section("server").Key("BUILTIN_SSH_SERVER_USER").MustString(RunUser)
 
-	// Determine and create root git repository path.
-	sec = Cfg.Section("repository")
-	Repository.DisableHTTPGit = sec.Key("DISABLE_HTTP_GIT").MustBool()
-	Repository.UseCompatSSHURI = sec.Key("USE_COMPAT_SSH_URI").MustBool()
-	Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1)
-	RepoRootPath = sec.Key("ROOT").MustString(path.Join(homeDir, "gitea-repositories"))
-	forcePathSeparator(RepoRootPath)
-	if !filepath.IsAbs(RepoRootPath) {
-		RepoRootPath = filepath.Join(AppWorkPath, RepoRootPath)
-	} else {
-		RepoRootPath = filepath.Clean(RepoRootPath)
-	}
-	ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash")
-	if err = Cfg.Section("repository").MapTo(&Repository); err != nil {
-		log.Fatal(4, "Failed to map Repository settings: %v", err)
-	} else if err = Cfg.Section("repository.editor").MapTo(&Repository.Editor); err != nil {
-		log.Fatal(4, "Failed to map Repository.Editor settings: %v", err)
-	} else if err = Cfg.Section("repository.upload").MapTo(&Repository.Upload); err != nil {
-		log.Fatal(4, "Failed to map Repository.Upload settings: %v", err)
-	} else if err = Cfg.Section("repository.local").MapTo(&Repository.Local); err != nil {
-		log.Fatal(4, "Failed to map Repository.Local settings: %v", err)
-	} else if err = Cfg.Section("repository.pull-request").MapTo(&Repository.PullRequest); err != nil {
-		log.Fatal(4, "Failed to map Repository.PullRequest settings: %v", err)
-	}
-
-	if !filepath.IsAbs(Repository.Upload.TempPath) {
-		Repository.Upload.TempPath = path.Join(AppWorkPath, Repository.Upload.TempPath)
-	}
+	newRepository()
 
 	sec = Cfg.Section("picture")
 	AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString(path.Join(AppDataPath, "avatars"))
@@ -1145,17 +850,14 @@ func NewContext() {
 		log.Fatal(4, "Failed to map Markdown settings: %v", err)
 	} else if err = Cfg.Section("admin").MapTo(&Admin); err != nil {
 		log.Fatal(4, "Fail to map Admin settings: %v", err)
-	} else if err = Cfg.Section("cron").MapTo(&Cron); err != nil {
-		log.Fatal(4, "Failed to map Cron settings: %v", err)
-	} else if err = Cfg.Section("git").MapTo(&Git); err != nil {
-		log.Fatal(4, "Failed to map Git settings: %v", err)
 	} else if err = Cfg.Section("api").MapTo(&API); err != nil {
 		log.Fatal(4, "Failed to map API settings: %v", err)
 	} else if err = Cfg.Section("metrics").MapTo(&Metrics); err != nil {
 		log.Fatal(4, "Failed to map Metrics settings: %v", err)
 	}
 
-	git.DefaultCommandExecutionTimeout = time.Duration(Git.Timeout.Default) * time.Second
+	newCron()
+	newGit()
 
 	sec = Cfg.Section("mirror")
 	Mirror.MinInterval = sec.Key("MIN_INTERVAL").MustDuration(10 * time.Minute)
@@ -1193,57 +895,11 @@ func NewContext() {
 
 	HasRobotsTxt = com.IsFile(path.Join(CustomPath, "robots.txt"))
 
-	extensionReg := regexp.MustCompile(`\.\w`)
-	for _, sec := range Cfg.Section("markup").ChildSections() {
-		name := strings.TrimPrefix(sec.Name(), "markup.")
-		if name == "" {
-			log.Warn("name is empty, markup " + sec.Name() + "ignored")
-			continue
-		}
-
-		extensions := sec.Key("FILE_EXTENSIONS").Strings(",")
-		var exts = make([]string, 0, len(extensions))
-		for _, extension := range extensions {
-			if !extensionReg.MatchString(extension) {
-				log.Warn(sec.Name() + " file extension " + extension + " is invalid. Extension ignored")
-			} else {
-				exts = append(exts, extension)
-			}
-		}
-
-		if len(exts) == 0 {
-			log.Warn(sec.Name() + " file extension is empty, markup " + name + " ignored")
-			continue
-		}
-
-		command := sec.Key("RENDER_COMMAND").MustString("")
-		if command == "" {
-			log.Warn(" RENDER_COMMAND is empty, markup " + name + " ignored")
-			continue
-		}
-
-		ExternalMarkupParsers = append(ExternalMarkupParsers, MarkupParser{
-			Enabled:        sec.Key("ENABLED").MustBool(false),
-			MarkupName:     name,
-			FileExtensions: exts,
-			Command:        command,
-			IsInputFile:    sec.Key("IS_INPUT_FILE").MustBool(false),
-		})
-	}
+	newMarkup()
 
 	sec = Cfg.Section("U2F")
 	U2F.TrustedFacets, _ = shellquote.Split(sec.Key("TRUSTED_FACETS").MustString(strings.TrimRight(AppURL, "/")))
 	U2F.AppID = sec.Key("APP_ID").MustString(strings.TrimRight(AppURL, "/"))
-
-	binVersion, err := git.BinVersion()
-	if err != nil {
-		log.Fatal(4, "Error retrieving git version: %v", err)
-	}
-
-	if version.Compare(binVersion, "2.9", ">=") {
-		// Explicitly disable credential helper, otherwise Git credentials might leak
-		git.GlobalCommandArgs = append(git.GlobalCommandArgs, "-c", "credential.helper=")
-	}
 }
 
 func loadInternalToken(sec *ini.Section) string {