Fix #264
This commit is contained in:
		
							parent
							
								
									91e5c24a31
								
							
						
					
					
						commit
						64c68220d2
					
				
					 18 changed files with 317 additions and 19 deletions
				
			
		|  | @ -5,7 +5,7 @@ Gogs(Go Git Service) is a painless self-hosted Git Service written in Go. | |||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### Current version: 0.5.4 Beta | ||||
| ##### Current version: 0.5.5 Beta | ||||
| 
 | ||||
| ### NOTICES | ||||
| 
 | ||||
|  | @ -44,7 +44,7 @@ The goal of this project is to make the easiest, fastest and most painless way t | |||
| - Slack webhook integration | ||||
| - Supports MySQL, PostgreSQL and SQLite3 | ||||
| - Social account login(GitHub, Google, QQ, Weibo) | ||||
| - Multi-language support(English, Chinese, Germany, French etc.) | ||||
| - Multi-language support(English, Chinese, Germany, French, Dutch etc.) | ||||
| 
 | ||||
| ## System Requirements | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ Gogs(Go Git Service) 是一个基于 Go 语言的自助 Git 服务。 | |||
| 
 | ||||
|  | ||||
| 
 | ||||
| ##### 当前版本:0.5.4 Beta | ||||
| ##### 当前版本:0.5.5 Beta | ||||
| 
 | ||||
| ## 开发目的 | ||||
| 
 | ||||
|  | @ -35,7 +35,7 @@ Gogs 的目标是打造一个最简单、最快速和最轻松的方式搭建自 | |||
| - Slack Web 钩子集成 | ||||
| - 支持 MySQL、PostgreSQL 以及 SQLite3 数据库 | ||||
| - 社交帐号登录(GitHub、Google、QQ、微博) | ||||
| - 多语言支持(英文、简体中文、德语、法语等等) | ||||
| - 多语言支持(英文、简体中文、德语、法语、荷兰语等等) | ||||
| 
 | ||||
| ## 系统要求 | ||||
| 
 | ||||
|  |  | |||
|  | @ -313,6 +313,12 @@ func runWeb(*cli.Context) { | |||
| 			r.Get("/hooks/:id", repo.WebHooksEdit) | ||||
| 			r.Post("/hooks/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost) | ||||
| 			r.Post("/hooks/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost) | ||||
| 
 | ||||
| 			m.Group("/hooks/git", func(r *macaron.Router) { | ||||
| 				r.Get("", repo.GitHooks) | ||||
| 				r.Get("/:name", repo.GitHooksEdit) | ||||
| 				r.Post("/:name", repo.GitHooksEditPost) | ||||
| 			}, middleware.GitHookService()) | ||||
| 		}) | ||||
| 	}, reqSignIn, middleware.RepoAssignment(true), reqTrueOwner) | ||||
| 
 | ||||
|  |  | |||
|  | @ -70,6 +70,8 @@ ENABLE_CACHE_AVATAR = false | |||
| ENABLE_NOTIFY_MAIL = false | ||||
| ; More detail: https://github.com/gogits/gogs/issues/165 | ||||
| ENABLE_REVERSE_PROXY_AUTHENTICATION = false | ||||
| ; Repository Git hooks | ||||
| ENABLE_GIT_HOOKS = false | ||||
| 
 | ||||
