<commit_before>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"io"

	"github.com/golang/glog"
	cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/util"

	"github.com/spf13/cobra"
)

const (
	bash_completion_func = `# call kubectl get $1,
__kubectl_parse_get()
{
    local template
    template="{{ range .items  }}{{ .metadata.name }} {{ end }}"
    local kubectl_out
    if kubectl_out=$(kubectl get -o template --template="${template}" "$1" 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

__kubectl_get_resource()
{
    if [[ ${#nouns[@]} -eq 0 ]]; then
        return 1
    fi
    __kubectl_parse_get "${nouns[${#nouns[@]} -1]}"
}

__kubectl_get_resource_pod()
{
    __kubectl_parse_get "pod"
}

__kubectl_get_resource_rc()
{
    __kubectl_parse_get "rc"
}

# $1 is the name of the pod we want to get the list of containers inside
__kubectl_get_containers()
{
    local template
    template="{{ range .spec.containers  }}{{ .name }} {{ end }}"
    __debug "${FUNCNAME} nouns are ${nouns[*]}"

    local len="${#nouns[@]}"
    if [[ ${len} -ne 1 ]]; then
        return
    fi
    local last=${nouns[${len} -1]}
    local kubectl_out
    if kubectl_out=$(kubectl get -o template --template="${template}" pods "${last}" 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

# Require both a pod and a container to be specified
__kubectl_require_pod_and_container()
{
    if [[ ${#nouns[@]} -eq 0 ]]; then
        __kubectl_parse_get pods
        return 0
    fi;
    __kubectl_get_containers
    return 0
}

__custom_func() {
    case ${last_command} in
        kubectl_get | kubectl_describe | kubectl_delete | kubectl_label | kubectl_stop)
            __kubectl_get_resource
            return
            ;;
        kubectl_logs)
            __kubectl_require_pod_and_container
            return
            ;;
        kubectl_exec)
            __kubectl_get_resource_pod
            return
            ;;
        kubectl_rolling-update)
            __kubectl_get_resource_rc
            return
            ;;
        *)
            ;;
    esac
}
`
	valid_resources = `Valid resource types include:
   * pods (aka 'po')
   * replicationcontrollers (aka 'rc')
   * daemonsets (aka 'ds')
   * services (aka 'svc')
   * events (aka 'ev')
   * nodes (aka 'no')
   * namespaces (aka 'ns')
   * secrets
   * persistentvolumes (aka 'pv')
   * persistentvolumeclaims (aka 'pvc')
   * limitranges (aka 'limits')
   * resourcequotas (aka 'quota')
   * componentstatuses (aka 'cs')
   * endpoints (aka 'ep')
   * quota
   * horizontalpodautoscalers (aka 'hpa')
   * serviceaccounts
`
)

// NewKubectlCommand creates the `kubectl` command and its nested children.
func NewKubectlCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command {
	// Parent command to which all subcommands are added.
	cmds := &cobra.Command{
		Use:   "kubectl",
		Short: "kubectl controls the Kubernetes cluster manager",
		Long: `kubectl controls the Kubernetes cluster manager.

Find more information at https://github.com/kubernetes/kubernetes.`,
		Run: runHelp,
		BashCompletionFunction: bash_completion_func,
	}

	f.BindFlags(cmds.PersistentFlags())

	// From this point and forward we get warnings on flags that contain "_" separators
	cmds.SetGlobalNormalizationFunc(util.WarnWordSepNormalizeFunc)

	cmds.AddCommand(NewCmdGet(f, out))
	cmds.AddCommand(NewCmdDescribe(f, out))
	cmds.AddCommand(NewCmdCreate(f, out))
	cmds.AddCommand(NewCmdReplace(f, out))
	cmds.AddCommand(NewCmdPatch(f, out))
	cmds.AddCommand(NewCmdDelete(f, out))
	cmds.AddCommand(NewCmdEdit(f, out))
	cmds.AddCommand(NewCmdApply(f, out))

	cmds.AddCommand(NewCmdNamespace(out))
	cmds.AddCommand(NewCmdLogs(f, out))
	cmds.AddCommand(NewCmdRollingUpdate(f, out))
	cmds.AddCommand(NewCmdScale(f, out))

	cmds.AddCommand(NewCmdAttach(f, in, out, err))
	cmds.AddCommand(NewCmdExec(f, in, out, err))
	cmds.AddCommand(NewCmdPortForward(f))
	cmds.AddCommand(NewCmdProxy(f, out))

	cmds.AddCommand(NewCmdRun(f, in, out, err))
	cmds.AddCommand(NewCmdStop(f, out))
	cmds.AddCommand(NewCmdExposeService(f, out))
	cmds.AddCommand(NewCmdAutoscale(f, out))

	cmds.AddCommand(NewCmdLabel(f, out))
	cmds.AddCommand(NewCmdAnnotate(f, out))

	cmds.AddCommand(cmdconfig.NewCmdConfig(cmdconfig.NewDefaultPathOptions(), out))
	cmds.AddCommand(NewCmdClusterInfo(f, out))
	cmds.AddCommand(NewCmdApiVersions(f, out))
	cmds.AddCommand(NewCmdVersion(f, out))
	cmds.AddCommand(NewCmdExplain(f, out))
	cmds.AddCommand(NewCmdConvert(f, out))

	return cmds
}

func runHelp(cmd *cobra.Command, args []string) {
	cmd.Help()
}

