fix #580
This commit is contained in:
		
							parent
							
								
									b6437b5a4c
								
							
						
					
					
						commit
						d75013a0e8
					
				
					 10 changed files with 65 additions and 13 deletions
				
			
		|  | @ -257,6 +257,12 @@ CONN = | ||||||
| 
 | 
 | ||||||
| [git] | [git] | ||||||
| MAX_GITDIFF_LINES = 10000 | 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] | [i18n] | ||||||
| LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL | LANGS = en-US,zh-CN,zh-HK,de-DE,fr-CA,nl-NL | ||||||
|  |  | ||||||
|  | @ -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_inactivate_accounts_success = All inactivate accounts have been deleted successfully. | ||||||
| dashboard.delete_repo_archives = Delete all repositories archives | dashboard.delete_repo_archives = Delete all repositories archives | ||||||
| dashboard.delete_repo_archives_success = All repositories archives have been deleted successfully. | 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.server_uptime = Server Uptime | ||||||
| dashboard.current_goroutine = Current Goroutines | dashboard.current_goroutine = Current Goroutines | ||||||
| dashboard.current_memory_usage = Current Memory Usage | dashboard.current_memory_usage = Current Memory Usage | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							|  | @ -17,7 +17,7 @@ import ( | ||||||
| 	"github.com/gogits/gogs/modules/setting" | 	"github.com/gogits/gogs/modules/setting" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const APP_VER = "0.5.8.1128 Beta" | const APP_VER = "0.5.8.1130 Beta" | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||||
|  |  | ||||||
|  | @ -1140,18 +1140,8 @@ type SearchOption struct { | ||||||
| 	Private bool | 	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.
 | // SearchRepositoryByName returns given number of repositories whose name contains keyword.
 | ||||||
| func SearchRepositoryByName(opt SearchOption) (repos []*Repository, err error) { | func SearchRepositoryByName(opt SearchOption) (repos []*Repository, err error) { | ||||||
| 	// Prevent SQL inject.
 |  | ||||||
| 	opt.Keyword = FilterSQLInject(opt.Keyword) |  | ||||||
| 	if len(opt.Keyword) == 0 { | 	if len(opt.Keyword) == 0 { | ||||||
| 		return repos, nil | 		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 | ||||||
|  | 		}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| //  __      __         __         .__
 | //  __      __         __         .__
 | ||||||
| // /  \    /  \_____ _/  |_  ____ |  |__
 | // /  \    /  \_____ _/  |_  ____ |  |__
 | ||||||
| // \   \/\/   /\__  \\   __\/ ___\|  |  \
 | // \   \/\/   /\__  \\   __\/ ___\|  |  \
 | ||||||
|  |  | ||||||
|  | @ -628,7 +628,6 @@ func GetUserByEmail(email string) (*User, error) { | ||||||
| 
 | 
 | ||||||
| // SearchUserByName returns given number of users whose name contains keyword.
 | // SearchUserByName returns given number of users whose name contains keyword.
 | ||||||
| func SearchUserByName(opt SearchOption) (us []*User, err error) { | func SearchUserByName(opt SearchOption) (us []*User, err error) { | ||||||
| 	opt.Keyword = FilterSQLInject(opt.Keyword) |  | ||||||
| 	if len(opt.Keyword) == 0 { | 	if len(opt.Keyword) == 0 { | ||||||
| 		return us, nil | 		return us, nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -14,8 +14,10 @@ import ( | ||||||
| var c = New() | var c = New() | ||||||
| 
 | 
 | ||||||
| func NewCronContext() { | func NewCronContext() { | ||||||
|  | 	models.GitFsck() | ||||||
| 	c.AddFunc("Update mirrors", "@every 1h", models.MirrorUpdate) | 	c.AddFunc("Update mirrors", "@every 1h", models.MirrorUpdate) | ||||||
| 	c.AddFunc("Deliver hooks", fmt.Sprintf("@every %dm", setting.WebhookTaskInterval), models.DeliverHooks) | 	c.AddFunc("Deliver hooks", fmt.Sprintf("@every %dm", setting.WebhookTaskInterval), models.DeliverHooks) | ||||||
|  | 	c.AddFunc("Repository health check", "@every 1h", models.GitFsck) | ||||||
| 	c.Start() | 	c.Start() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -109,6 +109,8 @@ var ( | ||||||
| 
 | 
 | ||||||
| 	// Git settings.
 | 	// Git settings.
 | ||||||
| 	MaxGitDiffLines int | 	MaxGitDiffLines int | ||||||
|  | 	GitFsckArgs     []string | ||||||
|  | 	GitGcArgs       []string | ||||||
| 
 | 
 | ||||||
| 	// I18n settings.
 | 	// I18n settings.
 | ||||||
| 	Langs, Names []string | 	Langs, Names []string | ||||||
|  | @ -288,6 +290,8 @@ func NewConfigContext() { | ||||||
| 	DisableGravatar = Cfg.MustBool("picture", "DISABLE_GRAVATAR") | 	DisableGravatar = Cfg.MustBool("picture", "DISABLE_GRAVATAR") | ||||||
| 
 | 
 | ||||||
| 	MaxGitDiffLines = Cfg.MustInt("git", "MAX_GITDIFF_LINES", 10000) | 	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", ",") | 	Langs = Cfg.MustValueArray("i18n", "LANGS", ",") | ||||||
| 	Names = Cfg.MustValueArray("i18n", "NAMES", ",") | 	Names = Cfg.MustValueArray("i18n", "NAMES", ",") | ||||||
|  |  | ||||||
|  | @ -117,6 +117,7 @@ const ( | ||||||
| 	CLEAN_UNBIND_OAUTH AdminOperation = iota + 1 | 	CLEAN_UNBIND_OAUTH AdminOperation = iota + 1 | ||||||
| 	CLEAN_INACTIVATE_USER | 	CLEAN_INACTIVATE_USER | ||||||
| 	CLEAN_REPO_ARCHIVES | 	CLEAN_REPO_ARCHIVES | ||||||
|  | 	GIT_GC_REPOS | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func Dashboard(ctx *middleware.Context) { | func Dashboard(ctx *middleware.Context) { | ||||||
|  | @ -140,6 +141,9 @@ func Dashboard(ctx *middleware.Context) { | ||||||
| 		case CLEAN_REPO_ARCHIVES: | 		case CLEAN_REPO_ARCHIVES: | ||||||
| 			success = ctx.Tr("admin.dashboard.delete_repo_archives_success") | 			success = ctx.Tr("admin.dashboard.delete_repo_archives_success") | ||||||
| 			err = models.DeleteRepositoryArchives() | 			err = models.DeleteRepositoryArchives() | ||||||
|  | 		case GIT_GC_REPOS: | ||||||
|  | 			success = ctx.Tr("admin.dashboard.git_gc_repos_success") | ||||||
|  | 			err = models.GitGcRepos() | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
|  |  | ||||||
|  | @ -1 +1 @@ | ||||||
| 0.5.8.1128 Beta | 0.5.8.1130 Beta | ||||||
|  | @ -44,6 +44,10 @@ | ||||||
|                                                 <td>{{.i18n.Tr "admin.dashboard.delete_repo_archives"}}</td> |                                                 <td>{{.i18n.Tr "admin.dashboard.delete_repo_archives"}}</td> | ||||||
|                                                 <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=3">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> |                                                 <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=3">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | ||||||
|                                             </tr> |                                             </tr> | ||||||
|  |                                             <tr> | ||||||
|  |                                                 <td>{{.i18n.Tr "admin.dashboard.git_gc_repos"}}</td> | ||||||
|  |                                                 <td><i class="fa fa-caret-square-o-right"></i> <a href="{{AppSubUrl}}/admin?op=4">{{.i18n.Tr "admin.dashboard.operation_run"}}</a></td> | ||||||
|  |                                             </tr> | ||||||
|                                         </tbody> |                                         </tbody> | ||||||
|                                     </table> |                                     </table> | ||||||
|                                 </div> |                                 </div> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue