mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 16:40:24 +08:00 
			
		
		
		
	Fix #264
This commit is contained in:
		@@ -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
 | 
					### NOTICES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,7 +44,7 @@ The goal of this project is to make the easiest, fastest and most painless way t
 | 
				
			|||||||
- Slack webhook integration
 | 
					- Slack webhook integration
 | 
				
			||||||
- Supports MySQL, PostgreSQL and SQLite3
 | 
					- Supports MySQL, PostgreSQL and SQLite3
 | 
				
			||||||
- Social account login(GitHub, Google, QQ, Weibo)
 | 
					- 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
 | 
					## 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 钩子集成
 | 
					- Slack Web 钩子集成
 | 
				
			||||||
- 支持 MySQL、PostgreSQL 以及 SQLite3 数据库
 | 
					- 支持 MySQL、PostgreSQL 以及 SQLite3 数据库
 | 
				
			||||||
- 社交帐号登录(GitHub、Google、QQ、微博)
 | 
					- 社交帐号登录(GitHub、Google、QQ、微博)
 | 
				
			||||||
- 多语言支持(英文、简体中文、德语、法语等等)
 | 
					- 多语言支持(英文、简体中文、德语、法语、荷兰语等等)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 系统要求
 | 
					## 系统要求
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -313,6 +313,12 @@ func runWeb(*cli.Context) {
 | 
				
			|||||||
			r.Get("/hooks/:id", repo.WebHooksEdit)
 | 
								r.Get("/hooks/:id", repo.WebHooksEdit)
 | 
				
			||||||
			r.Post("/hooks/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
 | 
								r.Post("/hooks/gogs/:id", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksEditPost)
 | 
				
			||||||
			r.Post("/hooks/slack/:id", bindIgnErr(auth.NewSlackHookForm{}), repo.SlackHooksEditPost)
 | 
								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)
 | 
						}, reqSignIn, middleware.RepoAssignment(true), reqTrueOwner)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,6 +70,8 @@ ENABLE_CACHE_AVATAR = false
 | 
				
			|||||||
ENABLE_NOTIFY_MAIL = false
 | 
					ENABLE_NOTIFY_MAIL = false
 | 
				
			||||||
; More detail: https://github.com/gogits/gogs/issues/165
 | 
					; More detail: https://github.com/gogits/gogs/issues/165
 | 
				
			||||||
ENABLE_REVERSE_PROXY_AUTHENTICATION = false
 | 
					ENABLE_REVERSE_PROXY_AUTHENTICATION = false
 | 
				
			||||||
 | 
					; Repository Git hooks
 | 
				
			||||||
 | 
					ENABLE_GIT_HOOKS = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[webhook]
 | 
					[webhook]
 | 
				
			||||||
; Cron task interval in minutes
 | 
					; Cron task interval in minutes
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -287,6 +287,7 @@ settings = Settings
 | 
				
			|||||||
settings.options = Options
 | 
					settings.options = Options
 | 
				
			||||||
settings.collaboration = Collaboration
 | 
					settings.collaboration = Collaboration
 | 
				
			||||||
settings.hooks = Webhooks
 | 
					settings.hooks = Webhooks
 | 
				
			||||||
 | 
					settings.githooks = Git Hooks
 | 
				
			||||||
settings.deploy_keys = Deploy Keys
 | 
					settings.deploy_keys = Deploy Keys
 | 
				
			||||||
settings.basic_settings = Basic Settings
 | 
					settings.basic_settings = Basic Settings
 | 
				
			||||||
settings.danger_zone = Danger Zone
 | 
					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.remove_collaborator_success = Collaborator has been removed.
 | 
				
			||||||
settings.add_webhook = Add Webhook
 | 
					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.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.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.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
 | 
					settings.payload_url = Payload URL
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -287,6 +287,7 @@ settings = 仓库设置
 | 
				
			|||||||
