mirror of
https://github.com/Luzifer/clean-github-branches.git
synced 2024-11-08 14:10:04 +00:00
Log branch age
Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
2b085e2e87
commit
dd8da5cac4
7 changed files with 583 additions and 2 deletions
17
Gopkg.lock
generated
17
Gopkg.lock
generated
|
@ -1,6 +1,14 @@
|
|||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
digest = "1:52b6c8beb19a31fe7b40b23c9b694caf4213cfa3d6cce711cd0636db68ce67aa"
|
||||
name = "github.com/Luzifer/go_helpers"
|
||||
packages = ["duration"]
|
||||
pruneopts = "NUT"
|
||||
revision = "4e368ddb27c0a08a0c84e5ceac52d57b464bffce"
|
||||
version = "v2.7.0"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:3c2b6707179ff866ca06c5eecd544c9079a6ec35d735031a1bf61abfff336186"
|
||||
name = "github.com/Luzifer/rconfig"
|
||||
|
@ -33,6 +41,14 @@
|
|||
pruneopts = "NUT"
|
||||
revision = "53e6ce116135b80d037921a7fdd5138cf32d7a8a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
digest = "1:071a57a67bde66b0e6438ffee4599ef99532a0e29de3ea12926b5438608f90a6"
|
||||
name = "github.com/leekchan/gtf"
|
||||
packages = ["."]
|
||||
pruneopts = "NUT"
|
||||
revision = "79e3a68ab435edb72c6490289a33ef8bedcee15a"
|
||||
|
||||
[[projects]]
|
||||
digest = "1:5cf3f025cbee5951a4ee961de067c8a89fc95a5adabead774f82822efabab121"
|
||||
name = "github.com/pkg/errors"
|
||||
|
@ -134,6 +150,7 @@
|
|||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
input-imports = [
|
||||
"github.com/Luzifer/go_helpers/duration",
|
||||
"github.com/Luzifer/rconfig",
|
||||
"github.com/google/go-github/github",
|
||||
"github.com/pkg/errors",
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Luzifer/go_helpers"
|
||||
version = "2.7.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/Luzifer/rconfig"
|
||||
version = "2.1.0"
|
||||
|
|
|
@ -28,8 +28,8 @@ Usage of clean-github-branches:
|
|||
--version Prints current version and exits
|
||||
|
||||
$ clean-github-branches -r '^[lL]uzifer(-docker|-ansible|)/'
|
||||
WARN[0013] Stale branch found ahead=1 behind=1 branch=develop dry-run=true repo=luzifer-docker/etherpad-lite
|
||||
INFO[0013] Done.
|
||||
WARN[0012] Stale branch found age=2y174d23h ahead=1 behind=1 branch=develop dry-run=true repo=luzifer-docker/etherpad-lite
|
||||
INFO[0012] Done.
|
||||
```
|
||||
|
||||
All parameters causing destructive actions are set to sane defaults: By default a `dry-run` is done which prevents any deletion. Also `delete-stale` is disabled as it might cause data loss as the branch is not merged and all commits in it will be lost.
|
||||
|
|
7
main.go
7
main.go
|
@ -10,6 +10,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Luzifer/go_helpers/duration"
|
||||
"github.com/Luzifer/rconfig"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
|
@ -18,6 +19,10 @@ import (
|
|||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const humanizeTemplate = `{{if gt .Years 0}}{{.Years}}y{{end}}` +
|
||||
`{{if gt .Days 0}}{{.Days}}d{{end}}` +
|
||||
`{{if gt .Hours 0}}{{.Hours}}h{{end}}`
|
||||
|
||||
var (
|
||||
cfg = struct {
|
||||
BranchStaleness time.Duration `flag:"branch-staleness" default:"2160h" description:"When to see a branch as stale (default 90d)"`
|
||||
|
@ -277,6 +282,8 @@ func processRepo(ctx context.Context, logger *log.Entry, client *github.Client,
|
|||
float64(time.Since(b.GetCommit().GetCommit().GetAuthor().GetDate())),
|
||||
float64(time.Since(b.GetCommit().GetCommit().GetCommitter().GetDate())),
|
||||
))
|
||||
d, _ := duration.CustomHumanizeDuration(branchLastModified, humanizeTemplate)
|
||||
branchLogger = branchLogger.WithField("age", d)
|
||||
|
||||
// Check all PRs whether they match the branch (head) and are merged
|
||||
hasValidMerge, hasOpenPR := analysePullRequests(branchLogger, prs, b)
|
||||
|
|
61
vendor/github.com/Luzifer/go_helpers/duration/time.go
generated
vendored
Normal file
61
vendor/github.com/Luzifer/go_helpers/duration/time.go
generated
vendored
Normal file
|
@ -0,0 +1,61 @@
|
|||
package duration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math"
|
||||
"strings"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/leekchan/gtf"
|
||||
)
|
||||
|
||||
const defaultDurationFormat = `{{if gt .Years 0}}{{.Years}} year{{.Years|pluralize "s"}}, {{end}}` +
|
||||
`{{if gt .Days 0}}{{.Days}} day{{.Days|pluralize "s"}}, {{end}}` +
|
||||
`{{if gt .Hours 0}}{{.Hours}} hour{{.Hours|pluralize "s"}}, {{end}}` +
|
||||
`{{if gt .Minutes 0}}{{.Minutes}} minute{{.Minutes|pluralize "s"}}, {{end}}` +
|
||||
`{{if gt .Seconds 0}}{{.Seconds}} second{{.Seconds|pluralize "s"}}{{end}}`
|
||||
|
||||
func HumanizeDuration(in time.Duration) string {
|
||||
f, err := CustomHumanizeDuration(in, defaultDurationFormat)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return strings.Trim(f, " ,")
|
||||
}
|
||||
|
||||
func CustomHumanizeDuration(in time.Duration, tpl string) (string, error) {
|
||||
result := struct{ Years, Days, Hours, Minutes, Seconds int64 }{}
|
||||
|
||||
in = time.Duration(math.Abs(float64(in)))
|
||||
|
||||
for in > 0 {
|
||||
switch {
|
||||
case in > 365.25*24*time.Hour:
|
||||
result.Years = int64(in / (365 * 24 * time.Hour))
|
||||
in = in - time.Duration(result.Years)*365*24*time.Hour
|
||||
case in > 24*time.Hour:
|
||||
result.Days = int64(in / (24 * time.Hour))
|
||||
in = in - time.Duration(result.Days)*24*time.Hour
|
||||
case in > time.Hour:
|
||||
result.Hours = int64(in / time.Hour)
|
||||
in = in - time.Duration(result.Hours)*time.Hour
|
||||
case in > time.Minute:
|
||||
result.Minutes = int64(in / time.Minute)
|
||||
in = in - time.Duration(result.Minutes)*time.Minute
|
||||
default:
|
||||
result.Seconds = int64(in / time.Second)
|
||||
in = 0
|
||||
}
|
||||
}
|
||||
|
||||
tmpl, err := template.New("timeformat").Funcs(template.FuncMap(gtf.GtfFuncMap)).Parse(tpl)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
tmpl.Execute(buf, result)
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
22
vendor/github.com/leekchan/gtf/LICENSE
generated
vendored
Normal file
22
vendor/github.com/leekchan/gtf/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Kyoung-chan Lee (leekchan@gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
470
vendor/github.com/leekchan/gtf/gtf.go
generated
vendored
Normal file
470
vendor/github.com/leekchan/gtf/gtf.go
generated
vendored
Normal file
|
@ -0,0 +1,470 @@
|
|||
package gtf
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
htmlTemplate "html/template"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
textTemplate "text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
var striptagsRegexp = regexp.MustCompile("<[^>]*?>")
|
||||
|
||||
// recovery will silently swallow all unexpected panics.
|
||||
func recovery() {
|
||||
recover()
|
||||
}
|
||||
|
||||
var GtfTextFuncMap = textTemplate.FuncMap{
|
||||
"replace": func(s1 string, s2 string) string {
|
||||
defer recovery()
|
||||
|
||||
return strings.Replace(s2, s1, "", -1)
|
||||
},
|
||||
"title": func(s string) string {
|
||||
defer recovery()
|
||||
return strings.Title(s)
|
||||
},
|
||||
"default": func(arg interface{}, value interface{}) interface{} {
|
||||
defer recovery()
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Kind() {
|
||||
case reflect.String, reflect.Slice, reflect.Array, reflect.Map:
|
||||
if v.Len() == 0 {
|
||||
return arg
|
||||
}
|
||||
case reflect.Bool:
|
||||
if !v.Bool() {
|
||||
return arg
|
||||
}
|
||||
default:
|
||||
return value
|
||||
}
|
||||
|
||||
return value
|
||||
},
|
||||
"length": func(value interface{}) int {
|
||||
defer recovery()
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Kind() {
|
||||
case reflect.Slice, reflect.Array, reflect.Map:
|
||||
return v.Len()
|
||||
case reflect.String:
|
||||
return len([]rune(v.String()))
|
||||
}
|
||||
|
||||
return 0
|
||||
},
|
||||
"lower": func(s string) string {
|
||||
defer recovery()
|
||||
|
||||
return strings.ToLower(s)
|
||||
},
|
||||
"upper": func(s string) string {
|
||||
defer recovery()
|
||||
|
||||
return strings.ToUpper(s)
|
||||
},
|
||||
"truncatechars": func(n int, s string) string {
|
||||
defer recovery()
|
||||
|
||||
if n < 0 {
|
||||
return s
|
||||
}
|
||||
|
||||
r := []rune(s)
|
||||
rLength := len(r)
|
||||
|
||||
if n >= rLength {
|
||||
return s
|
||||
}
|
||||
|
||||
if n > 3 && rLength > 3 {
|
||||
return string(r[:n-3]) + "..."
|
||||
}
|
||||
|
||||
return string(r[:n])
|
||||
},
|
||||
"urlencode": func(s string) string {
|
||||
defer recovery()
|
||||
|
||||
return url.QueryEscape(s)
|
||||
},
|
||||
"wordcount": func(s string) int {
|
||||
defer recovery()
|
||||
|
||||
return len(strings.Fields(s))
|
||||
},
|
||||
"divisibleby": func(arg interface{}, value interface{}) bool {
|
||||
defer recovery()
|
||||
|
||||
var v float64
|
||||
switch value.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
v = float64(reflect.ValueOf(value).Int())
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
v = float64(reflect.ValueOf(value).Uint())
|
||||
case float32, float64:
|
||||
v = reflect.ValueOf(value).Float()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
var a float64
|
||||
switch arg.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
a = float64(reflect.ValueOf(arg).Int())
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
a = float64(reflect.ValueOf(arg).Uint())
|
||||
case float32, float64:
|
||||
a = reflect.ValueOf(arg).Float()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
return math.Mod(v, a) == 0
|
||||
},
|
||||
"lengthis": func(arg int, value interface{}) bool {
|
||||
defer recovery()
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Kind() {
|
||||
case reflect.Slice, reflect.Array, reflect.Map:
|
||||
return v.Len() == arg
|
||||
case reflect.String:
|
||||
return len([]rune(v.String())) == arg
|
||||
}
|
||||
|
||||
return false
|
||||
},
|
||||
"trim": func(s string) string {
|
||||
defer recovery()
|
||||
|
||||
return strings.TrimSpace(s)
|
||||
},
|
||||
"capfirst": func(s string) string {
|
||||
defer recovery()
|
||||
|
||||
return strings.ToUpper(string(s[0])) + s[1:]
|
||||
},
|
||||
"pluralize": func(arg string, value interface{}) string {
|
||||
defer recovery()
|
||||
|
||||
flag := false
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
flag = v.Int() == 1
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
flag = v.Uint() == 1
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
if !strings.Contains(arg, ",") {
|
||||
arg = "," + arg
|
||||
}
|
||||
|
||||
bits := strings.Split(arg, ",")
|
||||
|
||||
if len(bits) > 2 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if flag {
|
||||
return bits[0]
|
||||
}
|
||||
|
||||
return bits[1]
|
||||
},
|
||||
"yesno": func(yes string, no string, value bool) string {
|
||||
defer recovery()
|
||||
|
||||
if value {
|
||||
return yes
|
||||
}
|
||||
|
||||
return no
|
||||
},
|
||||
"rjust": func(arg int, value string) string {
|
||||
defer recovery()
|
||||
|
||||
n := arg - len([]rune(value))
|
||||
|
||||
if n > 0 {
|
||||
value = strings.Repeat(" ", n) + value
|
||||
}
|
||||
|
||||
return value
|
||||
},
|
||||
"ljust": func(arg int, value string) string {
|
||||
defer recovery()
|
||||
|
||||
n := arg - len([]rune(value))
|
||||
|
||||
if n > 0 {
|
||||
value = value + strings.Repeat(" ", n)
|
||||
}
|
||||
|
||||
return value
|
||||
},
|
||||
"center": func(arg int, value string) string {
|
||||
defer recovery()
|
||||
|
||||
n := arg - len([]rune(value))
|
||||
|
||||
if n > 0 {
|
||||
left := n / 2
|
||||
right := n - left
|
||||
value = strings.Repeat(" ", left) + value + strings.Repeat(" ", right)
|
||||
}
|
||||
|
||||
return value
|
||||
},
|
||||
"filesizeformat": func(value interface{}) string {
|
||||
defer recovery()
|
||||
|
||||
var size float64
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
size = float64(v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
size = float64(v.Uint())
|
||||
case reflect.Float32, reflect.Float64:
|
||||
size = v.Float()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
var KB float64 = 1 << 10
|
||||
var MB float64 = 1 << 20
|
||||
var GB float64 = 1 << 30
|
||||
var TB float64 = 1 << 40
|
||||
var PB float64 = 1 << 50
|
||||
|
||||
filesizeFormat := func(filesize float64, suffix string) string {
|
||||
return strings.Replace(fmt.Sprintf("%.1f %s", filesize, suffix), ".0", "", -1)
|
||||
}
|
||||
|
||||
var result string
|
||||
if size < KB {
|
||||
result = filesizeFormat(size, "bytes")
|
||||
} else if size < MB {
|
||||
result = filesizeFormat(size/KB, "KB")
|
||||
} else if size < GB {
|
||||
result = filesizeFormat(size/MB, "MB")
|
||||
} else if size < TB {
|
||||
result = filesizeFormat(size/GB, "GB")
|
||||
} else if size < PB {
|
||||
result = filesizeFormat(size/TB, "TB")
|
||||
} else {
|
||||
result = filesizeFormat(size/PB, "PB")
|
||||
}
|
||||
|
||||
return result
|
||||
},
|
||||
"apnumber": func(value interface{}) interface{} {
|
||||
defer recovery()
|
||||
|
||||
name := [10]string{"one", "two", "three", "four", "five",
|
||||
"six", "seven", "eight", "nine"}
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if v.Int() < 10 {
|
||||
return name[v.Int()-1]
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
if v.Uint() < 10 {
|
||||
return name[v.Uint()-1]
|
||||
}
|
||||
}
|
||||
|
||||
return value
|
||||
},
|
||||
"intcomma": func(value interface{}) string {
|
||||
defer recovery()
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
var x uint
|
||||
minus := false
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if v.Int() < 0 {
|
||||
minus = true
|
||||
x = uint(-v.Int())
|
||||
} else {
|
||||
x = uint(v.Int())
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
x = uint(v.Uint())
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
var result string
|
||||
for x >= 1000 {
|
||||
result = fmt.Sprintf(",%03d%s", x%1000, result)
|
||||
x /= 1000
|
||||
}
|
||||
result = fmt.Sprintf("%d%s", x, result)
|
||||
|
||||
if minus {
|
||||
result = "-" + result
|
||||
}
|
||||
|
||||
return result
|
||||
},
|
||||
"ordinal": func(value interface{}) string {
|
||||
defer recovery()
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
var x uint
|
||||
switch v.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if v.Int() < 0 {
|
||||
return ""
|
||||
}
|
||||
x = uint(v.Int())
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
x = uint(v.Uint())
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
|
||||
suffixes := [10]string{"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"}
|
||||
|
||||
switch x % 100 {
|
||||
case 11, 12, 13:
|
||||
return fmt.Sprintf("%d%s", x, suffixes[0])
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%d%s", x, suffixes[x%10])
|
||||
},
|
||||
"first": func(value interface{}) interface{} {
|
||||
defer recovery()
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
return string([]rune(v.String())[0])
|
||||
case reflect.Slice, reflect.Array:
|
||||
return v.Index(0).Interface()
|
||||
}
|
||||
|
||||
return ""
|
||||
},
|
||||
"last": func(value interface{}) interface{} {
|
||||
defer recovery()
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
str := []rune(v.String())
|
||||
return string(str[len(str)-1])
|
||||
case reflect.Slice, reflect.Array:
|
||||
return v.Index(v.Len() - 1).Interface()
|
||||
}
|
||||
|
||||
return ""
|
||||
},
|
||||
"join": func(arg string, value []string) string {
|
||||
defer recovery()
|
||||
|
||||
return strings.Join(value, arg)
|
||||
},
|
||||
"slice": func(start int, end int, value interface{}) interface{} {
|
||||
defer recovery()
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
str := []rune(v.String())
|
||||
|
||||
if end > len(str) {
|
||||
end = len(str)
|
||||
}
|
||||
|
||||
return string(str[start:end])
|
||||
case reflect.Slice:
|
||||
return v.Slice(start, end).Interface()
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"random": func(value interface{}) interface{} {
|
||||
defer recovery()
|
||||
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
|
||||
v := reflect.ValueOf(value)
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.String:
|
||||
str := []rune(v.String())
|
||||
return string(str[rand.Intn(len(str))])
|
||||
case reflect.Slice, reflect.Array:
|
||||
return v.Index(rand.Intn(v.Len())).Interface()
|
||||
}
|
||||
|
||||
return ""
|
||||
},
|
||||
"striptags": func(s string) string {
|
||||
return strings.TrimSpace(striptagsRegexp.ReplaceAllString(s, ""))
|
||||
},
|
||||
}
|
||||
|
||||
var GtfFuncMap = htmlTemplate.FuncMap(GtfTextFuncMap)
|
||||
|
||||
// gtf.New is a wrapper function of template.New(https://golang.org/pkg/html/template/#New).
|
||||
// It automatically adds the gtf functions to the template's function map
|
||||
// and returns template.Template(http://golang.org/pkg/html/template/#Template).
|
||||
func New(name string) *htmlTemplate.Template {
|
||||
return htmlTemplate.New(name).Funcs(GtfFuncMap)
|
||||
}
|
||||
|
||||
// gtf.Inject injects gtf functions into the passed FuncMap.
|
||||
// It does not overwrite the original function which have same name as a gtf function.
|
||||
func Inject(funcs map[string]interface{}) {
|
||||
for k, v := range GtfFuncMap {
|
||||
if _, ok := funcs[k]; !ok {
|
||||
funcs[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// gtf.ForceInject injects gtf functions into the passed FuncMap.
|
||||
// It overwrites the original function which have same name as a gtf function.
|
||||
func ForceInject(funcs map[string]interface{}) {
|
||||
for k, v := range GtfFuncMap {
|
||||
funcs[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// gtf.Inject injects gtf functions into the passed FuncMap.
|
||||
// It prefixes the gtf functions with the specified prefix.
|
||||
// If there are many function which have same names as the gtf functions,
|
||||
// you can use this function to prefix the gtf functions.
|
||||
func InjectWithPrefix(funcs map[string]interface{}, prefix string) {
|
||||
for k, v := range GtfFuncMap {
|
||||
funcs[prefix+k] = v
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue