func InitializeOptions(opts *Options) *Options {
	if opts == nil {
		opts = &Options{}
	}

	if opts.Extension == "" {
		opts.Extension = defaultExtension
	}

	if opts.DelimLeft == "" {
		opts.DelimLeft = defaultDelimLeft
	}

	if opts.DelimRight == "" {
		opts.DelimRight = defaultDelimRight
	}

	if opts.AttributeNameClass == "" {
		opts.AttributeNameClass = defaultAttributeNameClass
	}
	if opts.NoCloseTagNames == nil {
		opts.NoCloseTagNames = make([]string, len(defaultNoCloseTagNames))
		copy(opts.NoCloseTagNames, defaultNoCloseTagNames)
	}

	if opts.Indent != "" {
		opts.formatter = newFormatter(opts.Indent)
	}

	return opts
}

func InitializeOptions ( opts * Options ) * Options { if opts == nil { opts = & Options { } } if opts . Extension == " " { opts . Extension = defaultExtension } if opts . DelimLeft == " " { opts . DelimLeft = defaultDelimLeft } if opts . DelimRight == " " { opts . DelimRight = defaultDelimRight } if opts . AttributeNameClass == " " { opts . AttributeNameClass = defaultAttributeNameClass } if opts . NoCloseTagNames == nil { opts . NoCloseTagNames = make ( [ ] string , len ( defaultNoCloseTagNames ) ) copy ( opts . NoCloseTagNames , defaultNoCloseTagNames ) } if opts . Indent != " " { opts . formatter = newFormatter ( opts . Indent ) } return opts }

// InitializeOptions initializes the options.

InitializeOptions initializes the options .


func (opts *Options) AddNoCloseTagName(name string) {
	opts.NoCloseTagNames = append(opts.NoCloseTagNames, name)
}

func ( opts * Options ) AddNoCloseTagName ( name string ) { opts . NoCloseTagNames = append ( opts . NoCloseTagNames , name ) }

// AddNoCloseTagName appends name to .NoCloseTagNames set.

AddNoCloseTagName appends name to . NoCloseTagNames set .


func (opts *Options) DeleteNoCloseTagName(name string) {
	var newset []string
	for _, n := range opts.NoCloseTagNames {
		if n != name {
			newset = append(newset, n)
		}
	}
	opts.NoCloseTagNames = newset
}

func ( opts * Options ) DeleteNoCloseTagName ( name string ) { var newset [ ] string for _ , n := range opts . NoCloseTagNames { if n != name { newset = append ( newset , n ) } } opts . NoCloseTagNames = newset }

// DeleteNoCloseTagName deletes name from .NoCloseTagNames set.

DeleteNoCloseTagName deletes name from . NoCloseTagNames set .


func Asset(name string) ([]byte, error) {
	if f, ok := _bindata[name]; ok {
		return f()
	}
	return nil, fmt.Errorf("Asset %s not found", name)
}

func Asset ( name string ) ( [ ] byte , error ) { if f , ok := _bindata [ name ] ; ok { return f ( ) } return nil , fmt . Errorf ( " " , name ) }

// Asset loads and returns the asset for the given name.
// It returns an error if the asset could not be found or
// could not be loaded.

Asset loads and returns the asset for the given name . It returns an error if the asset could not be found or could not be loaded .


func newAction(ln *line, rslt *result, src *source, parent element, opts *Options) *action {
	return &action{
		elementBase: newElementBase(ln, rslt, src, parent, opts),
	}
}

func newAction ( ln * line , rslt * result , src * source , parent element , opts * Options ) * action { return & action { elementBase : newElementBase ( ln , rslt , src , parent , opts ) , } }

// newAction creates and returns an action.

newAction creates and returns an action .


func AddRelayTransport(ctx context.Context, h host.Host, upgrader *tptu.Upgrader, opts ...RelayOpt) error {
	n, ok := h.Network().(tpt.Network)
	if !ok {
		return fmt.Errorf("%v is not a transport network", h.Network())
	}

	r, err := NewRelay(ctx, h, upgrader, opts...)
	if err != nil {
		return err
	}

	// There's no nice way to handle these errors as we have no way to tear
	// down the relay.
	// TODO
	if err := n.AddTransport(r.Transport()); err != nil {
		log.Error("failed to add relay transport:", err)
	} else if err := n.Listen(r.Listener().Multiaddr()); err != nil {
		log.Error("failed to listen on relay transport:", err)
	}
	return nil
}

// AddRelayTransport constructs a relay and adds it as a transport to the host network.

AddRelayTransport constructs a relay and adds it as a transport to the host network .


func NewRelay(ctx context.Context, h host.Host, upgrader *tptu.Upgrader, opts ...RelayOpt) (*Relay, error) {
	r := &Relay{
		upgrader: upgrader,
		host:     h,
		ctx:      ctx,
		self:     h.ID(),
		incoming: make(chan *Conn),
		relays:   make(map[peer.ID]struct{}),
		liveHops: make(map[peer.ID]map[peer.ID]int),
	}

	for _, opt := range opts {
		switch opt {
		case OptActive:
			r.active = true
		case OptHop:
			r.hop = true
		case OptDiscovery:
			r.discovery = true
		default:
			return nil, fmt.Errorf("unrecognized option: %d", opt)
		}
	}

	h.SetStreamHandler(ProtoID, r.handleNewStream)

	if r.discovery {
		h.Network().Notify(r.notifiee())
	}

	return r, nil
}

func NewRelay ( ctx context . Context , h host . Host , upgrader * tptu . Upgrader , opts ... RelayOpt ) ( * Relay , error ) { r := & Relay { upgrader : upgrader , host : h , ctx : ctx , self : h . ID ( ) , incoming : make ( chan * Conn ) , relays : make ( map [ peer . ID ] struct { } ) , liveHops : make ( map [ peer . ID ] map [ peer . ID ] int ) , } for _ , opt := range opts { switch opt { case OptActive : r . active = true case OptHop : r . hop = true case OptDiscovery : r . discovery = true default : return nil , fmt . Errorf ( " " , opt ) } } h . SetStreamHandler ( ProtoID , r . handleNewStream ) if r . discovery { h . Network ( ) . Notify ( r . notifiee ( ) ) } return r , nil }


func ParseJSONBody(r io.Reader) (interface{}, error) {
	var v interface{}
	if err := json.NewDecoder(r).Decode(&v); err != nil {
		return nil, err
	}
	return v, nil
}

func ParseJSONBody ( r io . Reader ) ( interface { } , error ) { var v interface { } if err := json . NewDecoder ( r ) . Decode ( & v ) ; err != nil { return nil , err } return v , nil }


func New(t T, URL string) *Runner {
	r := &Runner{
		t:         t,
		rootURL:   URL,
		vars:      make(map[string]*parse.Value),
		DoRequest: http.DefaultTransport.RoundTrip,
		Log: func(s string) {
			fmt.Println(s)
		},
		Verbose: func(args ...interface{}) {
			if !testing.Verbose() {
				return
			}
			fmt.Println(args...)
		},
		ParseBody:  ParseJSONBody,
		NewRequest: http.NewRequest,
	}
	// capture environment variables by default
	for _, e := range os.Environ() {
		pair := strings.Split(e, "=")
		r.vars[pair[0]] = parse.ParseValue([]byte(pair[1]))
	}
	return r
}

// New makes a new Runner with the given testing T target and the
// root URL.

New makes a new Runner with the given testing T target and the root URL .


func (r *Runner) RunGroup(groups ...*parse.Group) {
	for _, group := range groups {
		r.runGroup(group)
	}
}

func ( r * Runner ) RunGroup ( groups ... * parse . Group ) { for _ , group := range groups { r . runGroup ( group ) } }

// RunGroup runs a parse.Group.
// Consider RunFile instead.

RunGroup runs a parse . Group . Consider RunFile instead .


func ParseFile(files ...string) ([]*Group, error) {
	var groups []*Group
	for _, file := range files {
		if err := func(file string) error {
			f, err := os.Open(file)
			if err != nil {
				return err
			}
			defer f.Close()
			gs, err := Parse(file, f)
			if err != nil {
				return err
			}
			groups = append(groups, gs...)
			return nil
		}(file); err != nil {
			return nil, err
		}
	}
	return groups, nil
}

func ParseFile ( files ... string ) ( [ ] * Group , error ) { var groups [ ] * Group for _ , file := range files { if err := func ( file string ) error { f , err := os . Open ( file ) if err != nil { return err } defer f . Close ( ) gs , err := Parse ( file , f ) if err != nil { return err } groups = append ( groups , gs ... ) return nil } ( file ) ; err != nil { return nil , err } } return groups , nil }

// ParseFile parses the specified files.


func ParseLine(n int, unsafeText []byte) (*Line, error) {
	linetype := LineTypePlain
	// trim off comments
	var comment []byte
	text := make([]byte, len(unsafeText))
	copy(text, unsafeText)
	if bytes.Contains(text, commentPrefix) {
		segs := bytes.Split(text, commentPrefix)
		text = segs[0]
		comment = segs[1]
	}
	var rx *regexp.Regexp
	for _, item := range matchTypes {
		if regexes[item.R].Match(text) {
			linetype = item.Type
			rx = regexes[item.R]
			break
		}
	}
	// parse the detail now
	var d *Detail
	if linetype == LineTypeDetail || linetype == LineTypeParam {
		var err error
		d, err = parseDetail(text, rx)
		if err != nil {
			return nil, &ErrLine{N: n, Err: err}
		}
	}
	return &Line{
		Number:  n,
		Type:    linetype,
		Bytes:   text,
		Regexp:  rx,
		Comment: comment,
		detail:  d,
	}, nil
}

func
ParseLine
(
n
int
,
unsafeText
[
]
byte
)
(
*
Line
,
error
)
{
linetype
:=
LineTypePlain
// trim off comments
var
comment
[
]
byte
text
:=
make
(
[
]
byte
,
len
(
unsafeText
)
)
copy
(
text
,
unsafeText
)
if
bytes
.
Contains
(
text
,
commentPrefix
)
{
segs
:=
bytes
.
Split
(
text
,
commentPrefix
)
text
=
segs
[
0
]
comment
=
segs
[
1
]
}
var
rx
*
regexp
.
Regexp
for
_
,
item
:=
range
matchTypes
{
if
regexes
[
item
.
R
]
.
Match
(
text
)
{
linetype
=
item
.
Type
rx
=
regexes
[
item
.
R
]
break
}
}
// parse the detail now
var
d
*
Detail
if
linetype
==
LineTypeDetail
||
linetype
==
LineTypeParam
{
var
err
error
d
,
err
=
parseDetail
(
text
,
rx
)
if
err
!=
{
return
,
&
ErrLine
{
N
:
n
,
Err
:
err
}
}
}
return
&
Line
{
Number
:
n
,
Type
:
linetype
,
Bytes
:
text
,
Regexp
:
rx
,
Comment
:
comment
,
detail
:
d
,
}
,
}

// ParseLine makes a new Line with the given data.

ParseLine makes a new Line with the given data .


func (l *Line) Capture() string {
	if len(l.Comment) == 0 {
		return ""
	}
	matches := placeholderRegexp.FindSubmatch(l.Comment)
	if len(matches) < 2 {
		return ""
	}
	return string(matches[1])
}

func ( l * Line ) Capture ( ) string { if len ( l . Comment ) == 0 { return " " } matches := placeholderRegexp . FindSubmatch ( l . Comment ) if len ( matches ) < 2 { return " " } return string ( matches [ 1 ] ) }

// Capture extracts the first placeholder value from the
// comments.

Capture extracts the first placeholder value from the comments .


func (l Lines) Bytes() []byte {
	var lines [][]byte
	for _, line := range l {
		lines = append(lines, line.Bytes)
	}
	return bytes.Join(lines, []byte("\n"))
}

func ( l Lines ) Bytes ( ) [ ] byte { var lines [ ] [ ] byte for _ , line := range l { lines = append ( lines , line . Bytes ) } return bytes . Join ( lines , [ ] byte ( " \n " ) ) }

// Bytes gets the joined bytes of all lines.

Bytes gets the joined bytes of all lines .


func (v Value) Equal(val interface{}) bool {
	var str string
	var ok bool
	if str, ok = v.Data.(string); !ok {
		return v.Data == val
	}
	if isRegex(str) {
		// looks like regexp to me
		regex := regexp.MustCompile(str[1 : len(str)-1])
		// turn the value into a string
		valStr := fmt.Sprintf("%v", val)
		if regex.Match([]byte(valStr)) {
			return true
		}
	}
	return fmt.Sprintf("%v", v.Data) == fmt.Sprintf("%v", val)
}

func
(
v
Value
)
Equal
(
val
interface
{
}
)
bool
{
var
str
string
var
ok
bool
if
str
,
ok
=
v
.
Data
.
(
string
)
;
!
ok
{
return
v
.
Data
==
val
}
if
isRegex
(
str
)
{
// looks like regexp to me
regex
:=
regexp
.
MustCompile
(
str
[
1
:
len
(
str
)
1
]
)
// turn the value into a string
valStr
:=
fmt
.
Sprintf
(
"
"
,
val
)
if
regex
.
Match
(
[
]
byte
(
valStr
)
)
{
return
true
}
}
return
fmt
.
Sprintf
(
"
"
,
v
.
Data
)
==
fmt
.
Sprintf
(
"
"
,
val
)
}

// Equal gets whether the Data and specified value are equal.
// Supports regexp values.

Equal gets whether the Data and specified value are equal . Supports regexp values .


func (v Value) Type() string {
	var str string
	var ok bool
	if str, ok = v.Data.(string); !ok {
		return fmt.Sprintf("%T", v.Data)
	}
	if isRegex(str) {
		return "regex"
	}
	return "string"
}

func ( v Value ) Type ( ) string { var str string var ok bool if str , ok = v . Data . ( string ) ; ! ok { return fmt . Sprintf ( " " , v . Data ) } if isRegex ( str ) { return " " } return " " }

// Type gets a string describing the type of this Value.

Type gets a string describing the type of this Value .


func NewServer() http.Handler {
	r := mux.NewRouter()
	r.Path("/hello").Methods("GET").HandlerFunc(handleHello)
	return r
}

func NewServer ( ) http . Handler { r := mux . NewRouter ( ) r . Path ( " " ) . Methods ( " " ) . HandlerFunc ( handleHello ) return r }

// NewServer makes a new example server.


func PrettyPrintAsJSON(input interface{}, indent ...string) error {
	var indentStr string
	if len(indent) == 0 {
		indentStr = "  "
	} else {
		indentStr = strings.Join(indent, "")
	}
	data, err := json.MarshalIndent(input, "", indentStr)
	if err != nil {
		return err
	}
	_, err = fmt.Println(string(data))
	return err
}

func PrettyPrintAsJSON ( input interface { } , indent ... string ) error { var indentStr string if len ( indent ) == 0 { indentStr = " " } else { indentStr = strings . Join ( indent , " " ) } data , err := json . MarshalIndent ( input , " " , indentStr ) if err != nil { return err } _ , err = fmt . Println ( string ( data ) ) return err }

// PrettyPrintAsJSON marshalles input as indented JSON
// and calles fmt.Println with the result.
// If indent arguments are given, they are joined into
// a string and used as JSON line indent.
// If no indet argument is given, two spaces will be used
// to indent JSON lines.

PrettyPrintAsJSON marshalles input as indented JSON and calles fmt . Println with the result . If indent arguments are given they are joined into a string and used as JSON line indent . If no indet argument is given two spaces will be used to indent JSON lines .


func StringMarshalJSON(data interface{}, indent string) string {
	buffer, err := json.MarshalIndent(data, "", indent)
	if err != nil {
		return ""
	}
	return string(buffer)
}

func StringMarshalJSON ( data interface { } , indent string ) string { buffer , err := json . MarshalIndent ( data , " " , indent ) if err != nil { return " " } return string ( buffer ) }

// StringMarshalJSON marshals data to an indented string.

StringMarshalJSON marshals data to an indented string .


func StringMD5Hex(data string) string {
	hash := md5.New()
	hash.Write([]byte(data))
	return fmt.Sprintf("%x", hash.Sum(nil))
}

func StringMD5Hex ( data string ) string { hash := md5 . New ( ) hash . Write ( [ ] byte ( data ) ) return fmt . Sprintf ( " " , hash . Sum ( nil ) ) }

// StringMD5Hex returns the hex encoded MD5 hash of data


func StringSHA1Base64(data string) string {
	hash := sha1.Sum([]byte(data))
	return base64.StdEncoding.EncodeToString(hash[:])
}

func StringSHA1Base64 ( data string ) string { hash := sha1 . Sum ( [ ] byte ( data ) ) return base64 . StdEncoding . EncodeToString ( hash [ : ] ) }

// StringSHA1Base64 returns the base64 encoded SHA1 hash of data


func StringJoinFormat(format string, values interface{}, sep string) string {
	v := reflect.ValueOf(values)
	if v.Kind() != reflect.Slice {
		panic("values is not a slice")
	}
	var buffer bytes.Buffer
	for i := 0; i < v.Len(); i++ {
		if i > 0 {
			buffer.WriteString(sep)
		}
		buffer.WriteString(fmt.Sprintf(format, v.Index(i).Interface()))
	}
	return buffer.String()
}

func StringJoinFormat ( format string , values interface { } , sep string ) string { v := reflect . ValueOf ( values ) if v . Kind ( ) != reflect . Slice { panic ( " " ) } var buffer bytes . Buffer for i := 0 ; i < v . Len ( ) ; i ++ { if i > 0 { buffer . WriteString ( sep ) } buffer . WriteString ( fmt . Sprintf ( format , v . Index ( i ) . Interface ( ) ) ) } return buffer . String ( ) }

// StringJoinFormat formats every value in values with format
// and joins the result with sep as separator.
// values must be a slice of a formatable type

StringJoinFormat formats every value in values with format and joins the result with sep as separator . values must be a slice of a formatable type


func StringJoin(values interface{}, sep string) string {
	v := reflect.ValueOf(values)
	if v.Kind() != reflect.Slice {
		panic("values is not a slice")
	}
	var buffer bytes.Buffer
	for i := 0; i < v.Len(); i++ {
		if i > 0 {
			buffer.WriteString(sep)
		}
		buffer.WriteString(fmt.Sprint(v.Index(i).Interface()))
	}
	return buffer.String()
}

func StringJoin ( values interface { } , sep string ) string { v := reflect . ValueOf ( values ) if v . Kind ( ) != reflect . Slice { panic ( " " ) } var buffer bytes . Buffer for i := 0 ; i < v . Len ( ) ; i ++ { if i > 0 { buffer . WriteString ( sep ) } buffer . WriteString ( fmt . Sprint ( v . Index ( i ) . Interface ( ) ) ) } return buffer . String ( ) }

// StringJoin formats every value in values according to its default formatting
// and joins the result with sep as separator.
// values must be a slice of a formatable type

StringJoin formats every value in values according to its default formatting and joins the result with sep as separator . values must be a slice of a formatable type


func (s StringGroupedNumberPostfixSorter) Less(i, j int) bool {
	bi, ni := StringSplitNumberPostfix(s[i])
	bj, nj := StringSplitNumberPostfix(s[j])

	if bi == bj {
		if len(ni) == len(nj) {
			inti, _ := strconv.Atoi(ni)
			intj, _ := strconv.Atoi(nj)
			return inti < intj
		} else {
			return len(ni) < len(nj)
		}
	}

	return bi < bj
}

func ( s StringGroupedNumberPostfixSorter ) Less ( i , j int ) bool { bi , ni := StringSplitNumberPostfix ( s [ i ] ) bj , nj := StringSplitNumberPostfix ( s [ j ] ) if bi == bj { if len ( ni ) == len ( nj ) { inti , _ := strconv . Atoi ( ni ) intj , _ := strconv . Atoi ( nj ) return inti < intj } else { return len ( ni ) < len ( nj ) } } return bi < bj }

// Less reports whether the element with
// index i should sort before the element with index j.

Less reports whether the element with index i should sort before the element with index j .


func (s StringGroupedNumberPostfixSorter) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func ( s StringGroupedNumberPostfixSorter ) Swap ( i , j int ) { s [ i ] , s [ j ] = s [ j ] , s [ i ] }

// Swap swaps the elements with indexes i and j.

Swap swaps the elements with indexes i and j .


func StringMap(f func(string) string, data []string) []string {
	size := len(data)
	result := make([]string, size, size)
	for i := 0; i < size; i++ {
		result[i] = f(data[i])
	}
	return result
}

func StringMap ( f func ( string ) string , data [ ] string ) [ ] string { size := len ( data ) result := make ( [ ] string , size , size ) for i := 0 ; i < size ; i ++ { result [ i ] = f ( data [ i ] ) } return result }

// Map a function on each element of a slice of strings.

Map a function on each element of a slice of strings .


func StringFilter(f func(string) bool, data []string) []string {
	result := make([]string, 0, 0)
	for _, element := range data {
		if f(element) {
			result = append(result, element)
		}
	}
	return result
}

func StringFilter ( f func ( string ) bool , data [ ] string ) [ ] string { result := make ( [ ] string , 0 , 0 ) for _ , element := range data { if f ( element ) { result = append ( result , element ) } } return result }

// Filter out all strings where the function does not return true.

Filter out all strings where the function does not return true .


func StringFindBetween(s, start, stop string) (between, remainder string, found bool) {
	begin := strings.Index(s, start)
	if begin == -1 {
		return "", s, false
	}
	between = s[begin+len(start):]
	end := strings.Index(between, stop)
	if end == -1 {
		return "", s, false
	}
	return between[:end], s[begin+len(start)+end+len(stop):], true
}

func StringFindBetween ( s , start , stop string ) ( between , remainder string , found bool ) { begin := strings . Index ( s , start ) if begin == - 1 { return " " , s , false } between = s [ begin + len ( start ) : ] end := strings . Index ( between , stop ) if end == - 1 { return " " , s , false } return between [ : end ] , s [ begin + len ( start ) + end + len ( stop ) : ] , true }

// StringFindBetween returns the string between the first occurrences of the tokens start and stop.
// The remainder of the string after the stop token will be returned if found.
// If the tokens couldn't be found, then the whole string will be returned as remainder.

StringFindBetween returns the string between the first occurrences of the tokens start and stop . The remainder of the string after the stop token will be returned if found . If the tokens couldn t be found then the whole string will be returned as remainder .


func StringFind(s, token string) (remainder string, found bool) {
	i := strings.Index(s, token)
	if i == -1 {
		return s, false
	}
	return s[i+len(token):], true
}

func StringFind ( s , token string ) ( remainder string , found bool ) { i := strings . Index ( s , token ) if i == - 1 { return s , false } return s [ i + len ( token ) : ] , true }

// StringFind returns in found if token has been found in s,
// and returns the remaining string afte token in remainder.
// The whole string s will be returned if found is false.

StringFind returns in found if token has been found in s and returns the remaining string afte token in remainder . The whole string s will be returned if found is false .


func EncryptAES(key []byte, plaintext []byte) []byte {
	block := AES.GetCypher(key)
	defer AES.ReturnCypher(key, block)

	// The IV needs to be unique, but not secure. Therefore it's common to
	// include it at the beginning of the ciphertext.
	ciphertext := make([]byte, aes.BlockSize+len(plaintext))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], plaintext)

	return ciphertext
}

// EncryptAES encrypts plaintext using AES with the given key.
// key should be either 16, 24, or 32 bytes to select
// AES-128, AES-192, or AES-256.
// plaintext must not be shorter than key.

EncryptAES encrypts plaintext using AES with the given key . key should be either 16 24 or 32 bytes to select AES - 128 AES - 192 or AES - 256 . plaintext must not be shorter than key .


func DecryptAES(key []byte, ciphertext []byte) []byte {
	block := AES.GetCypher(key)
	defer AES.ReturnCypher(key, block)

	// The IV needs to be unique, but not secure. Therefore it's common to
	// include it at the beginning of the ciphertext.
	if len(ciphertext) < aes.BlockSize {
		panic("ciphertext too short")
	}
	iv := ciphertext[:aes.BlockSize]
	ciphertext = ciphertext[aes.BlockSize:]

	stream := cipher.NewCFBDecrypter(block, iv)

	// XORKeyStream can work in-place if the two arguments are the same.
	stream.XORKeyStream(ciphertext, ciphertext)

	return ciphertext
}

// DecryptAES decrypts ciphertext using AES with the given key.
// key should be either 16, 24, or 32 bytes to select
// AES-128, AES-192, or AES-256.

DecryptAES decrypts ciphertext using AES with the given key . key should be either 16 24 or 32 bytes to select AES - 128 AES - 192 or AES - 256 .


func PanicIfErr(args ...interface{}) {
	for _, v := range args {
		if err, _ := v.(error); err != nil {
			panic(fmt.Errorf("Panicking because of error: %s\nAt:\n%s\n", err, StackTrace(2)))
		}
	}
}

func PanicIfErr ( args ... interface { } ) { for _ , v := range args { if err , _ := v . ( error ) ; err != nil { panic ( fmt . Errorf ( " \n \n \n " , err , StackTrace ( 2 ) ) ) } } }

// PanicIfErr panics with a stack trace if any
// of the passed args is a non nil error

PanicIfErr panics with a stack trace if any of the passed args is a non nil error


func AsError(r interface{}) error {
	if r == nil {
		return nil
	}
	if err, ok := r.(error); ok {
		return err
	}
	return fmt.Errorf("%v", r)
}

func AsError ( r interface { } ) error { if r == nil { return nil } if err , ok := r . ( error ) ; ok { return err } return fmt . Errorf ( " " , r ) }

// AsError returns r as error, converting it when necessary

AsError returns r as error converting it when necessary


func FirstError(errs ...error) error {
	for _, err := range errs {
		if err != nil {
			return err
		}
	}
	return nil
}

func FirstError ( errs ... error ) error { for _ , err := range errs { if err != nil { return err } } return nil }

// FirstError returns the first non nil error, or nil

FirstError returns the first non nil error or nil


func LastError(errs ...error) error {
	for i := len(errs) - 1; i >= 0; i-- {
		err := errs[i]
		if err != nil {
			return err
		}
	}
	return nil
}

func LastError ( errs ... error ) error { for i := len ( errs ) - 1 ; i >= 0 ; i -- { err := errs [ i ] if err != nil { return err } } return nil }

// LastError returns the last non nil error, or nil

LastError returns the last non nil error or nil


func AsErrorList(err error) ErrorList {
	if list, ok := err.(ErrorList); ok {
		return list
	}
	return ErrorList{err}
}

func AsErrorList ( err error ) ErrorList { if list , ok := err . ( ErrorList ) ; ok { return list } return ErrorList { err } }

// AsErrorList checks if err is already an ErrorList
// and returns it if this is the case.
// Else an ErrorList with err as element is created.
// Useful if a function potentially returns an ErrorList as error
// and you want to avoid creating nested ErrorLists.

AsErrorList checks if err is already an ErrorList and returns it if this is the case . Else an ErrorList with err as element is created . Useful if a function potentially returns an ErrorList as error and you want to avoid creating nested ErrorLists .


func (list ErrorList) Error() string {
	if len(list) == 0 {
		return "Empty ErrorList"
	}
	var b strings.Builder
	for _, err := range list {
		fmt.Fprintln(&b, err)
	}
	return b.String()
}