| [webhook] | ||||
| ; Cron task interval in minutes | ||||
|  |  | |||
|  | @ -287,6 +287,7 @@ settings = Settings | |||
| settings.options = Options | ||||
| settings.collaboration = Collaboration | ||||
| settings.hooks = Webhooks | ||||
| settings.githooks = Git Hooks | ||||
| settings.deploy_keys = Deploy Keys | ||||
| settings.basic_settings = Basic Settings | ||||
| settings.danger_zone = Danger Zone | ||||
|  | @ -310,6 +311,11 @@ settings.add_collaborator_success = New collaborator has been added. | |||
| settings.remove_collaborator_success = Collaborator has been removed. | ||||
| settings.add_webhook = Add Webhook | ||||
| settings.hooks_desc = Webhooks allow external services to be notified when certain events happen on Gogs. When the specified events happen, we'll send a POST request to each of the URLs you provide. Learn more in our <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks Guide</a>. | ||||
| settings.githooks_desc = Git Hooks are powered by Git itself, you can edit files of supported hooks in the list below to apply custom operations. | ||||
| settings.githook_edit_desc = If hook is not active, sample content will be presented. Leave content to be blank will disable this hook. | ||||
| settings.githook_name = Hook Name | ||||
| settings.githook_content = Hook Content | ||||
| settings.update_githook = Update Hook | ||||
| settings.remove_hook_success = Webhook has been removed. | ||||
| settings.add_webhook_desc = We’ll send a <code>POST</code> request to the URL below with details of any subscribed events. You can also specify which data format you'd like to receive (JSON, <code>x-www-form-urlencoded</code>, <em>etc</em>). More information can be found in <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks Guide</a>. | ||||
| settings.payload_url = Payload URL | ||||
|  |  | |||
|  | @ -287,6 +287,7 @@ settings = 仓库设置 | |||
| settings.options = 基本设置 | ||||
| settings.collaboration = 管理协作者 | ||||
| settings.hooks = 管理 Web 钩子 | ||||
| settings.githooks = 管理 Git 钩子 | ||||
| settings.deploy_keys = 管理部署密钥 | ||||
| settings.basic_settings = 基本设置 | ||||
| settings.danger_zone = 危险操作区 | ||||
|  | @ -312,6 +313,11 @@ settings.add_webhook = 添加 Web 钩子 | |||
| settings.hooks_desc = Web 钩子允许您设定在 Gogs 上发生指定事件时对指定 URL 发送 POST 通知。查看 <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks 文档</a> 获取更多信息。 | ||||
| settings.remove_hook_success = Web 钩子删除成功! | ||||
| settings.add_webhook_desc = 我们会通过 <code>POST</code> 请求将订阅事件信息发送至向指定 URL 地址。您可以设置不同的数据接收方式(JSON 或 <code>x-www-form-urlencoded</code>)。 请查阅 <a target="_blank" href="http://gogs.io/docs/features/webhook.html">Webhooks 文档</a> 获取更多信息。 | ||||
| settings.githooks_desc = Git 钩子是由 Git 本身提供的功能,以下为 Gogs 所支持的钩子列表。 | ||||
| settings.githook_edit_desc = 如果钩子未启动,则会显示样例文件中的内容。如果想要删除某个钩子,则提交空白文本即可。 | ||||
| settings.githook_name = 钩子名称 | ||||
| settings.githook_content = 钩子文本 | ||||
| settings.update_githook = 更新钩子设置 | ||||
| settings.payload_url = 推送地址 | ||||
| settings.content_type = 数据格式 | ||||
| settings.secret = 密钥文本 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							|  | @ -17,7 +17,7 @@ import ( | |||
| 	"github.com/gogits/gogs/modules/setting" | ||||
| ) | ||||
| 
 | ||||
| const APP_VER = "0.5.4.1005 Beta" | ||||
| const APP_VER = "0.5.5.1006 Beta" | ||||
| 
 | ||||