func printDeprecationWarning(command, alias string) {
	glog.Warningf("%s is DEPRECATED and will be removed in a future version. Use %s instead.", alias, command)
}
<commit_msg>UPSTREAM: 15451: <partial>: Add our types to kubectl get error<commit_after>/*
Copyright 2014 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"io"

	"github.com/golang/glog"
	cmdconfig "k8s.io/kubernetes/pkg/kubectl/cmd/config"
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
	"k8s.io/kubernetes/pkg/util"

	"github.com/spf13/cobra"
)

const (
	bash_completion_func = `# call kubectl get $1,
__kubectl_parse_get()
{
    local template
    template="{{ range .items  }}{{ .metadata.name }} {{ end }}"
    local kubectl_out
    if kubectl_out=$(kubectl get -o template --template="${template}" "$1" 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

__kubectl_get_resource()
{
    if [[ ${#nouns[@]} -eq 0 ]]; then
        return 1
    fi
    __kubectl_parse_get "${nouns[${#nouns[@]} -1]}"
}

__kubectl_get_resource_pod()
{
    __kubectl_parse_get "pod"
}

__kubectl_get_resource_rc()
{
    __kubectl_parse_get "rc"
}

# $1 is the name of the pod we want to get the list of containers inside
__kubectl_get_containers()
{
    local template
    template="{{ range .spec.containers  }}{{ .name }} {{ end }}"
    __debug "${FUNCNAME} nouns are ${nouns[*]}"

    local len="${#nouns[@]}"
    if [[ ${len} -ne 1 ]]; then
        return
    fi
    local last=${nouns[${len} -1]}
    local kubectl_out
    if kubectl_out=$(kubectl get -o template --template="${template}" pods "${last}" 2>/dev/null); then
        COMPREPLY=( $( compgen -W "${kubectl_out[*]}" -- "$cur" ) )
    fi
}

# Require both a pod and a container to be specified
__kubectl_require_pod_and_container()
{
    if [[ ${#nouns[@]} -eq 0 ]]; then
        __kubectl_parse_get pods
        return 0
    fi;
    __kubectl_get_containers
    return 0
}

__custom_func() {
    case ${last_command} in
        kubectl_get | kubectl_describe | kubectl_delete | kubectl_label | kubectl_stop)
            __kubectl_get_resource
            return
            ;;
        kubectl_logs)
            __kubectl_require_pod_and_container
            return
            ;;
        kubectl_exec)
            __kubectl_get_resource_pod
            return
            ;;
        kubectl_rolling-update)
            __kubectl_get_resource_rc
            return
            ;;
        *)
            ;;
    esac
}
`
	valid_resources = `Valid resource types include:
   * pods (aka 'po')
   * replicationcontrollers (aka 'rc')
   * daemonsets (aka 'ds')
   * services (aka 'svc')
   * deploymentconfigs (aka 'dc')
   * buildconfigs (aka 'bc')
   * builds
   * routes
   * replicationcontrollers (aka 'rc')
   * events (aka 'ev')
   * projects
   * secrets
   * imagestreams (aka 'is')
   * imagestreamtags (aka 'istag')
   * imagestreamimages (aka 'isimage')
   * persistentvolumes (aka 'pv')
   * persistentvolumeclaims (aka 'pvc')
   * policies
   * rolebindings
   * limitranges (aka 'limits')
   * resourcequotas (aka 'quota')
   * componentstatuses (aka 'cs')
   * endpoints (aka 'ep')
   * quota
   * horizontalpodautoscalers (aka 'hpa')
   * serviceaccounts
   * nodes (aka 'no')
   * namespaces (aka 'ns')
   * users
   * groups
`
)

// NewKubectlCommand creates the `kubectl` command and its nested children.
func NewKubectlCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command {
	// Parent command to which all subcommands are added.
	cmds := &cobra.Command{
		Use:   "kubectl",
		Short: "kubectl controls the Kubernetes cluster manager",
		Long: `kubectl controls the Kubernetes cluster manager.

Find more information at https://github.com/kubernetes/kubernetes.`,
		Run: runHelp,
		BashCompletionFunction: bash_completion_func,
	}

	f.BindFlags(cmds.PersistentFlags())

	// From this point and forward we get warnings on flags that contain "_" separators
	cmds.SetGlobalNormalizationFunc(util.WarnWordSepNormalizeFunc)

	cmds.AddCommand(NewCmdGet(f, out))
	cmds.AddCommand(NewCmdDescribe(f, out))
	cmds.AddCommand(NewCmdCreate(f, out))
	cmds.AddCommand(NewCmdReplace(f, out))
	cmds.AddCommand(NewCmdPatch(f, out))
	cmds.AddCommand(NewCmdDelete(f, out))
	cmds.AddCommand(NewCmdEdit(f, out))
	cmds.AddCommand(NewCmdApply(f, out))

	cmds.AddCommand(NewCmdNamespace(out))
	cmds.AddCommand(NewCmdLogs(f, out))
	cmds.AddCommand(NewCmdRollingUpdate(f, out))
	cmds.AddCommand(NewCmdScale(f, out))

	cmds.AddCommand(NewCmdAttach(f, in, out, err))
	cmds.AddCommand(NewCmdExec(f, in, out, err))
	cmds.AddCommand(NewCmdPortForward(f))
	cmds.AddCommand(NewCmdProxy(f, out))

	cmds.AddCommand(NewCmdRun(f, in, out, err))
	cmds.AddCommand(NewCmdStop(f, out))
	cmds.AddCommand(NewCmdExposeService(f, out))
	cmds.AddCommand(NewCmdAutoscale(f, out))

	cmds.AddCommand(NewCmdLabel(f, out))
	cmds.AddCommand(NewCmdAnnotate(f, out))

	cmds.AddCommand(cmdconfig.NewCmdConfig(cmdconfig.NewDefaultPathOptions(), out))
	cmds.AddCommand(NewCmdClusterInfo(f, out))
	cmds.AddCommand(NewCmdApiVersions(f, out))
	cmds.AddCommand(NewCmdVersion(f, out))
	cmds.AddCommand(NewCmdExplain(f, out))
	cmds.AddCommand(NewCmdConvert(f, out))

	return cmds
}

func runHelp(cmd *cobra.Command, args []string) {
	cmd.Help()
}

func printDeprecationWarning(command, alias string) {
	glog.Warningf("%s is DEPRECATED and will be removed in a future version. Use %s instead.", alias, command)
}
<|endoftext|>


<commit_before>package main

import (
	"./anaconda"
	"fmt"
	"net/url"
	"strings"
)

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

func isUserFollowing(userName string) (bool, error) {
	friendships, err := api.GetFriendshipsLookup(url.Values{"screen_name": []string{userName}})
	if err != nil {
		fmt.Println("Error while querying twitter api for friendships", err)
		return false, err
	}

	following := false
	for _, friendship := range friendships {
		if stringInSlice("followed_by", friendship.Connections) {
			following = true
		}
	}

	return following, nil
}

func isUserAcceptable(tweet anaconda.Tweet) bool {
	words := strings.Split(tweet.Text, " ")
	for _, word := range words {
		if stringInSlice(strings.ToLower(word), BANNED_KEYWORDS) {
			return false
		}
	}

	if tweet.User.Description == "" {
		return false
	}

	words = strings.Split(tweet.User.Description, " ")
	for _, word := range words {
		if stringInSlice(strings.ToLower(word), BANNED_KEYWORDS) {
			return false
		}
	}

	return true
}

func generateAPISearchValues(word string) (string, url.Values) {
	searchString := word

	for _, word := range BANNED_KEYWORDS {
		searchString += " -" + word
	}

	v := url.Values{}
	v.Add("lang", ACCEPTED_LANGUAGE)
	v.Add("count", "100")

	return url.QueryEscape(searchString), v
}

func isMentionOrRT(tweet anaconda.Tweet) bool {
	return strings.HasPrefix(tweet.Text, "RT") || strings.HasPrefix(tweet.Text, "@")
}

func isMe(tweet anaconda.Tweet) bool {
	return strings.ToLower(tweet.User.ScreenName) == strings.ToLower(USER_NAME)
}
<commit_msg>Use recent result search<commit_after>package main

import (
	"./anaconda"
	"fmt"
	"net/url"
	"strings"
)

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

func isUserFollowing(userName string) (bool, error) {
	friendships, err := api.GetFriendshipsLookup(url.Values{"screen_name": []string{userName}})
	if err != nil {
		fmt.Println("Error while querying twitter api for friendships", err)
		return false, err
	}

	following := false
	for _, friendship := range friendships {
		if stringInSlice("followed_by", friendship.Connections) {
			following = true
		}
	}

	return following, nil
}

func isUserAcceptable(tweet anaconda.Tweet) bool {
	words := strings.Split(tweet.Text, " ")
	for _, word := range words {
		if stringInSlice(strings.ToLower(word), BANNED_KEYWORDS) {
			return false
		}
	}

	if tweet.User.Description == "" {
		return false
	}

	words = strings.Split(tweet.User.Description, " ")
	for _, word := range words {
		if stringInSlice(strings.ToLower(word), BANNED_KEYWORDS) {
			return false
		}
	}

	return true
}

func generateAPISearchValues(word string) (string, url.Values) {
	searchString := word

	for _, word := range BANNED_KEYWORDS {
		searchString += " -" + word
	}

	for _, account := range BANNED_ACCOUNTS {
		searchString +=
	}

	v := url.Values{}
	v.Add("lang", ACCEPTED_LANGUAGE)
	v.Add("count", "100")
	v.Add("result_type", "recent")

	return url.QueryEscape(searchString), v
}

func isMentionOrRT(tweet anaconda.Tweet) bool {
	return strings.HasPrefix(tweet.Text, "RT") || strings.HasPrefix(tweet.Text, "@")
}

func isMe(tweet anaconda.Tweet) bool {
	return strings.ToLower(tweet.User.ScreenName) == strings.ToLower(USER_NAME)
}
<|endoftext|>


<commit_before>package imagick

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/gographics/imagick/imagick"
	"github.com/pressly/imgry"
)

var (
	ErrEngineReleased = errors.New("imagick: engine has been released.")
	ErrEngineFailure  = errors.New("imagick: unable to request a MagickWand")
)

type Engine struct {
	tmpDir string
	// TODO: perhaps we have counter of wands here..
	// it ensures we'll always release them..
	// AvailableWands .. .. set to MaxSizers ..
	// then, NewMagickWand() will limit, or error..
	// perhaps we make a channel of these things..
	// then block.. + ctx will have a timeout if it wants to stop waiting..
	// we can log these timeouts etc..
}

func (ng Engine) Version() string {
	v, _ := imagick.GetVersion()
	return fmt.Sprintf("%s", v)
}

func (ng Engine) Initialize(tmpDir string) error {
	if tmpDir != "" {
		if err := os.MkdirAll(tmpDir, 0755); err != nil {
			return err
		}
		ng.tmpDir = tmpDir
		os.Setenv("MAGICK_TMPDIR", tmpDir)
		ng.SweepTmpDir()
	}
	imagick.Initialize()
	return nil
}

func (ng Engine) Terminate() {
	imagick.Terminate()
	ng.SweepTmpDir()
}

func (ng Engine) SweepTmpDir() error {
	if ng.tmpDir == "" {
		return nil
	}
	err := filepath.Walk(
		ng.tmpDir,
		func(path string, info os.FileInfo, err error) error {
			if ng.tmpDir == path {
				return nil // skip the root
			}
			if strings.Index(filepath.Base(path), "magick") >= 0 {
				if err = os.Remove(path); err != nil {
					return fmt.Errorf("failed to sweet engine tmpdir %s, because: %s", path, err)
				}
			}
			return nil
		},
	)
	if err != nil {
		return err
	}
	return nil
}

func (ng Engine) LoadFile(filename string, srcFormat ...string) (imgry.Image, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return ng.LoadBlob(b, srcFormat...)
}

func (ng Engine) LoadBlob(b []byte, srcFormat ...string) (imgry.Image, error) {
	if len(b) == 0 {
		return nil, imgry.ErrInvalidImageData
	}

	mw := imagick.NewMagickWand()
	if !mw.IsVerified() {
		return nil, ErrEngineFailure
	}

	// Offer a hint to the decoder of the file format
	if len(srcFormat) > 0 {
		f := srcFormat[0]
		if f != "" {
			mw.SetFormat(f)
		}
	}

	err := mw.ReadImageBlob(b)
	if err != nil {
		mw.Destroy()
		return nil, imgry.ErrInvalidImageData
	}

	// TODO: perhaps we pass the engine instance like Image{engine: i}
	im := &Image{mw: mw, data: b}
	if err := im.sync(); err != nil {
		mw.Destroy()
		return nil, err
	}

	return im, nil
}

func (ng Engine) GetImageInfo(b []byte, srcFormat ...string) (*imgry.ImageInfo, error) {
	if len(b) == 0 {
		return nil, imgry.ErrInvalidImageData
	}

	mw := imagick.NewMagickWand()
	defer mw.Destroy()

	if !mw.IsVerified() {
		return nil, ErrEngineFailure
	}

	err := mw.PingImageBlob(b)
	if err != nil {
		return nil, imgry.ErrInvalidImageData
	}

	w, h := int(mw.GetImageWidth()), int(mw.GetImageHeight())
	ar := float64(int(float64(w)/float64(h)*10000)) / 10000

	format := strings.ToLower(mw.GetImageFormat())
	if format == "jpeg" {
		format = "jpg"
	}

	imfo := &imgry.ImageInfo{
		Format: format, Width: w, Height: h,
		AspectRatio: ar, ContentLength: len(b),
	}

	return imfo, nil
}

type Image struct {
	mw *imagick.MagickWand

	data   []byte
	width  int
	height int
	format string
}

func (i *Image) Data() []byte {
	return i.data
}

func (i *Image) Width() int {
	return i.width
}

func (i *Image) Height() int {
	return i.height
}

func (i *Image) Format() string {
	return i.format
}

func (i *Image) SetFormat(format string) error {
	if i.Released() {
		return ErrEngineReleased
	}
	if err := i.mw.SetImageFormat(format); err != nil {
		return err
	}
	if err := i.sync(); err != nil {
		return err
	}
	return nil
}

func (i *Image) Released() bool {
	return i.mw == nil
}

func (i *Image) Release() {
	if i.mw != nil {
		i.mw.Destroy()
		i.mw = nil
	}
}

func (i *Image) Clone() imgry.Image {
	i2 := &Image{}
	i2.data = i.data
	i2.width = i.width
	i2.height = i.height
	i2.format = i.format
	if i.mw != nil && i.mw.IsVerified() {
		i2.mw = i.mw.Clone()
	}
	return i2
}

func (i *Image) SizeIt(sz *imgry.Sizing) error {
	if i.Released() {
		return ErrEngineReleased
	}

	if err := i.sizeFrames(sz); err != nil {
		return err
	}

	if sz.Format != "" {
		if err := i.mw.SetFormat(sz.Format); err != nil {
			return err
		}
	}

	if sz.Quality > 0 {
		if err := i.mw.SetImageCompressionQuality(uint(sz.Quality)); err != nil {
			return err
		}
	}

	if err := i.sync(sz.Flatten); err != nil {
		return err
	}

	return nil
}

func (i *Image) sizeFrames(sz *imgry.Sizing) error {
	var canvas *imagick.MagickWand
	var bg *imagick.PixelWand

	// Shortcut if there is nothing to size
	if sz.Size.Equal(imgry.ZeroRect) && sz.CropBox.Equal(imgry.ZeroFloatingRect) {
		return nil
	}

	coalesceAndDeconstruct := !sz.Flatten && i.mw.GetNumberImages() > 1

	if coalesceAndDeconstruct {
		i.mw = i.mw.CoalesceImages()
	}

	if sz.Canvas != nil {
		// If the user requested a canvas.
		canvas = imagick.NewMagickWand()
		bg = imagick.NewPixelWand()
		bg.SetColor("transparent")
	}

	defer func() {
		bg.Destroy()

		if canvas != nil && canvas != i.mw {
			canvas.Destroy()
		}
	}()

	i.mw.SetFirstIterator()
	for n := true; n; n = i.mw.NextImage() {
		pw, ph := int(i.mw.GetImageWidth()), int(i.mw.GetImageHeight())
		srcSize := imgry.NewRect(pw, ph)

		// Initial crop of the source image
		cropBox, cropOrigin, err := sz.CalcCropBox(srcSize)
		if err != nil {
			return err
		}

		if cropBox != nil && cropOrigin != nil && !cropBox.Equal(imgry.ZeroRect) {
			err := i.mw.CropImage(uint(cropBox.Width), uint(cropBox.Height), cropOrigin.X, cropOrigin.Y)
			if err != nil {
				return err
			}
			srcSize = cropBox
			i.mw.ResetImagePage("")
		}

		// Resize the image
		resizeRect, cropBox, cropOrigin := sz.CalcResizeRect(srcSize)
		if resizeRect != nil && !resizeRect.Equal(imgry.ZeroRect) {
			err := i.mw.ResizeImage(uint(resizeRect.Width), uint(resizeRect.Height), imagick.FILTER_LANCZOS, 1.0)
			if err != nil {
				return err
			}
			i.mw.ResetImagePage("")
		}

		// Perform any final crops from an operation
		if cropBox != nil && cropOrigin != nil && !cropBox.Equal(imgry.ZeroRect) {
			err := i.mw.CropImage(uint(cropBox.Width), uint(cropBox.Height), cropOrigin.X, cropOrigin.Y)
			if err != nil {
				return err
			}
			i.mw.ResetImagePage("")
		}

		// If we have a canvas we put the image at its center.
		if canvas != nil {
			canvas.NewImage(uint(sz.Canvas.Width), uint(sz.Canvas.Height), bg)
			canvas.SetImageBackgroundColor(bg)
			canvas.SetImageFormat(i.mw.GetImageFormat())

			x := (sz.Canvas.Width - int(i.mw.GetImageWidth())) / 2
			y := (sz.Canvas.Height - int(i.mw.GetImageHeight())) / 2
			canvas.CompositeImage(i.mw, imagick.COMPOSITE_OP_OVER, x, y)
			canvas.ResetImagePage("")
		}

		if sz.Flatten {
			break
		}
	}

	if canvas != nil {
		i.mw.Destroy()
		i.mw = canvas
	}

	if coalesceAndDeconstruct {
		// Compares each frame of the image, removes pixels that are already on the
		// background and updates offsets accordingly.
		i.mw = i.mw.DeconstructImages()
	}

	return nil
}

func (i *Image) WriteToFile(fn string) error {
	err := ioutil.WriteFile(fn, i.Data(), 0664)
	return err
}

func (i *Image) sync(optFlatten ...bool) error {
	if i.Released() {
		return ErrEngineReleased
	}

	var flatten bool
	if len(optFlatten) > 0 {
		flatten = optFlatten[0]
	}

	if flatten {
		i.data = i.mw.GetImageBlob()
	} else {
		i.data = i.mw.GetImagesBlob()
	}

	i.width = int(i.mw.GetImageWidth())
	i.height = int(i.mw.GetImageHeight())

	i.format = strings.ToLower(i.mw.GetImageFormat())
	if i.format == "jpeg" {
		i.format = "jpg"
	}

	return nil
}
<commit_msg>Move canvas defer destroy to when its used<commit_after>package imagick

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/gographics/imagick/imagick"
	"github.com/pressly/imgry"
)

var (
	ErrEngineReleased = errors.New("imagick: engine has been released.")
	ErrEngineFailure  = errors.New("imagick: unable to request a MagickWand")
)

type Engine struct {
	tmpDir string
	// TODO: perhaps we have counter of wands here..
	// it ensures we'll always release them..
	// AvailableWands .. .. set to MaxSizers ..
	// then, NewMagickWand() will limit, or error..
	// perhaps we make a channel of these things..
	// then block.. + ctx will have a timeout if it wants to stop waiting..
	// we can log these timeouts etc..
}

func (ng Engine) Version() string {
	v, _ := imagick.GetVersion()
	return fmt.Sprintf("%s", v)
}

func (ng Engine) Initialize(tmpDir string) error {
	if tmpDir != "" {
		if err := os.MkdirAll(tmpDir, 0755); err != nil {
			return err
		}
		ng.tmpDir = tmpDir
		os.Setenv("MAGICK_TMPDIR", tmpDir)
		ng.SweepTmpDir()
	}
	imagick.Initialize()
	return nil
}

func (ng Engine) Terminate() {
	imagick.Terminate()
	ng.SweepTmpDir()
}

func (ng Engine) SweepTmpDir() error {
	if ng.tmpDir == "" {
		return nil
	}
	err := filepath.Walk(
		ng.tmpDir,
		func(path string, info os.FileInfo, err error) error {
			if ng.tmpDir == path {
				return nil // skip the root
			}
			if strings.Index(filepath.Base(path), "magick") >= 0 {
				if err = os.Remove(path); err != nil {
					return fmt.Errorf("failed to sweet engine tmpdir %s, because: %s", path, err)
				}
			}
			return nil
		},
	)
	if err != nil {
		return err
	}
	return nil
}

func (ng Engine) LoadFile(filename string, srcFormat ...string) (imgry.Image, error) {
	b, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return ng.LoadBlob(b, srcFormat...)
}

func (ng Engine) LoadBlob(b []byte, srcFormat ...string) (imgry.Image, error) {
	if len(b) == 0 {
		return nil, imgry.ErrInvalidImageData
	}

	mw := imagick.NewMagickWand()
	if !mw.IsVerified() {
		return nil, ErrEngineFailure
	}

	// Offer a hint to the decoder of the file format
	if len(srcFormat) > 0 {
		f := srcFormat[0]
		if f != "" {
			mw.SetFormat(f)
		}
	}

	err := mw.ReadImageBlob(b)
	if err != nil {
		mw.Destroy()
		return nil, imgry.ErrInvalidImageData
	}

	// TODO: perhaps we pass the engine instance like Image{engine: i}
	im := &Image{mw: mw, data: b}
	if err := im.sync(); err != nil {
		mw.Destroy()
		return nil, err
	}

	return im, nil
}

func (ng Engine) GetImageInfo(b []byte, srcFormat ...string) (*imgry.ImageInfo, error) {
	if len(b) == 0 {
		return nil, imgry.ErrInvalidImageData
	}

	mw := imagick.NewMagickWand()
	defer mw.Destroy()

	if !mw.IsVerified() {
		return nil, ErrEngineFailure
	}

	err := mw.PingImageBlob(b)
	if err != nil {
		return nil, imgry.ErrInvalidImageData
	}

	w, h := int(mw.GetImageWidth()), int(mw.GetImageHeight())
	ar := float64(int(float64(w)/float64(h)*10000)) / 10000

	format := strings.ToLower(mw.GetImageFormat())
	if format == "jpeg" {
		format = "jpg"
	}

	imfo := &imgry.ImageInfo{
		Format: format, Width: w, Height: h,
		AspectRatio: ar, ContentLength: len(b),
	}

	return imfo, nil
}

type Image struct {
	mw *imagick.MagickWand

	data   []byte
	width  int
	height int
	format string
}

func (i *Image) Data() []byte {
	return i.data
}

func (i *Image) Width() int {
	return i.width
}

func (i *Image) Height() int {
	return i.height
}

func (i *Image) Format() string {
	return i.format
}

func (i *Image) SetFormat(format string) error {
	if i.Released() {
		return ErrEngineReleased
	}
	if err := i.mw.SetImageFormat(format); err != nil {
		return err
	}
	if err := i.sync(); err != nil {
		return err
	}
	return nil
}

func (i *Image) Released() bool {
	return i.mw == nil
}

func (i *Image) Release() {
	if i.mw != nil {
		i.mw.Destroy()
		i.mw = nil
	}
}

func (i *Image) Clone() imgry.Image {
	i2 := &Image{}
	i2.data = i.data
	i2.width = i.width
	i2.height = i.height
	i2.format = i.format
	if i.mw != nil && i.mw.IsVerified() {
		i2.mw = i.mw.Clone()
	}
	return i2
}

func (i *Image) SizeIt(sz *imgry.Sizing) error {
	if i.Released() {
		return ErrEngineReleased
	}

	if err := i.sizeFrames(sz); err != nil {
		return err
	}

	if sz.Format != "" {
		if err := i.mw.SetFormat(sz.Format); err != nil {
			return err
		}
	}

	if sz.Quality > 0 {
		if err := i.mw.SetImageCompressionQuality(uint(sz.Quality)); err != nil {
			return err
		}
	}

	if err := i.sync(sz.Flatten); err != nil {
		return err
	}

	return nil
}

func (i *Image) sizeFrames(sz *imgry.Sizing) error {
	var canvas *imagick.MagickWand
	var bg *imagick.PixelWand

	// Shortcut if there is nothing to size
	if sz.Size.Equal(imgry.ZeroRect) && sz.CropBox.Equal(imgry.ZeroFloatingRect) {
		return nil
	}

	coalesceAndDeconstruct := !sz.Flatten && i.mw.GetNumberImages() > 1
	if coalesceAndDeconstruct {
		i.mw = i.mw.CoalesceImages()
	}

	if sz.Canvas != nil {
		// If the user requested a canvas.
		canvas = imagick.NewMagickWand()
		bg = imagick.NewPixelWand()
		bg.SetColor("transparent")

		defer func() {
			bg.Destroy()
			if canvas != nil && canvas != i.mw {
				canvas.Destroy()
			}
		}()
	}

	i.mw.SetFirstIterator()
	for n := true; n; n = i.mw.NextImage() {
		pw, ph := int(i.mw.GetImageWidth()), int(i.mw.GetImageHeight())
		srcSize := imgry.NewRect(pw, ph)

		// Initial crop of the source image
		cropBox, cropOrigin, err := sz.CalcCropBox(srcSize)
		if err != nil {
			return err
		}

		if cropBox != nil && cropOrigin != nil && !cropBox.Equal(imgry.ZeroRect) {
			err := i.mw.CropImage(uint(cropBox.Width), uint(cropBox.Height), cropOrigin.X, cropOrigin.Y)
			if err != nil {
				return err
			}
			srcSize = cropBox
			i.mw.ResetImagePage("")
		}

		// Resize the image
		resizeRect, cropBox, cropOrigin := sz.CalcResizeRect(srcSize)
		if resizeRect != nil && !resizeRect.Equal(imgry.ZeroRect) {
			err := i.mw.ResizeImage(uint(resizeRect.Width), uint(resizeRect.Height), imagick.FILTER_LANCZOS, 1.0)
			if err != nil {
				return err
			}
			i.mw.ResetImagePage("")
		}

		// Perform any final crops from an operation
		if cropBox != nil && cropOrigin != nil && !cropBox.Equal(imgry.ZeroRect) {
			err := i.mw.CropImage(uint(cropBox.Width), uint(cropBox.Height), cropOrigin.X, cropOrigin.Y)
			if err != nil {
				return err
			}
			i.mw.ResetImagePage("")
		}

		// If we have a canvas we put the image at its center.
		if canvas != nil {
			canvas.NewImage(uint(sz.Canvas.Width), uint(sz.Canvas.Height), bg)
			canvas.SetImageBackgroundColor(bg)
			canvas.SetImageFormat(i.mw.GetImageFormat())

			x := (sz.Canvas.Width - int(i.mw.GetImageWidth())) / 2
			y := (sz.Canvas.Height - int(i.mw.GetImageHeight())) / 2
			canvas.CompositeImage(i.mw, imagick.COMPOSITE_OP_OVER, x, y)
			canvas.ResetImagePage("")
		}

		if sz.Flatten {
			break
		}
	}

	if canvas != nil {
		i.mw.Destroy()
		i.mw = canvas
	}

	if coalesceAndDeconstruct {
		// Compares each frame of the image, removes pixels that are already on the
		// background and updates offsets accordingly.
		i.mw = i.mw.DeconstructImages()
	}

	return nil
}

func (i *Image) WriteToFile(fn string) error {
	err := ioutil.WriteFile(fn, i.Data(), 0664)
	return err
}

func (i *Image) sync(optFlatten ...bool) error {
	if i.Released() {
		return ErrEngineReleased
	}

	var flatten bool
	if len(optFlatten) > 0 {
		flatten = optFlatten[0]
	}

	if flatten {
		i.data = i.mw.GetImageBlob()
	} else {
		i.data = i.mw.GetImagesBlob()
	}

	i.width = int(i.mw.GetImageWidth())
	i.height = int(i.mw.GetImageHeight())

	i.format = strings.ToLower(i.mw.GetImageFormat())
	if i.format == "jpeg" {
		i.format = "jpg"
	}

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The hashmap package re-implements Go's builtin map type.
package hashmap

//import "fmt"

// These seem right, Java's lower 0.75 bound resizes too
// much, a higher 1.15 or 1.25 bound makes chains grow
const loadGrow = 1.0
const loadShrink = 0.25

// Hashable is an interface that keys have to implement.
type Hashable interface {
	Hash() uint
	Equal(other Hashable) bool
}

// HashMap is the container itself.
// You must call Init() before using it.
type HashMap struct {
	data	[]hashVector // each should be short
	count	int // to compute load factor
}

// HashPair is a key and a value.
// Iter() yields HashPairs.
type HashPair struct {
	key Hashable
	value interface{}
}

func (self *HashMap) loadFactor() float {
//	fmt.Printf("loadFactor %d/%d\n", self.count, len(self.data))
	return float(self.count) / float(len(self.data))
}

func (self *HashMap) rehashInto(data []hashVector) {
//	fmt.Printf("rehashInto %d\n", len(data))
	for b := range self.data {
		if self.data[b].count > 0 && self.data[b].data != nil {
			for i := 0; i < self.data[b].count; i++ {
				e := self.data[b].data[i]
				h := e.key.Hash() % uint(len(data))
				data[h].push(e)
			}
		}
	}
}

func (self *HashMap) grow() {
//	fmt.Printf("grow\n")
	d := make([]hashVector, len(self.data)*2)
	self.rehashInto(d)
	self.data = d
}

func (self *HashMap) shrink() {
//	fmt.Printf("shrink\n")
	d := make([]hashVector, len(self.data)/2)
	self.rehashInto(d)
	self.data = d
}

func (self *HashMap) find(key Hashable) (bucket int, position int) {
//	fmt.Printf("find %s\n", key)
	h := key.Hash() % uint(len(self.data))
	p := self.data[h].find(key)
	return int(h), p
}

// Init initializes or clears a HashMap.
func (self *HashMap) Init() *HashMap {
//	fmt.Printf("Init %s\n", self)
	self.data = make([]hashVector, 8)
	self.count = 0
	return self
}

// New returns an initialized hashmap.
func New() *HashMap {
//	fmt.Printf("New\n")
	return new(HashMap).Init()
}

func (self *HashMap) Insert(key Hashable, value interface{}) {
//	fmt.Printf("Insert %s->%s\n", key, value)
	if self.loadFactor() >= loadGrow {
		self.grow()
	}

	bucket, position := self.find(key)
	if position != -1 {
		panic("HashMap.Insert: duplicate key")
	}

	self.data[bucket].push(HashPair{key, value})
	self.count++
}

func (self *HashMap) Remove(key Hashable) {
//	fmt.Printf("Remove %s\n", key)
	bucket, position := self.find(key)
	if position == -1 {
		panic("HashMap.Remove: key not found")
	}

	self.data[bucket].pop(position)
	self.count--

	if self.loadFactor() <= loadShrink {
		self.shrink()
	}
}

func (self *HashMap) At(key Hashable) interface{} {
//	fmt.Printf("At %s\n", key)
	bucket, position := self.find(key)
	if position == -1 {
		panic("HashMap.At: key not found")
	}
	e := self.data[bucket].data[position]
	return e.value
}

func (self *HashMap) Set(key Hashable, value interface{}) {
//	fmt.Printf("Set %s->%s\n", key, value)
	bucket, position := self.find(key)
	if position == -1 {
		panic("HashMap.Set: key not found")
	}
	self.data[bucket].data[position].value = value
}

func (self *HashMap) Has(key Hashable) bool {
//	fmt.Printf("Has %s\n", key)
	_, position := self.find(key)
	return position != -1
}

func (self *HashMap) Len() int {
//	fmt.Printf("Len %d\n", self.count)
	return self.count
}

func (self *HashMap) Do(f func(key Hashable, value interface{})) {
//	fmt.Printf("Do %s\n", f)
	for b := range self.data {
		if self.data[b].count > 0 {
			for i := 0; i < self.data[b].count; i++ {
				e := self.data[b].data[i]
				f(e.key, e.value)
			}
		}
	}
}

func (self *HashMap) iterate(c chan<- interface{}) {
//	fmt.Printf("Iterate %s\n", c)
	for b := range self.data {
		if self.data[b].count > 0 {
			for i := 0; i < self.data[b].count; i++ {
				e := self.data[b].data[i]
				c <- e
			}
		}
	}
	close(c)
}

func (self *HashMap) Iter() <-chan interface{} {
//	fmt.Printf("Iter\n")
	c := make(chan interface{})
	go self.iterate(c)
	return c
}
<commit_msg>Pulled len() out of rehash loop.<commit_after>// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The hashmap package re-implements Go's builtin map type.
package hashmap

//import "fmt"

// These seem right, Java's lower 0.75 bound resizes too
// much, a higher 1.15 or 1.25 bound makes chains grow
const loadGrow = 1.0
const loadShrink = 0.25

// Hashable is an interface that keys have to implement.
type Hashable interface {
	Hash() uint
	Equal(other Hashable) bool
}

// HashMap is the container itself.
// You must call Init() before using it.
type HashMap struct {
	data	[]hashVector // each should be short
	count	int // to compute load factor
}

// HashPair is a key and a value.
// Iter() yields HashPairs.
type HashPair struct {
	key Hashable
	value interface{}
}

func (self *HashMap) loadFactor() float {
//	fmt.Printf("loadFactor %d/%d\n", self.count, len(self.data))
	return float(self.count) / float(len(self.data))
}

func (self *HashMap) rehashInto(data []hashVector) {
//	fmt.Printf("rehashInto %d\n", len(data))
	l := uint(len(data))
	for b := range self.data {
		if self.data[b].count > 0 && self.data[b].data != nil {
			for i := 0; i < self.data[b].count; i++ {
				e := self.data[b].data[i]
				h := e.key.Hash() % l
				data[h].push(e)
			}
		}
	}
}

func (self *HashMap) grow() {
//	fmt.Printf("grow\n")
	d := make([]hashVector, len(self.data)*2)
	self.rehashInto(d)
	self.data = d
}

func (self *HashMap) shrink() {
//	fmt.Printf("shrink\n")
	d := make([]hashVector, len(self.data)/2)
	self.rehashInto(d)
	self.data = d
}

func (self *HashMap) find(key Hashable) (bucket int, position int) {
//	fmt.Printf("find %s\n", key)
	h := key.Hash() % uint(len(self.data))
	p := self.data[h].find(key)
	return int(h), p
}

// Init initializes or clears a HashMap.
func (self *HashMap) Init() *HashMap {
//	fmt.Printf("Init %s\n", self)
	self.data = make([]hashVector, 8)
	self.count = 0
	return self
}

// New returns an initialized hashmap.
func New() *HashMap {
//	fmt.Printf("New\n")
	return new(HashMap).Init()
}

func (self *HashMap) Insert(key Hashable, value interface{}) {
//	fmt.Printf("Insert %s->%s\n", key, value)
	if self.loadFactor() >= loadGrow {
		self.grow()
	}

	bucket, position := self.find(key)
	if position != -1 {
		panic("HashMap.Insert: duplicate key")
	}

	self.data[bucket].push(HashPair{key, value})
	self.count++
}

func (self *HashMap) Remove(key Hashable) {
//	fmt.Printf("Remove %s\n", key)
	bucket, position := self.find(key)
	if position == -1 {
		panic("HashMap.Remove: key not found")
	}

	self.data[bucket].pop(position)
	self.count--

	if self.loadFactor() <= loadShrink {
		self.shrink()
	}
}

func (self *HashMap) At(key Hashable) interface{} {
//	fmt.Printf("At %s\n", key)
	bucket, position := self.find(key)
	if position == -1 {
		panic("HashMap.At: key not found")
	}
	e := self.data[bucket].data[position]
	return e.value
}

func (self *HashMap) Set(key Hashable, value interface{}) {
//	fmt.Printf("Set %s->%s\n", key, value)
	bucket, position := self.find(key)
	if position == -1 {
		panic("HashMap.Set: key not found")
	}
	self.data[bucket].data[position].value = value
}

func (self *HashMap) Has(key Hashable) bool {
//	fmt.Printf("Has %s\n", key)
	_, position := self.find(key)
	return position != -1
}

func (self *HashMap) Len() int {
//	fmt.Printf("Len %d\n", self.count)
	return self.count
}

func (self *HashMap) Do(f func(key Hashable, value interface{})) {
//	fmt.Printf("Do %s\n", f)
	for b := range self.data {
		if self.data[b].count > 0 {
			for i := 0; i < self.data[b].count; i++ {
				e := self.data[b].data[i]
				f(e.key, e.value)
			}
		}
	}
}

func (self *HashMap) iterate(c chan<- interface{}) {
//	fmt.Printf("Iterate %s\n", c)
	for b := range self.data {
		if self.data[b].count > 0 {
			for i := 0; i < self.data[b].count; i++ {
				e := self.data[b].data[i]
				c <- e
			}
		}
	}
	close(c)
}

func (self *HashMap) Iter() <-chan interface{} {
//	fmt.Printf("Iter\n")
	c := make(chan interface{})
	go self.iterate(c)
	return c
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"
	"text/template"
)

const (
	HTML_TEMPLATE = `<!DOCTYPE html>

<title>Change Log</title>
<meta charset="utf-8">
{{ range $stylesheet := .Stylesheets }}

{{ end }}

Change Log

{{ range $release := .Changelog }}

Release {{ .Version }} ({{ .Date }})

{{ .Summary }}

{{ if .Added }}

Added

{{ range $entry := .Added }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Changed }}

Changed

{{ range $entry := .Changed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Deprecated }}

Deprecated

{{ range $entry := .Deprecated }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Removed }}

Removed

{{ range $entry := .Removed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Fixed }}

Fixed

{{ range $entry := .Fixed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Security }}

Security

{{ range $entry := .Security }}

{{ . }}

{{ end }}

{{ end }}
{{ end }}

`
	STYLESHEET = `
body {
  font-family: Helvetica, arial, sans-serif;
  font-size: 16px;
  line-height: 1.4;
  padding-top: 10px;
  padding-bottom: 10px;
  background-color: white;
  padding: 30px;
  color: #333;
}

body > *:first-child {
  margin-top: 0 !important;
}

body > *:last-child {
  margin-bottom: 0 !important;
}

a {
  color: #4183C4;
  text-decoration: none;
}

a.absent {
  color: #cc0000;
}

a.anchor {
  display: block;
  padding-left: 30px;
  margin-left: -30px;
  cursor: pointer;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
}

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
  cursor: text;
  position: relative;
}

h2:first-child, h1:first-child, h1:first-child + h2, h3:first-child, h4:first-child, h5:first-child, h6:first-child {
  margin-top: 0;
  padding-top: 0;
}

h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
  text-decoration: none;
}

h1 tt, h1 code {
  font-size: inherit;
}

h2 tt, h2 code {
  font-size: inherit;
}

h3 tt, h3 code {
  font-size: inherit;
}

h4 tt, h4 code {
  font-size: inherit;
}

h5 tt, h5 code {
  font-size: inherit;
}

h6 tt, h6 code {
  font-size: inherit;
}

h1 {
  font-size: 32px;
  color: black;
}

h2 {
  font-size: 28px;
  border-bottom: 1px solid #cccccc;
  color: black;
}

h3 {
  font-size: 20px;
}

h4 {
  font-size: 16px;
}

h5 {
  font-size: 14px;
}

h6 {
  color: #777777;
  font-size: 14px;
}

p, blockquote, ul, ol, dl, table, pre {
  margin: 15px 0;
}

hr {
  background: transparent url("http://tinyurl.com/bq5kskr") repeat-x 0 0;
  border: 0 none;
  color: #cccccc;
  height: 4px;
  padding: 0;
}

body > h2:first-child {
  margin-top: 0;
  padding-top: 0;
}

body > h1:first-child {
  margin-top: 0;
  padding-top: 0;
}

body > h1:first-child + h2 {
  margin-top: 0;
  padding-top: 0;
}

body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
  margin-top: 0;
  padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0;
}

h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
  margin-top: 0;
}

li p.first {
  display: inline-block;
}

ul, ol {
  padding-left: 30px;
}

ul :first-child, ol :first-child {
  margin-top: 0;
}

ul :last-child, ol :last-child {
  margin-bottom: 0;
}

dl {
  padding: 0;
}

dl dt {
  font-size: 14px;
  font-weight: bold;
  font-style: italic;
  padding: 0;
  margin: 15px 0 5px;
}

dl dt:first-child {
  padding: 0;
}

dl dt > :first-child {
  margin-top: 0;
}

dl dt > :last-child {
  margin-bottom: 0;
}

dl dd {
  margin: 0 0 15px;
  padding: 0 15px;
}

dl dd > :first-child {
  margin-top: 0;
}

dl dd > :last-child {
  margin-bottom: 0;
}

blockquote {
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777;
}

blockquote > :first-child {
  margin-top: 0;
}

blockquote > :last-child {
  margin-bottom: 0;
}

table {
  padding: 0;
  border-spacing: 0;
  border-collapse: collapse;
}

table tr {
  border-top: 1px solid #cccccc;
  background-color: white;
  margin: 0;
  padding: 0;
}

table tr:nth-child(2n) {
  background-color: #f7f7f7;
}

table th {
  border: 1px solid #cccccc;
  font-weight: bold;
  text-align: left;
  margin: 0;
  padding: 5px 10px;
  background-color: #f0f0f0;
}

table td {
  border: 1px solid #cccccc;
  text-align: left;
  margin: 0;
  padding: 5px 10px;
}

table tr th :first-child, table tr td :first-child {
  margin-top: 0;
}

table tr th :last-child, table tr td :last-child {
  margin-bottom: 0;
}

img {
  max-width: 100%;
}

span.frame {
  display: block;
  overflow: hidden;
}

span.frame > span {
  border: 1px solid #dddddd;
  display: block;
  float: left;
  overflow: hidden;
  margin: 13px 0 0;
  padding: 7px;
  width: auto;
}

span.frame span img {
  display: block;
  float: left;
}

span.frame span span {
  clear: both;
  color: #333333;
  display: block;
  padding: 5px 0 0;
}

span.align-center {
  display: block;
  overflow: hidden;
  clear: both;
}

span.align-center > span {
  display: block;
  overflow: hidden;
  margin: 13px auto 0;
  text-align: center;
}

span.align-center span img {
  margin: 0 auto;
  text-align: center;
}

span.align-right {
  display: block;
  overflow: hidden;
  clear: both;
}

span.align-right > span {
  display: block;
  overflow: hidden;
  margin: 13px 0 0;
  text-align: right;
}

span.align-right span img {
  margin: 0;
  text-align: right;
}

span.float-left {
  display: block;
  margin-right: 13px;
  overflow: hidden;
  float: left;
}

span.float-left span {
  margin: 13px 0 0;
}

span.float-right {
  display: block;
  margin-left: 13px;
  overflow: hidden;
  float: right;
}

span.float-right > span {
  display: block;
  overflow: hidden;
  margin: 13px auto 0;
  text-align: right;
}

code, tt {
  margin: 0 2px;
  padding: 0 5px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px;
}

pre code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent;
}

.highlight pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}

pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}

pre code, pre tt {
  background-color: transparent;
  border: none;
}`

 MD_TEMPLATE = `# Change Log

{{ range $release := .Changelog }}## Release {{ .Version }} ({{ .Date }})

{{ .Summary }}

{{ if .Added }}### Added

{{ range $entry := .Added }}- {{ . }}
{{ end }}{{ end }}

{{ if .Changed }}### Changed

{{ range $entry := .Changed }}- {{ . }}
{{ end }}{{ end }}

{{ if .Deprecated }}### Deprecated

{{ range $entry := .Deprecated }}- {{ . }}
{{ end }}{{ end }}

{{ if .Removed }}### Removed

{{ range $entry := .Removed }}- {{ . }}
{{ end }}{{ end }}

{{ if .Fixed }}### Fixed

{{ range $entry := .Fixed }}- {{ . }}
{{ end }}{{ end }}

{{ if .Security }}### Security

{{ range $entry := .Security }}- {{ . }}
{{ end }}{{ end }}{{ end }}
`
)

type TemplateData struct {
	Changelog   *Changelog
	Stylesheets []string
}

func toHtml(changelog *Changelog, args []string) {
	stylesheets := make([]string, 0)
	for _, file := range args {
		var stylesheet []byte
		var err error
		if file == "style" {
			stylesheet = []byte(STYLESHEET)
		} else {
			stylesheet, err = ioutil.ReadFile(file)
			if err != nil {
				Errorf(ERROR_TRANSFORM, "Error loading stylesheet %s: %s", file, err.Error())
			}
		}
		stylesheets = append(stylesheets, string(stylesheet))
	}
	data := TemplateData{
		Stylesheets: stylesheets,
		Changelog:   changelog,
	}
	t := template.Must(template.New("changelog").Parse(HTML_TEMPLATE))
	err := t.Execute(os.Stdout, data)
	if err != nil {
		Errorf(ERROR_TRANSFORM, "Error processing template: %s", err)
	}
}

func toMarkdown(changelog *Changelog) {
	data := TemplateData{
		Stylesheets: nil,
		Changelog:   changelog,
	}
	t := template.Must(template.New("changelog").Parse(MD_TEMPLATE))
	err := t.Execute(os.Stdout, data)
	if err != nil {
		Errorf(ERROR_TRANSFORM, "Error processing template: %s", err)
	}
}

func transform(changelog *Changelog, args []string) {
	checkChangelog(changelog)
	if len(args) < 1 {
		Error(ERROR_TRANSFORM, "You must pass format to transform to")
	}
	format := args[0]
	if format == "html" {
     toHtml(changelog, args[1:])
	} else if format == "markdown" {
     toMarkdown(changelog)
  } else {
      Errorf(ERROR_TRANSFORM, "Unknown format %s", args[0])
   }
}
<commit_msg>Improved markdown output<commit_after>package main

import (
	"io/ioutil"
	"os"
	"text/template"
)

const (
	HTML_TEMPLATE = `<!DOCTYPE html>

<title>Change Log</title>
<meta charset="utf-8">
{{ range $stylesheet := .Stylesheets }}

{{ end }}

Change Log

{{ range $release := .Changelog }}

Release {{ .Version }} ({{ .Date }})

{{ .Summary }}

{{ if .Added }}

Added

{{ range $entry := .Added }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Changed }}

Changed

{{ range $entry := .Changed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Deprecated }}

Deprecated

{{ range $entry := .Deprecated }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Removed }}

Removed

{{ range $entry := .Removed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Fixed }}

Fixed

{{ range $entry := .Fixed }}

{{ . }}

{{ end }}

{{ end }}
{{ if .Security }}

Security

{{ range $entry := .Security }}

{{ . }}

{{ end }}

{{ end }}
{{ end }}

`
	STYLESHEET = `
body {
  font-family: Helvetica, arial, sans-serif;
  font-size: 16px;
  line-height: 1.4;
  padding-top: 10px;
  padding-bottom: 10px;
  background-color: white;
  padding: 30px;
  color: #333;
}

body > *:first-child {
  margin-top: 0 !important;
}

body > *:last-child {
  margin-bottom: 0 !important;
}

a {
  color: #4183C4;
  text-decoration: none;
}

a.absent {
  color: #cc0000;
}

a.anchor {
  display: block;
  padding-left: 30px;
  margin-left: -30px;
  cursor: pointer;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
}

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
  cursor: text;
  position: relative;
}

h2:first-child, h1:first-child, h1:first-child + h2, h3:first-child, h4:first-child, h5:first-child, h6:first-child {
  margin-top: 0;
  padding-top: 0;
}

h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
  text-decoration: none;
}

h1 tt, h1 code {
  font-size: inherit;
}

h2 tt, h2 code {
  font-size: inherit;
}

h3 tt, h3 code {
  font-size: inherit;
}

h4 tt, h4 code {
  font-size: inherit;
}

h5 tt, h5 code {
  font-size: inherit;
}

h6 tt, h6 code {
  font-size: inherit;
}

h1 {
  font-size: 32px;
  color: black;
}

h2 {
  font-size: 28px;
  border-bottom: 1px solid #cccccc;
  color: black;
}

h3 {
  font-size: 20px;
}

h4 {
  font-size: 16px;
}

h5 {
  font-size: 14px;
}

h6 {
  color: #777777;
  font-size: 14px;
}

p, blockquote, ul, ol, dl, table, pre {
  margin: 15px 0;
}

hr {
  background: transparent url("http://tinyurl.com/bq5kskr") repeat-x 0 0;
  border: 0 none;
  color: #cccccc;
  height: 4px;
  padding: 0;
}

body > h2:first-child {
  margin-top: 0;
  padding-top: 0;
}

body > h1:first-child {
  margin-top: 0;
  padding-top: 0;
}

body > h1:first-child + h2 {
  margin-top: 0;
  padding-top: 0;
}

body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
  margin-top: 0;
  padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0;
}

h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
  margin-top: 0;
}

li p.first {
  display: inline-block;
}

ul, ol {
  padding-left: 30px;
}

ul :first-child, ol :first-child {
  margin-top: 0;
}

ul :last-child, ol :last-child {
  margin-bottom: 0;
}

dl {
  padding: 0;
}

dl dt {
  font-size: 14px;
  font-weight: bold;
  font-style: italic;
  padding: 0;
  margin: 15px 0 5px;
}

dl dt:first-child {
  padding: 0;
}

dl dt > :first-child {
  margin-top: 0;
}

dl dt > :last-child {
  margin-bottom: 0;
}

dl dd {
  margin: 0 0 15px;
  padding: 0 15px;
}

dl dd > :first-child {
  margin-top: 0;
}

dl dd > :last-child {
  margin-bottom: 0;
}

blockquote {
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777;
}

blockquote > :first-child {
  margin-top: 0;
}

blockquote > :last-child {
  margin-bottom: 0;
}

table {
  padding: 0;
  border-spacing: 0;
  border-collapse: collapse;
}

table tr {
  border-top: 1px solid #cccccc;
  background-color: white;
  margin: 0;
  padding: 0;
}

table tr:nth-child(2n) {
  background-color: #f7f7f7;
}

table th {
  border: 1px solid #cccccc;
  font-weight: bold;
  text-align: left;
  margin: 0;
  padding: 5px 10px;
  background-color: #f0f0f0;
}

table td {
  border: 1px solid #cccccc;
  text-align: left;
  margin: 0;
  padding: 5px 10px;
}

table tr th :first-child, table tr td :first-child {
  margin-top: 0;
}

table tr th :last-child, table tr td :last-child {
  margin-bottom: 0;
}

img {
  max-width: 100%;
}

span.frame {
  display: block;
  overflow: hidden;
}

span.frame > span {
  border: 1px solid #dddddd;
  display: block;
  float: left;
  overflow: hidden;
  margin: 13px 0 0;
  padding: 7px;
  width: auto;
}

span.frame span img {
  display: block;
  float: left;
}

span.frame span span {
  clear: both;
  color: #333333;
  display: block;
  padding: 5px 0 0;
}

span.align-center {
  display: block;
  overflow: hidden;
  clear: both;
}

span.align-center > span {
  display: block;
  overflow: hidden;
  margin: 13px auto 0;
  text-align: center;
}

span.align-center span img {
  margin: 0 auto;
  text-align: center;
}

span.align-right {
  display: block;
  overflow: hidden;
  clear: both;
}

span.align-right > span {
  display: block;
  overflow: hidden;
  margin: 13px 0 0;
  text-align: right;
}

span.align-right span img {
  margin: 0;
  text-align: right;
}

span.float-left {
  display: block;
  margin-right: 13px;
  overflow: hidden;
  float: left;
}

span.float-left span {
  margin: 13px 0 0;
}

span.float-right {
  display: block;
  margin-left: 13px;
  overflow: hidden;
  float: right;
}

span.float-right > span {
  display: block;
  overflow: hidden;
  margin: 13px auto 0;
  text-align: right;
}

code, tt {
  margin: 0 2px;
  padding: 0 5px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px;
}

pre code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent;
}

.highlight pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}

pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}

pre code, pre tt {
  background-color: transparent;
  border: none;
}`

 MD_TEMPLATE = `# Change Log

{{ range $release := .Changelog }}## Release {{ .Version }} ({{ .Date }})

{{ if .Summary }}{{ .Summary }}{{ end }}

{{ if .Added }}### Added

{{ range $entry := .Added }}- {{ . }}
{{ end }}{{ end }}{{ if .Changed }}### Changed

{{ range $entry := .Changed }}- {{ . }}
{{ end }}{{ end }}{{ if .Deprecated }}### Deprecated

{{ range $entry := .Deprecated }}- {{ . }}
{{ end }}{{ end }}{{ if .Removed }}### Removed

{{ range $entry := .Removed }}- {{ . }}
{{ end }}{{ end }}{{ if .Fixed }}### Fixed

{{ range $entry := .Fixed }}- {{ . }}
{{ end }}{{ end }}{{ if .Security }}### Security

{{ range $entry := .Security }}- {{ . }}
{{ end }}{{ end }}{{ end }}`
)

type TemplateData struct {
	Changelog   *Changelog
	Stylesheets []string
}

func toHtml(changelog *Changelog, args []string) {
	stylesheets := make([]string, 0)
	for _, file := range args {
		var stylesheet []byte
		var err error
		if file == "style" {
			stylesheet = []byte(STYLESHEET)
		} else {
			stylesheet, err = ioutil.ReadFile(file)
			if err != nil {
				Errorf(ERROR_TRANSFORM, "Error loading stylesheet %s: %s", file, err.Error())
			}
		}
		stylesheets = append(stylesheets, string(stylesheet))
	}
	data := TemplateData{
		Stylesheets: stylesheets,
		Changelog:   changelog,
	}
	t := template.Must(template.New("changelog").Parse(HTML_TEMPLATE))
	err := t.Execute(os.Stdout, data)
	if err != nil {
		Errorf(ERROR_TRANSFORM, "Error processing template: %s", err)
	}
}

func toMarkdown(changelog *Changelog) {
	data := TemplateData{
		Stylesheets: nil,
		Changelog:   changelog,
	}
	t := template.Must(template.New("changelog").Parse(MD_TEMPLATE))
	err := t.Execute(os.Stdout, data)
	if err != nil {
		Errorf(ERROR_TRANSFORM, "Error processing template: %s", err)
	}
}

func transform(changelog *Changelog, args []string) {
	checkChangelog(changelog)
	if len(args) < 1 {
		Error(ERROR_TRANSFORM, "You must pass format to transform to")
	}
	format := args[0]
	if format == "html" {
     toHtml(changelog, args[1:])
	} else if format == "markdown" {
     toMarkdown(changelog)
  } else {
      Errorf(ERROR_TRANSFORM, "Unknown format %s", args[0])
   }
}
<|endoftext|>


<commit_before>package moves

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/url"
	"time"
)

// Transport implements http.RoundTripper. When configured, it can be
// used to make authenticated HTTP requests.
type Transport struct {
	// Key is the identifier string generated by the API for the handshake.
	// The key can be treated as a username.
	Key string

	// Secret is the unique token generated for signing requests.
	// The secret must be kept private.
	Secret string

	// CallbackURI is an absolute URI back to which the server will redirect the
	// resource owner when the Authorization step is completed. If omitted, the
	// default callback URI is used.
	CallbackURI string

	// Token contains an end-user's tokens.
	// This may be a set of temporary credentials.
	Token *Token

	// TokenCache allows tokens to be cached for subsequent requests.
	TokenCache Cache

	// Transport is the HTTP transport to use when making requests.
	// It will default to http.DefaultTransport if nil.
	// It should never be a moves.Transport.
	Transport http.RoundTripper
}

// DefaultTransport implements http.RoundTripper. With a valid token, it
// can be used to make authenticated HTTP requests.
type DefaultTransport struct {
	Token string
}

// AuthorizationURI is an absolute URI used to generate a code that
// can in turn be used to request an access token.
const AuthorizationURI = "https://api.moves-app.com/oauth/v1/authorize"

// ExchangeURI is an absolute URI used to request a set of token
// credentials using the authorization code.
const ExchangeURI = "https://api.moves-app.com/oauth/v1/access_token"

var (
	ErrNoToken        = errors.New("moves: token is nil")
	ErrNoRefreshToken = errors.New("moves: refresh token is empty")
)

// AuthCodeURL returns a URL that the end-user should be redirected to,
// so that they may obtain an authorization code.
func (t *Transport) AuthCodeURL(state string) string {
	auth, err := url.Parse(AuthorizationURI)
	if err != nil {
		panic("AuthorizationURI malformed: " + err.Error())
	}

	q := url.Values{
		"response_type": {"code"},
		"client_id":     {t.Key},
		"scope":         {"activity location"},
		"state":         {state},
	}

	if t.CallbackURI != "" {
		q.Add("redirect_uri", t.CallbackURI)
	}

	if auth.RawQuery == "" {
		auth.RawQuery = q.Encode()
	} else {
		auth.RawQuery += "&" + q.Encode()
	}

	return auth.String()
}

// Exchange takes a code and gets an access Token from the remote server.
func (t *Transport) Exchange(code string) (*Token, error) {
	if t.Token == nil && t.TokenCache != nil {
		t.Token, _ = t.TokenCache.Token()
	}

	if t.Token == nil {
		t.Token = &Token{}
	}

	q := url.Values{
		"grant_type":    {"authorization_code"},
		"code":          {code},
		"client_id":     {t.Key},
		"client_secret": {t.Secret},
	}

	if t.CallbackURI != "" {
		q.Add("redirect_uri", t.CallbackURI)
	}

	err := t.update(q)
	if err != nil {
		return nil, err
	}

	if t.TokenCache != nil {
		return t.Token, t.TokenCache.PutToken(t.Token)
	}

	return t.Token, nil
}

// Refresh renews the Transport's token using its refresh token.
func (t *Transport) Refresh() error {
	if t.Token == nil {
		return ErrNoToken
	}

	if t.Token.Refresh == "" {
		return ErrNoRefreshToken
	}

	q := url.Values{
		"grant_type":    {"refresh_token"},
		"refresh_token": {t.Token.Refresh},
		"client_id":     {t.Key},
		"client_secret": {t.Secret},
	}

	err := t.update(q)
	if err != nil {
		return err
	}

	if t.TokenCache != nil {
		return t.TokenCache.PutToken(t.Token)
	}

	return nil
}

// RoundTrip executes a single HTTP transaction using the Transport's Token as
// authorization headers.
//
// This method will attempt to renew the Token if it has expired and may return
// an error related to that Token renewal before attempting the client request.
// If the Token cannot be renewed a non-nil os.Error value will be returned.
// If the Token is invalid callers should expect HTTP-level errors,
// as indicated by the Response's StatusCode.
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
	if t.Token == nil {
		if t.TokenCache == nil {
			return nil, ErrNoToken
		}

		var err error
		t.Token, err = t.TokenCache.Token()
		if err != nil {
			return nil, err
		}
	}

	if t.Token.Expired() {
		err := t.Refresh()
		if err != nil {
			return nil, err
		}
	}

	// This is so that we don't modify the original request as specified
	// in the documentation for http.RoundTripper.
	req = cloneRequest(req)
	req.Header.Set("Authorization", "Bearer "+t.Token.Access)

	return t.transport().RoundTrip(req)
}

// Client returns a new Client that can make authenticated requests.
func (t *Transport) Client() *Client {
	return &Client{
		Client:  &http.Client{Transport: t},
		BaseURI: BaseURI,
	}
}

// transport returns the configured Transport, or the http.DefaultTransport.
func (t *Transport) transport() http.RoundTripper {
	if t.Transport != nil {
		return t.Transport
	}

	return http.DefaultTransport
}

// update requests a new access token.
func (t *Transport) update(q url.Values) error {
	update, err := url.Parse(ExchangeURI)
	if err != nil {
		panic("ExchangeURI malformed: " + err.Error())
	}

	if update.RawQuery == "" {
		update.RawQuery = q.Encode()
	} else {
		update.RawQuery += "&" + q.Encode()
	}

	// Empty JSON body so that we don't get HTML back on error.
	body := bytes.NewReader([]byte("{}"))
	resp, err := http.Post(update.String(), "application/json", body)
	if err != nil {
		return err
	}

	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		var accessTokenError struct {
			Code string `json:"error"`
		}

		err = json.NewDecoder(resp.Body).Decode(&accessTokenError)
		if err != nil {
			return err
		}

		return errors.New(accessTokenError.Code)
	}

	var b struct {
		AccessToken  string        `json:"access_token"`
		RefreshToken string        `json:"refresh_token"`
		ExpiresIn    time.Duration `json:"expires_in"`
		UserId       uint64        `json:"user_id"`
	}

	err = json.NewDecoder(resp.Body).Decode(&b)
	if err != nil {
		return err
	}

	t.Token.Access = b.AccessToken
	t.Token.UserId = b.UserId

	if b.RefreshToken != "" {
		t.Token.Refresh = b.RefreshToken
	}

	// The JSON decoder treats ExpiresIn as nanoseconds instead of seconds.
	b.ExpiresIn *= time.Second
	if b.ExpiresIn == 0 {
		t.Token.Expiry = time.Time{}
	} else {
		t.Token.Expiry = time.Now().Add(b.ExpiresIn).UTC()
	}

	return nil
}

// RoundTrip executes a single HTTP transaction using the Transport's Token as
// authorization headers.
func (t *DefaultTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	// This is so that we don't modify the original request as specified
	// in the documentation for http.RoundTripper.
	req = cloneRequest(req)
	req.Header.Set("Authorization", "Bearer "+t.Token)

	return http.DefaultTransport.RoundTrip(req)
}

// cloneRequest returns a copy of the given request.
func cloneRequest(r *http.Request) *http.Request {
	// shallow copy of the struct
	r2 := new(http.Request)
	*r2 = *r
	// deep copy of the Header
	r2.Header = make(http.Header)
	for k, s := range r.Header {
		r2.Header[k] = s
	}
	return r2
}
<commit_msg>Rename ExchangeURI to TokenURI.<commit_after>package moves

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/url"
	"time"
)

// Transport implements http.RoundTripper. When configured, it can be
// used to make authenticated HTTP requests.
type Transport struct {
	// Key is the identifier string generated by the API for the handshake.
	// The key can be treated as a username.
	Key string

	// Secret is the unique token generated for signing requests.
	// The secret must be kept private.
	Secret string

	// CallbackURI is an absolute URI back to which the server will redirect the
	// resource owner when the Authorization step is completed. If omitted, the
	// default callback URI is used.
	CallbackURI string

	// Token contains an end-user's tokens.
	// This may be a set of temporary credentials.
	Token *Token

	// TokenCache allows tokens to be cached for subsequent requests.
	TokenCache Cache

	// Transport is the HTTP transport to use when making requests.
	// It will default to http.DefaultTransport if nil.
	// It should never be a moves.Transport.
	Transport http.RoundTripper
}

// DefaultTransport implements http.RoundTripper. With a valid token, it
// can be used to make authenticated HTTP requests.
type DefaultTransport struct {
	Token string
}

// AuthorizationURI is an absolute URI used to generate a code that
// can in turn be used to request an access token.
const AuthorizationURI = "https://api.moves-app.com/oauth/v1/authorize"

// TokenURI is an absolute URI used to request a set of token
// credentials using the authorization code.
const TokenURI = "https://api.moves-app.com/oauth/v1/access_token"

var (
	ErrNoToken        = errors.New("moves: token is nil")
	ErrNoRefreshToken = errors.New("moves: refresh token is empty")
)

// AuthCodeURL returns a URL that the end-user should be redirected to,
// so that they may obtain an authorization code.
func (t *Transport) AuthCodeURL(state string) string {
	auth, err := url.Parse(AuthorizationURI)
	if err != nil {
		panic("AuthorizationURI malformed: " + err.Error())
	}

	q := url.Values{
		"response_type": {"code"},
		"client_id":     {t.Key},
		"scope":         {"activity location"},
		"state":         {state},
	}

	if t.CallbackURI != "" {
		q.Add("redirect_uri", t.CallbackURI)
	}

	if auth.RawQuery == "" {
		auth.RawQuery = q.Encode()
	} else {
		auth.RawQuery += "&" + q.Encode()
	}

	return auth.String()
}

// Exchange takes a code and gets an access Token from the remote server.
func (t *Transport) Exchange(code string) (*Token, error) {
	if t.Token == nil && t.TokenCache != nil {
		t.Token, _ = t.TokenCache.Token()
	}

	if t.Token == nil {
		t.Token = &Token{}
	}

	q := url.Values{
		"grant_type":    {"authorization_code"},
		"code":          {code},
		"client_id":     {t.Key},
		"client_secret": {t.Secret},
	}

	if t.CallbackURI != "" {
		q.Add("redirect_uri", t.CallbackURI)
	}

	err := t.update(q)
	if err != nil {
		return nil, err
	}

	if t.TokenCache != nil {
		return t.Token, t.TokenCache.PutToken(t.Token)
	}

	return t.Token, nil
}

// Refresh renews the Transport's token using its refresh token.
func (t *Transport) Refresh() error {
	if t.Token == nil {
		return ErrNoToken
	}

	if t.Token.Refresh == "" {
		return ErrNoRefreshToken
	}

	q := url.Values{
		"grant_type":    {"refresh_token"},
		"refresh_token": {t.Token.Refresh},
		"client_id":     {t.Key},
		"client_secret": {t.Secret},
	}

	err := t.update(q)
	if err != nil {
		return err
	}

	if t.TokenCache != nil {
		return t.TokenCache.PutToken(t.Token)
	}

	return nil
}

// RoundTrip executes a single HTTP transaction using the Transport's Token as
// authorization headers.
//
// This method will attempt to renew the Token if it has expired and may return
// an error related to that Token renewal before attempting the client request.
// If the Token cannot be renewed a non-nil os.Error value will be returned.
// If the Token is invalid callers should expect HTTP-level errors,
// as indicated by the Response's StatusCode.
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
	if t.Token == nil {
		if t.TokenCache == nil {
			return nil, ErrNoToken
		}

		var err error
		t.Token, err = t.TokenCache.Token()
		if err != nil {
			return nil, err
		}
	}

	if t.Token.Expired() {
		err := t.Refresh()
		if err != nil {
			return nil, err
		}
	}

	// This is so that we don't modify the original request as specified
	// in the documentation for http.RoundTripper.
	req = cloneRequest(req)
	req.Header.Set("Authorization", "Bearer "+t.Token.Access)

	return t.transport().RoundTrip(req)
}

// Client returns a new Client that can make authenticated requests.
func (t *Transport) Client() *Client {
	return &Client{
		Client:  &http.Client{Transport: t},
		BaseURI: BaseURI,
	}
}

// transport returns the configured Transport, or the http.DefaultTransport.
func (t *Transport) transport() http.RoundTripper {
	if t.Transport != nil {
		return t.Transport
	}

	return http.DefaultTransport
}

// update requests a new access token.
func (t *Transport) update(q url.Values) error {
	update, err := url.Parse(TokenURI)
	if err != nil {
		panic("ExchangeURI malformed: " + err.Error())
	}

	if update.RawQuery == "" {
		update.RawQuery = q.Encode()
	} else {
		update.RawQuery += "&" + q.Encode()
	}

	// Empty JSON body so that we don't get HTML back on error.
	body := bytes.NewReader([]byte("{}"))
	resp, err := http.Post(update.String(), "application/json", body)
	if err != nil {
		return err
	}

	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		var accessTokenError struct {
			Code string `json:"error"`
		}

		err = json.NewDecoder(resp.Body).Decode(&accessTokenError)
		if err != nil {
			return err
		}

		return errors.New(accessTokenError.Code)
	}

	var b struct {
		AccessToken  string        `json:"access_token"`
		RefreshToken string        `json:"refresh_token"`
		ExpiresIn    time.Duration `json:"expires_in"`
		UserId       uint64        `json:"user_id"`
	}

	err = json.NewDecoder(resp.Body).Decode(&b)
	if err != nil {
		return err
	}

	t.Token.Access = b.AccessToken
	t.Token.UserId = b.UserId

	if b.RefreshToken != "" {
		t.Token.Refresh = b.RefreshToken
	}

	// The JSON decoder treats ExpiresIn as nanoseconds instead of seconds.
	b.ExpiresIn *= time.Second
	if b.ExpiresIn == 0 {
		t.Token.Expiry = time.Time{}
	} else {
		t.Token.Expiry = time.Now().Add(b.ExpiresIn).UTC()
	}

	return nil
}

// RoundTrip executes a single HTTP transaction using the Transport's Token as
// authorization headers.
func (t *DefaultTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	// This is so that we don't modify the original request as specified
	// in the documentation for http.RoundTripper.
	req = cloneRequest(req)
	req.Header.Set("Authorization", "Bearer "+t.Token)

	return http.DefaultTransport.RoundTrip(req)
}

// cloneRequest returns a copy of the given request.
func cloneRequest(r *http.Request) *http.Request {
	// shallow copy of the struct
	r2 := new(http.Request)
	*r2 = *r
	// deep copy of the Header
	r2.Header = make(http.Header)
	for k, s := range r.Header {
		r2.Header[k] = s
	}
	return r2
}
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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 typed

import (
	"sigs.k8s.io/structured-merge-diff/fieldpath"
	"sigs.k8s.io/structured-merge-diff/schema"
	"sigs.k8s.io/structured-merge-diff/value"
)

func (tv TypedValue) walker() *validatingObjectWalker {
	return &validatingObjectWalker{
		value:   tv.value,
		schema:  tv.schema,
		typeRef: tv.typeRef,
	}
}

type validatingObjectWalker struct {
	errorFormatter
	value   value.Value
	schema  *schema.Schema
	typeRef schema.TypeRef

	// If set, this is called on "leaf fields":
	//  * scalars: int/string/float/bool
	//  * atomic maps and lists
	//  * untyped fields
	leafFieldCallback func(fieldpath.Path)

	// If set, this is called on "node fields":
	//  * list items
	//  * map items
	nodeFieldCallback func(fieldpath.Path)

	// internal housekeeping--don't set when constructing.
	inLeaf bool // Set to true if we're in a "big leaf"--atomic map/list
}

func (v validatingObjectWalker) validate() ValidationErrors {
	return resolveSchema(v.schema, v.typeRef, &v.value, v)
}

// doLeaf should be called on leaves before descending into children, if there
// will be a descent. It modifies v.inLeaf.
func (v *validatingObjectWalker) doLeaf() {
	if v.inLeaf {
		// We're in a "big leaf", an atomic map or list. Ignore
		// subsequent leaves.
		return
	}
	v.inLeaf = true

	if v.leafFieldCallback != nil {
		// At the moment, this is only used to build fieldsets; we can
		// add more than the path in here if needed.
		v.leafFieldCallback(v.path)
	}
}

// doNode should be called on nodes after descending into children
func (v *validatingObjectWalker) doNode() {
	if v.inLeaf {
		// We're in a "big leaf", an atomic map or list. Ignore
		// subsequent leaves.
		return
	}

	if v.nodeFieldCallback != nil {
		// At the moment, this is only used to build fieldsets; we can
		// add more than the path in here if needed.
		v.nodeFieldCallback(v.path)
	}
}

func (v validatingObjectWalker) doScalar(t schema.Scalar) ValidationErrors {
	if errs := v.validateScalar(t, &v.value, ""); len(errs) > 0 {
		return errs
	}

	// All scalars are leaf fields.
	v.doLeaf()

	return nil
}

func (v validatingObjectWalker) visitListItems(t schema.List, list *value.List) (errs ValidationErrors) {
	observedKeys := map[string]struct{}{}
	for i, child := range list.Items {
		pe, err := listItemToPathElement(t, i, child)
		if err != nil {
			errs = append(errs, v.errorf("element %v: %v", i, err.Error())...)
			// If we can't construct the path element, we can't
			// even report errors deeper in the schema, so bail on
			// this element.
			continue
		}
		keyStr := pe.String()
		if _, found := observedKeys[keyStr]; found {
			errs = append(errs, v.errorf("duplicate entries for key %v", keyStr)...)
		}
		observedKeys[keyStr] = struct{}{}
		v2 := v
		v2.errorFormatter.descend(pe)
		v2.value = child
		v2.typeRef = t.ElementType
		errs = append(errs, v2.validate()...)

		v2.doNode()
	}
	return errs
}

func (v validatingObjectWalker) doList(t schema.List) (errs ValidationErrors) {
	list, err := listValue(v.value)
	if err != nil {
		return v.error(err)
	}

	if t.ElementRelationship == schema.Atomic {
		v.doLeaf()
	}

	if list == nil {
		return nil
	}

	errs = v.visitListItems(t, list)

	return errs
}

func (v validatingObjectWalker) visitMapItems(t schema.Map, m *value.Map) (errs ValidationErrors) {
	fieldTypes := map[string]schema.TypeRef{}
	for i := range t.Fields {
		// I don't want to use the loop variable since a reference
		// might outlive the loop iteration (in an error message).
		f := t.Fields[i]
		fieldTypes[f.Name] = f.Type
	}

	for _, item := range m.Items {
		v2 := v
		name := item.Name
		v2.errorFormatter.descend(fieldpath.PathElement{FieldName: &name})
		v2.value = item.Value

		var ok bool
		if v2.typeRef, ok = fieldTypes[name]; ok {
			errs = append(errs, v2.validate()...)
		} else {
			v2.typeRef = t.ElementType
			errs = append(errs, v2.validate()...)
			v2.doNode()
		}
	}
	return errs
}

func (v validatingObjectWalker) doMap(t schema.Map) (errs ValidationErrors) {
	m, err := mapValue(v.value)
	if err != nil {
		return v.error(err)
	}

	if t.ElementRelationship == schema.Atomic {
		v.doLeaf()
	}

	if m == nil {
		return nil
	}

	errs = v.visitMapItems(t, m)

	return errs
}
<commit_msg>propagate memory management improvements to validator<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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 typed

import (
	"sigs.k8s.io/structured-merge-diff/fieldpath"
	"sigs.k8s.io/structured-merge-diff/schema"
	"sigs.k8s.io/structured-merge-diff/value"
)

func (tv TypedValue) walker() *validatingObjectWalker {
	return &validatingObjectWalker{
		value:   tv.value,
		schema:  tv.schema,
		typeRef: tv.typeRef,
	}
}

type validatingObjectWalker struct {
	errorFormatter
	value   value.Value
	schema  *schema.Schema
	typeRef schema.TypeRef

	// If set, this is called on "leaf fields":
	//  * scalars: int/string/float/bool
	//  * atomic maps and lists
	//  * untyped fields
	leafFieldCallback func(fieldpath.Path)

	// If set, this is called on "node fields":
	//  * list items
	//  * map items
	nodeFieldCallback func(fieldpath.Path)

	// internal housekeeping--don't set when constructing.
	inLeaf bool // Set to true if we're in a "big leaf"--atomic map/list

	// Allocate only as many walkers as needed for the depth by storing them here.
	spareWalkers *[]*validatingObjectWalker
}

func (v *validatingObjectWalker) prepareDescent(pe fieldpath.PathElement, tr schema.TypeRef) *validatingObjectWalker {
	if v.spareWalkers == nil {
		// first descent.
		v.spareWalkers = &[]*validatingObjectWalker{}
	}
	var v2 *validatingObjectWalker
	if n := len(*v.spareWalkers); n > 0 {
		v2, *v.spareWalkers = (*v.spareWalkers)[n-1], (*v.spareWalkers)[:n-1]
	} else {
		v2 = &validatingObjectWalker{}
	}
	*v2 = *v
	v2.typeRef = tr
	v2.errorFormatter.descend(pe)
	return v2
}

func (v *validatingObjectWalker) finishDescent(v2 *validatingObjectWalker) {
	// if the descent caused a realloc, ensure that we reuse the buffer
	// for the next sibling.
	v.errorFormatter = v2.errorFormatter.parent()
	*v.spareWalkers = append(*v.spareWalkers, v2)
}

func (v *validatingObjectWalker) validate() ValidationErrors {
	return resolveSchema(v.schema, v.typeRef, &v.value, v)
}

// doLeaf should be called on leaves before descending into children, if there
// will be a descent. It modifies v.inLeaf.
func (v *validatingObjectWalker) doLeaf() {
	if v.inLeaf {
		// We're in a "big leaf", an atomic map or list. Ignore
		// subsequent leaves.
		return
	}
	v.inLeaf = true

	if v.leafFieldCallback != nil {
		// At the moment, this is only used to build fieldsets; we can
		// add more than the path in here if needed.
		v.leafFieldCallback(v.path)
	}
}

// doNode should be called on nodes after descending into children
func (v *validatingObjectWalker) doNode() {
	if v.inLeaf {
		// We're in a "big leaf", an atomic map or list. Ignore
		// subsequent leaves.
		return
	}

	if v.nodeFieldCallback != nil {
		// At the moment, this is only used to build fieldsets; we can
		// add more than the path in here if needed.
		v.nodeFieldCallback(v.path)
	}
}

func (v *validatingObjectWalker) doScalar(t schema.Scalar) ValidationErrors {
	if errs := v.validateScalar(t, &v.value, ""); len(errs) > 0 {
		return errs
	}

	// All scalars are leaf fields.
	v.doLeaf()

	return nil
}

func (v *validatingObjectWalker) visitListItems(t schema.List, list *value.List) (errs ValidationErrors) {
	observedKeys := map[string]struct{}{}
	for i, child := range list.Items {
		pe, err := listItemToPathElement(t, i, child)
		if err != nil {
			errs = append(errs, v.errorf("element %v: %v", i, err.Error())...)
			// If we can't construct the path element, we can't
			// even report errors deeper in the schema, so bail on
			// this element.
			continue
		}
		keyStr := pe.String()
		if _, found := observedKeys[keyStr]; found {
			errs = append(errs, v.errorf("duplicate entries for key %v", keyStr)...)
		}
		observedKeys[keyStr] = struct{}{}
		v2 := v.prepareDescent(pe, t.ElementType)
		v2.value = child
		errs = append(errs, v2.validate()...)

		v2.doNode()
		v.finishDescent(v2)
	}
	return errs
}

func (v *validatingObjectWalker) doList(t schema.List) (errs ValidationErrors) {
	list, err := listValue(v.value)
	if err != nil {
		return v.error(err)
	}

	if t.ElementRelationship == schema.Atomic {
		v.doLeaf()
	}

	if list == nil {
		return nil
	}

	errs = v.visitListItems(t, list)

	return errs
}

func (v *validatingObjectWalker) visitMapItems(t schema.Map, m *value.Map) (errs ValidationErrors) {
	fieldTypes := map[string]schema.TypeRef{}
	for i := range t.Fields {
		// I don't want to use the loop variable since a reference
		// might outlive the loop iteration (in an error message).
		f := t.Fields[i]
		fieldTypes[f.Name] = f.Type
	}

	for i := range m.Items {
		item := &m.Items[i]
		pe := fieldpath.PathElement{FieldName: &item.Name}

		if tr, ok := fieldTypes[item.Name]; ok {
			v2 := v.prepareDescent(pe, tr)
			v2.value = item.Value
			errs = append(errs, v2.validate()...)
			v.finishDescent(v2)
		} else {
			v2 := v.prepareDescent(pe, t.ElementType)
			v2.value = item.Value
			errs = append(errs, v2.validate()...)
			v2.doNode()
			v.finishDescent(v2)
		}
	}
	return errs
}

func (v *validatingObjectWalker) doMap(t schema.Map) (errs ValidationErrors) {
	m, err := mapValue(v.value)
	if err != nil {
		return v.error(err)
	}

	if t.ElementRelationship == schema.Atomic {
		v.doLeaf()
	}

	if m == nil {
		return nil
	}

	errs = v.visitMapItems(t, m)

	return errs
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 harness

import (
	"context"
	"fmt"
	"os"
	"runtime"
	"time"

	"github.com/apache/beam/sdks/go/pkg/beam/internal/errors"
	"github.com/apache/beam/sdks/go/pkg/beam/log"
	fnpb "github.com/apache/beam/sdks/go/pkg/beam/model/fnexecution_v1"
	"github.com/golang/protobuf/ptypes"
)

// TODO(herohde) 10/12/2017: make this file a separate package. Then
// populate InstructionId and TransformId properly.

// TODO(herohde) 10/13/2017: add top-level harness.Main panic handler that flushes logs.
// Also make logger flush on Fatal severity messages.
type contextKey string

const instKey contextKey = "beam:inst"

func setInstID(ctx context.Context, id instructionID) context.Context {
	return context.WithValue(ctx, instKey, id)
}

func tryGetInstID(ctx context.Context) (string, bool) {
	id := ctx.Value(instKey)
	if id == nil {
		return "", false
	}
	return string(id.(instructionID)), true
}

type logger struct {
	out chan<- *fnpb.LogEntry
}

func (l *logger) Log(ctx context.Context, sev log.Severity, calldepth int, msg string) {
	now, _ := ptypes.TimestampProto(time.Now())

	entry := &fnpb.LogEntry{
		Timestamp: now,
		Severity:  convertSeverity(sev),
		Message:   msg,
	}
	if _, file, line, ok := runtime.Caller(calldepth + 1); ok {
		entry.LogLocation = fmt.Sprintf("%v:%v", file, line)
	}
	if id, ok := tryGetInstID(ctx); ok {
		entry.InstructionId = id
	}

	select {
	case l.out <- entry:
		// ok
	default:
		// buffer full: drop to stderr.
		fmt.Fprintln(os.Stderr, msg)
	}
}

func convertSeverity(sev log.Severity) fnpb.LogEntry_Severity_Enum {
	switch sev {
	case log.SevDebug:
		return fnpb.LogEntry_Severity_DEBUG
	case log.SevInfo:
		return fnpb.LogEntry_Severity_INFO
	case log.SevWarn:
		return fnpb.LogEntry_Severity_WARN
	case log.SevError:
		return fnpb.LogEntry_Severity_ERROR
	case log.SevFatal:
		return fnpb.LogEntry_Severity_CRITICAL
	default:
		return fnpb.LogEntry_Severity_INFO
	}
}

// setupRemoteLogging redirects local log messages to FnHarness. It will
// try to reconnect, if a connection goes bad. Falls back to stdout.
func setupRemoteLogging(ctx context.Context, endpoint string) {
	buf := make(chan *fnpb.LogEntry, 2000)
	log.SetLogger(&logger{out: buf})

	w := &remoteWriter{buf, endpoint}
	go w.Run(ctx)
}

type remoteWriter struct {
	buffer   chan *fnpb.LogEntry
	endpoint string
}

func (w *remoteWriter) Run(ctx context.Context) error {
	for {
		err := w.connect(ctx)

		fmt.Fprintf(os.Stderr, "Remote logging failed: %v. Retrying in 5 sec ...\n", err)
		time.Sleep(5 * time.Second)
	}
}

func (w *remoteWriter) connect(ctx context.Context) error {
	conn, err := dial(ctx, w.endpoint, 30*time.Second)
	if err != nil {
		return err
	}
	defer conn.Close()

	client, err := fnpb.NewBeamFnLoggingClient(conn).Logging(ctx)
	if err != nil {
		return err
	}
	defer client.CloseSend()

	for msg := range w.buffer {
		// fmt.Fprintf(os.Stderr, "REMOTE: %v\n", proto.MarshalTextString(msg))

		// TODO: batch up log messages

		list := &fnpb.LogEntry_List{
			LogEntries: []*fnpb.LogEntry{msg},
		}

		recordLogEntries(list)

		if err := client.Send(list); err != nil {
			fmt.Fprintf(os.Stderr, "Failed to send message: %v\n%v", err, msg)
			return err
		}

		// fmt.Fprintf(os.Stderr, "SENT: %v\n", msg)
	}
	return errors.New("internal: buffer closed?")
}
<commit_msg>[BEAM-10610] Make missed logs more readable.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 harness

import (
	"context"
	"fmt"
	"os"
	"runtime"
	"time"

	"github.com/apache/beam/sdks/go/pkg/beam/internal/errors"
	"github.com/apache/beam/sdks/go/pkg/beam/log"
	fnpb "github.com/apache/beam/sdks/go/pkg/beam/model/fnexecution_v1"
	"github.com/golang/protobuf/ptypes"
)

// TODO(herohde) 10/12/2017: make this file a separate package. Then
// populate InstructionId and TransformId properly.

// TODO(herohde) 10/13/2017: add top-level harness.Main panic handler that flushes logs.
// Also make logger flush on Fatal severity messages.
type contextKey string

const instKey contextKey = "beam:inst"

func setInstID(ctx context.Context, id instructionID) context.Context {
	return context.WithValue(ctx, instKey, id)
}

func tryGetInstID(ctx context.Context) (string, bool) {
	id := ctx.Value(instKey)
	if id == nil {
		return "", false
	}
	return string(id.(instructionID)), true
}

type logger struct {
	out chan<- *fnpb.LogEntry
}

func (l *logger) Log(ctx context.Context, sev log.Severity, calldepth int, msg string) {
	now, _ := ptypes.TimestampProto(time.Now())

	entry := &fnpb.LogEntry{
		Timestamp: now,
		Severity:  convertSeverity(sev),
		Message:   msg,
	}
	if _, file, line, ok := runtime.Caller(calldepth + 1); ok {
		entry.LogLocation = fmt.Sprintf("%v:%v", file, line)
	}
	if id, ok := tryGetInstID(ctx); ok {
		entry.InstructionId = id
	}

	select {
	case l.out <- entry:
		// ok
	default:
		// buffer full: drop to stderr.
		fmt.Fprintln(os.Stderr, msg)
	}
}

func convertSeverity(sev log.Severity) fnpb.LogEntry_Severity_Enum {
	switch sev {
	case log.SevDebug:
		return fnpb.LogEntry_Severity_DEBUG
	case log.SevInfo:
		return fnpb.LogEntry_Severity_INFO
	case log.SevWarn:
		return fnpb.LogEntry_Severity_WARN
	case log.SevError:
		return fnpb.LogEntry_Severity_ERROR
	case log.SevFatal:
		return fnpb.LogEntry_Severity_CRITICAL
	default:
		return fnpb.LogEntry_Severity_INFO
	}
}

// setupRemoteLogging redirects local log messages to FnHarness. It will
// try to reconnect, if a connection goes bad. Falls back to stdout.
func setupRemoteLogging(ctx context.Context, endpoint string) {
	buf := make(chan *fnpb.LogEntry, 2000)
	log.SetLogger(&logger{out: buf})

	w := &remoteWriter{buf, endpoint}
	go w.Run(ctx)
}

type remoteWriter struct {
	buffer   chan *fnpb.LogEntry
	endpoint string
}

func (w *remoteWriter) Run(ctx context.Context) error {
	for {
		err := w.connect(ctx)

		fmt.Fprintf(os.Stderr, "Remote logging failed: %v. Retrying in 5 sec ...\n", err)
		time.Sleep(5 * time.Second)
	}
}

func (w *remoteWriter) connect(ctx context.Context) error {
	conn, err := dial(ctx, w.endpoint, 30*time.Second)
	if err != nil {
		return err
	}
	defer conn.Close()

	client, err := fnpb.NewBeamFnLoggingClient(conn).Logging(ctx)
	if err != nil {
		return err
	}
	defer client.CloseSend()

	for msg := range w.buffer {
		// fmt.Fprintf(os.Stderr, "REMOTE: %v\n", proto.MarshalTextString(msg))

		// TODO: batch up log messages

		list := &fnpb.LogEntry_List{
			LogEntries: []*fnpb.LogEntry{msg},
		}

		recordLogEntries(list)

		if err := client.Send(list); err != nil {
			fmt.Fprintf(os.Stderr, "Failed to send message: %v\n%v\n", err, msg)
			return err
		}

		// fmt.Fprintf(os.Stderr, "SENT: %v\n", msg)
	}
	return errors.New("internal: buffer closed?")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"

	"github.com/dgrijalva/jwt-go"
)

func generateKeys() {
	var err error

	signKey, err = ioutil.ReadFile(*privateKeyPath)

	if err != nil {
		fmt.Println("Could not find your private key!")
		os.Exit(1)
	}

	verifyKey, err = ioutil.ReadFile(*publicKeyPath)

	if err != nil {
		fmt.Println("Could not find your public key!")
		os.Exit(1)
	}

	signingMethod = jwt.GetSigningMethod("RS256")
}

func createUserRegex() {
	var err error
	usernameAndPasswordRegex, err = regexp.Compile(usernameAndPasswordRegexString)

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	emailRegex, err = regexp.Compile(emailRegexString)

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
<commit_msg>helpers: use regexp.MustCompile for regex that *must* compile ;D<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"

	"github.com/dgrijalva/jwt-go"
)

func generateKeys() {
	var err error

	signKey, err = ioutil.ReadFile(*privateKeyPath)

	if err != nil {
		fmt.Println("Could not find your private key!")
		os.Exit(1)
	}

	verifyKey, err = ioutil.ReadFile(*publicKeyPath)

	if err != nil {
		fmt.Println("Could not find your public key!")
		os.Exit(1)
	}

	signingMethod = jwt.GetSigningMethod("RS256")
}

func createUserRegex() {
	usernameAndPasswordRegex = regexp.MustCompile(usernameAndPasswordRegexString)
	emailRegex = regexp.MustCompile(emailRegexString)
}
<|endoftext|>


<commit_before>package xweb

import (
	"bytes"
	"net/http"
	"net/url"
	"os"
	"path"
	"reflect"
	"regexp"
	"strings"
	"sync"
	"time"
)

// the func is the same as condition ? true : false
func Ternary(express bool, trueVal interface{}, falseVal interface{}) interface{} {
	if express {
		return trueVal
	}
	return falseVal
}

// internal utility methods
func webTime(t time.Time) string {
	ftime := t.Format(time.RFC1123)
	if strings.HasSuffix(ftime, "UTC") {
		ftime = ftime[0:len(ftime)-3] + "GMT"
	}
	return ftime
}

func JoinPath(paths ...string) string {
	if len(paths) < 1 {
		return ""
	}
	res := ""
	for _, p := range paths {
		res = path.Join(res, p)
	}
	return res
}

func PageSize(total, limit int) int {
	if total <= 0 {
		return 1
	} else {
		x := total % limit
		if x > 0 {
			return total/limit + 1
		} else {
			return total / limit
		}
	}
}

func SimpleParse(data string) map[string]string {
	configs := make(map[string]string)
	lines := strings.Split(string(data), "\n")
	for _, line := range lines {
		line = strings.TrimRight(line, "\r")
		vs := strings.Split(line, "=")
		if len(vs) == 2 {
			configs[strings.TrimSpace(vs[0])] = strings.TrimSpace(vs[1])
		}
	}
	return configs
}

func dirExists(dir string) bool {
	d, e := os.Stat(dir)
	switch {
	case e != nil:
		return false
	case !d.IsDir():
		return false
	}

	return true
}

func fileExists(dir string) bool {
	info, err := os.Stat(dir)
	if err != nil {
		return false
	}

	return !info.IsDir()
}

// Urlencode is a helper method that converts a map into URL-encoded form data.
// It is a useful when constructing HTTP POST requests.
func Urlencode(data map[string]string) string {
	var buf bytes.Buffer
	for k, v := range data {
		buf.WriteString(url.QueryEscape(k))
		buf.WriteByte('=')
		buf.WriteString(url.QueryEscape(v))
		buf.WriteByte('&')
	}
	s := buf.String()
	return s[0 : len(s)-1]
}

func UnTitle(s string) string {
	if len(s) < 2 {
		return strings.ToLower(s)
	}
	return strings.ToLower(string(s[0])) + s[1:]
}

var slugRegex = regexp.MustCompile(`(?i:[^a-z0-9\-_])`)

// Slug is a helper function that returns the URL slug for string s.
// It's used to return clean, URL-friendly strings that can be
// used in routing.
func Slug(s string, sep string) string {
	if s == "" {
		return ""
	}
	slug := slugRegex.ReplaceAllString(s, sep)
	if slug == "" {
		return ""
	}
	quoted := regexp.QuoteMeta(sep)
	sepRegex := regexp.MustCompile("(" + quoted + "){2,}")
	slug = sepRegex.ReplaceAllString(slug, sep)
	sepEnds := regexp.MustCompile("^" + quoted + "|" + quoted + "$")
	slug = sepEnds.ReplaceAllString(slug, "")
	return strings.ToLower(slug)
}

// NewCookie is a helper method that returns a new http.Cookie object.
// Duration is specified in seconds. If the duration is zero, the cookie is permanent.
// This can be used in conjunction with ctx.SetCookie.
func NewCookie(name string, value string, age int64) *http.Cookie {
	var utctime time.Time
	if age == 0 {
		// 2^31 - 1 seconds (roughly 2038)
		utctime = time.Unix(2147483647, 0)
	} else {
		utctime = time.Unix(time.Now().Unix()+age, 0)
	}
	return &http.Cookie{Name: name, Value: value, Expires: utctime}
}

func removeStick(uri string) string {
	uri = strings.TrimRight(uri, "/")
	if uri == "" {
		uri = "/"
	}
	return uri
}

var (
	fieldCache      = make(map[reflect.Type]map[string]int)
	fieldCacheMutex sync.RWMutex
)

// this method cache fields' index to field name
func fieldByName(v reflect.Value, name string) reflect.Value {
	t := v.Type()
	fieldCacheMutex.RLock()
	cache, ok := fieldCache[t]
	fieldCacheMutex.RUnlock()
	if !ok {
		cache = make(map[string]int)
		for i := 0; i < v.NumField(); i++ {
			cache[t.Field(i).Name] = i
		}
		fieldCacheMutex.Lock()
		fieldCache[t] = cache
		fieldCacheMutex.Unlock()
	}

	if i, ok := cache[name]; ok {
		return v.Field(i)
	}

	return reflect.Zero(t)
}
<commit_msg>完善NewCookie()<commit_after>package xweb

import (
	"bytes"
	"net/http"
	"net/url"
	"os"
	"path"
	"reflect"
	"regexp"
	"strings"
	"sync"
	"time"
)

// the func is the same as condition ? true : false
func Ternary(express bool, trueVal interface{}, falseVal interface{}) interface{} {
	if express {
		return trueVal
	}
	return falseVal
}

// internal utility methods
func webTime(t time.Time) string {
	ftime := t.Format(time.RFC1123)
	if strings.HasSuffix(ftime, "UTC") {
		ftime = ftime[0:len(ftime)-3] + "GMT"
	}
	return ftime
}

func JoinPath(paths ...string) string {
	if len(paths) < 1 {
		return ""
	}
	res := ""
	for _, p := range paths {
		res = path.Join(res, p)
	}
	return res
}

func PageSize(total, limit int) int {
	if total <= 0 {
		return 1
	} else {
		x := total % limit
		if x > 0 {
			return total/limit + 1
		} else {
			return total / limit
		}
	}
}

func SimpleParse(data string) map[string]string {
	configs := make(map[string]string)
	lines := strings.Split(string(data), "\n")
	for _, line := range lines {
		line = strings.TrimRight(line, "\r")
		vs := strings.Split(line, "=")
		if len(vs) == 2 {
			configs[strings.TrimSpace(vs[0])] = strings.TrimSpace(vs[1])
		}
	}
	return configs
}

func dirExists(dir string) bool {
	d, e := os.Stat(dir)
	switch {
	case e != nil:
		return false
	case !d.IsDir():
		return false
	}

	return true
}

func fileExists(dir string) bool {
	info, err := os.Stat(dir)
	if err != nil {
		return false
	}

	return !info.IsDir()
}

// Urlencode is a helper method that converts a map into URL-encoded form data.
// It is a useful when constructing HTTP POST requests.
func Urlencode(data map[string]string) string {
	var buf bytes.Buffer
	for k, v := range data {
		buf.WriteString(url.QueryEscape(k))
		buf.WriteByte('=')
		buf.WriteString(url.QueryEscape(v))
		buf.WriteByte('&')
	}
	s := buf.String()
	return s[0 : len(s)-1]
}

func UnTitle(s string) string {
	if len(s) < 2 {
		return strings.ToLower(s)
	}
	return strings.ToLower(string(s[0])) + s[1:]
}

var slugRegex = regexp.MustCompile(`(?i:[^a-z0-9\-_])`)

// Slug is a helper function that returns the URL slug for string s.
// It's used to return clean, URL-friendly strings that can be
// used in routing.
func Slug(s string, sep string) string {
	if s == "" {
		return ""
	}
	slug := slugRegex.ReplaceAllString(s, sep)
	if slug == "" {
		return ""
	}
	quoted := regexp.QuoteMeta(sep)
	sepRegex := regexp.MustCompile("(" + quoted + "){2,}")
	slug = sepRegex.ReplaceAllString(slug, sep)
	sepEnds := regexp.MustCompile("^" + quoted + "|" + quoted + "$")
	slug = sepEnds.ReplaceAllString(slug, "")
	return strings.ToLower(slug)
}

// NewCookie is a helper method that returns a new http.Cookie object.
// Duration is specified in seconds. If the duration is zero, the cookie is permanent.
// This can be used in conjunction with ctx.SetCookie.
func NewCookie(name string, value string, age int64, args ...string) *http.Cookie {
	var (
		utctime  time.Time
		secure   bool
		httpOnly bool
		path     string
		domain   string
	)
	switch len(args) {
	case 1:
		path = args[0]
	case 2:
		path = args[0]
		domain = args[1]
	case 3:
		path = args[0]
		domain = args[1]
		str := strings.ToLower(args[2])
		if str == "true" || str == "1" || str == "on" {
			secure = true
		}
	case 4:
		path = args[0]
		domain = args[1]
		str := strings.ToLower(args[2])
		if str == "true" || str == "1" || str == "on" {
			secure = true
		}
		str = strings.ToLower(args[3])
		if str == "true" || str == "1" || str == "on" {
			httpOnly = true
		}
	}
	if age == 0 {
		// 2^31 - 1 seconds (roughly 2038)
		utctime = time.Unix(2147483647, 0)
	} else {
		utctime = time.Unix(time.Now().Unix()+age, 0)
	}
	return &http.Cookie{
		Name:       name,
		Value:      value,
		Path:       path,
		Domain:     domain,
		Expires:    utctime,
		RawExpires: "",
		MaxAge:     0,
		Secure:     secure,
		HttpOnly:   httpOnly,
		Raw:        "",
		Unparsed:   make([]string, 0),
	}
}

func removeStick(uri string) string {
	uri = strings.TrimRight(uri, "/")
	if uri == "" {
		uri = "/"
	}
	return uri
}

var (
	fieldCache      = make(map[reflect.Type]map[string]int)
	fieldCacheMutex sync.RWMutex
)

// this method cache fields' index to field name
func fieldByName(v reflect.Value, name string) reflect.Value {
	t := v.Type()
	fieldCacheMutex.RLock()
	cache, ok := fieldCache[t]
	fieldCacheMutex.RUnlock()
	if !ok {
		cache = make(map[string]int)
		for i := 0; i < v.NumField(); i++ {
			cache[t.Field(i).Name] = i
		}
		fieldCacheMutex.Lock()
		fieldCache[t] = cache
		fieldCacheMutex.Unlock()
	}

	if i, ok := cache[name]; ok {
		return v.Field(i)
	}

	return reflect.Zero(t)
}
<|endoftext|>