func ( list ErrorList ) Error ( ) string { if len ( list ) == 0 { return " " } var b strings . Builder for _ , err := range list { fmt . Fprintln ( & b , err ) } return b . String ( ) }

// Error calls fmt.Println for of every error in the list
// and returns the concernated text.
// Can be called for a nil ErrorList.

Error calls fmt . Println for of every error in the list and returns the concernated text . Can be called for a nil ErrorList .


func (list ErrorList) Last() error {
	if len(list) == 0 {
		return nil
	}
	return list[len(list)-1]
}

func ( list ErrorList ) Last ( ) error { if len ( list ) == 0 { return nil } return list [ len ( list ) - 1 ] }

// Last returns the last error in the list or nil.
// Can be called for a nil ErrorList.

Last returns the last error in the list or nil . Can be called for a nil ErrorList .


func (list *ErrorList) Collect(args ...interface{}) {
	for _, a := range args {
		if err, _ := a.(error); err != nil {
			*list = append(*list, err)
		}
	}
}

func ( list * ErrorList ) Collect ( args ... interface { } ) { for _ , a := range args { if err , _ := a . ( error ) ; err != nil { * list = append ( * list , err ) } } }

// Collect adds any non nil errors in args to the list.

Collect adds any non nil errors in args to the list .


func HTTPCompressHandlerFunc(handlerFunc http.HandlerFunc) http.HandlerFunc {
	return func(response http.ResponseWriter, request *http.Request) {
		NewHTTPCompressHandlerFromFunc(handlerFunc).ServeHTTP(response, request)
	}
}

func HTTPCompressHandlerFunc ( handlerFunc http . HandlerFunc ) http . HandlerFunc { return func ( response http . ResponseWriter , request * http . Request ) { NewHTTPCompressHandlerFromFunc ( handlerFunc ) . ServeHTTP ( response , request ) } }

// HTTPCompressHandlerFunc wraps a http.HandlerFunc so that the response gets
// gzip or deflate compressed if the Accept-Encoding header of the request allows it.

HTTPCompressHandlerFunc wraps a http . HandlerFunc so that the response gets gzip or deflate compressed if the Accept - Encoding header of the request allows it .


func HTTPPostJSON(url string, data interface{}) error {
	b, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		return err
	}
	response, err := http.Post(url, "application/json", bytes.NewBuffer(b))
	if err == nil && (response.StatusCode < 200 || response.StatusCode > 299) {
		err = errors.New(response.Status)
	}
	return err
}

func HTTPPostJSON ( url string , data interface { } ) error { b , err := json . MarshalIndent ( data , " " , " " ) if err != nil { return err } response , err := http . Post ( url , " " , bytes . NewBuffer ( b ) ) if err == nil && ( response . StatusCode < 200 || response . StatusCode > 299 ) { err = errors . New ( response . Status ) } return err }

// HTTPPostJSON marshalles data as JSON
// and sends it as HTTP POST request to url.
// If the response status code is not 200 OK,
// then the status is returned as an error.

HTTPPostJSON marshalles data as JSON and sends it as HTTP POST request to url . If the response status code is not 200 OK then the status is returned as an error .


func HTTPDelete(url string) (statusCode int, statusText string, err error) {
	request, err := http.NewRequest("DELETE", url, nil)
	if err != nil {
		return 0, "", err
	}
	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return 0, "", err
	}
	return response.StatusCode, response.Status, nil
}

func HTTPDelete ( url string ) ( statusCode int , statusText string , err error ) { request , err := http . NewRequest ( " " , url , nil ) if err != nil { return 0 , " " , err } response , err := http . DefaultClient . Do ( request ) if err != nil { return 0 , " " , err } return response . StatusCode , response . Status , nil }

// HTTPDelete performs a HTTP DELETE request


func HTTPUnmarshalRequestBodyJSON(request *http.Request, result interface{}) error {
	defer request.Body.Close()
	body, err := ioutil.ReadAll(request.Body)
	if err != nil {
		return err
	}
	return json.Unmarshal(body, result)
}

func HTTPUnmarshalRequestBodyJSON ( request * http . Request , result interface { } ) error { defer request . Body . Close ( ) body , err := ioutil . ReadAll ( request . Body ) if err != nil { return err } return json . Unmarshal ( body , result ) }

// HTTPUnmarshalRequestBodyJSON reads a http.Request body and unmarshals it as JSON to result.

HTTPUnmarshalRequestBodyJSON reads a http . Request body and unmarshals it as JSON to result .


func (pool *DeflatePool) GetWriter(dst io.Writer) (writer *flate.Writer) {
	if w := pool.pool.Get(); w != nil {
		writer = w.(*flate.Writer)
		writer.Reset(dst)
	} else {
		writer, _ = flate.NewWriter(dst, flate.BestCompression)
	}
	return writer
}

func ( pool * DeflatePool ) GetWriter ( dst io . Writer ) ( writer * flate . Writer ) { if w := pool . pool . Get ( ) ; w != nil { writer = w . ( * flate . Writer ) writer . Reset ( dst ) } else { writer , _ = flate . NewWriter ( dst , flate . BestCompression ) } return writer }

// GetWriter returns flate.Writer from the pool, or creates a new one
// with flate.BestCompression if the pool is empty.

GetWriter returns flate . Writer from the pool or creates a new one with flate . BestCompression if the pool is empty .


func (pool *DeflatePool) ReturnWriter(writer *flate.Writer) {
	writer.Close()
	pool.pool.Put(writer)
}

func ( pool * DeflatePool ) ReturnWriter ( writer * flate . Writer ) { writer . Close ( ) pool . pool . Put ( writer ) }

// ReturnWriter returns a flate.Writer to the pool that can
// late be reused via GetWriter.
// Don't close the writer, Flush will be called before returning
// it to the pool.

ReturnWriter returns a flate . Writer to the pool that can late be reused via GetWriter . Don t close the writer Flush will be called before returning it to the pool .


func (pool *GzipPool) GetWriter(dst io.Writer) (writer *gzip.Writer) {
	if w := pool.pool.Get(); w != nil {
		writer = w.(*gzip.Writer)
		writer.Reset(dst)
	} else {
		writer, _ = gzip.NewWriterLevel(dst, gzip.BestCompression)
	}
	return writer
}

func ( pool * GzipPool ) GetWriter ( dst io . Writer ) ( writer * gzip . Writer ) { if w := pool . pool . Get ( ) ; w != nil { writer = w . ( * gzip . Writer ) writer . Reset ( dst ) } else { writer , _ = gzip . NewWriterLevel ( dst , gzip . BestCompression ) } return writer }

// GetWriter returns gzip.Writer from the pool, or creates a new one
// with gzip.BestCompression if the pool is empty.

GetWriter returns gzip . Writer from the pool or creates a new one with gzip . BestCompression if the pool is empty .


func (pool *GzipPool) ReturnWriter(writer *gzip.Writer) {
	writer.Close()
	pool.pool.Put(writer)
}

func ( pool * GzipPool ) ReturnWriter ( writer * gzip . Writer ) { writer . Close ( ) pool . pool . Put ( writer ) }

// ReturnWriter returns a gzip.Writer to the pool that can
// late be reused via GetWriter.
// Don't close the writer, Flush will be called before returning
// it to the pool.

ReturnWriter returns a gzip . Writer to the pool that can late be reused via GetWriter . Don t close the writer Flush will be called before returning it to the pool .


func FileGetLines(filenameOrURL string, timeout ...time.Duration) (lines []string, err error) {
	data, err := FileGetBytes(filenameOrURL, timeout...)
	if err != nil {
		return nil, err
	}

	lastR := -1
	lastN := -1

	for i, c := range data {
		if c == '\r' {
			l := string(data[lastN+1 : i])
			lines = append(lines, l)
			lastR = i
		}
		if c == '\n' {
			if i != lastR+1 {
				l := string(data[lastN+1 : i])
				lines = append(lines, l)
			}
			lastN = i
		}
	}
	l := string(data[lastN+1:])
	lines = append(lines, l)

	return lines, nil
}

func FileGetLines ( filenameOrURL string , timeout ... time . Duration ) ( lines [ ] string , err error ) { data , err := FileGetBytes ( filenameOrURL , timeout ... ) if err != nil { return nil , err } lastR := - 1 lastN := - 1 for i , c := range data { if c == '\r' { l := string ( data [ lastN + 1 : i ] ) lines = append ( lines , l ) lastR = i } if c == '\n' { if i != lastR + 1 { l := string ( data [ lastN + 1 : i ] ) lines = append ( lines , l ) } lastN = i } } l := string ( data [ lastN + 1 : ] ) lines = append ( lines , l ) return lines , nil }

// FileGetLines returns a string slice with the text lines of filenameOrURL.
// The lines can be separated by \n or \r\n.

FileGetLines returns a string slice with the text lines of filenameOrURL . The lines can be separated by \ n or \ r \ n .


func FileGetLastLine(filenameOrURL string, timeout ...time.Duration) (line string, err error) {
	if strings.Index(filenameOrURL, "file://") == 0 {
		return FileGetLastLine(filenameOrURL[len("file://"):])
	}

	var data []byte

	if strings.Contains(filenameOrURL, "://") {
		data, err = FileGetBytes(filenameOrURL, timeout...)
		if err != nil {
			return "", err
		}
	} else {
		file, err := os.Open(filenameOrURL)
		if err != nil {
			return "", err
		}
		defer file.Close()
		info, err := file.Stat()
		if err != nil {
			return "", err
		}
		if start := info.Size() - 64*1024; start > 0 {
			file.Seek(start, os.SEEK_SET)
		}
		data, err = ioutil.ReadAll(file)
		if err != nil {
			return "", err
		}
	}

	pos := bytes.LastIndex(data, []byte{'\n'})
	return string(data[pos+1:]), nil
}

func FileGetLastLine ( filenameOrURL string , timeout ... time . Duration ) ( line string , err error ) { if strings . Index ( filenameOrURL , " " ) == 0 { return FileGetLastLine ( filenameOrURL [ len ( " " ) : ] ) } var data [ ] byte if strings . Contains ( filenameOrURL , " " ) { data , err = FileGetBytes ( filenameOrURL , timeout ... ) if err != nil { return " " , err } } else { file , err := os . Open ( filenameOrURL ) if err != nil { return " " , err } defer file . Close ( ) info , err := file . Stat ( ) if err != nil { return " " , err } if start := info . Size ( ) - 64 * 1024 ; start > 0 { file . Seek ( start , os . SEEK_SET ) } data , err = ioutil . ReadAll ( file ) if err != nil { return " " , err } } pos := bytes . LastIndex ( data , [ ] byte { '\n' } ) return string ( data [ pos + 1 : ] ) , nil }

// FileGetLastLine reads the last line from a file.
// In case of a network file, the whole file is read.
// In case of a local file, the last 64kb are read,
// so if the last line is longer than 64kb it is not returned completely.
// The first optional timeout is used for network files only.

FileGetLastLine reads the last line from a file . In case of a network file the whole file is read . In case of a local file the last 64kb are read so if the last line is longer than 64kb it is not returned completely . The first optional timeout is used for network files only .


func FileSize(filename string) int64 {
	info, err := os.Stat(filename)
	if err != nil {
		return 0
	}
	return info.Size()
}

func FileSize ( filename string ) int64 { info , err := os . Stat ( filename ) if err != nil { return 0 } return info . Size ( ) }

// FileSize returns the size of a file or zero in case of an error.

FileSize returns the size of a file or zero in case of an error .


func BytesHead(data []byte, numLines int) (lines []string, rest []byte) {
	if numLines <= 0 {
		panic("numLines must be greater than zero")
	}
	lines = make([]string, 0, numLines)
	begin := 0
	for i := range data {
		if data[i] == '\n' {
			end := i
			if i > 0 && data[i-1] == '\r' {
				end--
			}
			lines = append(lines, string(data[begin:end]))
			begin = i + 1
			if len(lines) == numLines {
				break
			}
		}
	}
	if len(lines) != numLines {
		lines = append(lines, string(data[begin:]))
		begin = len(data)
	}
	return lines, data[begin:]
}

func BytesHead ( data [ ] byte , numLines int ) ( lines [ ] string , rest [ ] byte ) { if numLines <= 0 { panic ( " " ) } lines = make ( [ ] string , 0 , numLines ) begin := 0 for i := range data { if data [ i ] == '\n' { end := i if i > 0 && data [ i - 1 ] == '\r' { end -- } lines = append ( lines , string ( data [ begin : end ] ) ) begin = i + 1 if len ( lines ) == numLines { break } } } if len ( lines ) != numLines { lines = append ( lines , string ( data [ begin : ] ) ) begin = len ( data ) } return lines , data [ begin : ] }

// BytesHead returns at most numLines from data starting at the beginning.
// A slice of the remaining data is returned as rest.
// \n is used to detect line ends, a preceding \r will be stripped away.
// BytesHead resembles the Unix head command.

BytesHead returns at most numLines from data starting at the beginning . A slice of the remaining data is returned as rest . \ n is used to detect line ends a preceding \ r will be stripped away . BytesHead resembles the Unix head command .


func BytesMap(f func(byte) byte, data []byte) []byte {
	size := len(data)
	result := make([]byte, size, size)
	for i := 0; i < size; i++ {
		result[i] = f(data[i])
	}
	return result
}

func BytesMap ( f func ( byte ) byte , data [ ] byte ) [ ] byte { size := len ( data ) result := make ( [ ] byte , size , size ) for i := 0 ; i < size ; i ++ { result [ i ] = f ( data [ i ] ) } return result }

// BytesMap maps a function on each element of a slice of bytes.

BytesMap maps a function on each element of a slice of bytes .


func BytesFilter(f func(byte) bool, data []byte) []byte {
	result := make([]byte, 0, 0)
	for _, element := range data {
		if f(element) {
			result = append(result, element)
		}
	}
	return result
}