| func init() { | ||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
|  |  | |||
							
								
								
									
										111
									
								
								modules/git/hooks.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								modules/git/hooks.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,111 @@ | |||
| // Copyright 2014 The Gogs 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 git | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| // hookNames is a list of Git hooks' name that are supported.
 | ||||
| var hookNames = []string{ | ||||
| 	"pre-applypatch", | ||||
| 	"applypatch-msg", | ||||
| 	"prepare-commit-msg", | ||||
| 	"commit-msg", | ||||
| 	"pre-commit", | ||||
| 	"pre-rebase", | ||||
| 	"post-commit", | ||||
| 	"post-receive", | ||||
| 	"post-update", | ||||
| } | ||||
| 
 | ||||
| var ( | ||||
| 	ErrNotValidHook = errors.New("not a valid Git hook") | ||||
| ) | ||||
| 
 | ||||
| // IsValidHookName returns true if given name is a valid Git hook.
 | ||||
| func IsValidHookName(name string) bool { | ||||
| 	for _, hn := range hookNames { | ||||
| 		if hn == name { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| // Hook represents a Git hook.
 | ||||
| type Hook struct { | ||||
| 	name     string | ||||
| 	IsActive bool   // Indicates whether repository has this hook.
 | ||||
| 	Content  string // Content of hook if it's active.
 | ||||
| 	Sample   string // Sample content from Git.
 | ||||
| 	path     string // Hook file path.
 | ||||
| } | ||||
| 
 | ||||
| // GetHook returns a Git hook by given name and repository.
 | ||||
| func GetHook(repoPath, name string) (*Hook, error) { | ||||
| 	if !IsValidHookName(name) { | ||||
| 		return nil, ErrNotValidHook | ||||
| 	} | ||||
| 	h := &Hook{ | ||||
| 		name: name, | ||||
| 		path: path.Join(repoPath, "hooks", name), | ||||
| 	} | ||||
| 	if isFile(h.path) { | ||||
| 		data, err := ioutil.ReadFile(h.path) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		h.IsActive = true | ||||
| 		h.Content = string(data) | ||||
| 	} else if isFile(h.path + ".sample") { | ||||
| 		data, err := ioutil.ReadFile(h.path + ".sample") | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		h.Sample = string(data) | ||||
| 	} | ||||
| 	return h, nil | ||||
| } | ||||
| 
 | ||||
| func (h *Hook) Name() string { | ||||
| 	return h.name | ||||
| } | ||||
| 
 | ||||
| // Update updates hook settings.
 | ||||
| func (h *Hook) Update() error { | ||||
| 	if len(strings.TrimSpace(h.Content)) == 0 { | ||||
| 		return os.Remove(h.path) | ||||
| 	} | ||||
| 	return ioutil.WriteFile(h.path, []byte(h.Content), os.ModePerm) | ||||
| } | ||||
| 
 | ||||
| // ListHooks returns a list of Git hooks of given repository.
 | ||||
| func ListHooks(repoPath string) (_ []*Hook, err error) { | ||||
| 	if !isDir(path.Join(repoPath, "hooks")) { | ||||
| 		return nil, errors.New("hooks path does not exist") | ||||
| 	} | ||||
| 
 | ||||
| 	hooks := make([]*Hook, len(hookNames)) | ||||
| 	for i, name := range hookNames { | ||||
| 		hooks[i], err = GetHook(repoPath, name) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
| 	return hooks, nil | ||||
| } | ||||
| 
 | ||||
| func (repo *Repository) GetHook(name string) (*Hook, error) { | ||||
| 	return GetHook(repo.Path, name) | ||||
| } | ||||
| 
 | ||||
| func (repo *Repository) Hooks() ([]*Hook, error) { | ||||
| 	return ListHooks(repo.Path) | ||||
| } | ||||
|  | @ -7,6 +7,7 @@ package git | |||
| import ( | ||||
| 	"bytes" | ||||
| 	"container/list" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| ) | ||||
|  | @ -46,3 +47,23 @@ func RefEndName(refStr string) string { | |||
| func filepathFromSHA1(rootdir, sha1 string) string { | ||||
| 	return filepath.Join(rootdir, "objects", sha1[:2], sha1[2:]) | ||||
| } | ||||
| 
 | ||||
| // isDir returns true if given path is a directory,
 | ||||
| // or returns false when it's a file or does not exist.
 | ||||
| func isDir(dir string) bool { | ||||
| 	f, e := os.Stat(dir) | ||||
| 	if e != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	return f.IsDir() | ||||
| } | ||||
| 
 | ||||
| // isFile returns true if given path is a file,
 | ||||
| // or returns false when it's a directory or does not exist.
 | ||||
| func isFile(filePath string) bool { | ||||
| 	f, e := os.Stat(filePath) | ||||
| 	if e != nil { | ||||
| 		return false | ||||
| 	} | ||||
| 	return !f.IsDir() | ||||
| } | ||||
|  |  | |||
|  | @ -308,3 +308,13 @@ func RequireTrueOwner() macaron.Handler { | |||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // GitHookService checks if repsitory Git hooks service has been enabled.
 | ||||
| func GitHookService() macaron.Handler { | ||||
| 	return func(ctx *Context) { | ||||
| 		if !setting.Service.EnableGitHooks { | ||||
| 			ctx.Handle(404, "GitHookService", nil) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -275,6 +275,7 @@ var Service struct { | |||
| 	LdapAuth               bool | ||||
| 	ActiveCodeLives        int | ||||
| 	ResetPwdCodeLives      int | ||||
| 	EnableGitHooks         bool | ||||
| } | ||||
| 
 | ||||
| func newService() { | ||||
|  | @ -284,6 +285,7 @@ func newService() { | |||
| 	Service.RequireSignInView = Cfg.MustBool("service", "REQUIRE_SIGNIN_VIEW") | ||||
| 	Service.EnableCacheAvatar = Cfg.MustBool("service", "ENABLE_CACHE_AVATAR") | ||||
| 	Service.EnableReverseProxyAuth = Cfg.MustBool("service", "ENABLE_REVERSE_PROXY_AUTHENTICATION") | ||||
| 	Service.EnableGitHooks = Cfg.MustBool("service", "ENABLE_GIT_HOOKS") | ||||
| } | ||||
| 
 | ||||
| var logLevels = map[string]string{ | ||||
|  |  | |||
|  | @ -480,6 +480,10 @@ dt { | |||
| .ipt-large { | ||||
|   font-size: 14.4px; | ||||
| } | ||||
| .ipt-textarea { | ||||
|   height: auto !important; | ||||
|   width: auto; | ||||
| } | ||||
| .ipt-disabled, | ||||
| input[disabled] { | ||||
|   background-color: #f2f2f2 !important; | ||||
|  |  | |||
|  | @ -116,25 +116,24 @@ | |||
| } | ||||
| 
 | ||||
| // input form elements | ||||
| 
 | ||||
| .ipt { | ||||
|   &:focus { | ||||
|     border-color: @iptFocusBorderColor; | ||||
|   } | ||||
|     &:focus { | ||||
|         border-color: @iptFocusBorderColor; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| .ipt-radius { | ||||
|   border-radius: .25em; | ||||
|     border-radius: .25em; | ||||
| } | ||||
| 
 | ||||
| .ipt-small { | ||||
|   font-size: .8*@baseFontSize; | ||||
|     font-size: .8*@baseFontSize; | ||||
| } | ||||
| 
 | ||||
| .ipt-large { | ||||
|   font-size: 1.2*@baseFontSize; | ||||
|     font-size: 1.2*@baseFontSize; | ||||
| } | ||||
| .ipt-textarea { | ||||
|     height: auto !important; | ||||
|     width: auto; | ||||
| } | ||||
| 
 | ||||
| .ipt-disabled, | ||||
| input[disabled] { | ||||
|   background-color: @iptDisabledColor !important; | ||||
|  | @ -144,14 +143,12 @@ input[disabled] { | |||
|   color: #888; | ||||
|   cursor: not-allowed; | ||||
| } | ||||
| 
 | ||||
| .ipt-readonly, | ||||
| input[readonly] { | ||||
|   &:focus { | ||||
|     background-color: @iptDisabledColor !important; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .ipt-error { | ||||
|   border-color: @iptErrorBorderColor !important; | ||||
|   background-color: @iptErrorFocusColor !important; | ||||
|  |  | |||
|  | @ -16,6 +16,7 @@ import ( | |||
| 	"github.com/gogits/gogs/models" | ||||
| 	"github.com/gogits/gogs/modules/auth" | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| 	"github.com/gogits/gogs/modules/git" | ||||
| 	"github.com/gogits/gogs/modules/log" | ||||
| 	"github.com/gogits/gogs/modules/mailer" | ||||
| 	"github.com/gogits/gogs/modules/middleware" | ||||
|  | @ -26,6 +27,8 @@ const ( | |||
| 	SETTINGS_OPTIONS base.TplName = "repo/settings/options" | ||||
| 	COLLABORATION    base.TplName = "repo/settings/collaboration" | ||||
| 	HOOKS            base.TplName = "repo/settings/hooks" | ||||
| 	GITHOOKS         base.TplName = "repo/settings/githooks" | ||||
| 	GITHOOK_EDIT     base.TplName = "repo/settings/githook_edit" | ||||
| 	HOOK_NEW         base.TplName = "repo/settings/hook_new" | ||||
| 	ORG_HOOK_NEW     base.TplName = "org/settings/hook_new" | ||||
| ) | ||||
|  | @ -591,3 +594,54 @@ func getOrgRepoCtx(ctx *middleware.Context) (*OrgRepoCtx, error) { | |||
| 		return &OrgRepoCtx{}, errors.New("Unable to set OrgRepo context") | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func GitHooks(ctx *middleware.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("repo.settings") | ||||
| 	ctx.Data["PageIsSettingsGitHooks"] = true | ||||
| 
 | ||||
| 	hooks, err := ctx.Repo.GitRepo.Hooks() | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "Hooks", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Hooks"] = hooks | ||||
| 
 | ||||
| 	ctx.HTML(200, GITHOOKS) | ||||
| } | ||||
| 
 | ||||
| func GitHooksEdit(ctx *middleware.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("repo.settings") | ||||
| 	ctx.Data["PageIsSettingsGitHooks"] = true | ||||
| 
 | ||||
| 	name := ctx.Params(":name") | ||||
| 	hook, err := ctx.Repo.GitRepo.GetHook(name) | ||||
| 	if err != nil { | ||||
| 		if err == git.ErrNotValidHook { | ||||
| 			ctx.Handle(404, "GetHook", err) | ||||
| 		} else { | ||||
| 			ctx.Handle(500, "GetHook", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Hook"] = hook | ||||
| 	ctx.HTML(200, GITHOOK_EDIT) | ||||
| } | ||||
| 
 | ||||
| func GitHooksEditPost(ctx *middleware.Context) { | ||||
| 	name := ctx.Params(":name") | ||||
| 	hook, err := ctx.Repo.GitRepo.GetHook(name) | ||||
| 	if err != nil { | ||||
| 		if err == git.ErrNotValidHook { | ||||
| 			ctx.Handle(404, "GetHook", err) | ||||
| 		} else { | ||||
| 			ctx.Handle(500, "GetHook", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	hook.Content = ctx.Query("content") | ||||
| 	if err = hook.Update(); err != nil { | ||||
| 		ctx.Handle(500, "hook.Update", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Redirect(ctx.Repo.RepoLink + "/settings/hooks/git") | ||||
| } | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| 0.5.4.1005 Beta | ||||
| 0.5.5.1006 Beta | ||||
							
								
								
									
										41
									
								
								templates/repo/settings/githook_edit.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								templates/repo/settings/githook_edit.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| {{template "ng/base/head" .}} | ||||
| {{template "ng/base/header" .}} | ||||
| <div id="repo-wrapper"> | ||||
|     {{template "repo/header" .}} | ||||
| 	<div id="setting-wrapper" class="main-wrapper"> | ||||
| 	    <div id="repo-setting" class="container clear"> | ||||
| 	        {{template "repo/settings/nav" .}} | ||||
| 	        <div class="grid-4-5 left"> | ||||
| 	            <div class="setting-content"> | ||||
| 	                {{template "ng/base/alert" .}} | ||||
| 	                <div id="setting-content"> | ||||
| 	                    <div id="repo-hooks-panel" class="panel panel-radius"> | ||||
| 	                        <div class="panel-header"> | ||||
| 	                        	<strong>{{.i18n.Tr "repo.settings.githooks"}}</strong> | ||||
| 	                        </div> | ||||
| 	                        <form class="form form-align panel-body" id="repo-setting-form" action="{{.RepoLink}}/settings/hooks/git/{{.Hook.Name}}" method="post"> | ||||
| 	                            {{.CsrfTokenHtml}} | ||||
|                         		<div class="text-center panel-desc">{{.i18n.Tr "repo.settings.githook_edit_desc"}}</div> | ||||
| 	                            {{with .Hook}} | ||||
| 	                            <div class="field"> | ||||
| 	                                <label>{{$.i18n.Tr "repo.settings.githook_name"}}</label> | ||||
| 	                                <label class="text-left">{{.Name}}</label> | ||||
| 	                            </div> | ||||
| 					            <div class="field clear"> | ||||
| 					                <label class="left" for="content">{{$.i18n.Tr "repo.settings.githook_content"}}</label> | ||||
| 					                <textarea class="ipt-textarea ipt-large ipt-radius" id="content" name="content" cols="60" rows="20" wrap="off">{{if .IsActive}}{{.Content}}{{else}}{{.Sample}}{{end}}</textarea> | ||||
| 					            </div> | ||||
| 	                            <div class="field"> | ||||
| 	                                <span class="form-label"></span> | ||||
| 	                                <button class="btn btn-green btn-large btn-radius" id="change-reponame-btn" href="#change-reponame-modal">{{$.i18n.Tr "repo.settings.update_githook"}}</button> | ||||
| 	                            </div> | ||||
| 	                            {{end}} | ||||
| 	                        </form> | ||||
| 	                    </div> | ||||
| 	                </div> | ||||
| 	            </div> | ||||
| 	        </div> | ||||
| 	    </div> | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "ng/base/footer" .}} | ||||
							
								
								
									
										37
									
								
								templates/repo/settings/githooks.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								templates/repo/settings/githooks.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| {{template "ng/base/head" .}} | ||||
| {{template "ng/base/header" .}} | ||||
| <div id="repo-wrapper"> | ||||
|     {{template "repo/header" .}} | ||||
| 	<div id="setting-wrapper" class="main-wrapper"> | ||||
| 	    <div id="repo-setting" class="container clear"> | ||||
| 	        {{template "repo/settings/nav" .}} | ||||
| 	        <div class="grid-4-5 left"> | ||||
| 	            <div class="setting-content"> | ||||
| 	                {{template "ng/base/alert" .}} | ||||
| 	                <div id="setting-content"> | ||||
| 	                    <div id="repo-hooks-panel" class="panel panel-radius"> | ||||
| 	                        <div class="panel-header"> | ||||
| 	                        	<strong>{{.i18n.Tr "repo.settings.githooks"}}</strong> | ||||
| 	                        </div> | ||||
| 	                        <ul class="panel-body setting-list"> | ||||
|                             	<li>{{.i18n.Tr "repo.settings.githooks_desc" | Str2html}}</li> | ||||
|                             	{{range .Hooks}} | ||||
| 								<li> | ||||
| 									{{if .IsActive}} | ||||
| 									<span class="left text-success"><i class="octicon octicon-check"></i></span> | ||||
| 									{{else}} | ||||
| 									<span class="left text-grey"><i class="octicon octicon-primitive-dot"></i></span> | ||||
| 									{{end}} | ||||
| 									<span>{{.Name}}</span> | ||||
|                         			<a href="{{$.RepoLink}}/settings/hooks/git/{{.Name}}" class="text-blue right"><i class="fa fa-pencil"></i></a> | ||||
| 								</li> | ||||
|                             	{{end}} | ||||
| 	                       	</ul> | ||||
| 	                    </div> | ||||
| 	                </div> | ||||
| 	            </div> | ||||
| 	        </div> | ||||
| 	    </div> | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "ng/base/footer" .}} | ||||
|  | @ -5,6 +5,7 @@ | |||
|             <li {{if .PageIsSettingsOptions}}class="current"{{end}}><a href="{{.RepoLink}}/settings">{{.i18n.Tr "repo.settings.options"}}</a></li> | ||||
|             <li {{if .PageIsSettingsCollaboration}}class="current"{{end}}><a href="{{.RepoLink}}/settings/collaboration">{{.i18n.Tr "repo.settings.collaboration"}}</a></li> | ||||
|             <li {{if .PageIsSettingsHooks}}class="current"{{end}}><a href="{{.RepoLink}}/settings/hooks">{{.i18n.Tr "repo.settings.hooks"}}</a></li> | ||||
|             <li {{if .PageIsSettingsGitHooks}}class="current"{{end}}><a href="{{.RepoLink}}/settings/hooks/git">{{.i18n.Tr "repo.settings.githooks"}}</a></li> | ||||
|             <!-- <li {{if .PageIsSettingsKeys}}class="current"{{end}}><a href="{{.RepoLink}}/settings/keys">{{.i18n.Tr "repo.settings.deploy_keys"}}</a></li> --> | ||||
|         </ul> | ||||
|     </div> | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue