<commit_before>package main_test

import (
	"io"
	"strings"

	. "github.com/rightscale/right_st"

	"gopkg.in/yaml.v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
)

var _ = Describe("RightScript Metadata", func() {
	var (
		validScript                     io.ReadSeeker
		noMetadataScript                io.ReadSeeker
		missingEndDelimiterScript       io.ReadSeeker
		invalidYamlSyntaxScript         io.ReadSeeker
		invalidMetadataStructureScript  io.ReadSeeker
		incorrectInputTypeSyntaxScript  io.ReadSeeker
		incorrectInputValueSyntaxScript io.ReadSeeker
		emptyTextValueScript            io.ReadSeeker
		unknownFieldScript              io.ReadSeeker
		buffer                          *gbytes.Buffer
		emptyMetadata                   RightScriptMetadata
		emptyMetadataScript             string
		populatedMetadata               RightScriptMetadata
		populatedMetadataScript         string
		differentCommentMetadata        RightScriptMetadata
		differentCommentMetadataScript  string
	)

	BeforeEach(func() {
		validScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: text:foobar
#     Possible Values:
#       - text:foobar
#       - text:barfoo
#   SUPPORTED_VERSIONS:
#     Category: Uncategorized
#     Description: Some array input
#     Input Type: array
#     Required: false
#     Advanced: true
#     Default: array:["text:v1","text:v2"]
# Attachments:
#   - attachments/some_attachment.zip
#   - attachments/another_attachment.tar.xz
# ...
`)
		noMetadataScript = strings.NewReader(`#!/bin/bash
# There is no metadata comment here
`)
		missingEndDelimiterScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: text:foobar
#     Possible Values:
#       - text:foobar
#       - text:barfoo
#
# We should have used the '...' end delimiter above
`)
		invalidYamlSyntaxScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: bogus
#     Required: true
#     Advanced: false
#     Default: text:
# ...
# The Default line is invalid YAML
`)
		invalidMetadataStructureScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   - TEXT_INPUT
# ...
# The Inputs field should have a map not an array
`)
		incorrectInputTypeSyntaxScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: bogus
#     Required: true
#     Advanced: false
# ...
# The Input Type line is not a valid type
`)
		incorrectInputValueSyntaxScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: foobar
# ...
# The Default line is not valid Inputs 2.0 syntax
`)
		emptyTextValueScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: "text:"
# ...
# The Default line should be blank or ignore in Inputs 2.0 syntax
`)
		unknownFieldScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Some Bogus Field: Some bogus value
# ...
`)
		buffer = gbytes.NewBuffer()
		emptyMetadata = RightScriptMetadata{}
		emptyMetadataScript = `# ---
# RightScript Name: ""
# Inputs: {}
# Attachments: []
# ...
`
		populatedMetadata = RightScriptMetadata{
			Name:        "Some RightScript Name",
			Description: "Some description of stuff",
			Inputs: InputMap{
				InputMetadata{
					Name:           "TEXT_INPUT",
					Category:       "Uncategorized",
					Description:    "Some test input",
					InputType:      0,
					Required:       true,
					Advanced:       false,
					Default:        &InputValue{"text", "foobar"},
					PossibleValues: []*InputValue{&InputValue{"text", "foobar"}, &InputValue{"text", "barfoo"}},
				},
				InputMetadata{
					Name:        "SUPPORTED_VERSIONS",
					Category:    "Uncategorized",
					Description: "Some array input",
					InputType:   1,
					Required:    false,
					Advanced:    true,
					Default:     &InputValue{"array", `["text:v1","text:v2"]`},
				},
			},
			Attachments: []string{
				"attachments/some_attachment.zip",
				"attachments/another_attachment.tar.xz",
			},
		}
		populatedMetadataScript = `# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: text:foobar
#     Possible Values:
#     - text:foobar
#     - text:barfoo
#   SUPPORTED_VERSIONS:
#     Category: Uncategorized
#     Description: Some array input
#     Input Type: array
#     Required: false
#     Advanced: true
#     Default: array:["text:v1","text:v2"]
# Attachments:
# - attachments/some_attachment.zip
# - attachments/another_attachment.tar.xz
# ...
`
		differentCommentMetadata = RightScriptMetadata{Comment: "//"}
		differentCommentMetadataScript = `// ---
// RightScript Name: ""
// Inputs: {}
// Attachments: []
// ...
`
	})

	Describe("Parse RightScript metadata", func() {
		Context("With valid script metadata", func() {
			It("should parse correctly", func() {
				metadata, err := ParseRightScriptMetadata(validScript)
				Expect(err).To(Succeed())
				Expect(metadata).NotTo(BeNil())
				Expect(metadata.Name).To(Equal("Some RightScript Name"))
				Expect(metadata.Description).To(Equal("Some description of stuff"))
				Expect(metadata.Inputs).To(Equal(InputMap{
					InputMetadata{
						Name:           "TEXT_INPUT",
						Category:       "Uncategorized",
						Description:    "Some test input",
						InputType:      0,
						Required:       true,
						Advanced:       false,
						Default:        &InputValue{"text", "foobar"},
						PossibleValues: []*InputValue{&InputValue{"text", "foobar"}, &InputValue{"text", "barfoo"}},
					},
					InputMetadata{
						Name:        "SUPPORTED_VERSIONS",
						Category:    "Uncategorized",
						Description: "Some array input",
						InputType:   1,
						Required:    false,
						Advanced:    true,
						Default:     &InputValue{"array", `["text:v1","text:v2"]`},
					},
				}))
				Expect(metadata.Attachments).To(Equal([]string{
					"attachments/some_attachment.zip",
					"attachments/another_attachment.tar.xz",
				}))
			})
		})

		Context("With no script metadata", func() {
			It("should not return metadata", func() {
				metadata, err := ParseRightScriptMetadata(noMetadataScript)
				Expect(err).To(Succeed())
				Expect(metadata).To(BeNil())
			})
		})

		Context("With missing end delimiter in script metadata", func() {
			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(missingEndDelimiterScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("Unterminated RightScript metadata comment"))
			})
		})

		Context("With invalid YAML syntax in script metadata", func() {
			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(invalidYamlSyntaxScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("yaml: line 13: mapping values are not allowed in this context"))
			})
		})

		Context("With invalid structure in script metadata", func() {
			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(invalidMetadataStructureScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError(&yaml.TypeError{
					Errors: []string{
						"line 7: cannot unmarshal !!seq into map[string]main.InputMetadata",
					},
				}))
			})
		})

		Context("With incorrect input type syntax in script metadata", func() {
			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(incorrectInputTypeSyntaxScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("Invalid input type value: bogus"))
			})
		})

		Context("With incorrect input value syntax in script metadata", func() {
			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(incorrectInputValueSyntaxScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("Invalid input value: foobar"))
			})
		})

		Context("With a blank text input value in script metadata", func() {
			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(emptyTextValueScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("Use 'blank' or 'ignore' instead of 'text:'"))
			})
		})

		Context("With an unknown field in script metadata", func() {
			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(unknownFieldScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError(&yaml.TypeError{
					Errors: []string{
						"line 6: field Some Bogus Field not found in type main.RightScriptMetadata",
					},
				}))
			})
		})
	})

	Describe("Write RightScript metadata", func() {
		Context("With empty metadata", func() {
			It("should write a metadata comment", func() {
				n, err := emptyMetadata.WriteTo(buffer)
				Expect(err).To(Succeed())
				Expect(buffer.Contents()).To(BeEquivalentTo(emptyMetadataScript))
				Expect(n).To(BeEquivalentTo(66))
			})
		})
		Context("With populated metadata", func() {
			It("should write a metadata comment", func() {
				n, err := populatedMetadata.WriteTo(buffer)
				Expect(err).To(Succeed())
				Expect(buffer.Contents()).To(BeEquivalentTo(populatedMetadataScript))
				Expect(n).To(BeEquivalentTo(637))
			})
		})
		Context("With a different comment string for metadata", func() {
			It("should write a metadata comment", func() {
				n, err := differentCommentMetadata.WriteTo(buffer)
				Expect(err).To(Succeed())
				Expect(buffer.Contents()).To(BeEquivalentTo(differentCommentMetadataScript))
				Expect(n).To(BeEquivalentTo(71))
			})
		})
	})
})
<commit_msg>Rearrange variables in metadata tests<commit_after>package main_test

import (
	"io"
	"strings"

	. "github.com/rightscale/right_st"

	"gopkg.in/yaml.v2"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
)