settings.options = 基本设置
 | 
					settings.options = 基本设置
 | 
				
			||||||
settings.collaboration = 管理协作者
 | 
					settings.collaboration = 管理协作者
 | 
				
			||||||
settings.hooks = 管理 Web 钩子
 | 
					settings.hooks = 管理 Web 钩子
 | 
				
			||||||
 | 
					settings.githooks = 管理 Git 钩子
 | 
				
			||||||
settings.deploy_keys = 管理部署密钥
 | 
					settings.deploy_keys = 管理部署密钥
 | 
				
			||||||
settings.basic_settings = 基本设置
 | 
					settings.basic_settings = 基本设置
 | 
				
			||||||
settings.danger_zone = 危险操作区
 | 
					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.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.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.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.payload_url = 推送地址
 | 
				
			||||||
settings.content_type = 数据格式
 | 
					settings.content_type = 数据格式
 | 
				
			||||||
settings.secret = 密钥文本
 | 
					settings.secret = 密钥文本
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										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.4.1005 Beta"
 | 
					const APP_VER = "0.5.5.1006 Beta"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	runtime.GOMAXPROCS(runtime.NumCPU())
 | 
						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 (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"container/list"
 | 
						"container/list"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -46,3 +47,23 @@ func RefEndName(refStr string) string {
 | 
				
			|||||||
func filepathFromSHA1(rootdir, sha1 string) string {
 | 
					func filepathFromSHA1(rootdir, sha1 string) string {
 | 
				
			||||||
	return filepath.Join(rootdir, "objects", sha1[:2], sha1[2:])
 | 
						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
 | 
						LdapAuth               bool
 | 
				
			||||||
	ActiveCodeLives        int
 | 
						ActiveCodeLives        int
 | 
				
			||||||
	ResetPwdCodeLives      int
 | 
						ResetPwdCodeLives      int
 | 
				
			||||||
 | 
						EnableGitHooks         bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newService() {
 | 
					func newService() {
 | 
				
			||||||
@@ -284,6 +285,7 @@ func newService() {
 | 
				
			|||||||
	Service.RequireSignInView = Cfg.MustBool("service", "REQUIRE_SIGNIN_VIEW")
 | 
						Service.RequireSignInView = Cfg.MustBool("service", "REQUIRE_SIGNIN_VIEW")
 | 
				
			||||||
	Service.EnableCacheAvatar = Cfg.MustBool("service", "ENABLE_CACHE_AVATAR")
 | 
						Service.EnableCacheAvatar = Cfg.MustBool("service", "ENABLE_CACHE_AVATAR")
 | 
				
			||||||
	Service.EnableReverseProxyAuth = Cfg.MustBool("service", "ENABLE_REVERSE_PROXY_AUTHENTICATION")
 | 
						Service.EnableReverseProxyAuth = Cfg.MustBool("service", "ENABLE_REVERSE_PROXY_AUTHENTICATION")
 | 
				
			||||||
 | 
						Service.EnableGitHooks = Cfg.MustBool("service", "ENABLE_GIT_HOOKS")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var logLevels = map[string]string{
 | 
					var logLevels = map[string]string{
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -480,6 +480,10 @@ dt {
 | 
				
			|||||||
.ipt-large {
 | 
					.ipt-large {
 | 
				
			||||||
  font-size: 14.4px;
 | 
					  font-size: 14.4px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.ipt-textarea {
 | 
				
			||||||
 | 
					  height: auto !important;
 | 
				
			||||||
 | 
					  width: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
.ipt-disabled,
 | 
					.ipt-disabled,
 | 
				
			||||||
input[disabled] {
 | 
					input[disabled] {
 | 
				
			||||||
  background-color: #f2f2f2 !important;
 | 
					  background-color: #f2f2f2 !important;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,25 +116,24 @@
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// input form elements
 | 
					// input form elements
 | 
				
			||||||
 | 
					 | 
				
			||||||
.ipt {
 | 
					.ipt {
 | 
				
			||||||
  &:focus {
 | 
					    &:focus {
 | 
				
			||||||
    border-color: @iptFocusBorderColor;
 | 
					        border-color: @iptFocusBorderColor;
 | 
				
			||||||
  }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.ipt-radius {
 | 
					.ipt-radius {
 | 
				
			||||||
  border-radius: .25em;
 | 
					    border-radius: .25em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.ipt-small {
 | 
					.ipt-small {
 | 
				
			||||||
  font-size: .8*@baseFontSize;
 | 
					    font-size: .8*@baseFontSize;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.ipt-large {
 | 
					.ipt-large {
 | 
				
			||||||
  font-size: 1.2*@baseFontSize;
 | 
					    font-size: 1.2*@baseFontSize;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.ipt-textarea {
 | 
				
			||||||
 | 
					    height: auto !important;
 | 
				
			||||||
 | 
					    width: auto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.ipt-disabled,
 | 
					.ipt-disabled,
 | 
				
			||||||
input[disabled] {
 | 
					input[disabled] {
 | 
				
			||||||
  background-color: @iptDisabledColor !important;
 | 
					  background-color: @iptDisabledColor !important;
 | 
				
			||||||
@@ -144,14 +143,12 @@ input[disabled] {
 | 
				
			|||||||
  color: #888;
 | 
					  color: #888;
 | 
				
			||||||
  cursor: not-allowed;
 | 
					  cursor: not-allowed;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.ipt-readonly,
 | 
					.ipt-readonly,
 | 
				
			||||||
input[readonly] {
 | 
					input[readonly] {
 | 
				
			||||||
  &:focus {
 | 
					  &:focus {
 | 
				
			||||||
    background-color: @iptDisabledColor !important;
 | 
					    background-color: @iptDisabledColor !important;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
.ipt-error {
 | 
					.ipt-error {
 | 
				
			||||||
  border-color: @iptErrorBorderColor !important;
 | 
					  border-color: @iptErrorBorderColor !important;
 | 
				
			||||||
  background-color: @iptErrorFocusColor !important;
 | 
					  background-color: @iptErrorFocusColor !important;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,7 @@ import (
 | 
				
			|||||||
	"github.com/gogits/gogs/models"
 | 
						"github.com/gogits/gogs/models"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/auth"
 | 
						"github.com/gogits/gogs/modules/auth"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/base"
 | 
						"github.com/gogits/gogs/modules/base"
 | 
				
			||||||
 | 
						"github.com/gogits/gogs/modules/git"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/log"
 | 
						"github.com/gogits/gogs/modules/log"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/mailer"
 | 
						"github.com/gogits/gogs/modules/mailer"
 | 
				
			||||||
	"github.com/gogits/gogs/modules/middleware"
 | 
						"github.com/gogits/gogs/modules/middleware"
 | 
				
			||||||
@@ -26,6 +27,8 @@ const (
 | 
				
			|||||||
	SETTINGS_OPTIONS base.TplName = "repo/settings/options"
 | 
						SETTINGS_OPTIONS base.TplName = "repo/settings/options"
 | 
				
			||||||
	COLLABORATION    base.TplName = "repo/settings/collaboration"
 | 
						COLLABORATION    base.TplName = "repo/settings/collaboration"
 | 
				
			||||||
	HOOKS            base.TplName = "repo/settings/hooks"
 | 
						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"
 | 
						HOOK_NEW         base.TplName = "repo/settings/hook_new"
 | 
				
			||||||
	ORG_HOOK_NEW     base.TplName = "org/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")
 | 
							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 .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 .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 .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> -->
 | 
					            <!-- <li {{if .PageIsSettingsKeys}}class="current"{{end}}><a href="{{.RepoLink}}/settings/keys">{{.i18n.Tr "repo.settings.deploy_keys"}}</a></li> -->
 | 
				
			||||||
        </ul>
 | 
					        </ul>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user