func BytesFilter ( f func ( byte ) bool , data [ ] byte ) [ ] byte { result := make ( [ ] byte , 0 , 0 ) for _ , element := range data { if f ( element ) { result = append ( result , element ) } } return result }

// BytesFilter filters out all bytes where the function does not return true.

BytesFilter filters out all bytes where the function does not return true .


func ReflectSetStructFieldString(structPtr interface{}, name, value string) error {
	v := reflect.ValueOf(structPtr)
	if v.Kind() != reflect.Ptr || v.Elem().Kind() != reflect.Struct {
		return fmt.Errorf("structPtr must be pointer to a struct, but is %T", structPtr)
	}
	v = v.Elem()

	if f := v.FieldByName(name); f.IsValid() {
		if f.Kind() == reflect.String {
			f.SetString(value)
		} else {
			_, err := fmt.Sscan(value, f.Addr().Interface())
			if err != nil {
				return err
			}
		}
	} else {
		return fmt.Errorf("%T has no struct field '%s'", v.Interface(), name)
	}

	return nil
}

func ReflectSetStructFieldString ( structPtr interface { } , name , value string ) error { v := reflect . ValueOf ( structPtr ) if v . Kind ( ) != reflect . Ptr || v . Elem ( ) . Kind ( ) != reflect . Struct { return fmt . Errorf ( " " , structPtr ) } v = v . Elem ( ) if f := v . FieldByName ( name ) ; f . IsValid ( ) { if f . Kind ( ) == reflect . String { f . SetString ( value ) } else { _ , err := fmt . Sscan ( value , f . Addr ( ) . Interface ( ) ) if err != nil { return err } } } else { return fmt . Errorf ( " " , v . Interface ( ) , name ) } return nil }

// ReflectSetStructFieldString sets the field with name to value.

ReflectSetStructFieldString sets the field with name to value .


func ReadBinary(r io.Reader, order binary.ByteOrder, data interface{}) (n int, err error) {
	countingReader := CountingReader{Reader: r}
	err = binary.Read(&countingReader, order, data)
	return countingReader.BytesRead, err
}

func ReadBinary ( r io . Reader , order binary . ByteOrder , data interface { } ) ( n int , err error ) { countingReader := CountingReader { Reader : r } err = binary . Read ( & countingReader , order , data ) return countingReader . BytesRead , err }

// ReadBinary wraps binary.Read with a CountingReader and returns
// the acutal bytes read by it.

ReadBinary wraps binary . Read with a CountingReader and returns the acutal bytes read by it .


func WriteFull(data []byte, writer io.Writer) (n int, err error) {
	dataSize := len(data)
	for n = 0; n < dataSize; {
		m, err := writer.Write(data[n:])
		n += m
		if err != nil {
			return n, err
		}
	}
	return dataSize, nil
}

func WriteFull ( data [ ] byte , writer io . Writer ) ( n int , err error ) { dataSize := len ( data ) for n = 0 ; n < dataSize ; { m , err := writer . Write ( data [ n : ] ) n += m if err != nil { return n , err } } return dataSize , nil }

// WriteFull calls writer.Write until all of data is written,
// or an is error returned.

WriteFull calls writer . Write until all of data is written or an is error returned .


func ReadLine(reader io.Reader) (line string, err error) {
	buffer := bytes.NewBuffer(make([]byte, 0, 4096))
	p := make([]byte, 1)
	for {
		var n int
		n, err = reader.Read(p)
		if err != nil || p[0] == '\n' {
			break
		}
		if n > 0 {
			buffer.WriteByte(p[0])
		}
	}
	data := buffer.Bytes()
	if len(data) > 0 && data[len(data)-1] == '\r' {
		data = data[:len(data)-1]
	}
	return string(data), err
}

func ReadLine ( reader io . Reader ) ( line string , err error ) { buffer := bytes . NewBuffer ( make ( [ ] byte , 0 , 4096 ) ) p := make ( [ ] byte , 1 ) for { var n int n , err = reader . Read ( p ) if err != nil || p [ 0 ] == '\n' { break } if n > 0 { buffer . WriteByte ( p [ 0 ] ) } } data := buffer . Bytes ( ) if len ( data ) > 0 && data [ len ( data ) - 1 ] == '\r' { data = data [ : len ( data ) - 1 ] } return string ( data ) , err }

// ReadLine reads unbuffered until a newline '\n' byte and removes
// an optional carriege return '\r' at the end of the line.
// In case of an error, the string up to the error is returned.

ReadLine reads unbuffered until a newline \ n byte and removes an optional carriege return \ r at the end of the line . In case of an error the string up to the error is returned .


func WaitForStdin(println ...interface{}) byte {
	if len(println) > 0 {
		fmt.Println(println...)
	}
	buffer := make([]byte, 1)
	os.Stdin.Read(buffer)
	return buffer[0]
}

func WaitForStdin ( println ... interface { } ) byte { if len ( println ) > 0 { fmt . Println ( println ... ) } buffer := make ( [ ] byte , 1 ) os . Stdin . Read ( buffer ) return buffer [ 0 ] }

// WaitForStdin blocks until input is available from os.Stdin.
// The first byte from os.Stdin is returned as result.
// If there are println arguments, then fmt.Println will be
// called with those before reading from os.Stdin.

WaitForStdin blocks until input is available from os . Stdin . The first byte from os . Stdin is returned as result . If there are println arguments then fmt . Println will be called with those before reading from os . Stdin .


func GetenvDefault(key, defaultValue string) string {
	ret := os.Getenv(key)
	if ret == "" {
		return defaultValue
	}

	return ret
}

func GetenvDefault ( key , defaultValue string ) string { ret := os . Getenv ( key ) if ret == " " { return defaultValue } return ret }

// GetenvDefault retrieves the value of the environment variable
// named by the key. It returns the given defaultValue if the
// variable is not present.

GetenvDefault retrieves the value of the environment variable named by the key . It returns the given defaultValue if the variable is not present .


func NetIP() string {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return ""
	}
	for _, addr := range addrs {
		ip := addr.String()
		if ip != "127.0.0.1" {
			return ip
		}
	}
	return ""
}

func NetIP ( ) string { addrs , err := net . InterfaceAddrs ( ) if err != nil { return " " } for _ , addr := range addrs { ip := addr . String ( ) if ip != " " { return ip } } return " " }

// NetIP returns the primary IP address of the system or an empty string.

NetIP returns the primary IP address of the system or an empty string .


func RealNetIP() string {
	addrs, err := net.InterfaceAddrs()

	if err != nil {
		fmt.Println(err)
		return ""
	}

	// get real local IP
	for _, address := range addrs {
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}

		}
	}
	return ""
}

func
RealNetIP
(
)
string
{
addrs
,
err
:=
net
.
InterfaceAddrs
(
)
if
err
!=
{
fmt
.
Println
(
err
)
return
"
"
}
// get real local IP
for
_
,
address
:=
range
addrs
{
if
ipnet
,
ok
:=
address
.
(
*
net
.
IPNet
)
;
ok
&&
!
ipnet
.
IP
.
IsLoopback
(
)
{
if
ipnet
.
IP
.
To4
(
)
!=
{
return
ipnet
.
IP
.
String
(
)
}
}
}
return
"
"
}

// RealNetIP returns the real local IP of the system or an empty string.

RealNetIP returns the real local IP of the system or an empty string .


func Load(conf interface{}, configPaths ...string) error {
	return loadWithFunc(conf, configPaths, nil, yaml.Unmarshal)
}

func Load ( conf interface { } , configPaths ... string ) error { return loadWithFunc ( conf , configPaths , nil , yaml . Unmarshal ) }

// Load loads YAML files from `configPaths`.
// and assigns decoded values into the `conf` value.

Load loads YAML files from configPaths . and assigns decoded values into the conf value .


func LoadJSON(conf interface{}, configPaths ...string) error {
	return loadWithFunc(conf, configPaths, nil, json.Unmarshal)
}

func LoadJSON ( conf interface { } , configPaths ... string ) error { return loadWithFunc ( conf , configPaths , nil , json . Unmarshal ) }

// Load loads JSON files from `configPaths`.
// and assigns decoded values into the `conf` value.

Load loads JSON files from configPaths . and assigns decoded values into the conf value .


func LoadTOML(conf interface{}, configPaths ...string) error {
	return loadWithFunc(conf, configPaths, nil, toml.Unmarshal)
}

func LoadTOML ( conf interface { } , configPaths ... string ) error { return loadWithFunc ( conf , configPaths , nil , toml . Unmarshal ) }

// Load loads TOML files from `configPaths`.
// and assigns decoded values into the `conf` value.

Load loads TOML files from configPaths . and assigns decoded values into the conf value .


func LoadBytes(conf interface{}, src []byte) error {
	return loadConfigBytes(conf, src, nil, yaml.Unmarshal)
}

func LoadBytes ( conf interface { } , src [ ] byte ) error { return loadConfigBytes ( conf , src , nil , yaml . Unmarshal ) }


func LoadJSONBytes(conf interface{}, src []byte) error {
	return loadConfigBytes(conf, src, nil, json.Unmarshal)
}

func LoadJSONBytes ( conf interface { } , src [ ] byte ) error { return loadConfigBytes ( conf , src , nil , json . Unmarshal ) }


func LoadTOMLBytes(conf interface{}, src []byte) error {
	return loadConfigBytes(conf, src, nil, toml.Unmarshal)
}

func LoadTOMLBytes ( conf interface { } , src [ ] byte ) error { return loadConfigBytes ( conf , src , nil , toml . Unmarshal ) }


func LoadWithEnvJSON(conf interface{}, configPaths ...string) error {
	return loadWithFunc(conf, configPaths, envReplacer, json.Unmarshal)
}

func LoadWithEnvJSON ( conf interface { } , configPaths ... string ) error { return loadWithFunc ( conf , configPaths , envReplacer , json . Unmarshal ) }

// LoadWithEnvJSON loads JSON files with Env


func LoadWithEnvTOML(conf interface{}, configPaths ...string) error {
	return loadWithFunc(conf, configPaths, envReplacer, toml.Unmarshal)
}

func LoadWithEnvTOML ( conf interface { } , configPaths ... string ) error { return loadWithFunc ( conf , configPaths , envReplacer , toml . Unmarshal ) }

// LoadWithEnvTOML loads TOML files with Env


func LoadWithEnvBytes(conf interface{}, src []byte) error {
	return loadConfigBytes(conf, src, envReplacer, yaml.Unmarshal)
}

func LoadWithEnvBytes ( conf interface { } , src [ ] byte ) error { return loadConfigBytes ( conf , src , envReplacer , yaml . Unmarshal ) }

// LoadWithEnvBytes loads YAML bytes with Env


func LoadWithEnvJSONBytes(conf interface{}, src []byte) error {
	return loadConfigBytes(conf, src, envReplacer, json.Unmarshal)
}

func LoadWithEnvJSONBytes ( conf interface { } , src [ ] byte ) error { return loadConfigBytes ( conf , src , envReplacer , json . Unmarshal ) }

// LoadWithEnvJSONBytes loads JSON bytes with Env


func LoadWithEnvTOMLBytes(conf interface{}, src []byte) error {
	return loadConfigBytes(conf, src, envReplacer, toml.Unmarshal)
}

func LoadWithEnvTOMLBytes ( conf interface { } , src [ ] byte ) error { return loadConfigBytes ( conf , src , envReplacer , toml . Unmarshal ) }

// LoadWithEnvTOMLBytes loads TOML bytes with Env


func Crop(img image.Image, c Config) (image.Image, error) {
	maxBounds := c.maxBounds(img.Bounds())
	size := c.computeSize(maxBounds, image.Point{c.Width, c.Height})
	cr := c.computedCropArea(img.Bounds(), size)
	cr = img.Bounds().Intersect(cr)

	if c.Options&Copy == Copy {
		return cropWithCopy(img, cr)
	}
	if dImg, ok := img.(subImageSupported); ok {
		return dImg.SubImage(cr), nil
	}
	return cropWithCopy(img, cr)
}

func Crop ( img image . Image , c Config ) ( image . Image , error ) { maxBounds := c . maxBounds ( img . Bounds ( ) ) size := c . computeSize ( maxBounds , image . Point { c . Width , c . Height } ) cr := c . computedCropArea ( img . Bounds ( ) , size ) cr = img . Bounds ( ) . Intersect ( cr ) if c . Options & Copy == Copy { return cropWithCopy ( img , cr ) } if dImg , ok := img . ( subImageSupported ) ; ok { return dImg . SubImage ( cr ) , nil } return cropWithCopy ( img , cr ) }

// Crop retrieves an image that is a
// cropped copy of the original img.
//
// The crop is made given the informations provided in config.

Crop retrieves an image that is a cropped copy of the original img . The crop is made given the informations provided in config .


func (c Config) computeSize(bounds image.Rectangle, ratio image.Point) (p image.Point) {
	if c.Options&Ratio == Ratio {
		// Ratio option is on, so we take the biggest size available that fit the given ratio.
		if float64(ratio.X)/float64(bounds.Dx()) > float64(ratio.Y)/float64(bounds.Dy()) {
			p = image.Point{bounds.Dx(), (bounds.Dx() / ratio.X) * ratio.Y}
		} else {
			p = image.Point{(bounds.Dy() / ratio.Y) * ratio.X, bounds.Dy()}
		}
	} else {
		p = image.Point{ratio.X, ratio.Y}
	}
	return
}

// computeSize retrieve the effective size of the cropped image.
// It is defined by Height, Width, and Ratio option.

computeSize retrieve the effective size of the cropped image . It is defined by Height Width and Ratio option .


