diff --git a/conf/app.ini b/conf/app.ini index dba75ed1b5..0fec297bc5 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -257,6 +257,12 @@ CONN = [git] MAX_GITDIFF_LINES = 10000 +; Arguments for command 'git fsck', e.g.: "--unreachable --tags" +; see more on http://git-scm.com/docs/git-fsck/1.7.5 +FSCK_ARGS = +; Arguments for command 'git gc', e.g.: "--aggressive --auto" +; see more on http://git-scm.com/docs/git-gc/1.7.5 +GC_ARGS = [i18n] LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL diff --git a/conf/locale/locale_en-US.ini b/conf/locale/locale_en-US.ini index d798f23ecc..2b60811206 100644 --- a/conf/locale/locale_en-US.ini +++ b/conf/locale/locale_en-US.ini @@ -476,6 +476,8 @@ dashboard.delete_inactivate_accounts = Delete all inactive accounts dashboard.delete_inactivate_accounts_success = All inactivate accounts have been deleted successfully. dashboard.delete_repo_archives = Delete all repositories archives dashboard.delete_repo_archives_success = All repositories archives have been deleted successfully. +dashboard.git_gc_repos = Do garbage collection on repositories +dashboard.git_gc_repos_success = All repositories have done garbage collection successfully. dashboard.server_uptime = Server Uptime dashboard.current_goroutine = Current Goroutines dashboard.current_memory_usage = Current Memory Usage diff --git a/gogs.go b/gogs.go index c555b56ccc..ec8fa48695 100644 --- a/gogs.go +++ b/gogs.go @@ -17,7 +17,7 @@ import ( "github.com/gogits/gogs/modules/setting" ) -const APP_VER = "0.5.8.1128 Beta" +const APP_VER = "0.5.8.1130 Beta" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/repo.go b/models/repo.go index e4f470680f..5676a443ff 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1140,18 +1140,8 @@ type SearchOption struct { Private bool } -// FilterSQLInject tries to prevent SQL injection. -func FilterSQLInject(key string) string { - key = strings.TrimSpace(key) - key = strings.Split(key, " ")[0] - key = strings.Replace(key, ",", "", -1) - return key -} - // SearchRepositoryByName returns given number of repositories whose name contains keyword. func SearchRepositoryByName(opt SearchOption) (repos []*Repository, err error) { - // Prevent SQL inject. - opt.Keyword = FilterSQLInject(opt.Keyword) if len(opt.Keyword) == 0 { return repos, nil } @@ -1183,6 +1173,47 @@ func DeleteRepositoryArchives() error { }) } +// GitFsck calls 'git fsck' to check repository health. +func GitFsck() { + args := append([]string{"fsck"}, setting.GitFsckArgs...) + if err := x.Where("id > 0").Iterate(new(Repository), + func(idx int, bean interface{}) error { + repo := bean.(*Repository) + if err := repo.GetOwner(); err != nil { + return err + } + + repoPath := RepoPath(repo.Owner.Name, repo.Name) + _, _, err := process.ExecDir(-1, repoPath, "Repository health check", "git", args...) + if err != nil { + desc := fmt.Sprintf("Fail to health check repository(%s)", repoPath) + log.Warn(desc) + if err = CreateRepositoryNotice(desc); err != nil { + log.Error(4, "Fail to add notice: %v", err) + } + } + return nil + }); err != nil { + log.Error(4, "repo.Fsck: %v", err) + } +} + +func GitGcRepos() error { + args := append([]string{"gc"}, setting.GitGcArgs...) + return x.Where("id > 0").Iterate(new(Repository), + func(idx int, bean interface{}) error { + repo := bean.(*Repository) + if err := repo.GetOwner(); err != nil { + return err + } + _, stderr, err := process.ExecDir(-1, RepoPath(repo.Owner.Name, repo.Name), "Repository garbage collection", "git", args...) + if err != nil { + return fmt.Errorf("%v: %v", err, stderr) + } + return nil + }) +} + // __ __ __ .__ // / \ / \_____ _/ |_ ____ | |__ // \ \/\/ /\__ \\ __\/ ___\| | \ diff --git a/models/user.go b/models/user.go index 9eead462e2..61a43ba9bf 100644 --- a/models/user.go +++ b/models/user.go @@ -628,7 +628,6 @@ func GetUserByEmail(email string) (*User, error) { // SearchUserByName returns given number of users whose name contains keyword. func SearchUserByName(opt SearchOption) (us []*User, err error) { - opt.Keyword = FilterSQLInject(opt.Keyword) if len(opt.Keyword) == 0 { return us, nil } diff --git a/modules/cron/manager.go b/modules/cron/manager.go index 563426fb79..fcf559bcb0 100644 --- a/modules/cron/manager.go +++ b/modules/cron/manager.go @@ -14,8 +14,10 @@ import ( var c = New() func NewCronContext() { + models.GitFsck() c.AddFunc("Update mirrors", "@every 1h", models.MirrorUpdate) c.AddFunc("Deliver hooks", fmt.Sprintf("@every %dm", setting.WebhookTaskInterval), models.DeliverHooks) + c.AddFunc("Repository health check", "@every 1h", models.GitFsck) c.Start() } diff --git a/modules/setting/setting.go b/modules/setting/setting.go index 9737fa7c1d..476fc6affa 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -109,6 +109,8 @@ var ( // Git settings. MaxGitDiffLines int + GitFsckArgs []string + GitGcArgs []string // I18n settings. Langs, Names []string @@ -288,6 +290,8 @@ func NewConfigContext() { DisableGravatar = Cfg.MustBool("picture", "DISABLE_GRAVATAR") MaxGitDiffLines = Cfg.MustInt("git", "MAX_GITDIFF_LINES", 10000) + GitFsckArgs = Cfg.MustValueArray("git", "FSCK_ARGS", " ") + GitGcArgs = Cfg.MustValueArray("git", "GC_ARGS", " ") Langs = Cfg.MustValueArray("i18n", "LANGS", ",") Names = Cfg.MustValueArray("i18n", "NAMES", ",") diff --git a/routers/admin/admin.go b/routers/admin/admin.go index db36696c77..99bae8819a 100644 --- a/routers/admin/admin.go +++ b/routers/admin/admin.go @@ -117,6 +117,7 @@ const ( CLEAN_UNBIND_OAUTH AdminOperation = iota + 1 CLEAN_INACTIVATE_USER CLEAN_REPO_ARCHIVES + GIT_GC_REPOS ) func Dashboard(ctx *middleware.Context) { @@ -140,6 +141,9 @@ func Dashboard(ctx *middleware.Context) { case CLEAN_REPO_ARCHIVES: success = ctx.Tr("admin.dashboard.delete_repo_archives_success") err = models.DeleteRepositoryArchives() + case GIT_GC_REPOS: + success = ctx.Tr("admin.dashboard.git_gc_repos_success") + err = models.GitGcRepos() } if err != nil { diff --git a/templates/.VERSION b/templates/.VERSION index c4127c31a3..27cf20dd2f 100644 --- a/templates/.VERSION +++ b/templates/.VERSION @@ -1 +1 @@ -0.5.8.1128 Beta \ No newline at end of file +0.5.8.1130 Beta \ No newline at end of file diff --git a/templates/admin/dashboard.tmpl b/templates/admin/dashboard.tmpl index 7038910596..8d17c360b0 100644 --- a/templates/admin/dashboard.tmpl +++ b/templates/admin/dashboard.tmpl @@ -44,6 +44,10 @@ {{.i18n.Tr "admin.dashboard.delete_repo_archives"}} {{.i18n.Tr "admin.dashboard.operation_run"}} + + {{.i18n.Tr "admin.dashboard.git_gc_repos"}} + {{.i18n.Tr "admin.dashboard.operation_run"}} +