var _ = Describe("RightScript Metadata", func() {
	Describe("Parse RightScript metadata", func() {
		Context("With valid script metadata", func() {
			var validScript io.ReadSeeker
			validScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: text:foobar
#     Possible Values:
#       - text:foobar
#       - text:barfoo
#   SUPPORTED_VERSIONS:
#     Category: Uncategorized
#     Description: Some array input
#     Input Type: array
#     Required: false
#     Advanced: true
#     Default: array:["text:v1","text:v2"]
# Attachments:
#   - attachments/some_attachment.zip
#   - attachments/another_attachment.tar.xz
# ...
`)

			It("should parse correctly", func() {
				metadata, err := ParseRightScriptMetadata(validScript)
				Expect(err).To(Succeed())
				Expect(metadata).NotTo(BeNil())
				Expect(metadata.Name).To(Equal("Some RightScript Name"))
				Expect(metadata.Description).To(Equal("Some description of stuff"))
				Expect(metadata.Inputs).To(Equal(InputMap{
					InputMetadata{
						Name:           "TEXT_INPUT",
						Category:       "Uncategorized",
						Description:    "Some test input",
						InputType:      0,
						Required:       true,
						Advanced:       false,
						Default:        &InputValue{"text", "foobar"},
						PossibleValues: []*InputValue{&InputValue{"text", "foobar"}, &InputValue{"text", "barfoo"}},
					},
					InputMetadata{
						Name:        "SUPPORTED_VERSIONS",
						Category:    "Uncategorized",
						Description: "Some array input",
						InputType:   1,
						Required:    false,
						Advanced:    true,
						Default:     &InputValue{"array", `["text:v1","text:v2"]`},
					},
				}))
				Expect(metadata.Attachments).To(Equal([]string{
					"attachments/some_attachment.zip",
					"attachments/another_attachment.tar.xz",
				}))
			})
		})

		Context("With no script metadata", func() {
			var noMetadataScript io.ReadSeeker
			noMetadataScript = strings.NewReader(`#!/bin/bash
# There is no metadata comment here
`)

			It("should not return metadata", func() {
				metadata, err := ParseRightScriptMetadata(noMetadataScript)
				Expect(err).To(Succeed())
				Expect(metadata).To(BeNil())
			})
		})

		Context("With missing end delimiter in script metadata", func() {
			var missingEndDelimiterScript io.ReadSeeker
			missingEndDelimiterScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: text:foobar
#     Possible Values:
#       - text:foobar
#       - text:barfoo
#
# We should have used the '...' end delimiter above
`)

			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(missingEndDelimiterScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("Unterminated RightScript metadata comment"))
			})
		})

		Context("With invalid YAML syntax in script metadata", func() {
			var invalidYamlSyntaxScript io.ReadSeeker
			invalidYamlSyntaxScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: bogus
#     Required: true
#     Advanced: false
#     Default: text:
# ...
# The Default line is invalid YAML
`)

			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(invalidYamlSyntaxScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("yaml: line 13: mapping values are not allowed in this context"))
			})
		})

		Context("With invalid structure in script metadata", func() {
			var invalidMetadataStructureScript io.ReadSeeker
			invalidMetadataStructureScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   - TEXT_INPUT
# ...
# The Inputs field should have a map not an array
`)

			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(invalidMetadataStructureScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError(&yaml.TypeError{
					Errors: []string{
						"line 7: cannot unmarshal !!seq into map[string]main.InputMetadata",
					},
				}))
			})
		})

		Context("With incorrect input type syntax in script metadata", func() {
			var incorrectInputTypeSyntaxScript io.ReadSeeker
			incorrectInputTypeSyntaxScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: bogus
#     Required: true
#     Advanced: false
# ...
# The Input Type line is not a valid type
`)

			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(incorrectInputTypeSyntaxScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("Invalid input type value: bogus"))
			})
		})

		Context("With incorrect input value syntax in script metadata", func() {
			var incorrectInputValueSyntaxScript io.ReadSeeker
			incorrectInputValueSyntaxScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: foobar
# ...
# The Default line is not valid Inputs 2.0 syntax
`)

			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(incorrectInputValueSyntaxScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("Invalid input value: foobar"))
			})
		})

		Context("With a blank text input value in script metadata", func() {
			var emptyTextValueScript io.ReadSeeker
			emptyTextValueScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: "text:"
# ...
# The Default line should be blank or ignore in Inputs 2.0 syntax
`)

			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(emptyTextValueScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError("Use 'blank' or 'ignore' instead of 'text:'"))
			})
		})

		Context("With an unknown field in script metadata", func() {
			var unknownFieldScript io.ReadSeeker
			unknownFieldScript = strings.NewReader(`#!/bin/bash
# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Some Bogus Field: Some bogus value
# ...
`)

			It("should return an error", func() {
				_, err := ParseRightScriptMetadata(unknownFieldScript)
				Expect(err).To(HaveOccurred())
				Expect(err).To(MatchError(&yaml.TypeError{
					Errors: []string{
						"line 6: field Some Bogus Field not found in type main.RightScriptMetadata",
					},
				}))
			})
		})
	})

	Describe("Write RightScript metadata", func() {
		var buffer *gbytes.Buffer

		BeforeEach(func() {
			buffer = gbytes.NewBuffer()
		})

		Context("With empty metadata", func() {
			var (
				emptyMetadata       RightScriptMetadata
				emptyMetadataScript string
			)
			emptyMetadata = RightScriptMetadata{}
			emptyMetadataScript = `# ---
# RightScript Name: ""
# Inputs: {}
# Attachments: []
# ...
`

			It("should write a metadata comment", func() {
				n, err := emptyMetadata.WriteTo(buffer)
				Expect(err).To(Succeed())
				Expect(buffer.Contents()).To(BeEquivalentTo(emptyMetadataScript))
				Expect(n).To(BeEquivalentTo(66))
			})
		})

		Context("With populated metadata", func() {
			var (
				populatedMetadata       RightScriptMetadata
				populatedMetadataScript string
			)
			populatedMetadata = RightScriptMetadata{
				Name:        "Some RightScript Name",
				Description: "Some description of stuff",
				Inputs: InputMap{
					InputMetadata{
						Name:           "TEXT_INPUT",
						Category:       "Uncategorized",
						Description:    "Some test input",
						InputType:      0,
						Required:       true,
						Advanced:       false,
						Default:        &InputValue{"text", "foobar"},
						PossibleValues: []*InputValue{&InputValue{"text", "foobar"}, &InputValue{"text", "barfoo"}},
					},
					InputMetadata{
						Name:        "SUPPORTED_VERSIONS",
						Category:    "Uncategorized",
						Description: "Some array input",
						InputType:   1,
						Required:    false,
						Advanced:    true,
						Default:     &InputValue{"array", `["text:v1","text:v2"]`},
					},
				},
				Attachments: []string{
					"attachments/some_attachment.zip",
					"attachments/another_attachment.tar.xz",
				},
			}
			populatedMetadataScript = `# ---
# RightScript Name: Some RightScript Name
# Description: Some description of stuff
# Inputs:
#   TEXT_INPUT:
#     Category: Uncategorized
#     Description: Some test input
#     Input Type: single
#     Required: true
#     Advanced: false
#     Default: text:foobar
#     Possible Values:
#     - text:foobar
#     - text:barfoo
#   SUPPORTED_VERSIONS:
#     Category: Uncategorized
#     Description: Some array input
#     Input Type: array
#     Required: false
#     Advanced: true
#     Default: array:["text:v1","text:v2"]
# Attachments:
# - attachments/some_attachment.zip
# - attachments/another_attachment.tar.xz
# ...
`

			It("should write a metadata comment", func() {
				n, err := populatedMetadata.WriteTo(buffer)
				Expect(err).To(Succeed())
				Expect(buffer.Contents()).To(BeEquivalentTo(populatedMetadataScript))
				Expect(n).To(BeEquivalentTo(637))
			})
		})

		Context("With a different comment string for metadata", func() {
			var (
				differentCommentMetadata       RightScriptMetadata
				differentCommentMetadataScript string
			)
			differentCommentMetadata = RightScriptMetadata{Comment: "//"}
			differentCommentMetadataScript = `// ---
// RightScript Name: ""
// Inputs: {}
// Attachments: []
// ...
`

			It("should write a metadata comment", func() {
				n, err := differentCommentMetadata.WriteTo(buffer)
				Expect(err).To(Succeed())
				Expect(buffer.Contents()).To(BeEquivalentTo(differentCommentMetadataScript))
				Expect(n).To(BeEquivalentTo(71))
			})
		})
	})
})
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package metrics

import (
	"errors"
	"strconv"
)

// Float implements NumValue with float64 storage. Note that Float is not concurrency
// safe.
type Float struct {
	f float64
	// If Str is defined, this is method used to convert Float into a string.
	Str func(float64) string
}

// NewFloat returns a new Float.
func NewFloat(f float64) *Float {
	return &Float{f: f}
}

// Clone returns a copy the receiver Float
func (f *Float) Clone() Value {
	return &Float{
		f:   f.f,
		Str: f.Str,
	}
}

// Int64 returns the stored float64 as int64.
func (f *Float) Int64() int64 {
	return int64(f.f)
}

// Float64 returns the stored float64.
func (f *Float) Float64() float64 {
	return f.f
}

// Inc increments the receiver Float by one.
// It's part of the NumValue interface.
func (f *Float) Inc() {
	f.f++
}

// IncBy increments the receiver Float by "delta" NumValue.
// It's part of the NumValue interface.
func (f *Float) IncBy(delta NumValue) {
	f.f += delta.Float64()
}

// Add adds a Value to the receiver Float. If Value is not Float, an error is returned.
// It's part of the Value interface.
func (f *Float) Add(val Value) error {
	delta, ok := val.(*Float)
	if !ok {
		return errors.New("incompatible value to add")
	}
	f.f += delta.f
	return nil
}

// AddInt64 adds an int64 to the receiver Float.
func (f *Float) AddInt64(i int64) {
	f.f += float64(i)
}

// AddFloat64 adds a float64 to the receiver Float.
func (f *Float) AddFloat64(ff float64) {
	f.f += ff
}

// String returns the string representation of Float.
// It's part of the Value interface.
func (f *Float) String() string {
	if f.Str != nil {
		return f.Str(f.Float64())
	}
	// Truncate the float to 3-digit precision.
	// Example: 3.33333333333 -> 3.333
	ff := float64(int(f.f*1000)) / 1000
	return strconv.FormatFloat(ff, 'f', -1, 64)
}
<commit_msg>float: Don't cast a float value as an int<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package metrics

import (
	"errors"
	"strconv"
)

// Float implements NumValue with float64 storage. Note that Float is not concurrency
// safe.
type Float struct {
	f float64
	// If Str is defined, this is method used to convert Float into a string.
	Str func(float64) string
}

// NewFloat returns a new Float.
func NewFloat(f float64) *Float {
	return &Float{f: f}
}

// Clone returns a copy the receiver Float
func (f *Float) Clone() Value {
	return &Float{
		f:   f.f,
		Str: f.Str,
	}
}

// Int64 returns the stored float64 as int64.
func (f *Float) Int64() int64 {
	return int64(f.f)
}

// Float64 returns the stored float64.
func (f *Float) Float64() float64 {
	return f.f
}

// Inc increments the receiver Float by one.
// It's part of the NumValue interface.
func (f *Float) Inc() {
	f.f++
}

// IncBy increments the receiver Float by "delta" NumValue.
// It's part of the NumValue interface.
func (f *Float) IncBy(delta NumValue) {
	f.f += delta.Float64()
}

// Add adds a Value to the receiver Float. If Value is not Float, an error is returned.
// It's part of the Value interface.
func (f *Float) Add(val Value) error {
	delta, ok := val.(*Float)
	if !ok {
		return errors.New("incompatible value to add")
	}
	f.f += delta.f
	return nil
}

// AddInt64 adds an int64 to the receiver Float.
func (f *Float) AddInt64(i int64) {
	f.f += float64(i)
}

// AddFloat64 adds a float64 to the receiver Float.
func (f *Float) AddFloat64(ff float64) {
	f.f += ff
}

// String returns the string representation of Float.
// It's part of the Value interface.
func (f *Float) String() string {
	if f.Str != nil {
		return f.Str(f.Float64())
	}
	return strconv.FormatFloat(f.f, 'f', 3, 64)
}
<|endoftext|>


<commit_before>package controllers

import (
	"crypto/sha1"
	"encoding/xml"
	"fmt"
	"github.com/astaxie/beego"
	"io/ioutil"
	"sort"
	"strings"
	"time"
)

const (
	TOKEN       = "yiiliwechattoken"
	Text        = "text"
	Location    = "location"
	Image       = "image"
	Link        = "link"
	Event       = "event"
	Music       = "music"
	News        = "news"
	HelpContent = `您好，感谢关注衣丽社区微信公众号i-yiili，希望我们能为您的生活提供一点帮助。
            我们会通过微信公众号向您不定期地推送一些涉及美容美发化妆、穿着搭配、运动健康、饮食营养、情绪修养等跟女性生活息息相关的文章。
            同时借助微信公众号强大的可定制性，我们也提供了一系列丰富的功能，并且将不断增加新的实用的功能。
            输入“文章+日期”或“wz+日期”如（文章20141022 或 wz20141022），显示该天衣丽社区微信公众号发布的文章链接。
            输入“微店”或“wd”，显示衣丽社区关联的微店地址。
            输入“女装”或“nz”，显示衣丽社区主持出售的女装商品信息。
            输入“面膜”或“mm”，显示衣丽社区主持出售的面膜商品信息。
            输入商品id（如：310148677），显示衣丽社区主持出售的对应商品信息。
            输入任意关键字，显示包含该关键字的衣丽社区主持出售的商品信息。
            其他更多功能，敬请期待。`
)

type msgBase struct {
	ToUserName   string
	FromUserName string
	CreateTime   time.Duration
	MsgType      string
	Content      string
}

type Request struct {
	XMLName                xml.Name `xml:"xml"`
	msgBase                         // base struct
	Location_X, Location_Y float32
	Scale                  int
	Label                  string
	PicUrl                 string
	MsgId                  int
}

type Response struct {
	XMLName xml.Name `xml:"xml"`
	msgBase
	ArticleCount int     `xml:",omitempty"`
	Articles     []*item `xml:"Articles>item,omitempty"`
	FuncFlag     int
}

type item struct {
	XMLName     xml.Name `xml:"item"`
	Title       string
	Description string
	PicUrl      string
	Url         string
}

type MainController struct {
	beego.Controller
}

func (this *MainController) Get() {
	signature := this.Input().Get("signature")
	beego.Info("signature:" + signature)
	timestamp := this.Input().Get("timestamp")
	beego.Info("timestamp:" + timestamp)
	nonce := this.Input().Get("nonce")
	beego.Info("nonce:" + nonce)
	echostr := this.Input().Get("echostr")
	beego.Info("echostr:" + echostr)
	beego.Info(Signature(timestamp, nonce))
	if Signature(timestamp, nonce) == signature {
		beego.Info("signature matched")
		this.Ctx.WriteString(echostr)
	} else {
		beego.Info("signature not matched")
		this.Ctx.WriteString("")
	}
}

func (this *MainController) Post() {
	body, err := ioutil.ReadAll(this.Ctx.Request.Body)
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	beego.Info(string(body))
	var wreq *Request
	if wreq, err = DecodeRequest(body); err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	beego.Info(wreq.Content)
	wresp, err := dealwith(wreq)
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	data, err := wresp.Encode()
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	this.Ctx.WriteString(string(data))
	return
}

func dealwith(req *Request) (resp *Response, err error) {
	resp = NewResponse()
	resp.ToUserName = req.FromUserName
	resp.FromUserName = req.ToUserName
	resp.MsgType = Text
	beego.Info(req.MsgType)
	beego.Info(req.Content)
	if req.MsgType == Text {
		userInputText := strings.Trim(strings.ToLower(req.Content), " ")
		if userInputText == "help" || userInputText == `帮助` {
			resp.Content = HelpContent
			return resp, nil
		}
		if userInputText == "wd" || userInputText == `微店` {
			resp.MsgType = News
			resp.ArticleCount = 2
			var a item
			a.Description = `女装专卖，经典时尚大方，赶快来看看吧:)`
			a.Title = `凯莉小姐的梦想女装店，经典时尚大方，适合都市年轻女性，赶快来吧:)`
			a.PicUrl = "http://wd.geilicdn.com/vshop215091300-1413902752.jpg"
			a.Url = "http://shopwd.yii.li"
			resp.Articles = append(resp.Articles, &a)
			var a2 item
			a2.Description = `多款精品面膜，效果超好，输入mm看看吧:)`
			a2.Title = `清韵诗面膜，多款精品面膜，效果超好，输入mm看看吧:)`
			a2.PicUrl = "http://wd.geilicdn.com/vshop1015143-1413815285.jpg"
			a2.Url = "http://wd.koudai.com/s/1015143"
			resp.Articles = append(resp.Articles, &a2)

			resp.FuncFlag = 1
			return resp, nil
		}
		if userInputText == "mm" || userInputText == `面膜` {
			resp.MsgType = News
			resp.ArticleCount = 6
			var a [6]item
			a[0].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[0].Title = `清韵诗完美净肤面膜，售价仅88元一盒，赶快来看看吧:)`
			a[0].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814758-1.jpg"
			a[0].Url = "http://wd.koudai.com/item.html?itemID=307973157"
			resp.Articles = append(resp.Articles, &a[0])
			a[1].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[1].Title = `清韵诗焕颜靓白面膜，售价仅88元一盒，赶快来看看吧:)`
			a[1].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814687-1.jpg"
			a[1].Url = "http://wd.koudai.com/item.html?itemID=307970560"
			resp.Articles = append(resp.Articles, &a[1])
			a[2].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[2].Title = `清韵诗弹力胶原面膜，售价仅88元一盒，赶快来看看吧:)`
			a[2].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814573-1.jpg"
			a[2].Url = "http://wd.koudai.com/item.html?itemID=307966427"
			resp.Articles = append(resp.Articles, &a[2])
			a[3].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[3].Title = `清韵诗植物修复面膜，售价仅88元一盒，赶快来看看吧:)`
			a[3].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814512-1.jpg"
			a[3].Url = "http://wd.koudai.com/item.html?itemID=307964195"
			resp.Articles = append(resp.Articles, &a[3])
			a[4].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[4].Title = `清韵诗魔法冰瓷面膜，售价仅88元一盒，赶快来看看吧:)`
			a[4].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814406-1.jpg"
			a[4].Url = "http://wd.koudai.com/item.html?itemID=307960310"
			resp.Articles = append(resp.Articles, &a[4])
			a[5].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[5].Title = `清韵诗水嫩宝贝面膜，售价仅88元一盒，赶快来看看吧:)`
			a[5].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814179-1.jpg"
			a[5].Url = "http://wd.koudai.com/item.html?itemID=307953149"
			resp.Articles = append(resp.Articles, &a[5])

			resp.FuncFlag = 1
			return resp, nil
		}

		resp.Content = "衣丽已经很努力地在学习了，但仍然不能理解您的需求，请您输入help查看衣丽能懂的一些命令吧:("
	} else {
		resp.Content = "暂时还不支持其他的命令类型，请输入help查看说明。"
	}
	return resp, nil
}

func Signature(timestamp, nonce string) string {
	strs := sort.StringSlice{TOKEN, timestamp, nonce}
	sort.Strings(strs)
	str := ""
	for _, s := range strs {
		str += s
	}
	h := sha1.New()
	h.Write([]byte(str))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func DecodeRequest(data []byte) (req *Request, err error) {
	req = &Request{}
	if err = xml.Unmarshal(data, req); err != nil {
		return
	}
	req.CreateTime *= time.Second
	return
}

func NewResponse() (resp *Response) {
	resp = &Response{}
	resp.CreateTime = time.Duration(time.Now().Unix())
	return
}

func (resp Response) Encode() (data []byte, err error) {
	resp.CreateTime = time.Second
	data, err = xml.Marshal(resp)
	return
}
<commit_msg>(*)support query by item id<commit_after>package controllers

import (
	"crypto/sha1"
	"encoding/xml"
	"fmt"
	"github.com/astaxie/beego"
	"io/ioutil"
	"regexp"
	"sort"
	"strings"
	"time"
)

const (
	TOKEN       = "yiiliwechattoken"
	Text        = "text"
	Location    = "location"
	Image       = "image"
	Link        = "link"
	Event       = "event"
	Music       = "music"
	News        = "news"
	HelpContent = `您好，感谢关注衣丽社区微信公众号i-yiili，希望我们能为您的生活提供一点帮助。
            我们会通过微信公众号向您不定期地推送一些涉及美容美发化妆、穿着搭配、运动健康、饮食营养、情绪修养等跟女性生活息息相关的文章。
            同时借助微信公众号强大的可定制性，我们也提供了一系列丰富的功能，并且将不断增加新的实用的功能。
            输入“文章+日期”或“wz+日期”如（文章20141022 或 wz20141022），显示该天衣丽社区微信公众号发布的文章链接。
            输入“微店”或“wd”，显示衣丽社区关联的微店地址。
            输入“女装”或“nz”，显示衣丽社区主持出售的女装商品信息。
            输入“面膜”或“mm”，显示衣丽社区主持出售的面膜商品信息。
            输入商品id（如：310148677），显示衣丽社区主持出售的对应商品信息。
            输入任意关键字，显示包含该关键字的衣丽社区主持出售的商品信息。
            其他更多功能，敬请期待。`
)

type msgBase struct {
	ToUserName   string
	FromUserName string
	CreateTime   time.Duration
	MsgType      string
	Content      string
}

type Request struct {
	XMLName                xml.Name `xml:"xml"`
	msgBase                         // base struct
	Location_X, Location_Y float32
	Scale                  int
	Label                  string
	PicUrl                 string
	MsgId                  int
}

type Response struct {
	XMLName xml.Name `xml:"xml"`
	msgBase
	ArticleCount int     `xml:",omitempty"`
	Articles     []*item `xml:"Articles>item,omitempty"`
	FuncFlag     int
}

type item struct {
	XMLName     xml.Name `xml:"item"`
	Title       string
	Description string
	PicUrl      string
	Url         string
}

type MainController struct {
	beego.Controller
}

func (this *MainController) Get() {
	signature := this.Input().Get("signature")
	beego.Info("signature:" + signature)
	timestamp := this.Input().Get("timestamp")
	beego.Info("timestamp:" + timestamp)
	nonce := this.Input().Get("nonce")
	beego.Info("nonce:" + nonce)
	echostr := this.Input().Get("echostr")
	beego.Info("echostr:" + echostr)
	beego.Info(Signature(timestamp, nonce))
	if Signature(timestamp, nonce) == signature {
		beego.Info("signature matched")
		this.Ctx.WriteString(echostr)
	} else {
		beego.Info("signature not matched")
		this.Ctx.WriteString("")
	}
}

func (this *MainController) Post() {
	body, err := ioutil.ReadAll(this.Ctx.Request.Body)
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	beego.Info(string(body))
	var wreq *Request
	if wreq, err = DecodeRequest(body); err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	beego.Info(wreq.Content)
	wresp, err := dealwith(wreq)
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	data, err := wresp.Encode()
	if err != nil {
		beego.Error(err)
		this.Ctx.ResponseWriter.WriteHeader(500)
		return
	}
	this.Ctx.WriteString(string(data))
	return
}

func dealwith(req *Request) (resp *Response, err error) {
	resp = NewResponse()
	resp.ToUserName = req.FromUserName
	resp.FromUserName = req.ToUserName
	resp.MsgType = Text
	beego.Info(req.MsgType)
	beego.Info(req.Content)
	if req.MsgType == Text {
		userInputText := strings.Trim(strings.ToLower(req.Content), " ")
		if userInputText == "help" || userInputText == `帮助` {
			resp.Content = HelpContent
			return resp, nil
		}
		if userInputText == "wd" || userInputText == `微店` {
			resp.MsgType = News
			resp.ArticleCount = 2
			var a item
			a.Description = `女装专卖，经典时尚大方，赶快来看看吧:)`
			a.Title = `凯莉小姐的梦想女装店，经典时尚大方，适合都市年轻女性，赶快来吧:)`
			a.PicUrl = "http://wd.geilicdn.com/vshop215091300-1413902752.jpg"
			a.Url = "http://shopwd.yii.li"
			resp.Articles = append(resp.Articles, &a)
			var a2 item
			a2.Description = `多款精品面膜，效果超好，输入mm看看吧:)`
			a2.Title = `清韵诗面膜，多款精品面膜，效果超好，输入mm看看吧:)`
			a2.PicUrl = "http://wd.geilicdn.com/vshop1015143-1413815285.jpg"
			a2.Url = "http://wd.koudai.com/s/1015143"
			resp.Articles = append(resp.Articles, &a2)

			resp.FuncFlag = 1
			return resp, nil
		}
		if userInputText == "mm" || userInputText == `面膜` {
			resp.MsgType = News
			resp.ArticleCount = 6
			var a [6]item
			a[0].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[0].Title = `清韵诗完美净肤面膜，售价仅88元一盒，赶快来看看吧:)`
			a[0].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814758-1.jpg"
			a[0].Url = "http://wd.koudai.com/item.html?itemID=307973157"
			resp.Articles = append(resp.Articles, &a[0])
			a[1].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[1].Title = `清韵诗焕颜靓白面膜，售价仅88元一盒，赶快来看看吧:)`
			a[1].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814687-1.jpg"
			a[1].Url = "http://wd.koudai.com/item.html?itemID=307970560"
			resp.Articles = append(resp.Articles, &a[1])
			a[2].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[2].Title = `清韵诗弹力胶原面膜，售价仅88元一盒，赶快来看看吧:)`
			a[2].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814573-1.jpg"
			a[2].Url = "http://wd.koudai.com/item.html?itemID=307966427"
			resp.Articles = append(resp.Articles, &a[2])
			a[3].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[3].Title = `清韵诗植物修复面膜，售价仅88元一盒，赶快来看看吧:)`
			a[3].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814512-1.jpg"
			a[3].Url = "http://wd.koudai.com/item.html?itemID=307964195"
			resp.Articles = append(resp.Articles, &a[3])
			a[4].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[4].Title = `清韵诗魔法冰瓷面膜，售价仅88元一盒，赶快来看看吧:)`
			a[4].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814406-1.jpg"
			a[4].Url = "http://wd.koudai.com/item.html?itemID=307960310"
			resp.Articles = append(resp.Articles, &a[4])
			a[5].Description = `售价仅88元一盒，赶快来看看吧:)`
			a[5].Title = `清韵诗水嫩宝贝面膜，售价仅88元一盒，赶快来看看吧:)`
			a[5].PicUrl = "http://wd.geilicdn.com/vshop1015143-1413814179-1.jpg"
			a[5].Url = "http://wd.koudai.com/item.html?itemID=307953149"
			resp.Articles = append(resp.Articles, &a[5])

			resp.FuncFlag = 1
			return resp, nil
		}
		matched, err := regexp.MatchString("[0-9]+", userInputText)
		if err == nil && matched == true {
			resp.MsgType = News
			resp.ArticleCount = 1
			var a item
			a.Description = `女装专卖，经典时尚大方，赶快来看看吧:)`
			a.Title = `凯莉小姐的梦想女装店，经典时尚大方，适合都市年轻女性，赶快来吧:)`
			a.PicUrl = "http://wd.geilicdn.com/vshop215091300-1413902752.jpg"
			a.Url = "http://wd.koudai.com/item.html?itemID=" + userInputText
			resp.Articles = append(resp.Articles, &a)
			resp.FuncFlag = 1
			return resp, nil
		}

		resp.Content = "衣丽已经很努力地在学习了，但仍然不能理解您的需求，请您输入help查看衣丽能懂的一些命令吧:("
	} else {
		resp.Content = "暂时还不支持其他的命令类型，请输入help查看说明。"
	}
	return resp, nil
}

func Signature(timestamp, nonce string) string {
	strs := sort.StringSlice{TOKEN, timestamp, nonce}
	sort.Strings(strs)
	str := ""
	for _, s := range strs {
		str += s
	}
	h := sha1.New()
	h.Write([]byte(str))
	return fmt.Sprintf("%x", h.Sum(nil))
}

func DecodeRequest(data []byte) (req *Request, err error) {
	req = &Request{}
	if err = xml.Unmarshal(data, req); err != nil {
		return
	}
	req.CreateTime *= time.Second
	return
}

func NewResponse() (resp *Response) {
	resp = &Response{}
	resp.CreateTime = time.Duration(time.Now().Unix())
	return
}

func (resp Response) Encode() (data []byte, err error) {
	resp.CreateTime = time.Second
	data, err = xml.Marshal(resp)
	return
}
<|endoftext|>


<commit_before>package controllers

import (
	"github.com/Shaked/gomobiledetect"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"
)

type MainController struct {
	beego.Controller
}

func (index *MainController) Get() {
	index.Data["Website"] = "Golang-CMS, Fast CMS"
	index.Data["description"] = "Fastest and stable CMS"
	index.Data["Email"] = "dionyself@gmail.com"
	index.TplNames = "index.tpl"
}

var DetectUserAgent = func(ctx *context.Context) {
	deviceDetector := mobiledetect.NewMobileDetect(ctx.Request, nil)
	device := ctx.Input.Cookie("Device-Type")
	if device == "" {
		device, ok := ctx.Input.GetData("device_type").(string)
		if ok {
			ctx.Output.Cookie("Device-Type", device)
		} else {
			if deviceDetector.IsMobile() {
				device = "Mobile"
			}
			if deviceDetector.IsTablet() {
				device = "Tablet"
			}
			if device != "" {
				ctx.Output.Cookie("Device-Type", device)
			} else {
				device = beego.AppConfig.String("DefaultVersion")
				ctx.Output.Cookie("Device-Type", device)
			}
		}
	}
	ctx.Input.SetData("device_type", device)
}
<commit_msg>fixed device detector<commit_after>package controllers

import (
	"github.com/Shaked/gomobiledetect"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context"
)

type MainController struct {
	beego.Controller
}

func (index *MainController) Get() {
	index.Data["Website"] = "Golang-CMS, Fast CMS"
	index.Data["description"] = "Fastest and stable CMS"
	index.Data["Email"] = "dionyself@gmail.com"
	index.TplNames = "index.tpl"
}

var DetectUserAgent = func(ctx *context.Context) {
	deviceDetector := mobiledetect.NewMobileDetect(ctx.Request, nil)
	device, _ := ctx.Input.GetData("device_type").(string)
	if device == "" {
		device = ctx.Input.Cookie("Device-Type")
	}
	if device == "" {
		if deviceDetector.IsMobile() {
			device = "Mobile"
		}
		if deviceDetector.IsTablet() {
			device = "Tablet"
		}
		if device == "" {
			device = beego.AppConfig.String("DefaultDevice")
		}
	}
	ctx.Output.Cookie("Device-Type", device)
	ctx.Input.SetData("device_type", device)
}
<|endoftext|>


<commit_before>package model

import (
	"bytes"
	"go/doc"
	"regexp"
	"strings"

	"code.google.com/p/go.net/html"
	"github.com/aarzilli/sandblast"
)

func godoc(member, content string) string {
	undocumented := "// " + exportable(member) + " is undocumented.\n"

	node, err := html.Parse(strings.NewReader(content))
	if err != nil {
		return undocumented
	}

	_, v, err := sandblast.Extract(node)
	if err != nil {
		return undocumented
	}

	v = strings.TrimSpace(v)
	if v == "" {
		return undocumented
	}

	if member != "" {
		v = exportable(member) + " " + strings.ToLower(v[0:1]) + v[1:]
	}

	out := bytes.NewBuffer(nil)
	doc.ToText(out, v, "// ", "", 72)
	return out.String()
}

func exportable(name string) string {
	// make sure the symbol is exportable
	name = strings.ToUpper(name[0:1]) + name[1:]

	// fix common AWS<->Go bugaboos
	for regexp, repl := range replacements {
		name = regexp.ReplaceAllString(name, repl)
	}
	return name
}

var replacements = map[*regexp.Regexp]string{
	regexp.MustCompile(`Acl`):          "ACL",
	regexp.MustCompile(`Adm([^i]|$)`):  "ADM$1",
	regexp.MustCompile(`Aes`):          "AES",
	regexp.MustCompile(`Api`):          "API",
	regexp.MustCompile(`Ami`):          "AMI",
	regexp.MustCompile(`Apns`):         "APNS",
	regexp.MustCompile(`Arn`):          "ARN",
	regexp.MustCompile(`Asn`):          "ASN",
	regexp.MustCompile(`Aws`):          "AWS",
	regexp.MustCompile(`Bcc([A-Z])`):   "BCC$1",
	regexp.MustCompile(`Bgp`):          "BGP",
	regexp.MustCompile(`Cc([A-Z])`):    "CC$1",
	regexp.MustCompile(`Cidr`):         "CIDR",
	regexp.MustCompile(`Cors`):         "CORS",
	regexp.MustCompile(`Csv`):          "CSV",
	regexp.MustCompile(`Cpu`):          "CPU",
	regexp.MustCompile(`Db`):           "DB",
	regexp.MustCompile(`Dhcp`):         "DHCP",
	regexp.MustCompile(`Dns`):          "DNS",
	regexp.MustCompile(`Ebs`):          "EBS",
	regexp.MustCompile(`Ec2`):          "EC2",
	regexp.MustCompile(`Eip`):          "EIP",
	regexp.MustCompile(`Gcm`):          "GCM",
	regexp.MustCompile(`Html`):         "HTML",
	regexp.MustCompile(`Https`):        "HTTPS",
	regexp.MustCompile(`Http([^s]|$)`): "HTTP$1",
	regexp.MustCompile(`Hsm`):          "HSM",
	regexp.MustCompile(`Hvm`):          "HVM",
	regexp.MustCompile(`Iam`):          "IAM",
	regexp.MustCompile(`Icmp`):         "ICMP",
	regexp.MustCompile(`Id$`):          "ID",
	regexp.MustCompile(`Id([A-Z])`):    "ID$1",
	regexp.MustCompile(`Idn`):          "IDN",
	regexp.MustCompile(`Ids$`):         "IDs",
	regexp.MustCompile(`Ids([A-Z])`):   "IDs$1",
	regexp.MustCompile(`Iops`):         "IOPS",
	regexp.MustCompile(`Ip`):           "IP",
	regexp.MustCompile(`Jar`):          "JAR",
	regexp.MustCompile(`Json`):         "JSON",
	regexp.MustCompile(`Jvm`):          "JVM",
	regexp.MustCompile(`Kms`):          "KMS",
	regexp.MustCompile(`Mac([^h]|$)`):  "MAC$1",
	regexp.MustCompile(`Md5`):          "MD5",
	regexp.MustCompile(`Mfa`):          "MFA",
	regexp.MustCompile(`Ok`):           "OK",
	regexp.MustCompile(`Os`):           "OS",
	regexp.MustCompile(`Php`):          "PHP",
	regexp.MustCompile(`Raid`):         "RAID",
	regexp.MustCompile(`Ramdisk`):      "RAMDisk",
	regexp.MustCompile(`Rds`):          "RDS",
	regexp.MustCompile(`Sni`):          "SNI",
	regexp.MustCompile(`Sns`):          "SNS",
	regexp.MustCompile(`Sriov`):        "SRIOV",
	regexp.MustCompile(`Ssh`):          "SSH",
	regexp.MustCompile(`Ssl`):          "SSL",
	regexp.MustCompile(`Svn`):          "SVN",
	regexp.MustCompile(`Tar([^g]|$)`):  "TAR$1",
	regexp.MustCompile(`Tde`):          "TDE",
	regexp.MustCompile(`Tcp`):          "TCP",
	regexp.MustCompile(`Tgz`):          "TGZ",
	regexp.MustCompile(`Tls`):          "TLS",
	regexp.MustCompile(`Uri`):          "URI",
	regexp.MustCompile(`Url`):          "URL",
	regexp.MustCompile(`Vgw`):          "VGW",
	regexp.MustCompile(`Vhd`):          "VHD",
	regexp.MustCompile(`Vip`):          "VIP",
	regexp.MustCompile(`Vlan`):         "VLAN",
	regexp.MustCompile(`Vm([^d]|$)`):   "VM$1",
	regexp.MustCompile(`Vmdk`):         "VMDK",
	regexp.MustCompile(`Vpc`):          "VPC",
	regexp.MustCompile(`Vpn`):          "VPN",
	regexp.MustCompile(`Xml`):          "XML",
}
<commit_msg>Update net/html package to golang.org format.<commit_after>package model

import (
	"bytes"
	"go/doc"
	"regexp"
	"strings"

	"golang.org/x/net/html"
	"github.com/aarzilli/sandblast"
)

func godoc(member, content string) string {
	undocumented := "// " + exportable(member) + " is undocumented.\n"

	node, err := html.Parse(strings.NewReader(content))
	if err != nil {
		return undocumented
	}

	_, v, err := sandblast.Extract(node)
	if err != nil {
		return undocumented
	}

	v = strings.TrimSpace(v)
	if v == "" {
		return undocumented
	}

	if member != "" {
		v = exportable(member) + " " + strings.ToLower(v[0:1]) + v[1:]
	}

	out := bytes.NewBuffer(nil)
	doc.ToText(out, v, "// ", "", 72)
	return out.String()
}

func exportable(name string) string {
	// make sure the symbol is exportable
	name = strings.ToUpper(name[0:1]) + name[1:]

	// fix common AWS<->Go bugaboos
	for regexp, repl := range replacements {
		name = regexp.ReplaceAllString(name, repl)
	}
	return name
}

var replacements = map[*regexp.Regexp]string{
	regexp.MustCompile(`Acl`):          "ACL",
	regexp.MustCompile(`Adm([^i]|$)`):  "ADM$1",
	regexp.MustCompile(`Aes`):          "AES",
	regexp.MustCompile(`Api`):          "API",
	regexp.MustCompile(`Ami`):          "AMI",
	regexp.MustCompile(`Apns`):         "APNS",
	regexp.MustCompile(`Arn`):          "ARN",
	regexp.MustCompile(`Asn`):          "ASN",
	regexp.MustCompile(`Aws`):          "AWS",
	regexp.MustCompile(`Bcc([A-Z])`):   "BCC$1",
	regexp.MustCompile(`Bgp`):          "BGP",
	regexp.MustCompile(`Cc([A-Z])`):    "CC$1",
	regexp.MustCompile(`Cidr`):         "CIDR",
	regexp.MustCompile(`Cors`):         "CORS",
	regexp.MustCompile(`Csv`):          "CSV",
	regexp.MustCompile(`Cpu`):          "CPU",
	regexp.MustCompile(`Db`):           "DB",
	regexp.MustCompile(`Dhcp`):         "DHCP",
	regexp.MustCompile(`Dns`):          "DNS",
	regexp.MustCompile(`Ebs`):          "EBS",
	regexp.MustCompile(`Ec2`):          "EC2",
	regexp.MustCompile(`Eip`):          "EIP",
	regexp.MustCompile(`Gcm`):          "GCM",
	regexp.MustCompile(`Html`):         "HTML",
	regexp.MustCompile(`Https`):        "HTTPS",
	regexp.MustCompile(`Http([^s]|$)`): "HTTP$1",
	regexp.MustCompile(`Hsm`):          "HSM",
	regexp.MustCompile(`Hvm`):          "HVM",
	regexp.MustCompile(`Iam`):          "IAM",
	regexp.MustCompile(`Icmp`):         "ICMP",
	regexp.MustCompile(`Id$`):          "ID",
	regexp.MustCompile(`Id([A-Z])`):    "ID$1",
	regexp.MustCompile(`Idn`):          "IDN",
	regexp.MustCompile(`Ids$`):         "IDs",
	regexp.MustCompile(`Ids([A-Z])`):   "IDs$1",
	regexp.MustCompile(`Iops`):         "IOPS",
	regexp.MustCompile(`Ip`):           "IP",
	regexp.MustCompile(`Jar`):          "JAR",
	regexp.MustCompile(`Json`):         "JSON",
	regexp.MustCompile(`Jvm`):          "JVM",
	regexp.MustCompile(`Kms`):          "KMS",
	regexp.MustCompile(`Mac([^h]|$)`):  "MAC$1",
	regexp.MustCompile(`Md5`):          "MD5",
	regexp.MustCompile(`Mfa`):          "MFA",
	regexp.MustCompile(`Ok`):           "OK",
	regexp.MustCompile(`Os`):           "OS",
	regexp.MustCompile(`Php`):          "PHP",
	regexp.MustCompile(`Raid`):         "RAID",
	regexp.MustCompile(`Ramdisk`):      "RAMDisk",
	regexp.MustCompile(`Rds`):          "RDS",
	regexp.MustCompile(`Sni`):          "SNI",
	regexp.MustCompile(`Sns`):          "SNS",
	regexp.MustCompile(`Sriov`):        "SRIOV",
	regexp.MustCompile(`Ssh`):          "SSH",
	regexp.MustCompile(`Ssl`):          "SSL",
	regexp.MustCompile(`Svn`):          "SVN",
	regexp.MustCompile(`Tar([^g]|$)`):  "TAR$1",
	regexp.MustCompile(`Tde`):          "TDE",
	regexp.MustCompile(`Tcp`):          "TCP",
	regexp.MustCompile(`Tgz`):          "TGZ",
	regexp.MustCompile(`Tls`):          "TLS",
	regexp.MustCompile(`Uri`):          "URI",
	regexp.MustCompile(`Url`):          "URL",
	regexp.MustCompile(`Vgw`):          "VGW",
	regexp.MustCompile(`Vhd`):          "VHD",
	regexp.MustCompile(`Vip`):          "VIP",
	regexp.MustCompile(`Vlan`):         "VLAN",
	regexp.MustCompile(`Vm([^d]|$)`):   "VM$1",
	regexp.MustCompile(`Vmdk`):         "VMDK",
	regexp.MustCompile(`Vpc`):          "VPC",
	regexp.MustCompile(`Vpn`):          "VPN",
	regexp.MustCompile(`Xml`):          "XML",
}
<|endoftext|>


<commit_before>package finder

import (
	"bytes"
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/lomik/graphite-clickhouse/config"
	"github.com/lomik/graphite-clickhouse/helper/clickhouse"
	"github.com/lomik/graphite-clickhouse/pkg/scope"
	"github.com/lomik/graphite-clickhouse/pkg/where"
)

const ReverseLevelOffset = 10000
const TreeLevelOffset = 20000
const ReverseTreeLevelOffset = 30000

const DefaultTreeDate = "1970-02-12"

const (
	queryAuto     = config.IndexAuto
	queryDirect   = config.IndexDirect
	queryReversed = config.IndexReversed
)

type IndexFinder struct {
	url          string             // clickhouse dsn
	table        string             // graphite_tree table
	opts         clickhouse.Options // timeout, connectTimeout
	dailyEnabled bool
	confReverse  uint8
	confReverses config.IndexReverses
	reverse      uint8  // calculated in IndexFinder.useReverse only once
	body         []byte // clickhouse response body
	useDaily     bool
}

func NewIndex(url string, table string, dailyEnabled bool, reverse string, reverses config.IndexReverses, opts clickhouse.Options) Finder {
	return &IndexFinder{
		url:          url,
		table:        table,
		opts:         opts,
		dailyEnabled: dailyEnabled,
		confReverse:  config.IndexReverse[reverse],
		confReverses: reverses,
	}
}

func (idx *IndexFinder) where(query string, levelOffset int) *where.Where {
	level := strings.Count(query, ".") + 1

	w := where.New()

	w.And(where.Eq("Level", level+levelOffset))
	w.And(where.TreeGlob("Path", query))

	return w
}

func (idx *IndexFinder) checkReverses(query string) uint8 {
	for _, rule := range idx.confReverses {
		if len(rule.Prefix) > 0 && !strings.HasPrefix(query, rule.Prefix) {
			continue
		}
		if len(rule.Suffix) > 0 && !strings.HasSuffix(query, rule.Suffix) {
			continue
		}
		if rule.Regex != nil && rule.Regex.FindStringIndex(query) == nil {
			continue
		}
		return config.IndexReverse[rule.Reverse]
	}
	return idx.confReverse
}

func (idx *IndexFinder) useReverse(query string) bool {
	if idx.reverse == queryDirect {
		return false
	} else if idx.reverse == queryReversed {
		return true
	}

	if idx.reverse = idx.checkReverses(query); idx.reverse != queryAuto {
		return idx.useReverse(query)
	}

	w := where.IndexWildcard(query)
	if w == -1 {
		idx.reverse = queryDirect
		return idx.useReverse(query)
	}
	firstWildcardNode := strings.Count(query[:w], ".")

	w = where.IndexLastWildcard(query)
	lastWildcardNode := strings.Count(query[w:], ".")

	if firstWildcardNode < lastWildcardNode {
		idx.reverse = queryReversed
		return idx.useReverse(query)
	}
	idx.reverse = queryDirect
	return idx.useReverse(query)
}

func (idx *IndexFinder) Execute(ctx context.Context, query string, from int64, until int64) (err error) {
	idx.useReverse(query)

	if idx.dailyEnabled && from > 0 && until > 0 {
		idx.useDaily = true
	} else {
		idx.useDaily = false
	}

	var levelOffset int
	if idx.useDaily {
		if idx.useReverse(query) {
			levelOffset = ReverseLevelOffset
		}
	} else {
		if idx.useReverse(query) {
			levelOffset = ReverseTreeLevelOffset
		} else {
			levelOffset = TreeLevelOffset
		}
	}

	if idx.useReverse(query) {
		query = ReverseString(query)
	}

	w := idx.where(query, levelOffset)

	if idx.useDaily {
		w.Andf(
			"Date >='%s' AND Date <= '%s'",
			time.Unix(from, 0).Format("2006-01-02"),
			time.Unix(until, 0).Format("2006-01-02"),
		)
	} else {
		w.And(where.Eq("Date", DefaultTreeDate))
	}

	idx.body, err = clickhouse.Query(
		scope.WithTable(ctx, idx.table),
		idx.url,
		fmt.Sprintf("SELECT Path FROM %s WHERE %s GROUP BY Path", idx.table, w),
		idx.opts,
		nil,
	)

	return
}

func (idx *IndexFinder) Abs(v []byte) []byte {
	return v
}

func (idx *IndexFinder) makeList(onlySeries bool) [][]byte {
	if idx.body == nil {
		return [][]byte{}
	}

	rows := bytes.Split(idx.body, []byte{'\n'})

	skip := 0
	for i := 0; i < len(rows); i++ {
		if len(rows[i]) == 0 {
			skip++
			continue
		}
		if onlySeries && rows[i][len(rows[i])-1] == '.' {
			skip++
			continue
		}
		if skip > 0 {
			rows[i-skip] = rows[i]
		}
	}

	rows = rows[:len(rows)-skip]

	if idx.useReverse("") {
		for i := 0; i < len(rows); i++ {
			rows[i] = ReverseBytes(rows[i])
		}
	}

	return rows
}

func (idx *IndexFinder) List() [][]byte {
	return idx.makeList(false)
}

func (idx *IndexFinder) Series() [][]byte {
	return idx.makeList(true)
}
<commit_msg>Update index.go<commit_after>package finder

import (
	"bytes"
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/lomik/graphite-clickhouse/config"
	"github.com/lomik/graphite-clickhouse/helper/clickhouse"
	"github.com/lomik/graphite-clickhouse/pkg/scope"
	"github.com/lomik/graphite-clickhouse/pkg/where"
)

const ReverseLevelOffset = 10000
const TreeLevelOffset = 20000
const ReverseTreeLevelOffset = 30000

const DefaultTreeDate = "1970-02-12"

const (
	queryAuto     = config.IndexAuto
	queryDirect   = config.IndexDirect
	queryReversed = config.IndexReversed
)

type IndexFinder struct {
	url          string             // clickhouse dsn
	table        string             // graphite_tree table
	opts         clickhouse.Options // timeout, connectTimeout
	dailyEnabled bool
	confReverse  uint8
	confReverses config.IndexReverses
	reverse      uint8  // calculated in IndexFinder.useReverse only once
	body         []byte // clickhouse response body
	useDaily     bool
}

func NewIndex(url string, table string, dailyEnabled bool, reverse string, reverses config.IndexReverses, opts clickhouse.Options) Finder {
	return &IndexFinder{
		url:          url,
		table:        table,
		opts:         opts,
		dailyEnabled: dailyEnabled,
		confReverse:  config.IndexReverse[reverse],
		confReverses: reverses,
	}
}

func (idx *IndexFinder) where(query string, levelOffset int) *where.Where {
	level := strings.Count(query, ".") + 1

	w := where.New()

	w.And(where.Eq("Level", level+levelOffset))
	w.And(where.TreeGlob("Path", query))

	return w
}

func (idx *IndexFinder) checkReverses(query string) uint8 {
	for _, rule := range idx.confReverses {
		if len(rule.Prefix) > 0 && !strings.HasPrefix(query, rule.Prefix) {
			continue
		}
		if len(rule.Suffix) > 0 && !strings.HasSuffix(query, rule.Suffix) {
			continue
		}
		if rule.Regex != nil && rule.Regex.FindStringIndex(query) == nil {
			continue
		}
		return config.IndexReverse[rule.Reverse]
	}
	return idx.confReverse
}

func (idx *IndexFinder) useReverse(query string) bool {
	if idx.reverse == queryDirect {
		return false
	} else if idx.reverse == queryReversed {
		return true
	}

	if idx.reverse = idx.checkReverses(query); idx.reverse != queryAuto {
		return idx.useReverse(query)
	}

	w := where.IndexWildcard(query)
	if w == -1 {
		idx.reverse = queryDirect
		return idx.useReverse(query)
	}
	firstWildcardNode := strings.Count(query[:w], ".")

	w = where.IndexLastWildcard(query)
	lastWildcardNode := strings.Count(query[w:], ".")

	if firstWildcardNode < lastWildcardNode {
		idx.reverse = queryReversed
		return idx.useReverse(query)
	}
	idx.reverse = queryDirect
	return idx.useReverse(query)
}

func (idx *IndexFinder) Execute(ctx context.Context, query string, from int64, until int64) (err error) {
	idx.useReverse(query)

	if idx.dailyEnabled && from > 0 && until > 0 {
		idx.useDaily = true
	} else {
		idx.useDaily = false
	}

	var levelOffset int
	if idx.useDaily {
		if idx.useReverse(query) {
			levelOffset = ReverseLevelOffset
		}
	} else {
		if idx.useReverse(query) {
			levelOffset = ReverseTreeLevelOffset
		} else {
			levelOffset = TreeLevelOffset
		}
	}

	if idx.useReverse(query) {
		query = ReverseString(query)
	}

	w := idx.where(query, levelOffset)

	if idx.useDaily {
		w.Andf(
			"Date >='%s' AND Date <= '%s'",
			time.Unix(from, 0).Format("2006-01-02"),
			time.Unix(until, 0).Format("2006-01-02"),
		)
	} else {
		w.And(where.Eq("Date", DefaultTreeDate))
	}

	idx.body, err = clickhouse.Query(
		scope.WithTable(ctx, idx.table),
		idx.url,
		fmt.Sprintf("SELECT Path FROM %s WHERE %s GROUP BY Path FORMAT TabSeparatedRaw", idx.table, w),
		idx.opts,
		nil,
	)

	return
}

func (idx *IndexFinder) Abs(v []byte) []byte {
	return v
}

func (idx *IndexFinder) makeList(onlySeries bool) [][]byte {
	if idx.body == nil {
		return [][]byte{}
	}

	rows := bytes.Split(idx.body, []byte{'\n'})

	skip := 0
	for i := 0; i < len(rows); i++ {
		if len(rows[i]) == 0 {
			skip++
			continue
		}
		if onlySeries && rows[i][len(rows[i])-1] == '.' {
			skip++
			continue
		}
		if skip > 0 {
			rows[i-skip] = rows[i]
		}
	}

	rows = rows[:len(rows)-skip]

	if idx.useReverse("") {
		for i := 0; i < len(rows); i++ {
			rows[i] = ReverseBytes(rows[i])
		}
	}

	return rows
}

func (idx *IndexFinder) List() [][]byte {
	return idx.makeList(false)
}

func (idx *IndexFinder) Series() [][]byte {
	return idx.makeList(true)
}
<|endoftext|>


<commit_before>package core

import (
	"errors"
	"github.com/jinzhu/gorm"
	"github.com/toorop/tmail/scope"
	"net"
	"strings"
)

// relayOkIp represents an IP that can use SMTP for relaying
type RelayIpOk struct {
	Id int64
	Ip string `sql:"unique"`
}

// remoteIpCanUseSmtp checks if an IP can relay
func IpCanRelay(ip net.Addr) (bool, error) {
	err := scope.DB.Where("addr = ?", ip.String()[:strings.Index(ip.String(), ":")]).Find(&RelayIpOk{}).Error
	if err == nil {
		return true, nil
	}
	if err != gorm.RecordNotFound {
		return false, err
	}
	return false, nil
}

// relayipAdd authorize IP to relay through tmail
func RelayIpAdd(ip string) error {
	// input validation
	if net.ParseIP(ip) == nil {
		return errors.New("Invalid IP: " + ip)
	}
	rip := RelayIpOk{
		Ip: ip,
	}
	return scope.DB.Save(&rip).Error
}

// RelayIpList return all IPs authorized to relay through tmail
func RelayIpGetAll() (ips []RelayIpOk, err error) {
	ips = []RelayIpOk{}
	err = scope.DB.Find(&ips).Error
	return
}

// RelayIpDel remove ip from authorized IP
func RelayIpDel(ip string) error {
	// input validation
	if net.ParseIP(ip) == nil {
		return errors.New("Invalid IP: " + ip)
	}
	return scope.DB.Where("ip = ?", ip).Delete(&RelayIpOk{}).Error
}
<commit_msg>bugfix ip vs addr<commit_after>package core

import (
	"errors"
	"github.com/jinzhu/gorm"
	"github.com/toorop/tmail/scope"
	"net"
	"strings"
)

// relayOkIp represents an IP that can use SMTP for relaying
type RelayIpOk struct {
	Id int64
	Ip string `sql:"unique"`
}

// remoteIpCanUseSmtp checks if an IP can relay
func IpCanRelay(ip net.Addr) (bool, error) {
	err := scope.DB.Where("ip = ?", ip.String()[:strings.Index(ip.String(), ":")]).Find(&RelayIpOk{}).Error
	if err == nil {
		return true, nil
	}
	if err != gorm.RecordNotFound {
		return false, err
	}
	return false, nil
}

// relayipAdd authorize IP to relay through tmail
func RelayIpAdd(ip string) error {
	// input validation
	if net.ParseIP(ip) == nil {
		return errors.New("Invalid IP: " + ip)
	}
	rip := RelayIpOk{
		Ip: ip,
	}
	return scope.DB.Save(&rip).Error
}

// RelayIpList return all IPs authorized to relay through tmail
func RelayIpGetAll() (ips []RelayIpOk, err error) {
	ips = []RelayIpOk{}
	err = scope.DB.Find(&ips).Error
	return
}

// RelayIpDel remove ip from authorized IP
func RelayIpDel(ip string) error {
	// input validation
	if net.ParseIP(ip) == nil {
		return errors.New("Invalid IP: " + ip)
	}
	return scope.DB.Where("ip = ?", ip).Delete(&RelayIpOk{}).Error
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

// [START admin_import]
import (
	"log"

	"golang.org/x/net/context"

	firebase "firebase.google.com/go"
	"firebase.google.com/go/auth"

	"google.golang.org/api/option"
)

// [END admin_import]

// ==================================================================
// https://firebase.google.com/docs/admin/setup
// ==================================================================

func initializeAppWithServiceAccount() *firebase.App {
	// [START initialize_app_service_account]
	opt := option.WithCredentialsFile("path/to/serviceAccountKey.json")
	app, err := firebase.NewApp(context.Background(), nil, opt)
	if err != nil {
		log.Fatalf("error initializing app: %v\n", err)
	}
	// [END initialize_app_service_account]

	return app
}

func initializeAppWithRefreshToken() *firebase.App {
	// [START initialize_app_refresh_token]
	opt := option.WithCredentialsFile("path/to/refreshToken.json")
	config := &firebase.Config{ProjectID: "my-project-id"}
	app, err := firebase.NewApp(context.Background(), config, opt)
	if err != nil {
		log.Fatalf("error initializing app: %v\n", err)
	}
	// [END initialize_app_refresh_token]

	return app
}

func initializeAppDefault() *firebase.App {
	// [START initialize_app_default]
	app, err := firebase.NewApp(context.Background(), nil)
	if err != nil {
		log.Fatalf("error initializing app: %v\n", err)
	}
	// [END initialize_app_default]

	return app
}

func accessServicesSingleApp() (*auth.Client, error) {
	// [START access_services_single_app]
	// Initialize default app
	app, err := firebase.NewApp(context.Background(), nil)
	if err != nil {
		log.Fatalf("error initializing app: %v\n", err)
	}

	// Access auth service from the default app
	client, err := app.Auth(context.Background())
	if err != nil {
		log.Fatalf("error getting Auth client: %v\n", err)
	}
	// [END access_services_single_app]

	return client, err
}

func accessServicesMultipleApp() (*auth.Client, error) {
	// [START access_services_multiple_app]
	// Initialize the default app
	defaultApp, err := firebase.NewApp(context.Background(), nil)
	if err != nil {
		log.Fatalf("error initializing app: %v\n", err)
	}

	// Initialize another app with a different config
	opt := option.WithCredentialsFile("service-account-other.json")
	otherApp, err := firebase.NewApp(context.Background(), nil, opt)
	if err != nil {
		log.Fatalf("error initializing app: %v\n", err)
	}

	// Access Auth service from default app
	defaultClient, err := defaultApp.Auth(context.Background())
	if err != nil {
		log.Fatalf("error getting Auth client: %v\n", err)
	}

	// Access auth service from other app
	otherClient, err := otherApp.Auth(context.Background())
	if err != nil {
		log.Fatalf("error getting Auth client: %v\n", err)
	}
	// [END access_services_multiple_app]
	// Avoid unused
	_ = defaultClient
	return otherClient, nil
}

// ==================================================================
// https://firebase.google.com/docs/auth/admin/create-custom-tokens
// ==================================================================

func createCustomToken(app *firebase.App) string {
	// [START create_custom_token]
	client, err := app.Auth(context.Background())
	if err != nil {
		log.Fatalf("error getting Auth client: %v\n", err)
	}

	token, err := client.CustomToken("some-uid")
	if err != nil {
		log.Fatalf("error minting custom token: %v\n", err)
	}

	log.Printf("Got custom token: %v\n", token)
	// [END create_custom_token]

	return token
}

func createCustomTokenWithClaims(app *firebase.App) string {
	// [START create_custom_token_claims]
	client, err := app.Auth(context.Background())
	if err != nil {
		log.Fatalf("error getting Auth client: %v\n", err)
	}

	claims := map[string]interface{}{
		"premiumAccount": true,
	}

	token, err := client.CustomTokenWithClaims("some-uid", claims)
	if err != nil {
		log.Fatalf("error minting custom token: %v\n", err)
	}

	log.Printf("Got custom token: %v\n", token)
	// [END create_custom_token_claims]

	return token
}

// ==================================================================
// https://firebase.google.com/docs/auth/admin/verify-id-tokens
// ==================================================================

func verifyIDToken(app *firebase.App, idToken string) *auth.Token {
	// [START verify_id_token]
	client, err := app.Auth(context.Background())
	if err != nil {
		log.Fatalf("error getting Auth client: %v\n", err)
	}

	token, err := client.VerifyIDToken(idToken)
	if err != nil {
		log.Fatalf("error verifying ID token: %v\n", err)
	}

	log.Printf("Verified ID token: %v\n", token)
	// [END verify_id_token]

	return token
}

// ==================================================================
// https://firebase.google.com/docs/storage/admin/start
// ==================================================================

func cloudStorage() {
	// [START cloud_storage]
	config := &firebase.Config{
		StorageBucket: "<BUCKET_NAME>.appspot.com",
	}
	opt := option.WithCredentialsFile("path/to/serviceAccountKey.json")
	app, err := firebase.NewApp(context.Background(), config, opt)
	if err != nil {
		log.Fatalln(err)
	}

	client, err := app.Storage(context.Background())
	if err != nil {
		log.Fatalln(err)
	}

	bucket, err := client.DefaultBucket()
	if err != nil {
		log.Fatalln(err)
	}
	// 'bucket' is an object defined in the cloud.google.com/go/storage package.
	// See https://godoc.org/cloud.google.com/go/storage#BucketHandle
	// for more details.
	// [END cloud_storage]

	log.Printf("Created bucket handle: %v\n", bucket)
}

func cloudStorageCustomBucket(app *firebase.App) {
	client, err := app.Storage(context.Background())
	if err != nil {
		log.Fatalln(err)
	}

	// [START cloud_storage_custom_bucket]
	bucket, err := client.Bucket("my-custom-bucket")
	// [END cloud_storage_custom_bucket]
	if err != nil {
		log.Fatalln(err)
	}
	log.Printf("Created bucket handle: %v\n", bucket)
}

func main() {
	app := initializeAppWithServiceAccount()

	_ = createCustomToken(app)
	_ = createCustomTokenWithClaims(app)
	_ = verifyIDToken(app, "some-token")
	cloudStorage()
	cloudStorageCustomBucket(app)
}
<commit_msg>Revert "Updated sample snippets to the latest Auth() API"<commit_after>// Copyright 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

// [START admin_import]
import (
	"fmt"

	"golang.org/x/net/context"

	firebase "firebase.google.com/go"
	"firebase.google.com/go/auth"

	"google.golang.org/api/option"
)

// [END admin_import]

// ==================================================================
// https://firebase.google.com/docs/admin/setup
// ==================================================================

func initializeAppWithServiceAccount() (*firebase.App, error) {
	// [START initialize_app_service_account]
	opt := option.WithCredentialsFile("path/to/serviceAccountKey.json")
	app, err := firebase.NewApp(context.Background(), nil, opt)
	if err != nil {
		return nil, fmt.Errorf("error initializing app: %v", err)
	}
	// [END initialize_app_service_account]

	return app, nil
}

func initializeAppWithRefreshToken() (*firebase.App, error) {
	// [START initialize_app_refresh_token]
	opt := option.WithCredentialsFile("path/to/refreshToken.json")
	config := &firebase.Config{ProjectID: "my-project-id"}
	app, err := firebase.NewApp(context.Background(), config, opt)
	if err != nil {
		return nil, fmt.Errorf("error initializing app: %v", err)
	}
	// [END initialize_app_refresh_token]

	return app, nil
}

func initializeAppDefault() (*firebase.App, error) {
	// [START initialize_app_default]
	app, err := firebase.NewApp(context.Background(), nil)
	if err != nil {
		return nil, fmt.Errorf("error initializing app: %v", err)
	}
	// [END initialize_app_default]

	return app, nil
}

func accessServicesSingleApp() (*auth.Client, error) {
	// [START access_services_single_app]
	// Initialize default app
	app, err := firebase.NewApp(context.Background(), nil)
	if err != nil {
		return nil, fmt.Errorf("error initializing app: %v", err)
	}

	// Access auth service from the default app
	client, err := app.Auth()
	if err != nil {
		return nil, fmt.Errorf("error getting Auth client: %v", err)
	}
	// [END access_services_single_app]

	return client, err
}

func accessServicesMultipleApp() (*auth.Client, error) {
	// [START access_services_multiple_app]
	// Initialize the default app
	defaultApp, err := firebase.NewApp(context.Background(), nil)
	if err != nil {
		return nil, fmt.Errorf("error initializing app: %v", err)
	}

	// Initialize another app with a different config
	opt := option.WithCredentialsFile("service-account-other.json")
	otherApp, err := firebase.NewApp(context.Background(), nil, opt)
	if err != nil {
		return nil, fmt.Errorf("error initializing app: %v", err)
	}

	// Access Auth service from default app
	defaultClient, err := defaultApp.Auth()
	if err != nil {
		return nil, fmt.Errorf("error getting Auth client: %v", err)
	}

	// Access auth service from other app
	otherClient, err := otherApp.Auth()
	if err != nil {
		return nil, fmt.Errorf("error getting Auth client: %v", err)
	}
	// [END access_services_multiple_app]

	// Avoid unused
	_ = defaultClient
	return otherClient, nil
}

// ==================================================================
// https://firebase.google.com/docs/auth/admin/create-custom-tokens
// ==================================================================

func createCustomToken(app *firebase.App) (string, error) {
	// [START create_custom_token]
	client, err := app.Auth()
	if err != nil {
		return "", fmt.Errorf("error getting Auth client: %v", err)
	}

	token, err := client.CustomToken("some-uid")
	if err != nil {
		return "", fmt.Errorf("error minting custom token: %v", err)
	}

	fmt.Printf("Got custom token: %v\n", token)
	// [END create_custom_token]

	return token, nil
}

func createCustomTokenWithClaims(app *firebase.App) (string, error) {
	// [START create_custom_token_claims]
	client, err := app.Auth()
	if err != nil {
		return "", fmt.Errorf("error getting Auth client: %v", err)
	}

	claims := map[string]interface{}{
		"premiumAccount": true,
	}

	token, err := client.CustomTokenWithClaims("some-uid", claims)
	if err != nil {
		return "", fmt.Errorf("error minting custom token: %v", err)
	}

	fmt.Printf("Got custom token: %v\n", token)
	// [END create_custom_token_claims]

	return token, nil
}

// ==================================================================
// https://firebase.google.com/docs/auth/admin/verify-id-tokens
// ==================================================================

func verifyIDToken(app *firebase.App, idToken string) (*auth.Token, error) {
	// [START verify_id_token]
	client, err := app.Auth()
	if err != nil {
		return nil, fmt.Errorf("error getting Auth client: %v", err)
	}

	token, err := client.VerifyIDToken(idToken)
	if err != nil {
		return nil, fmt.Errorf("error verifying ID token: %v", err)
	}

	fmt.Printf("Verified ID token: %v\n", token)
	// [END verify_id_token]

	return token, nil
}

func main() {
	app, err := initializeAppWithServiceAccount()
	if err != nil {
		fmt.Printf("error initializing app: %v\n", err)
		return
	}

	_, err = createCustomToken(app)
	if err != nil {
		fmt.Printf("Error in createCustomToken: %v\n", err)
	}

	_, err = createCustomTokenWithClaims(app)
	if err != nil {
		fmt.Printf("Error in createCustomTokenWithClaims: %v\n", err)
	}

	_, err = verifyIDToken(app, "some-token")
	if err != nil {
		fmt.Printf("Error in verifyIDToken: %v\n", err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2013 Matthew Baird
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//     http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package elastigo

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strings"
)

type Mapping map[string]MappingOptions

type MappingOptions struct {
	Id         IdOptions              `json:"_id"`
	Timestamp  TimestampOptions       `json:"_timestamp"`
	Analyzer   *AnalyzerOptions        `json:"_analyzer,omitempty"`
	Parent     *ParentOptions          `json:"_parent,omitempty"`
	Routing    *RoutingOptions         `json:"_routing,omitempty"`
	Size       *SizeOptions            `json:"_size,omitempty"`
	Source     *SourceOptions          `json:"_source,omitempty"`
	Type       *TypeOptions            `json:"_type,omitempty"`
	Properties map[string]interface{} `json:"properties"`
}

type TimestampOptions struct {
	Enabled bool `json:"enabled"`
}

type AnalyzerOptions struct {
	Path  string `json:"path,omitempty"`
	Index string `json:"index,omitempty"`
}

type ParentOptions struct {
	Type string `json:"type"`
}

type RoutingOptions struct {
	Required bool   `json:"required,omitempty"`
	Path     string `json:"path,omitempty"`
}

type SizeOptions struct {
	Enabled bool `json:"enabled,omitempty"`
	Store   bool `json:"store,omitempty"`
}

type SourceOptions struct {
	Enabled  bool     `json:"enabled,omitempty"`
	Includes []string `json:"includes,omitempty"`
	Excludes []string `json:"excludes,omitempty"`
}

type TypeOptions struct {
	Store bool   `json:"store,omitempty"`
	Index string `json:"index,omitempty"`
}

type IdOptions struct {
	Index string `json:"index,omitempty"`
	Path  string `json:"path,omitempty"`
}

func (m_ Mapping) Options() MappingOptions {
	m := map[string]MappingOptions(m_)
	for _, v := range m {
		return v
	}
	panic(fmt.Errorf("Malformed input: %v", m_))
}

func MappingForType(typeName string, opts MappingOptions) Mapping {
	return map[string]MappingOptions{typeName: opts}
}

func (c *Conn) PutMapping(index string, typeName string, instance interface{}, opt MappingOptions) error {
	instanceType := reflect.TypeOf(instance)
	if instanceType.Kind() != reflect.Struct {
		return fmt.Errorf("instance kind was not struct")
	}

	if opt.Properties == nil {
		opt.Properties = make(map[string]interface{})
	}
	getProperties(instanceType, opt.Properties)
	body, err := json.Marshal(MappingForType(typeName, opt))
	if err != nil {
		return err
	}
	_, err = c.DoCommand("PUT", fmt.Sprintf("/%s/%s/_mapping", index, typeName), nil, string(body))
	if err != nil {
		return err
	}

	return nil
}

func getProperties(t reflect.Type, prop map[string]interface{}) {
	n := t.NumField()
	for i := 0; i < n; i++ {
		field := t.Field(i)

		name := strings.Split(field.Tag.Get("json"), ",")[0]
		if name == "-" {
			continue
		} else if name == "" {
			name = field.Name
		}

		attrMap := make(map[string]interface{})
		attrs := splitTag(field.Tag.Get("elastic"))
		for _, attr := range attrs {
			keyvalue := strings.Split(attr, ":")
			attrMap[keyvalue[0]] = keyvalue[1]
		}

		if len(attrMap) == 0 || attrMap["type"] == "nested" {

			// We are looking for tags on any inner struct, independently of
			// whether the field is a struct, a pointer to struct, or a slice of structs
			targetType := field.Type
			if targetType.Kind() == reflect.Ptr ||
				targetType.Kind() == reflect.Slice {
				targetType = field.Type.Elem()
			}
			if targetType.Kind() == reflect.Struct {
				if field.Anonymous {
					getProperties(targetType, prop)
				} else {
					innerStructProp := make(map[string]interface{})
					getProperties(targetType, innerStructProp)
					attrMap["properties"] = innerStructProp
				}
			}
		}
		if len(attrMap) != 0 {
			prop[name] = attrMap
		}
	}
}

func splitTag(tag string) []string {
	tag = strings.Trim(tag, " ")
	if tag == "" {
		return []string{}
	} else {
		return strings.Split(tag, ",")
	}
}
<commit_msg>indicesputmappings formating updated using gofmt<commit_after>// Copyright 2013 Matthew Baird
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//     http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package elastigo

import (
	"encoding/json"
	"fmt"
	"reflect"
	"strings"
)

type Mapping map[string]MappingOptions

type MappingOptions struct {
	Id         IdOptions              `json:"_id"`
	Timestamp  TimestampOptions       `json:"_timestamp"`
	Analyzer   *AnalyzerOptions       `json:"_analyzer,omitempty"`
	Parent     *ParentOptions         `json:"_parent,omitempty"`
	Routing    *RoutingOptions        `json:"_routing,omitempty"`
	Size       *SizeOptions           `json:"_size,omitempty"`
	Source     *SourceOptions         `json:"_source,omitempty"`
	Type       *TypeOptions           `json:"_type,omitempty"`
	Properties map[string]interface{} `json:"properties"`
}

type TimestampOptions struct {
	Enabled bool `json:"enabled"`
}

type AnalyzerOptions struct {
	Path  string `json:"path,omitempty"`
	Index string `json:"index,omitempty"`
}

type ParentOptions struct {
	Type string `json:"type"`
}

type RoutingOptions struct {
	Required bool   `json:"required,omitempty"`
	Path     string `json:"path,omitempty"`
}

type SizeOptions struct {
	Enabled bool `json:"enabled,omitempty"`
	Store   bool `json:"store,omitempty"`
}

type SourceOptions struct {
	Enabled  bool     `json:"enabled,omitempty"`
	Includes []string `json:"includes,omitempty"`
	Excludes []string `json:"excludes,omitempty"`
}

type TypeOptions struct {
	Store bool   `json:"store,omitempty"`
	Index string `json:"index,omitempty"`
}

type IdOptions struct {
	Index string `json:"index,omitempty"`
	Path  string `json:"path,omitempty"`
}

func (m_ Mapping) Options() MappingOptions {
	m := map[string]MappingOptions(m_)
	for _, v := range m {
		return v
	}
	panic(fmt.Errorf("Malformed input: %v", m_))
}

func MappingForType(typeName string, opts MappingOptions) Mapping {
	return map[string]MappingOptions{typeName: opts}
}

func (c *Conn) PutMapping(index string, typeName string, instance interface{}, opt MappingOptions) error {
	instanceType := reflect.TypeOf(instance)
	if instanceType.Kind() != reflect.Struct {
		return fmt.Errorf("instance kind was not struct")
	}

	if opt.Properties == nil {
		opt.Properties = make(map[string]interface{})
	}
	getProperties(instanceType, opt.Properties)
	body, err := json.Marshal(MappingForType(typeName, opt))
	if err != nil {
		return err
	}
	_, err = c.DoCommand("PUT", fmt.Sprintf("/%s/%s/_mapping", index, typeName), nil, string(body))
	if err != nil {
		return err
	}

	return nil
}

func getProperties(t reflect.Type, prop map[string]interface{}) {
	n := t.NumField()
	for i := 0; i < n; i++ {
		field := t.Field(i)

		name := strings.Split(field.Tag.Get("json"), ",")[0]
		if name == "-" {
			continue
		} else if name == "" {
			name = field.Name
		}

		attrMap := make(map[string]interface{})
		attrs := splitTag(field.Tag.Get("elastic"))
		for _, attr := range attrs {
			keyvalue := strings.Split(attr, ":")
			attrMap[keyvalue[0]] = keyvalue[1]
		}

		if len(attrMap) == 0 || attrMap["type"] == "nested" {

			// We are looking for tags on any inner struct, independently of
			// whether the field is a struct, a pointer to struct, or a slice of structs
			targetType := field.Type
			if targetType.Kind() == reflect.Ptr ||
				targetType.Kind() == reflect.Slice {
				targetType = field.Type.Elem()
			}
			if targetType.Kind() == reflect.Struct {
				if field.Anonymous {
					getProperties(targetType, prop)
				} else {
					innerStructProp := make(map[string]interface{})
					getProperties(targetType, innerStructProp)
					attrMap["properties"] = innerStructProp
				}
			}
		}
		if len(attrMap) != 0 {
			prop[name] = attrMap
		}
	}
}

func splitTag(tag string) []string {
	tag = strings.Trim(tag, " ")
	if tag == "" {
		return []string{}
	} else {
		return strings.Split(tag, ",")
	}
}
<|endoftext|>


<commit_before>// +build linux darwin freebsd

package xattr

import (
	"io/ioutil"
	"os"
	"testing"
)

const UserPrefix = "user."

func Test_setxattr(t *testing.T) {
	tmp, err := ioutil.TempFile("", "")

	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(tmp.Name())

	err = Setxattr(tmp.Name(), UserPrefix+"test", []byte("test-attr-value"))
	if err != nil {
		t.Fatal(err)
	}

	var data []byte
	data, err = Getxattr(tmp.Name(), UserPrefix+"test")
	if err != nil {
		t.Fatal(err)
	}
	value := string(data)
	t.Log(value)
	if "test-attr-value" != value {
		t.Fail()
	}
}
<commit_msg>Add test for Listxattr and Removexattr<commit_after>// +build linux darwin freebsd

package xattr

import (
	"io/ioutil"
	"os"
	"testing"
)

const UserPrefix = "user."

func Test_setxattr(t *testing.T) {
	tmp, err := ioutil.TempFile("", "")

	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(tmp.Name())

	err = Setxattr(tmp.Name(), UserPrefix+"test", []byte("test-attr-value"))
	if err != nil {
		t.Fatal(err)
	}

	list, err := Listxattr(tmp.Name())
	if err != nil {
		t.Fatal(err)
	}

	found := false
	for _, name := range list {
		if name == UserPrefix+"test" {
			found = true
		}
	}

	if !found {
		t.Fatal("Listxattr did not return test attribute")
	}

	var data []byte
	data, err = Getxattr(tmp.Name(), UserPrefix+"test")
	if err != nil {
		t.Fatal(err)
	}
	value := string(data)
	t.Log(value)
	if "test-attr-value" != value {
		t.Fail()
	}

	err = Removexattr(tmp.Name(), UserPrefix+"test")
	if err != nil {
		t.Fatal(err)
	}
}
<|endoftext|>


<commit_before>/*!
 * Copyright 2014 Sam Alba <sam.alba@gmail.com>
 * Licensed under the Apache License, Version 2.0
 * github.com/samalba/dockerclient/LICENSE
 *
 * github.com/samalba/dockerclient/dockerclient.go
 */

package api

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

const (
	API_VERSION = "1.15"
)

type DockerClient struct {
	URL           *url.URL
	HTTPClient    *http.Client
	TLSConfig     *tls.Config
	monitorEvents int32
	out           io.Writer
}

type Error struct {
	StatusCode int
	Status     string
	msg        string
}

func (e Error) Error() string {
	return fmt.Sprintf("Error response from daemon: %s", strings.TrimSpace(e.msg))
}

func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration) *http.Client {
	httpTransport := &http.Transport{
		TLSClientConfig: tlsConfig,
	}

	switch u.Scheme {
	default:
		httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
			return net.DialTimeout(proto, addr, timeout)
		}
	case "unix":
		socketPath := u.Path
		unixDial := func(proto, addr string) (net.Conn, error) {
			return net.DialTimeout("unix", socketPath, timeout)
		}
		httpTransport.Dial = unixDial
		// Override the main URL object so the HTTP lib won't complain
		u.Scheme = "http"
		u.Host = "unix.sock"
		u.Path = ""
	}
	return &http.Client{Transport: httpTransport}
}

func NewDockerClient(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration, out io.Writer) (*DockerClient, error) {
	u, err := url.Parse(daemonUrl)
	if err != nil {
		return nil, err
	}
	if u.Scheme == "tcp" {
		if tlsConfig == nil {
			u.Scheme = "http"
		} else {
			u.Scheme = "https"
		}
	}
	httpClient := newHTTPClient(u, tlsConfig, timeout)
	return &DockerClient{u, httpClient, tlsConfig, 0, out}, nil
}

func (client *DockerClient) doRequest(method string, path string, body []byte, headers map[string]string) ([]byte, error) {
	b := bytes.NewBuffer(body)
	req, err := http.NewRequest(method, client.URL.String()+path, b)
	if err != nil {
		return nil, err
	}
	req.Header.Add("Content-Type", "application/json")
	if headers != nil {
		for header, value := range headers {
			req.Header.Add(header, value)
		}
	}
	resp, err := client.HTTPClient.Do(req)
	if err != nil {
		if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
			return nil, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
		}
		return nil, err
	}
	defer resp.Body.Close()

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		return nil, Error{StatusCode: resp.StatusCode, Status: resp.Status, msg: string(data)}
	}
	return data, nil
}

func (client *DockerClient) doStreamRequest(method string, path string, in io.Reader, headers map[string]string, quiet bool) (string, error) {
	if (method == "POST" || method == "PUT") && in == nil {
		in = bytes.NewReader([]byte{})
	}

	req, err := http.NewRequest(method, client.URL.String()+path, in)
	if err != nil {
		return "", err
	}
	req.Header.Add("Content-Type", "application/json")
	if headers != nil {
		for header, value := range headers {
			req.Header.Add(header, value)
		}
	}
	resp, err := client.HTTPClient.Do(req)
	if err != nil {
		if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
			return "", fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
		}
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "", err
		}
		if len(body) == 0 {
			return "", fmt.Errorf("Error :%s", http.StatusText(resp.StatusCode))
		}
		return "", fmt.Errorf("Error: %s", bytes.TrimSpace(body))
	}

	mimetype, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
	if err == nil && mimetype == "application/json" {
		out := client.out
		if quiet {
			f, err := os.Open(os.DevNull)
			if err == nil {
				out = f
			} else {
				quiet = false
			}
		}
		message, err := displayJSONMessagesStream(resp.Body, out)
		if quiet && (message != "") {
			fmt.Fprintf(client.out, "%s", message)
		}
		return message, err
	}

	_, err = io.Copy(client.out, resp.Body)
	return "", err
}
<commit_msg>Add NLs<commit_after>/*!
 * Copyright 2014 Sam Alba <sam.alba@gmail.com>
 * Licensed under the Apache License, Version 2.0
 * github.com/samalba/dockerclient/LICENSE
 *
 * github.com/samalba/dockerclient/dockerclient.go
 */

package api

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

const (
	API_VERSION = "1.15"
)

type DockerClient struct {
	URL           *url.URL
	HTTPClient    *http.Client
	TLSConfig     *tls.Config
	monitorEvents int32
	out           io.Writer
}

type Error struct {
	StatusCode int
	Status     string
	msg        string
}

func (e Error) Error() string {
	return fmt.Sprintf("Error response from daemon: %s", strings.TrimSpace(e.msg))
}

func newHTTPClient(u *url.URL, tlsConfig *tls.Config, timeout time.Duration) *http.Client {
	httpTransport := &http.Transport{
		TLSClientConfig: tlsConfig,
	}

	switch u.Scheme {
	default:
		httpTransport.Dial = func(proto, addr string) (net.Conn, error) {
			return net.DialTimeout(proto, addr, timeout)
		}
	case "unix":
		socketPath := u.Path
		unixDial := func(proto, addr string) (net.Conn, error) {
			return net.DialTimeout("unix", socketPath, timeout)
		}
		httpTransport.Dial = unixDial
		// Override the main URL object so the HTTP lib won't complain
		u.Scheme = "http"
		u.Host = "unix.sock"
		u.Path = ""
	}
	return &http.Client{Transport: httpTransport}
}

func NewDockerClient(daemonUrl string, tlsConfig *tls.Config, timeout time.Duration, out io.Writer) (*DockerClient, error) {
	u, err := url.Parse(daemonUrl)
	if err != nil {
		return nil, err
	}

	if u.Scheme == "tcp" {
		if tlsConfig == nil {
			u.Scheme = "http"
		} else {
			u.Scheme = "https"
		}
	}

	httpClient := newHTTPClient(u, tlsConfig, timeout)

	return &DockerClient{u, httpClient, tlsConfig, 0, out}, nil
}

func (client *DockerClient) doRequest(method string, path string, body []byte, headers map[string]string) ([]byte, error) {
	b := bytes.NewBuffer(body)

	req, err := http.NewRequest(method, client.URL.String()+path, b)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Content-Type", "application/json")
	if headers != nil {
		for header, value := range headers {
			req.Header.Add(header, value)
		}
	}

	resp, err := client.HTTPClient.Do(req)
	if err != nil {
		if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
			return nil, fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
		}
		return nil, err
	}
	defer resp.Body.Close()

	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		return nil, Error{StatusCode: resp.StatusCode, Status: resp.Status, msg: string(data)}
	}

	return data, nil
}

func (client *DockerClient) doStreamRequest(method string, path string, in io.Reader, headers map[string]string, quiet bool) (string, error) {
	if (method == "POST" || method == "PUT") && in == nil {
		in = bytes.NewReader([]byte{})
	}

	req, err := http.NewRequest(method, client.URL.String()+path, in)
	if err != nil {
		return "", err
	}

	req.Header.Add("Content-Type", "application/json")
	if headers != nil {
		for header, value := range headers {
			req.Header.Add(header, value)
		}
	}

	resp, err := client.HTTPClient.Do(req)
	if err != nil {
		if !strings.Contains(err.Error(), "connection refused") && client.TLSConfig == nil {
			return "", fmt.Errorf("%v. Are you trying to connect to a TLS-enabled daemon without TLS?", err)
		}
		return "", err
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 400 {
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return "", err
		}

		if len(body) == 0 {
			return "", fmt.Errorf("Error :%s", http.StatusText(resp.StatusCode))
		}

		return "", fmt.Errorf("Error: %s", bytes.TrimSpace(body))
	}

	mimetype, _, err := mime.ParseMediaType(resp.Header.Get("Content-Type"))
	if err == nil && mimetype == "application/json" {
		out := client.out
		if quiet {
			f, err := os.Open(os.DevNull)
			if err == nil {
				out = f
			} else {
				quiet = false
			}
		}

		message, err := displayJSONMessagesStream(resp.Body, out)
		if quiet && (message != "") {
			fmt.Fprintf(client.out, "%s", message)
		}

		return message, err
	}

	_, err = io.Copy(client.out, resp.Body)
	return "", err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"github.com/go-martini/martini"
	"github.com/grsakea/kappastat/common"
	"github.com/mrshankly/go-twitch/twitch"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"net/http"
	"strconv"
	"time"
)

func getDB() *mgo.Database {
	temp, _ := mgo.Dial("127.0.0.1")
	return (temp.DB("twitch"))
}

func apiViewer(w http.ResponseWriter, r *http.Request, params martini.Params) {
	var ret []kappastat.ViewerCount
	db := getDB()
	db.C("viewer_count").Find(bson.M{"channel": params["streamer"]}).All(&ret)
	data, _ := json.Marshal(ret)
	w.Write(data)

}

func apiFollowing(w http.ResponseWriter, r *http.Request) {
	var ret []twitch.UserS
	db := getDB()
	db.C("follow").Find(nil).All(&ret)
	data, _ := json.Marshal(ret)
	w.Write(data)
}

func apiStat(w http.ResponseWriter, r *http.Request, params martini.Params) {
	var ret []kappastat.StatEntry
	var dur int
	var err error
	db := getDB()
	temp := r.URL.Query().Get("duration")
	dur, err = strconv.Atoi(temp)

	if err != nil {
		dur = int(10 * time.Minute.Nanoseconds())
	}
	db.C("stat_entries").Find(bson.M{"channel": params["streamer"], "duration": dur}).All(&ret)
	data, _ := json.Marshal(ret)
	w.Write(data)
}
<commit_msg>Updated api<commit_after>package main

import (
	"encoding/json"
	"github.com/go-martini/martini"
	"github.com/grsakea/kappastat/common"
	"github.com/mrshankly/go-twitch/twitch"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"net/http"
	"strconv"
	"time"
)

func getDB() *mgo.Database {
	temp, _ := mgo.Dial("127.0.0.1")
	return (temp.DB("twitch"))
}

func apiViewer(w http.ResponseWriter, r *http.Request, params martini.Params) {
	var ret []kappastat.ViewerCount
	db := getDB()
	db.C("viewer_count").Find(bson.M{"channel": params["streamer"]}).All(&ret)
	data, _ := json.Marshal(ret)
	w.Write(data)

}

func apiFollowing(w http.ResponseWriter, r *http.Request) {
	var ret []twitch.UserS
	db := getDB()
	db.C("follow").Find(nil).All(&ret)
	data, _ := json.Marshal(ret)
	w.Write(data)
}

func apiStat(w http.ResponseWriter, r *http.Request, params martini.Params) {
	var ret []kappastat.StatEntry
	var dur int
	var err error
	db := getDB()
	temp := r.URL.Query().Get("duration")
	dur, err = strconv.Atoi(temp)

	if err != nil {
		dur = int(5 * time.Minute.Nanoseconds())
	}
	db.C("stat_entries").Find(bson.M{"channel": params["streamer"], "duration": dur}).All(&ret)
	data, _ := json.Marshal(ret)
	w.Write(data)
}
<|endoftext|>