func (c Config) computedCropArea(bounds image.Rectangle, size image.Point) (r image.Rectangle) {
	min := bounds.Min
	switch c.Mode {
	case Centered:
		rMin := c.centeredMin(bounds)
		r = image.Rect(rMin.X-size.X/2, rMin.Y-size.Y/2, rMin.X-size.X/2+size.X, rMin.Y-size.Y/2+size.Y)
	default: // TopLeft
		rMin := image.Point{min.X + c.Anchor.X, min.Y + c.Anchor.Y}
		r = image.Rect(rMin.X, rMin.Y, rMin.X+size.X, rMin.Y+size.Y)
	}
	return
}

func
(
c
Config
)
computedCropArea
(
bounds
image
.
Rectangle
,
size
image
.
Point
)
(
r
image
.
Rectangle
)
{
min
:=
bounds
.
Min
switch
c
.
Mode
{
case
Centered
:
rMin
:=
c
.
centeredMin
(
bounds
)
r
=
image
.
Rect
(
rMin
.
X
size
.
X
/
2
,
rMin
.
Y
size
.
Y
/
2
,
rMin
.
X
size
.
X
/
2
+
size
.
X
,
rMin
.
Y
size
.
Y
/
2
+
size
.
Y
)
default
:
// TopLeft
rMin
:=
image
.
Point
{
min
.
X
+
c
.
Anchor
.
X
,
min
.
Y
+
c
.
Anchor
.
Y
}
r
=
image
.
Rect
(
rMin
.
X
,
rMin
.
Y
,
rMin
.
X
+
size
.
X
,
rMin
.
Y
+
size
.
Y
)
}
return
}

// computedCropArea retrieve the theorical crop area.
// It is defined by Height, Width, Mode and

computedCropArea retrieve the theorical crop area . It is defined by Height Width Mode and


func NewThen(command string, args ...string) Then {
	return &gitCmd{command: command, args: args}
}

func NewThen ( command string , args ... string ) Then { return & gitCmd { command : command , args : args } }


func NewLongThen(command string, args ...string) Then {
	return &gitCmd{command: command, args: args, background: true, haltChan: make(chan struct{})}
}

func NewLongThen ( command string , args ... string ) Then { return & gitCmd { command : command , args : args , background : true , haltChan : make ( chan struct { } ) } }

// NewLongThen creates a new long running Then comand.

NewLongThen creates a new long running Then comand .


func (g *gitCmd) Command() string {
	return g.command + " " + strings.Join(g.args, " ")
}

func ( g * gitCmd ) Command ( ) string { return g . command + " " + strings . Join ( g . args , " " ) }

// Command returns the full command as configured in Caddyfile.

Command returns the full command as configured in Caddyfile .


func (g *gitCmd) Exec(dir string) error {
	g.Lock()
	g.dir = dir
	g.Unlock()

	if g.background {
		return g.execBackground(dir)
	}
	return g.exec(dir)
}

func ( g * gitCmd ) Exec ( dir string ) error { g . Lock ( ) g . dir = dir g . Unlock ( ) if g . background { return g . execBackground ( dir ) } return g . exec ( dir ) }

// Exec executes the command initiated in gitCmd.

Exec executes the command initiated in gitCmd .


func (g *gitCmd) haltProcess() {
	g.RLock()
	monitoring := g.monitoring
	g.RUnlock()

	if monitoring {
		g.haltChan <- struct{}{}
	}
}

func ( g * gitCmd ) haltProcess ( ) { g . RLock ( ) monitoring := g . monitoring g . RUnlock ( ) if monitoring { g . haltChan <- struct { } { } } }

// haltProcess halts the running process


func runCmd(command string, args []string, dir string) error {
	cmd := gos.Command(command, args...)
	cmd.Stdout(os.Stderr)
	cmd.Stderr(os.Stderr)
	cmd.Dir(dir)
	if err := cmd.Start(); err != nil {
		return err
	}
	return cmd.Wait()
}

func runCmd ( command string , args [ ] string , dir string ) error { cmd := gos . Command ( command , args ... ) cmd . Stdout ( os . Stderr ) cmd . Stderr ( os . Stderr ) cmd . Dir ( dir ) if err := cmd . Start ( ) ; err != nil { return err } return cmd . Wait ( ) }

// runCmd is a helper function to run commands.
// It runs command with args from directory at dir.
// The executed process outputs to os.Stderr

runCmd is a helper function to run commands . It runs command with args from directory at dir . The executed process outputs to os . Stderr


func runCmdOutput(command string, args []string, dir string) (string, error) {
	cmd := gos.Command(command, args...)
	cmd.Dir(dir)
	var err error
	if output, err := cmd.Output(); err == nil {
		return string(bytes.TrimSpace(output)), nil
	}
	return "", err
}

func runCmdOutput ( command string , args [ ] string , dir string ) ( string , error ) { cmd := gos . Command ( command , args ... ) cmd . Dir ( dir ) var err error if output , err := cmd . Output ( ) ; err == nil { return string ( bytes . TrimSpace ( output ) ) , nil } return " " , err }

// runCmdOutput is a helper function to run commands and return output.
// It runs command with args from directory at dir.
// If successful, returns output and nil error

runCmdOutput is a helper function to run commands and return output . It runs command with args from directory at dir . If successful returns output and nil error


func Init() error {
	// prevent concurrent call
	initMutex.Lock()
	defer initMutex.Unlock()

	// if validation has been done before and binary located in
	// PATH, return.
	if gitBinary != "" {
		return nil
	}

	// locate git binary in path
	var err error
	if gitBinary, err = gos.LookPath("git"); err != nil {
		return fmt.Errorf("git middleware requires git installed. Cannot find git binary in PATH")
	}

	// locate bash in PATH. If not found, fallback to sh.
	// If neither is found, return error.
	shell = "bash"
	if _, err = gos.LookPath("bash"); err != nil {
		shell = "sh"
		if _, err = gos.LookPath("sh"); err != nil {
			return fmt.Errorf("git middleware requires either bash or sh")
		}
	}
	return nil
}

// Init validates git installation, locates the git executable
// binary in PATH and check for available shell to use.

Init validates git installation locates the git executable binary in PATH and check for available shell to use .


func writeScriptFile(content []byte) (file gitos.File, err error) {
	if file, err = gos.TempFile("", "caddy"); err != nil {
		return nil, err
	}
	if _, err = file.Write(content); err != nil {
		return nil, err
	}
	if err = file.Chmod(os.FileMode(0755)); err != nil {
		return nil, err
	}
	return file, file.Close()
}

func writeScriptFile ( content [ ] byte ) ( file gitos . File , err error ) { if file , err = gos . TempFile ( " " , " " ) ; err != nil { return nil , err } if _ , err = file . Write ( content ) ; err != nil { return nil , err } if err = file . Chmod ( os . FileMode ( 0755 ) ) ; err != nil { return nil , err } return file , file . Close ( ) }

// writeScriptFile writes content to a temporary file.
// It changes the temporary file mode to executable and
// closes it to prepare it for execution.

writeScriptFile writes content to a temporary file . It changes the temporary file mode to executable and closes it to prepare it for execution .


func gitWrapperScript() []byte {
	scriptTemplate := `#!/usr/bin/env {shell}

# The MIT License (MIT)
# Copyright (c) 2013 Alvin Abad

if [ $# -eq 0 ]; then
    echo "Git wrapper script that can specify an ssh-key file
Usage:
    git.sh -i ssh-key-file git-command
    "
    exit 1
fi

# remove temporary file on exit
trap 'rm -f {tmp_dir}/.git_ssh.$$' 0

if [ "$1" = "-i" ]; then
    SSH_KEY=$2; shift; shift
    echo -e "#!/usr/bin/env {shell}\n \
    ssh -i $SSH_KEY \$@" > {tmp_dir}/.git_ssh.$$
    chmod +x {tmp_dir}/.git_ssh.$$
    export GIT_SSH={tmp_dir}/.git_ssh.$$
fi

# in case the git command is repeated
[ "$1" = "git" ] && shift

# Run the git command
{git_binary} "$@"

`
	replacer := strings.NewReplacer(
		"{shell}", shell,
		"{tmp_dir}", strings.TrimSuffix(gos.TempDir(), "/"),
		"{git_binary}", gitBinary,
	)
	return []byte(replacer.Replace(scriptTemplate))
}

// gitWrapperScript forms content for git.sh script

gitWrapperScript forms content for git . sh script


func bashScript(gitSSHPath string, repo *Repo, params []string) []byte {
	scriptTemplate := `#!/usr/bin/env {shell}

mkdir -p ~/.ssh;
touch ~/.ssh/known_hosts;
ssh-keyscan -t rsa,dsa {repo_host} 2>&1 | sort -u - ~/.ssh/known_hosts > ~/.ssh/tmp_hosts;
cat ~/.ssh/tmp_hosts | while read line
do
  grep -q "$line" ~/.ssh/known_hosts || echo $line >> ~/.ssh/known_hosts;
done
{git_ssh_path} -i {ssh_key_path} {ssh_params};
`
	replacer := strings.NewReplacer(
		"{shell}", shell,
		"{repo_host}", repo.Host,
		"{git_ssh_path}", gitSSHPath,
		"{ssh_key_path}", repo.KeyPath,
		"{ssh_params}", strings.Join(params, " "),
	)
	return []byte(replacer.Replace(scriptTemplate))
}

// bashScript forms content of bash script to clone or update a repo using ssh


func (g GitlabHook) handleToken(r *http.Request, body []byte, secret string) error {
	token := r.Header.Get("X-Gitlab-Token")
	if token != "" {
		if secret == "" {
			Logger().Print("Unable to verify request. Secret not set in caddyfile!\n")
		} else {
			if token != secret {
				return errors.New("Unable to verify request. The token and specified secret do not match!")
			}
		}
	}

	return nil
}

func ( g GitlabHook ) handleToken ( r * http . Request , body [ ] byte , secret string ) error { token := r . Header . Get ( " " ) if token != " " { if secret == " " { Logger ( ) . Print ( " \n " ) } else { if token != secret { return errors . New ( " " ) } } } return nil }

// handleToken checks for an optional token in the request. GitLab's webhook tokens are just
// simple strings that get sent as a header with the hook request. If one
// exists, verify that it matches the secret in the Caddy configuration.

handleToken checks for an optional token in the request . GitLab s webhook tokens are just simple strings that get sent as a header with the hook request . If one exists verify that it matches the secret in the Caddy configuration .


func (g GenericHook) Handle(w http.ResponseWriter, r *http.Request, repo *Repo) (int, error) {
	if r.Method != "POST" {
		return http.StatusMethodNotAllowed, errors.New("the request had an invalid method")
	}

	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return http.StatusRequestTimeout, errors.New("could not read body from request")
	}

	err = g.handlePush(body, repo)
	if err != nil {
		return http.StatusBadRequest, err
	}

	return http.StatusOK, nil
}

func ( g GenericHook ) Handle ( w http . ResponseWriter , r * http . Request , repo * Repo ) ( int , error ) { if r . Method != " " { return http . StatusMethodNotAllowed , errors . New ( " " ) } body , err := ioutil . ReadAll ( r . Body ) if err != nil { return http . StatusRequestTimeout , errors . New ( " " ) } err = g . handlePush ( body , repo ) if err != nil { return http . StatusBadRequest , err } return http . StatusOK , nil }


func (g GithubHook) handleSignature(r *http.Request, body []byte, secret string) error {
	signature := r.Header.Get("X-Hub-Signature")
	if signature != "" {
		if secret == "" {
			Logger().Print("Unable to verify request signature. Secret not set in caddyfile!\n")
		} else {
			mac := hmac.New(sha1.New, []byte(secret))
			mac.Write(body)
			expectedMac := hex.EncodeToString(mac.Sum(nil))

			if signature[5:] != expectedMac {
				return errors.New("could not verify request signature. The signature is invalid")
			}
		}
	}

	return nil
}

func ( g GithubHook ) handleSignature ( r * http . Request , body [ ] byte , secret string ) error { signature := r . Header . Get ( " " ) if signature != " " { if secret == " " { Logger ( ) . Print ( " \n " ) } else { mac := hmac . New ( sha1 . New , [ ] byte ( secret ) ) mac . Write ( body ) expectedMac := hex . EncodeToString ( mac . Sum ( nil ) ) if signature [ 5 : ] != expectedMac { return errors . New ( " " ) } } } return nil }

// Check for an optional signature in the request
// if it is signed, verify the signature.

Check for an optional signature in the request if it is signed verify the signature .


func setup(c *caddy.Controller) error {
	git, err := parse(c)
	if err != nil {
		return err
	}

	// repos configured with webhooks
	var hookRepos []*Repo

	// functions to execute at startup
	var startupFuncs []func() error

	// loop through all repos and and start monitoring
	for i := range git {
		repo := git.Repo(i)

		// If a HookUrl is set, we switch to event based pulling.
		// Install the url handler
		if repo.Hook.URL != "" {

			hookRepos = append(hookRepos, repo)

			startupFuncs = append(startupFuncs, func() error {
				return repo.Pull()
			})

		} else {
			startupFuncs = append(startupFuncs, func() error {

				// Start service routine in background
				Start(repo)

				// Do a pull right away to return error
				return repo.Pull()
			})
		}
	}

	// ensure the functions are executed once per server block
	// for cases like server1.com, server2.com { ... }
	c.OncePerServerBlock(func() error {
		for i := range startupFuncs {
			c.OnStartup(startupFuncs[i])
		}
		return nil
	})

	// if there are repo(s) with webhook
	// return handler
	if len(hookRepos) > 0 {
		webhook := &WebHook{Repos: hookRepos}
		httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
			webhook.Next = next
			return webhook
		})
	}

	return nil
}

// setup configures a new Git service routine.

setup configures a new Git service routine .


