Fix #264
parent
91e5c24a31
commit
64c68220d2
@ -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) |
||||
} |
@ -1 +1 @@ |
||||
0.5.4.1005 Beta |
||||
0.5.5.1006 Beta |
@ -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" .}} |
@ -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" .}} |
Loading…
Reference in new issue