func parseURL(repoURL string, private bool) (*url.URL, error) {
	// scheme
	urlParts := strings.Split(repoURL, "://")
	switch {
	case strings.HasPrefix(repoURL, "https://"):
	case strings.HasPrefix(repoURL, "http://"):
	case strings.HasPrefix(repoURL, "ssh://"):
	case len(urlParts) > 1:
		return nil, fmt.Errorf("Invalid url scheme %s. If url contains port, scheme is required", urlParts[0])
	default:
		if private {
			repoURL = "ssh://" + repoURL
		} else {
			repoURL = "https://" + repoURL
		}
	}

	u, err := url.Parse(repoURL)
	if err != nil {
		return nil, err
	}
	return u, nil
}

func
parseURL
(
repoURL
string
,
private
bool
)
(
*
url
.
URL
,
error
)
{
// scheme
urlParts
:=
strings
.
Split
(
repoURL
,
"
"
)
switch
{
case
strings
.
HasPrefix
(
repoURL
,
"
"
)
:
case
strings
.
HasPrefix
(
repoURL
,
"
"
)
:
case
strings
.
HasPrefix
(
repoURL
,
"
"
)
:
case
len
(
urlParts
)
>
1
:
return
,
fmt
.
Errorf
(
"
"
,
urlParts
[
0
]
)
default
:
if
private
{
repoURL
=
"
"
+
repoURL
}
else
{
repoURL
=
"
"
+
repoURL
}
}
u
,
err
:=
url
.
Parse
(
repoURL
)
if
err
!=
{
return
,
err
}
return
u
,
}

// parseURL validates if repoUrl is a valid git url.

parseURL validates if repoUrl is a valid git url .


func Start(repo *Repo) {
	if repo.Interval <= 0 {
		// ignore, don't setup periodic pull.
		Logger().Println("interval too small, periodic pull not enabled.")
		return
	}
	service := &repoService{
		repo,
		gos.NewTicker(repo.Interval),
		make(chan struct{}),
	}
	go func(s *repoService) {
		for {
			select {
			case <-s.ticker.C():
				err := repo.Pull()
				if err != nil {
					Logger().Println(err)
				}
			case <-s.halt:
				s.ticker.Stop()
				return
			}
		}
	}(service)

	// add to services to make it stoppable
	Services.add(service)
}

func
Start
(
repo
*
Repo
)
{
if
repo
.
Interval
<=
0
{
// ignore, don't setup periodic pull.
Logger
(
)
.
Println
(
"
"
)
return
}
service
:=
&
repoService
{
repo
,
gos
.
NewTicker
(
repo
.
Interval
)
,
make
(
chan
struct
{
}
)
,
}
go
func
(
s
*
repoService
)
{
for
{
select
{
case
<-
s
.
ticker
.
C
(
)
:
err
:=
repo
.
Pull
(
)
if
err
!=
{
Logger
(
)
.
Println
(
err
)
}
case
<-
s
.
halt
:
s
.
ticker
.
Stop
(
)
return
}
}
}
(
service
)
// add to services to make it stoppable
Services
.
add
(
service
)
}

// Start starts a new background service to pull periodically.

Start starts a new background service to pull periodically .


func (s *services) add(r *repoService) {
	s.Lock()
	defer s.Unlock()

	s.services = append(s.services, r)
}

func ( s * services ) add ( r * repoService ) { s . Lock ( ) defer s . Unlock ( ) s . services = append ( s . services , r ) }

// add adds a new service to list of services.

add adds a new service to list of services .


func (g Git) Repo(i int) *Repo {
	if i < len(g) {
		return g[i]
	}
	return nil
}

func ( g Git ) Repo ( i int ) * Repo { if i < len ( g ) { return g [ i ] } return nil }

// Repo retrieves repository at i or nil if not found.

Repo retrieves repository at i or nil if not found .


func (r RepoURL) String() string {
	u, err := url.Parse(string(r))
	if err != nil {
		return string(r)
	}
	if u.User != nil {
		u.User = url.User(u.User.Username())
	}
	return u.String()
}

func ( r RepoURL ) String ( ) string { u , err := url . Parse ( string ( r ) ) if err != nil { return string ( r ) } if u . User != nil { u . User = url . User ( u . User . Username ( ) ) } return u . String ( ) }

// String satisfies stringer and attempts to strip off authentication
// info from url if it exists.

String satisfies stringer and attempts to strip off authentication info from url if it exists .


func (r RepoURL) Val() string {
	if strings.HasPrefix(string(r), "ssh://") {
		return strings.TrimPrefix(string(r), "ssh://")
	}
	return string(r)
}

func ( r RepoURL ) Val ( ) string { if strings . HasPrefix ( string ( r ) , " " ) { return strings . TrimPrefix ( string ( r ) , " " ) } return string ( r ) }

// Val returns git friendly Val that can be
// passed to git clone.

Val returns git friendly Val that can be passed to git clone .


func (r *Repo) Pull() error {
	r.Lock()
	defer r.Unlock()

	// prevent a pull if the last one was less than 5 seconds ago
	if gos.TimeSince(r.lastPull) < 5*time.Second {
		return nil
	}

	// keep last commit hash for comparison later
	lastCommit := r.lastCommit

	var err error
	// Attempt to pull at most numRetries times
	for i := 0; i < numRetries; i++ {
		if err = r.pull(); err == nil {
			break
		}
		Logger().Println(err)
	}

	if err != nil {
		return err
	}

	// check if there are new changes,
	// then execute post pull command
	if r.lastCommit == lastCommit {
		Logger().Println("No new changes.")
		return nil
	}
	return r.execThen()
}

// Pull attempts a git pull.
// It retries at most numRetries times if error occurs

Pull attempts a git pull . It retries at most numRetries times if error occurs


func (r *Repo) pull() error {

	// if not pulled, perform clone
	if !r.pulled {
		return r.clone()
	}

	// if latest tag config is set
	if r.Branch == latestTag {
		return r.checkoutLatestTag()
	}

	params := append([]string{"pull"}, append(r.PullArgs, "origin", r.Branch)...)
	var err error
	if err = r.gitCmd(params, r.Path); err == nil {
		r.pulled = true
		r.lastPull = time.Now()
		Logger().Printf("%v pulled.\n", r.URL)
		r.lastCommit, err = r.mostRecentCommit()
	}
	return err
}

func
(
r
*
Repo
)
pull
(
)
error
{
// if not pulled, perform clone
if
!
r
.
pulled
{
return
r
.
clone
(
)
}
// if latest tag config is set
if
r
.
Branch
==
latestTag
{
return
r
.
checkoutLatestTag
(
)
}
params
:=
append
(
[
]
string
{
"
"
}
,
append
(
r
.
PullArgs
,
"
"
,
r
.
Branch
)
...
)
var
err
error
if
err
=
r
.
gitCmd
(
params
,
r
.
Path
)
;
err
==
{
r
.
pulled
=
true
r
.
lastPull
=
time
.
Now
(
)
Logger
(
)
.
Printf
(
"
\n
"
,
r
.
URL
)
r
.
lastCommit
,
err
=
r
.
mostRecentCommit
(
)
}
return
err
}

// pull performs git pull, or git clone if repository does not exist.

pull performs git pull or git clone if repository does not exist .


func (r *Repo) checkoutCommit(commitHash string) error {
	var err error
	params := []string{"checkout", commitHash}
	if err = r.gitCmd(params, r.Path); err == nil {
		Logger().Printf("Commit %v checkout done.\n", commitHash)
	}
	return err
}

func ( r * Repo ) checkoutCommit ( commitHash string ) error { var err error params := [ ] string { " " , commitHash } if err = r . gitCmd ( params , r . Path ) ; err == nil { Logger ( ) . Printf ( " \n " , commitHash ) } return err }

// checkoutCommit checks out the specified commitHash.

checkoutCommit checks out the specified commitHash .


func (r *Repo) gitCmd(params []string, dir string) error {
	// if key is specified, use ssh key
	if r.KeyPath != "" {
		return r.gitCmdWithKey(params, dir)
	}
	return runCmd(gitBinary, params, dir)
}

func
(
r
*
Repo
)
gitCmd
(
params
[
]
string
,
dir
string
)
error
{
// if key is specified, use ssh key
if
r
.
KeyPath
!=
"
"
{
return
r
.
gitCmdWithKey
(
params
,
dir
)
}
return
runCmd
(
gitBinary
,
params
,
dir
)
}


func (r *Repo) Prepare() error {
	// check if directory exists or is empty
	// if not, create directory
	fs, err := gos.ReadDir(r.Path)
	if err != nil || len(fs) == 0 {
		return gos.MkdirAll(r.Path, os.FileMode(0755))
	}

	// validate git repo
	isGit := false
	for _, f := range fs {
		if f.IsDir() && f.Name() == ".git" {
			isGit = true
			break
		}
	}

	if isGit {
		// check if same repository
		var repoURL string
		if repoURL, err = r.originURL(); err == nil {
			if strings.TrimSuffix(repoURL, ".git") == strings.TrimSuffix(r.URL.Val(), ".git") {
				r.pulled = true
				return nil
			}
		}
		if err != nil {
			return fmt.Errorf("cannot retrieve repo url for %v Error: %v", r.Path, err)
		}
		return fmt.Errorf("another git repo '%v' exists at %v", repoURL, r.Path)
	}
	return fmt.Errorf("cannot git clone into %v, directory not empty", r.Path)
}

// Prepare prepares for a git pull
// and validates the configured directory

Prepare prepares for a git pull and validates the configured directory


func (r *Repo) mostRecentCommit() (string, error) {
	command := gitBinary + ` --no-pager log -n 1 --pretty=format:"%H"`
	c, args, err := caddy.SplitCommandAndArgs(command)
	if err != nil {
		return "", err
	}
	return runCmdOutput(c, args, r.Path)
}

// getMostRecentCommit gets the hash of the most recent commit to the
// repository. Useful for checking if changes occur.

getMostRecentCommit gets the hash of the most recent commit to the repository . Useful for checking if changes occur .


func (r *Repo) originURL() (string, error) {
	_, err := gos.Stat(r.Path)
	if err != nil {
		return "", err
	}
	args := []string{"config", "--get", "remote.origin.url"}
	return runCmdOutput(gitBinary, args, r.Path)
}

func ( r * Repo ) originURL ( ) ( string , error ) { _ , err := gos . Stat ( r . Path ) if err != nil { return " " , err } args := [ ] string { " " , " " , " " } return runCmdOutput ( gitBinary , args , r . Path ) }

// originURL retrieves remote origin url for the git repository at path


func (r *Repo) execThen() error {
	var errs error
	for _, command := range r.Then {
		err := command.Exec(r.Path)
		if err == nil {
			Logger().Printf("Command '%v' successful.\n", command.Command())
		}
		errs = mergeErrors(errs, err)
	}
	return errs
}

func ( r * Repo ) execThen ( ) error { var errs error for _ , command := range r . Then { err := command . Exec ( r . Path ) if err == nil { Logger ( ) . Printf ( " \n " , command . Command ( ) ) } errs = mergeErrors ( errs , err ) } return errs }

// execThen executes r.Then.
// It is trigged after successful git pull

execThen executes r . Then . It is trigged after successful git pull


func (g *gitCmd) Stdin(stdin io.Reader) {
	g.Cmd.Stdin = stdin
}

func ( g * gitCmd ) Stdin ( stdin io . Reader ) { g . Cmd . Stdin = stdin }

// Stdin sets the process's standard input.

Stdin sets the process s standard input .


func (g *gitCmd) Stdout(stdout io.Writer) {
	g.Cmd.Stdout = stdout
}

func ( g * gitCmd ) Stdout ( stdout io . Writer ) { g . Cmd . Stdout = stdout }

// Stdout sets the process's standard output.

Stdout sets the process s standard output .


func (g *gitCmd) Stderr(stderr io.Writer) {
	g.Cmd.Stderr = stderr
}

func ( g * gitCmd ) Stderr ( stderr io . Writer ) { g . Cmd . Stderr = stderr }

// Stderr sets the process's standard output.

Stderr sets the process s standard output .


func (g GitOS) Mkdir(name string, perm os.FileMode) error {
	return os.Mkdir(name, perm)
}

func ( g GitOS ) Mkdir ( name string , perm os . FileMode ) error { return os . Mkdir ( name , perm ) }


func (g GitOS) MkdirAll(path string, perm os.FileMode) error {
	return os.MkdirAll(path, perm)
}

func ( g GitOS ) MkdirAll ( path string , perm os . FileMode ) error { return os . MkdirAll ( path , perm ) }


func (g GitOS) Stat(name string) (os.FileInfo, error) {
	return os.Stat(name)
}

func ( g GitOS ) Stat ( name string ) ( os . FileInfo , error ) { return os . Stat ( name ) }


func (g GitOS) LookPath(file string) (string, error) {
	return exec.LookPath(file)
}

func ( g GitOS ) LookPath ( file string ) ( string , error ) { return exec . LookPath ( file ) }


func (g GitOS) TempFile(dir, prefix string) (File, error) {
	return ioutil.TempFile(dir, prefix)
}

func ( g GitOS ) TempFile ( dir , prefix string ) ( File , error ) { return ioutil . TempFile ( dir , prefix ) }


func (g GitOS) ReadDir(dirname string) ([]os.FileInfo, error) {
	return ioutil.ReadDir(dirname)
}

func ( g GitOS ) ReadDir ( dirname string ) ( [ ] os . FileInfo , error ) { return ioutil . ReadDir ( dirname ) }


func (g GitOS) Command(name string, args ...string) Cmd {
	return &gitCmd{exec.Command(name, args...)}
}

func ( g GitOS ) Command ( name string , args ... string ) Cmd { return & gitCmd { exec . Command ( name , args ... ) } }


func (g GitOS) NewTicker(d time.Duration) Ticker {
	return &GitTicker{time.NewTicker(d)}
}

func ( g GitOS ) NewTicker ( d time . Duration ) Ticker { return & GitTicker { time . NewTicker ( d ) } }


func (g GitOS) TimeSince(t time.Time) time.Duration {
	return time.Since(t)
}

func ( g GitOS ) TimeSince ( t time . Time ) time . Duration { return time . Since ( t ) }


func (t TravisHook) handleSignature(r *http.Request, secret string) error {
	signature := r.Header.Get("Authorization")
	if signature == "" {
		return errors.New("request sent no authorization signature")
	}
	if secret == "" {
		Logger().Print("Unable to verify request signature. Secret not set in caddyfile!\n")
		return nil
	}

	content := r.Header.Get("Travis-Repo-Slug") + secret
	hash := sha256.Sum256([]byte(content))
	expectedMac := hex.EncodeToString(hash[:])
	if signature != expectedMac {
		fmt.Println(signature, expectedMac)
		return errors.New("Invalid authorization header")
	}
	return nil
}

func ( t TravisHook ) handleSignature ( r * http . Request , secret string ) error { signature := r . Header . Get ( " " ) if signature == " " { return errors . New ( " " ) } if secret == " " { Logger ( ) . Print ( " \n " ) return nil } content := r . Header . Get ( " " ) + secret hash := sha256 . Sum256 ( [ ] byte ( content ) ) expectedMac := hex . EncodeToString ( hash [ : ] ) if signature != expectedMac { fmt . Println ( signature , expectedMac ) return errors . New ( " " ) } return nil }

// Check for an authorization signature in the request. Reject if not present. If validation required, check the sha

Check for an authorization signature in the request . Reject if not present . If validation required check the sha


func (h hookIgnoredError) Error() string {
	return fmt.Sprintf("%s webhook ignored. Error: %v", h.hookType, h.err)
}

func ( h hookIgnoredError ) Error ( ) string { return fmt . Sprintf ( " " , h . hookType , h . err ) }


func hookName(h hookHandler) string {
	for name, handler := range handlers {
		if handler == h {
			return name
		}
	}
	return ""
}

func hookName ( h hookHandler ) string { for name , handler := range handlers { if handler == h { return name } } return " " }

// hookName returns the name of the hookHanlder h.

hookName returns the name of the hookHanlder h .


func (h WebHook) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {

	for _, repo := range h.Repos {

		if r.URL.Path == repo.Hook.URL {

			// if handler type is specified.
			if handler, ok := handlers[repo.Hook.Type]; ok {
				if !handler.DoesHandle(r.Header) {
					return http.StatusBadRequest, errors.New(http.StatusText(http.StatusBadRequest))
				}
				status, err := handler.Handle(w, r, repo)
				// if the webhook is ignored, log it and allow request to continue.
				if hookIgnored(err) {
					Logger().Println(err)
					err = nil
				}
				return status, err
			}

			// auto detect handler
			for _, h := range defaultHandlers {
				// if a handler indicates it does handle the request,
				// we do not try other handlers. Only one handler ever
				// handles a specific request.
				if handlers[h].DoesHandle(r.Header) {
					status, err := handlers[h].Handle(w, r, repo)
					// if the webhook is ignored, log it and allow request to continue.
					if hookIgnored(err) {
						Logger().Println(err)
						err = nil
					}
					return status, err
				}
			}

			// no compatible handler
			Logger().Println("No compatible handler found. Consider enabling generic handler with 'hook_type generic'.")
		}
	}

	return h.Next.ServeHTTP(w, r)
}

// ServeHTTP implements the middlware.Handler interface.

ServeHTTP implements the middlware . Handler interface .


func hostname(hostport string) string {
	colon := strings.IndexByte(hostport, ':')
	if colon == -1 {
		return hostport
	}
	if i := strings.IndexByte(hostport, ']'); i != -1 {
		return strings.TrimPrefix(hostport[:i], "[")
	}
	return hostport[:colon]
}

func hostname ( hostport string ) string { colon := strings . IndexByte ( hostport , ':' ) if colon == - 1 { return hostport } if i := strings . IndexByte ( hostport , ']' ) ; i != - 1 { return strings . TrimPrefix ( hostport [ : i ] , " " ) } return hostport [ : colon ] }

// contains code taken from go1.8, for purposes of backwards compatability with
// older go versions.
// hostname returns u.Host, without any port number.
//
// If Host is an IPv6 literal with a port number, Hostname returns the
// IPv6 literal without the square brackets. IPv6 literals may include
// a zone identifier.

contains code taken from go1 . 8 for purposes of backwards compatability with older go versions . hostname returns u . Host without any port number . If Host is an IPv6 literal with a port number Hostname returns the IPv6 literal without the square brackets . IPv6 literals may include a zone identifier .


func genOptionsODBC(q url.Values, skipWhenEmpty bool, ignore ...string) string {
	return genOptions(q, "", "=", ";", ",", skipWhenEmpty, ignore...)
}

func genOptionsODBC ( q url . Values , skipWhenEmpty bool , ignore ... string ) string { return genOptions ( q , " " , " " , " " , " " , skipWhenEmpty , ignore ... ) }

// genOptionsODBC is a util wrapper around genOptions that uses the fixed settings
// for ODBC style connection strings.

genOptionsODBC is a util wrapper around genOptions that uses the fixed settings for ODBC style connection strings .


func genQueryOptions(q url.Values) string {
	if s := q.Encode(); s != "" {
		return "?" + s
	}
	return ""
}

func genQueryOptions ( q url . Values ) string { if s := q . Encode ( ) ; s != " " { return " " + s } return " " }

// genQueryOptions generates standard query options.

genQueryOptions generates standard query options .


func convertOptions(q url.Values, pairs ...string) url.Values {
	n := make(url.Values)
	for k, v := range q {
		x := make([]string, len(v))
		for i, z := range v {
			for j := 0; j < len(pairs); j += 2 {
				if pairs[j] == z {
					z = pairs[j+1]
				}
			}
			x[i] = z
		}
		n[k] = x
	}

	return n
}

func convertOptions ( q url . Values , pairs ... string ) url . Values { n := make ( url . Values ) for k , v := range q { x := make ( [ ] string , len ( v ) ) for i , z := range v { for j := 0 ; j < len ( pairs ) ; j += 2 { if pairs [ j ] == z { z = pairs [ j + 1 ] } } x [ i ] = z } n [ k ] = x } return n }

// convertOptions converts an option value based on name, value pairs.

convertOptions converts an option value based on name value pairs .


func mode(path string) os.FileMode {
	if fi, err := os.Stat(path); err == nil {
		return fi.Mode()
	}

	return 0
}

func mode ( path string ) os . FileMode { if fi , err := os . Stat ( path ) ; err == nil { return fi . Mode ( ) } return 0 }


func registerAlias(name, alias string, doSort bool) {
	scheme, ok := schemeMap[name]
	if !ok {
		panic(fmt.Sprintf("scheme %s not registered", name))
	}

	if doSort && has(scheme.Aliases, alias) {
		panic(fmt.Sprintf("scheme %s already has alias %s", name, alias))
	}

	if _, ok := schemeMap[alias]; ok {
		panic(fmt.Sprintf("scheme %s already registered", alias))
	}

	scheme.Aliases = append(scheme.Aliases, alias)
	if doSort {
		sort.Sort(ss(scheme.Aliases))
	}

	schemeMap[alias] = scheme
}

func registerAlias ( name , alias string , doSort bool ) { scheme , ok := schemeMap [ name ] if ! ok { panic ( fmt . Sprintf ( " " , name ) ) } if doSort && has ( scheme . Aliases , alias ) { panic ( fmt . Sprintf ( " " , name , alias ) ) } if _ , ok := schemeMap [ alias ] ; ok { panic ( fmt . Sprintf ( " " , alias ) ) } scheme . Aliases = append ( scheme . Aliases , alias ) if doSort { sort . Sort ( ss ( scheme . Aliases ) ) } schemeMap [ alias ] = scheme }

// registerAlias registers a alias for an already registered Scheme.

registerAlias registers a alias for an already registered Scheme .


func Register(scheme Scheme) {
	if scheme.Generator == nil {
		panic("must specify Generator when registering Scheme")
	}

	if scheme.Opaque && scheme.Proto&ProtoUnix != 0 {
		panic("scheme must support only Opaque or Unix protocols, not both")
	}

	// register
	if _, ok := schemeMap[scheme.Driver]; ok {
		panic(fmt.Sprintf("scheme %s already registered", scheme.Driver))
	}

	sz := &Scheme{
		Driver:    scheme.Driver,
		Generator: scheme.Generator,
		Proto:     scheme.Proto,
		Opaque:    scheme.Opaque,
		Override:  scheme.Override,
	}

	schemeMap[scheme.Driver] = sz

	// add aliases
	var hasShort bool
	for _, alias := range scheme.Aliases {
		if len(alias) == 2 {
			hasShort = true
		}
		if scheme.Driver != alias {
			registerAlias(scheme.Driver, alias, false)
		}
	}

	if !hasShort && len(scheme.Driver) > 2 {
		registerAlias(scheme.Driver, scheme.Driver[:2], false)
	}

	// ensure always at least one alias, and that if Driver is 2 characters,
	// that it gets added as well
	if len(sz.Aliases) == 0 || len(scheme.Driver) == 2 {
		sz.Aliases = append(sz.Aliases, scheme.Driver)
	}

	// sort
	sort.Sort(ss(sz.Aliases))
}


func Unregister(name string) *Scheme {
	scheme, ok := schemeMap[name]
	if ok {
		for _, alias := range scheme.Aliases {
			delete(schemeMap, alias)
		}
		delete(schemeMap, name)
		return scheme
	}
	return nil
}

func Unregister ( name string ) * Scheme { scheme , ok := schemeMap [ name ] if ok { for _ , alias := range scheme . Aliases { delete ( schemeMap , alias ) } delete ( schemeMap , name ) return scheme } return nil }

// Unregister unregisters a Scheme and all associated aliases.

Unregister unregisters a Scheme and all associated aliases .


func has(a []string, b string) bool {
	for _, s := range a {
		if s == b {
			return true
		}
	}

	return false
}

func has ( a [ ] string , b string ) bool { for _ , s := range a { if s == b { return true } } return false }

// has is a util func to determine if a contains b.

has is a util func to determine if a contains b .


func SchemeDriverAndAliases(name string) (string, []string) {
	if scheme, ok := schemeMap[name]; ok {
		driver := scheme.Driver
		if scheme.Override != "" {
			driver = scheme.Override
		}

		var aliases []string
		for _, alias := range scheme.Aliases {
			if alias == driver {
				continue
			}
			aliases = append(aliases, alias)
		}

		sort.Sort(ss(aliases))

		return driver, aliases
	}

	return "", nil
}

func SchemeDriverAndAliases ( name string ) ( string , [ ] string ) { if scheme , ok := schemeMap [ name ] ; ok { driver := scheme . Driver if scheme . Override != " " { driver = scheme . Override } var aliases [ ] string for _ , alias := range scheme . Aliases { if alias == driver { continue } aliases = append ( aliases , alias ) } sort . Sort ( ss ( aliases ) ) return driver , aliases } return " " , nil }

// SchemeDriverAndAliases returns the registered driver and aliases for a
// database scheme.

SchemeDriverAndAliases returns the registered driver and aliases for a database scheme .


func GenFromURL(urlstr string) func(*URL) (string, error) {
	z, err := url.Parse(urlstr)
	if err != nil {
		panic(err)
	}

	return func(u *URL) (string, error) {
		opaque := z.Opaque
		if u.Opaque != "" {
			opaque = u.Opaque
		}

		user := z.User
		if u.User != nil {
			user = u.User
		}

		host, port := hostname(z.Host), hostport(z.Host)
		if h := hostname(u.Host); h != "" {
			host = h
		}
		if p := hostport(u.Host); p != "" {
			port = p
		}
		if port != "" {
			host += ":" + port
		}

		path := z.Path
		if u.Path != "" {
			path = u.Path
		}

		rawPath := z.RawPath
		if u.RawPath != "" {
			rawPath = u.RawPath
		}

		q := z.Query()
		for k, v := range u.Query() {
			q.Set(k, strings.Join(v, " "))
		}

		fragment := z.Fragment
		if u.Fragment != "" {
			fragment = u.Fragment
		}

		y := &url.URL{
			Scheme:   z.Scheme,
			Opaque:   opaque,
			User:     user,
			Host:     host,
			Path:     path,
			RawPath:  rawPath,
			RawQuery: q.Encode(),
			Fragment: fragment,
		}

		return y.String(), nil
	}
}

func GenFromURL ( urlstr string ) func ( * URL ) ( string , error ) { z , err := url . Parse ( urlstr ) if err != nil { panic ( err ) } return func ( u * URL ) ( string , error ) { opaque := z . Opaque if u . Opaque != " " { opaque = u . Opaque } user := z . User if u . User != nil { user = u . User } host , port := hostname ( z . Host ) , hostport ( z . Host ) if h := hostname ( u . Host ) ; h != " " { host = h } if p := hostport ( u . Host ) ; p != " " { port = p } if port != " " { host += " " + port } path := z . Path if u . Path != " " { path = u . Path } rawPath := z . RawPath if u . RawPath != " " { rawPath = u . RawPath } q := z . Query ( ) for k , v := range u . Query ( ) { q . Set ( k , strings . Join ( v , " " ) ) } fragment := z . Fragment if u . Fragment != " " { fragment = u . Fragment } y := & url . URL { Scheme : z . Scheme , Opaque : opaque , User : user , Host : host , Path : path , RawPath : rawPath , RawQuery : q . Encode ( ) , Fragment : fragment , } return y . String ( ) , nil } }

// GenFromURL returns a func that generates a DSN using urlstr as the default
// URL parameters, overriding the values only if when in the passed URL.

GenFromURL returns a func that generates a DSN using urlstr as the default URL parameters overriding the values only if when in the passed URL .


func GenOpaque(u *URL) (string, error) {
	if u.Opaque == "" {
		return "", ErrMissingPath
	}

	return u.Opaque + genQueryOptions(u.Query()), nil
}

func GenOpaque ( u * URL ) ( string , error ) { if u . Opaque == " " { return " " , ErrMissingPath } return u . Opaque + genQueryOptions ( u . Query ( ) ) , nil }

// GenOpaque generates a opaque file path DSN from the passed URL.

GenOpaque generates a opaque file path DSN from the passed URL .


func GenPostgres(u *URL) (string, error) {
	host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")
	if host == "." {
		return "", ErrRelativePathNotSupported
	}

	// resolve path
	if u.Proto == "unix" {
		if host == "" {
			dbname = "/" + dbname
		}

		host, port, dbname = resolveDir(stdpath.Join(host, dbname))
	}

	q := u.Query()
	q.Set("host", host)
	q.Set("port", port)
	q.Set("dbname", dbname)

	// add user/pass
	if u.User != nil {
		q.Set("user", u.User.Username())
		pass, _ := u.User.Password()
		q.Set("password", pass)
	}

	// save host, port, dbname
	if u.hostPortDB == nil {
		u.hostPortDB = []string{host, port, dbname}
	}

	return genOptions(q, "", "=", " ", ",", true), nil
}

func
GenPostgres
(
u
*
URL
)
(
string
,
error
)
{
host
,
port
,
dbname
:=
hostname
(
u
.
Host
)
,
hostport
(
u
.
Host
)
,
strings
.
TrimPrefix
(
u
.
Path
,
"
"
)
if
host
==
"
"
{
return
"
"
,
ErrRelativePathNotSupported
}
// resolve path
if
u
.
Proto
==
"
"
{
if
host
==
"
"
{
dbname
=
"
"
+
dbname
}
host
,
port
,
dbname
=
resolveDir
(
stdpath
.
Join
(
host
,
dbname
)
)
}
q
:=
u
.
Query
(
)
q
.
Set
(
"
"
,
host
)
q
.
Set
(
"
"
,
port
)
q
.
Set
(
"
"
,
dbname
)
// add user/pass
if
u
.
User
!=
{
q
.
Set
(
"
"
,
u
.
User
.
Username
(
)
)
pass
,
_
:=
u
.
User
.
Password
(
)
q
.
Set
(
"
"
,
pass
)
}
// save host, port, dbname
if
u
.
hostPortDB
==
{
u
.
hostPortDB
=
[
]
string
{
host
,
port
,
dbname
}
}
return
genOptions
(
q
,
"
"
,
"
"
,
"
"
,
"
"
,
true
)
,
}

// GenPostgres generates a postgres DSN from the passed URL.

GenPostgres generates a postgres DSN from the passed URL .


func GenSQLServer(u *URL) (string, error) {
	host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")

	// add instance name to host if present
	if i := strings.Index(dbname, "/"); i != -1 {
		host = host + `\` + dbname[:i]
		dbname = dbname[i+1:]
	}

	q := u.Query()
	q.Set("Server", host)
	q.Set("Port", port)
	q.Set("Database", dbname)

	// add user/pass
	if u.User != nil {
		q.Set("User ID", u.User.Username())
		pass, _ := u.User.Password()
		q.Set("Password", pass)
	}

	// save host, port, dbname
	if u.hostPortDB == nil {
		u.hostPortDB = []string{host, port, dbname}
	}

	return genOptionsODBC(q, true), nil
}

func
GenSQLServer
(
u
*
URL
)
(
string
,
error
)
{
host
,
port
,
dbname
:=
hostname
(
u
.
Host
)
,
hostport
(
u
.
Host
)
,
strings
.
TrimPrefix
(
u
.
Path
,
"
"
)
// add instance name to host if present
if
i
:=
strings
.
Index
(
dbname
,
"
"
)
;
i
!=
1
{
host
=
host
+
`\`
+
dbname
[
:
i
]
dbname
=
dbname
[
i
+
1
:
]
}
q
:=
u
.
Query
(
)
q
.
Set
(
"
"
,
host
)
q
.
Set
(
"
"
,
port
)
q
.
Set
(
"
"
,
dbname
)
// add user/pass
if
u
.
User
!=
{
q
.
Set
(
"
"
,
u
.
User
.
Username
(
)
)
pass
,
_
:=
u
.
User
.
Password
(
)
q
.
Set
(
"
"
,
pass
)
}
// save host, port, dbname
if
u
.
hostPortDB
==
{
u
.
hostPortDB
=
[
]
string
{
host
,
port
,
dbname
}
}
return
genOptionsODBC
(
q
,
true
)
,
}

// GenSQLServer generates a mssql DSN from the passed URL.

GenSQLServer generates a mssql DSN from the passed URL .


func GenMyMySQL(u *URL) (string, error) {
	host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")

	// resolve path
	if u.Proto == "unix" {
		if host == "" {
			dbname = "/" + dbname
		}
		host, dbname = resolveSocket(stdpath.Join(host, dbname))
		port = ""
	}

	// save host, port, dbname
	if u.hostPortDB == nil {
		u.hostPortDB = []string{host, port, dbname}
	}

	// if host or proto is not empty
	if u.Proto != "unix" {
		if host == "" {
			host = "127.0.0.1"
		}
		if port == "" {
			port = "3306"
		}
	}
	if port != "" {
		port = ":" + port
	}

	dsn := u.Proto + ":" + host + port

	// add opts
	dsn += genOptions(
		convertOptions(u.Query(), "true", ""),
		",", "=", ",", " ", false,
	)

	// add dbname
	dsn += "*" + dbname

	// add user/pass
	if u.User != nil {
		pass, _ := u.User.Password()
		dsn += "/" + u.User.Username() + "/" + pass
	} else if strings.HasSuffix(dsn, "*") {
		dsn += "//"
	}

	return dsn, nil
}

func
GenMyMySQL
(
u
*
URL
)
(
string
,
error
)
{
host
,
port
,
dbname
:=
hostname
(
u
.
Host
)
,
hostport
(
u
.
Host
)
,
strings
.
TrimPrefix
(
u
.
Path
,
"
"
)
// resolve path
if
u
.
Proto
==
"
"
{
if
host
==
"
"
{
dbname
=
"
"
+
dbname
}
host
,
dbname
=
resolveSocket
(
stdpath
.
Join
(
host
,
dbname
)
)
port
=
"
"
}
// save host, port, dbname
if
u
.
hostPortDB
==
{
u
.
hostPortDB
=
[
]
string
{
host
,
port
,
dbname
}
}
// if host or proto is not empty
if
u
.
Proto
!=
"
"
{
if
host
==
"
"
{
host
=
"
"
}
if
port
==
"
"
{
port
=
"
"
}
}
if
port
!=
"
"
{
port
=
"
"
+
port
}
dsn
:=
u
.
Proto
+
"
"
+
host
+
port
// add opts
dsn
+=
genOptions
(
convertOptions
(
u
.
Query
(
)
,
"
"
,
"
"
)
,
"
"
,
"
"
,
"
"
,
"
"
,
false
,
)
// add dbname
dsn
+=
"
"
+
dbname
// add user/pass
if
u
.
User
!=
{
pass
,
_
:=
u
.
User
.
Password
(
)
dsn
+=
"
"
+
u
.
User
.
Username
(
)
+
"
"
+
pass
}
else
if
strings
.
HasSuffix
(
dsn
,
"
"
)
{
dsn
+=
"
"
}
return
dsn
,
}

// GenMyMySQL generates a MyMySQL MySQL DSN from the passed URL.

GenMyMySQL generates a MyMySQL MySQL DSN from the passed URL .


func GenOracle(u *URL) (string, error) {
	// create dsn
	dsn := u.Host + u.Path

	// build user/pass
	var un string
	if u.User != nil {
		if un = u.User.Username(); len(un) > 0 {
			if up, ok := u.User.Password(); ok {
				un += "/" + up
			}
		}
	}

	return un + "@" + dsn, nil
}

func
GenOracle
(
u
*
URL
)
(
string
,
error
)
{
// create dsn
dsn
:=
u
.
Host
+
u
.
Path
// build user/pass
var
un
string
if
u
.
User
!=
{
if
un
=
u
.
User
.
Username
(
)
;
len
(
un
)
>
0
{
if
up
,
ok
:=
u
.
User
.
Password
(
)
;
ok
{
un
+=
"
"
+
up
}
}
}
return
un
+
"
"
+
dsn
,
}

// GenOracle generates a ora DSN from the passed URL.

GenOracle generates a ora DSN from the passed URL .


func GenFirebird(u *URL) (string, error) {
	z := &url.URL{
		User:     u.User,
		Host:     u.Host,
		Path:     u.Path,
		RawPath:  u.RawPath,
		RawQuery: u.RawQuery,
		Fragment: u.Fragment,
	}
	return strings.TrimPrefix(z.String(), "//"), nil
}

func GenFirebird ( u * URL ) ( string , error ) { z := & url . URL { User : u . User , Host : u . Host , Path : u . Path , RawPath : u . RawPath , RawQuery : u . RawQuery , Fragment : u . Fragment , } return strings . TrimPrefix ( z . String ( ) , " " ) , nil }

// GenFirebird generates a firebirdsql DSN from the passed URL.

GenFirebird generates a firebirdsql DSN from the passed URL .


func GenADODB(u *URL) (string, error) {
	// grab data source
	host, port := hostname(u.Host), hostport(u.Host)
	dsname, dbname := strings.TrimPrefix(u.Path, "/"), ""
	if dsname == "" {
		dsname = "."
	}

	// check if data source is not a path on disk
	if mode(dsname) == 0 {
		if i := strings.IndexAny(dsname, `\/`); i != -1 {
			dbname = dsname[i+1:]
			dsname = dsname[:i]
		}
	}

	q := u.Query()
	q.Set("Provider", host)
	q.Set("Port", port)
	q.Set("Data Source", dsname)
	q.Set("Database", dbname)

	// add user/pass
	if u.User != nil {
		q.Set("User ID", u.User.Username())
		pass, _ := u.User.Password()
		q.Set("Password", pass)
	}

	// save host, port, dbname
	if u.hostPortDB == nil {
		n := dsname
		if dbname != "" {
			n += "/" + dbname
		}
		u.hostPortDB = []string{host, port, n}
	}

	return genOptionsODBC(q, true), nil
}

// GenADODB generates a adodb DSN from the passed URL.

GenADODB generates a adodb DSN from the passed URL .


func GenODBC(u *URL) (string, error) {
	q := u.Query()

	host, port, dbname := hostname(u.Host), hostport(u.Host), strings.TrimPrefix(u.Path, "/")

	// save host, port, dbname
	if u.hostPortDB == nil {
		u.hostPortDB = []string{host, port, dbname}
	}

	q.Set("Driver", "{"+strings.Replace(u.Proto, "+", " ", -1)+"}")
	q.Set("Server", host)

	if port == "" {
		proto := strings.ToLower(u.Proto)
		switch {
		case strings.Contains(proto, "mysql"):
			q.Set("Port", "3306")
		case strings.Contains(proto, "postgres"):
			q.Set("Port", "5432")
		case strings.Contains(proto, "db2") || strings.Contains(proto, "ibm"):
			q.Set("ServiceName", "50000")
		default:
			q.Set("Port", "1433")
		}
	} else {
		q.Set("Port", port)
	}
	q.Set("Database", dbname)

	// add user/pass
	if u.User != nil {
		q.Set("UID", u.User.Username())
		p, _ := u.User.Password()
		q.Set("PWD", p)
	}

	return genOptionsODBC(q, true), nil
}

func
GenODBC
(
u
*
URL
)
(
string
,
error
)
{
q
:=
u
.
Query
(
)
host
,
port
,
dbname
:=
hostname
(
u
.
Host
)
,
hostport
(
u
.
Host
)
,
strings
.
TrimPrefix
(
u
.
Path
,
"
"
)
// save host, port, dbname
if
u
.
hostPortDB
==
{
u
.
hostPortDB
=
[
]
string
{
host
,
port
,
dbname
}
}
q
.
Set
(
"
"
,
"
"
+
strings
.
Replace
(
u
.
Proto
,
"
"
,
"
"
,
1
)
+
"
"
)
q
.
Set
(
"
"
,
host
)
if
port
==
"
"
{
proto
:=
strings
.
ToLower
(
u
.
Proto
)
switch
{
case
strings
.
Contains
(
proto
,
"
"
)
:
q
.
Set
(
"
"
,
"
"
)
case
strings
.
Contains
(
proto
,
"
"
)
:
q
.
Set
(
"
"
,
"
"
)
case
strings
.
Contains
(
proto
,
"
"
)
||
strings
.
Contains
(
proto
,
"
"
)
:
q
.
Set
(
"
"
,
"
"
)
default
:
q
.
Set
(
"
"
,
"
"
)
}
}
else
{
q
.
Set
(
"
"
,
port
)
}
q
.
Set
(
"
"
,
dbname
)
// add user/pass
if
u
.
User
!=
{
q
.
Set
(
"
"
,
u
.
User
.
Username
(
)
)
p
,
_
:=
u
.
User
.
Password
(
)
q
.
Set
(
"
"
,
p
)
}
return
genOptionsODBC
(
q
,
true
)
,
}

// GenODBC generates a odbc DSN from the passed URL.

GenODBC generates a odbc DSN from the passed URL .


func GenOLEODBC(u *URL) (string, error) {
	props, err := GenODBC(u)
	if err != nil {
		return "", nil
	}

	return `Provider=MSDASQL.1;Extended Properties="` + props + `"`, nil
}

// GenOLEODBC generates a oleodbc DSN from the passed URL.

GenOLEODBC generates a oleodbc DSN from the passed URL .