<commit_before>package bild

import (
	"image"
	"image/color"
	"math"
)

type normColor struct {
	r, g, b, a float64
}

// Add returns an image with the added color values of two images
func Add(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R)
		g0 := float64(c0.G)
		b0 := float64(c0.B)
		a0 := float64(c0.A)

		r1 := float64(c1.R)
		g1 := float64(c1.G)
		b1 := float64(c1.B)
		a1 := float64(c1.A)

		r2 := uint8(clampFloat64(r0+r1, 0, 255))
		g2 := uint8(clampFloat64(g0+g1, 0, 255))
		b2 := uint8(clampFloat64(b0+b1, 0, 255))
		a2 := uint8(clampFloat64(a0+a1, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Multiply returns an image with the normalized color values of two images multiplied
func Multiply(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R)
		g0 := float64(c0.G)
		b0 := float64(c0.B)
		a0 := float64(c0.A)

		r1 := float64(c1.R)
		g1 := float64(c1.G)
		b1 := float64(c1.B)
		a1 := float64(c1.A)

		r2 := uint8(r0 * r1 / 255)
		g2 := uint8(g0 * g1 / 255)
		b2 := uint8(b0 * b1 / 255)
		a2 := uint8(a0 * a1 / 255)

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Overlay returns an image that combines Multiply and Screen blend modes
func Overlay(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		var r2, g2, b2, a2 uint8
		if 0.3*r1+0.6*g1+0.1*b1 < 0.5 {
			r2 = uint8(clampFloat64(r0*r1*2*255, 0, 255))
			g2 = uint8(clampFloat64(g0*g1*2*255, 0, 255))
			b2 = uint8(clampFloat64(b0*b1*2*255, 0, 255))
			a2 = uint8(clampFloat64(a0*a1*2*255, 0, 255))
		} else {
			r2 = uint8(clampFloat64((1-2*(1-r0)*(1-r1))*255, 0, 255))
			g2 = uint8(clampFloat64((1-2*(1-g0)*(1-g1))*255, 0, 255))
			b2 = uint8(clampFloat64((1-2*(1-b0)*(1-b1))*255, 0, 255))
			a2 = uint8(clampFloat64((1-2*(1-a0)*(1-a1))*255, 0, 255))
		}

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// SoftLight returns an image has the Soft Light blend mode applied
func SoftLight(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		r2 := uint8(clampFloat64(((1-2*r1)*r0*r0+2*r0*r1)*255, 0, 255))
		g2 := uint8(clampFloat64(((1-2*g1)*g0*g0+2*g0*g1)*255, 0, 255))
		b2 := uint8(clampFloat64(((1-2*b1)*b0*b0+2*b0*b1)*255, 0, 255))
		a2 := uint8(clampFloat64(((1-2*a1)*a0*a0+2*a0*a1)*255, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Screen returns an image that has the screen blend mode applied
func Screen(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		r2 := uint8(clampFloat64((1-(1-r0)*(1-r1))*255, 0, 255))
		g2 := uint8(clampFloat64((1-(1-g0)*(1-g1))*255, 0, 255))
		b2 := uint8(clampFloat64((1-(1-b0)*(1-b1))*255, 0, 255))
		a2 := uint8(clampFloat64((1-(1-a0)*(1-a1))*255, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Difference returns an image which represts the absolute difference between the input images
func Difference(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		r2 := uint8(clampFloat64(math.Abs(r0-r1)*255, 0, 255))
		g2 := uint8(clampFloat64(math.Abs(g0-g1)*255, 0, 255))
		b2 := uint8(clampFloat64(math.Abs(b0-b1)*255, 0, 255))
		a2 := uint8(clampFloat64(math.Abs(a0-a1)*255, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Opacity returns an image which blends the two input images by the percentage provided.
// Percent must be of range 0 <= percent <= 1.0
func Opacity(a image.Image, b image.Image, percent float64) *image.RGBA {
	percent = clampFloat64(percent, 0, 1.0)

	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		r2 := uint8(clampFloat64((percent*r1+(1-percent)*r0)*255, 0, 255))
		g2 := uint8(clampFloat64((percent*g1+(1-percent)*g0)*255, 0, 255))
		b2 := uint8(clampFloat64((percent*b1+(1-percent)*b0)*255, 0, 255))
		a2 := uint8(clampFloat64((percent*a1+(1-percent)*a0)*255, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

func blendOperation(a image.Image, b image.Image, fn func(color.RGBA, color.RGBA) color.RGBA) *image.RGBA {
	// Currently only equal size images are supported
	if a.Bounds() != b.Bounds() {
		panic("blend operation: only equal size images are supported")
	}

	bounds := a.Bounds()
	srcA := CloneAsRGBA(a)
	srcB := CloneAsRGBA(b)

	dst := image.NewRGBA(bounds)

	w, h := bounds.Max.X, bounds.Max.Y

	parallelize(h, func(start, end int) {
		for x := 0; x < w; x++ {
			for y := start; y < end; y++ {
				pos := y*dst.Stride + x*4
				result := fn(color.RGBA{srcA.Pix[pos+0], srcA.Pix[pos+1], srcA.Pix[pos+2], srcA.Pix[pos+3]},
					color.RGBA{srcB.Pix[pos+0], srcB.Pix[pos+1], srcB.Pix[pos+2], srcB.Pix[pos+3]})

				dst.Pix[pos+0] = result.R
				dst.Pix[pos+1] = result.G
				dst.Pix[pos+2] = result.B
				dst.Pix[pos+3] = result.A
			}

		}
	})

	return dst
}
<commit_msg>added darken and lighten operations; switched overlay to per channel op<commit_after>package bild

import (
	"image"
	"image/color"
	"math"
)

type normColor struct {
	r, g, b, a float64
}

// Add returns an image with the added color values of two images
func Add(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R)
		g0 := float64(c0.G)
		b0 := float64(c0.B)
		a0 := float64(c0.A)

		r1 := float64(c1.R)
		g1 := float64(c1.G)
		b1 := float64(c1.B)
		a1 := float64(c1.A)

		r2 := uint8(clampFloat64(r0+r1, 0, 255))
		g2 := uint8(clampFloat64(g0+g1, 0, 255))
		b2 := uint8(clampFloat64(b0+b1, 0, 255))
		a2 := uint8(clampFloat64(a0+a1, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Multiply returns an image with the normalized color values of two images multiplied
func Multiply(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R)
		g0 := float64(c0.G)
		b0 := float64(c0.B)
		a0 := float64(c0.A)

		r1 := float64(c1.R)
		g1 := float64(c1.G)
		b1 := float64(c1.B)
		a1 := float64(c1.A)

		r2 := uint8(r0 * r1 / 255)
		g2 := uint8(g0 * g1 / 255)
		b2 := uint8(b0 * b1 / 255)
		a2 := uint8(a0 * a1 / 255)

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Overlay returns an image that combines Multiply and Screen blend modes
func Overlay(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		var r2, g2, b2, a2 uint8
		if r1 < 0.5 {
			r2 = uint8(clampFloat64(r0*r1*2*255, 0, 255))
		} else {
			r2 = uint8(clampFloat64((1-2*(1-r0)*(1-r1))*255, 0, 255))
		}
		if g1 < 0.5 {
			g2 = uint8(clampFloat64(g0*g1*2*255, 0, 255))
		} else {
			g2 = uint8(clampFloat64((1-2*(1-g0)*(1-g1))*255, 0, 255))
		}
		if b1 < 0.5 {
			b2 = uint8(clampFloat64(b0*b1*2*255, 0, 255))
		} else {
			b2 = uint8(clampFloat64((1-2*(1-b0)*(1-b1))*255, 0, 255))
		}
		if a1 < 0.5 {
			a2 = uint8(clampFloat64(a0*a1*2*255, 0, 255))
		} else {
			a2 = uint8(clampFloat64((1-2*(1-a0)*(1-a1))*255, 0, 255))
		}

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// SoftLight returns an image has the Soft Light blend mode applied
func SoftLight(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		r2 := uint8(clampFloat64(((1-2*r1)*r0*r0+2*r0*r1)*255, 0, 255))
		g2 := uint8(clampFloat64(((1-2*g1)*g0*g0+2*g0*g1)*255, 0, 255))
		b2 := uint8(clampFloat64(((1-2*b1)*b0*b0+2*b0*b1)*255, 0, 255))
		a2 := uint8(clampFloat64(((1-2*a1)*a0*a0+2*a0*a1)*255, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Screen returns an image that has the screen blend mode applied
func Screen(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		r2 := uint8(clampFloat64((1-(1-r0)*(1-r1))*255, 0, 255))
		g2 := uint8(clampFloat64((1-(1-g0)*(1-g1))*255, 0, 255))
		b2 := uint8(clampFloat64((1-(1-b0)*(1-b1))*255, 0, 255))
		a2 := uint8(clampFloat64((1-(1-a0)*(1-a1))*255, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Difference returns an image which represts the absolute difference between the input images
func Difference(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		r2 := uint8(clampFloat64(math.Abs(r0-r1)*255, 0, 255))
		g2 := uint8(clampFloat64(math.Abs(g0-g1)*255, 0, 255))
		b2 := uint8(clampFloat64(math.Abs(b0-b1)*255, 0, 255))
		a2 := uint8(clampFloat64(math.Abs(a0-a1)*255, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Opacity returns an image which blends the two input images by the percentage provided.
// Percent must be of range 0 <= percent <= 1.0
func Opacity(a image.Image, b image.Image, percent float64) *image.RGBA {
	percent = clampFloat64(percent, 0, 1.0)

	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {

		r0 := float64(c0.R) / 255
		g0 := float64(c0.G) / 255
		b0 := float64(c0.B) / 255
		a0 := float64(c0.A) / 255

		r1 := float64(c1.R) / 255
		g1 := float64(c1.G) / 255
		b1 := float64(c1.B) / 255
		a1 := float64(c1.A) / 255

		r2 := uint8(clampFloat64((percent*r1+(1-percent)*r0)*255, 0, 255))
		g2 := uint8(clampFloat64((percent*g1+(1-percent)*g0)*255, 0, 255))
		b2 := uint8(clampFloat64((percent*b1+(1-percent)*b0)*255, 0, 255))
		a2 := uint8(clampFloat64((percent*a1+(1-percent)*a0)*255, 0, 255))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Darken returns an image which has the respective darker pixel from each input image
func Darken(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {
		r0 := float64(c0.R)
		g0 := float64(c0.G)
		b0 := float64(c0.B)
		a0 := float64(c0.A)

		r1 := float64(c1.R)
		g1 := float64(c1.G)
		b1 := float64(c1.B)
		a1 := float64(c1.A)

		r2 := uint8(math.Min(r0, r1))
		g2 := uint8(math.Min(g0, g1))
		b2 := uint8(math.Min(b0, b1))
		a2 := uint8(math.Min(a0, a1))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

// Lighten returns an image which has the respective brighter pixel from each input image
func Lighten(a image.Image, b image.Image) *image.RGBA {
	dst := blendOperation(a, b, func(c0 color.RGBA, c1 color.RGBA) color.RGBA {
		r0 := float64(c0.R)
		g0 := float64(c0.G)
		b0 := float64(c0.B)
		a0 := float64(c0.A)

		r1 := float64(c1.R)
		g1 := float64(c1.G)
		b1 := float64(c1.B)
		a1 := float64(c1.A)

		r2 := uint8(math.Max(r0, r1))
		g2 := uint8(math.Max(g0, g1))
		b2 := uint8(math.Max(b0, b1))
		a2 := uint8(math.Max(a0, a1))

		return color.RGBA{r2, g2, b2, a2}
	})

	return dst
}

func blendOperation(a image.Image, b image.Image, fn func(color.RGBA, color.RGBA) color.RGBA) *image.RGBA {
	// Currently only equal size images are supported
	if a.Bounds() != b.Bounds() {
		panic("blend operation: only equal size images are supported")
	}

	bounds := a.Bounds()
	srcA := CloneAsRGBA(a)
	srcB := CloneAsRGBA(b)

	dst := image.NewRGBA(bounds)

	w, h := bounds.Max.X, bounds.Max.Y

	parallelize(h, func(start, end int) {
		for x := 0; x < w; x++ {
			for y := start; y < end; y++ {
				pos := y*dst.Stride + x*4
				result := fn(color.RGBA{srcA.Pix[pos+0], srcA.Pix[pos+1], srcA.Pix[pos+2], srcA.Pix[pos+3]},
					color.RGBA{srcB.Pix[pos+0], srcB.Pix[pos+1], srcB.Pix[pos+2], srcB.Pix[pos+3]})

				dst.Pix[pos+0] = result.R
				dst.Pix[pos+1] = result.G
				dst.Pix[pos+2] = result.B
				dst.Pix[pos+3] = result.A
			}

		}
	})

	return dst
}
<|endoftext|>


<commit_before>package parser

import (
	"fmt"
	"strings"
)

type ParseError struct {
	// starts with 1
	Line   uint
	Column uint

	Msg string

	Src string
}

func (p *ParseError) Error() string {
	return fmt.Sprintf("[%d:%d]: %s", p.Line, p.Column, p.Msg)
}

func (p *ParseError) Verbose() string {
	l := fmt.Sprintf("%d: ", p.Line)
	return p.Msg + "\n\n" +
		"\033[36m" + l + "\033[0m" + strings.Split(p.Src, "\n")[p.Line-1] + "\n" +
		strings.Repeat(" ", int(p.Column-1)+len(l)) + "\033[1m" + "^ error occurs" + "\033[0m"
}
<commit_msg>Update the behavior of formatting ParseError<commit_after>package parser

import (
	"fmt"
	"strings"
)

type ParseError struct {
	// starts with 1
	Line   uint
	Column uint

	Msg string

	Src string
}

func (p *ParseError) Error() string {
	return fmt.Sprintf("%d:%d: %s", p.Line, p.Column, p.Msg)
}

func (p *ParseError) Verbose() string {
	l := fmt.Sprintf("%d: ", p.Line)
	return p.Error() + "\n\n" +
		"\033[36m" + l + "\033[0m" + strings.Split(p.Src, "\n")[p.Line-1] + "\n" +
		strings.Repeat(" ", int(p.Column-1)+len(l)) + "\033[1m" + "^ error occurs" + "\033[0m"
}
<|endoftext|>


<commit_before>package blync

import (
	"fmt"
	"github.com/boombuler/hid"
	"os"
)

const (
	blyncVendorId  = 0x0E53
	blyncProductId = 0x2517
)

const (
	BlinkOff    = 0x00
	BlinkFast   = 0x46
	BlinkMedium = 0x64
	BlinkSlow   = 0x96
)

var Red = [3]byte{0xFF, 0x00, 0x00}
var Green = [3]byte{0x00, 0xFF, 0x00}
var Blue = [3]byte{0x00, 0x00, 0xFF}

type BlyncLight struct {
	devices []hid.Device
	bytes   []byte
}

func NewBlyncLight() (blync BlyncLight) {
	blync.devices = findDevices()
	blync.bytes = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0xFF}
	return
}

func findDevices() []hid.Device {
	devices := []hid.Device{}
	deviceInfos := hid.Devices()
	for {
		info, more := <-deviceInfos
		if more {
			device, error := info.Open()
			if error != nil {
				fmt.Println(error)
			}
			if !isBlyncDevice(*info) {
				fmt.Printf("%s %s is not a BlyncLight device.\n", info.Manufacturer, info.Product)
			} else {
				devices = append(devices, device)
				fmt.Printf("%s %s is a BlyncLight device.\n", info.Manufacturer, info.Product)
			}
		} else {
			break
		}
	}
	if len(devices) == 0 {
		fmt.Println("No BlyncLights found.")
		os.Exit(1)
	}
	return devices
}

func isBlyncDevice(deviceInfo hid.DeviceInfo) bool {
	// TODO from forums: "Blync creates 2 HID devices and the only way to find out the right device is the MaxFeatureReportLength = 0"
	if deviceInfo.VendorId == blyncVendorId && deviceInfo.ProductId == blyncProductId && deviceInfo.FeatureReportLength == 0 {
		return true
	}
	return false
}

func (b BlyncLight) sendFeatureReport() {
	for _, device := range b.devices {
		error := device.Write(b.bytes)
		if error != nil {
			fmt.Println(error)
		}
	}
}

func (b BlyncLight) Close() {
	b.Reset()
	for _, device := range b.devices {
		device.Close()
	}
}

func (b BlyncLight) Reset() {
	b.bytes = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0xFF}
	b.sendFeatureReport()
}

// color[0] = r
// color[1] = g
// color[2] = b
func (b BlyncLight) SetColor(color [3]byte) {
	b.bytes[1] = color[0]
	b.bytes[2] = color[2] // They reverse g and b
	b.bytes[3] = color[1]
	b.sendFeatureReport()
}

func (b BlyncLight) SetBlinkRate(rate byte) {
	b.bytes[4] = rate
	b.sendFeatureReport()
}

//18-30 play a tune single time
//49-59 plays never ending versions of the tunes
func (b BlyncLight) Play(mp3 byte) {
	b.bytes[5] = mp3
	b.sendFeatureReport()
}

func (b BlyncLight) StopPlay() {
	b.bytes[5] = 0x00
	b.sendFeatureReport()
}
<commit_msg>Updated comment<commit_after>package blync

import (
	"fmt"
	"github.com/boombuler/hid"
	"os"
)

const (
	blyncVendorId  = 0x0E53
	blyncProductId = 0x2517
)

const (
	BlinkOff    = 0x00
	BlinkFast   = 0x46
	BlinkMedium = 0x64
	BlinkSlow   = 0x96
)

var Red = [3]byte{0xFF, 0x00, 0x00}
var Green = [3]byte{0x00, 0xFF, 0x00}
var Blue = [3]byte{0x00, 0x00, 0xFF}

type BlyncLight struct {
	devices []hid.Device
	bytes   []byte
}

func NewBlyncLight() (blync BlyncLight) {
	blync.devices = findDevices()
	blync.bytes = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0xFF}
	return
}

func findDevices() []hid.Device {
	devices := []hid.Device{}
	deviceInfos := hid.Devices()
	for {
		info, more := <-deviceInfos
		if more {
			device, error := info.Open()
			if error != nil {
				fmt.Println(error)
			}
			if !isBlyncDevice(*info) {
				fmt.Printf("%s %s is not a BlyncLight device.\n", info.Manufacturer, info.Product)
			} else {
				devices = append(devices, device)
				fmt.Printf("%s %s is a BlyncLight device.\n", info.Manufacturer, info.Product)
			}
		} else {
			break
		}
	}
	if len(devices) == 0 {
		fmt.Println("No BlyncLights found.")
		os.Exit(1)
	}
	return devices
}

func isBlyncDevice(deviceInfo hid.DeviceInfo) bool {
	// TODO from forums: "Blync creates 2 HID devices and the only way to find out the right device is the MaxFeatureReportLength = 0"
	if deviceInfo.VendorId == blyncVendorId && deviceInfo.ProductId == blyncProductId && deviceInfo.FeatureReportLength == 0 {
		return true
	}
	return false
}

func (b BlyncLight) sendFeatureReport() {
	for _, device := range b.devices {
		error := device.Write(b.bytes)
		if error != nil {
			fmt.Println(error)
		}
	}
}

func (b BlyncLight) Close() {
	b.Reset()
	for _, device := range b.devices {
		device.Close()
	}
}

func (b BlyncLight) Reset() {
	b.bytes = []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0xFF}
	b.sendFeatureReport()
}

// color[0] = r
// color[1] = g
// color[2] = b
func (b BlyncLight) SetColor(color [3]byte) {
	b.bytes[1] = color[0]
	b.bytes[2] = color[2] // They reverse g and b
	b.bytes[3] = color[1]
	b.sendFeatureReport()
}

func (b BlyncLight) SetBlinkRate(rate byte) {
	b.bytes[4] = rate
	b.sendFeatureReport()
}

//16-30 play a tune single time
//49-59 plays never ending versions of the tunes
func (b BlyncLight) Play(mp3 byte) {
	b.bytes[5] = mp3
	b.sendFeatureReport()
}

func (b BlyncLight) StopPlay() {
	b.bytes[5] = 0x00
	b.sendFeatureReport()
}
<|endoftext|>


<commit_before>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT licese.
// Details in the LICENSE file.

package trello

import (
	"fmt"
	"time"
)

type Board struct {
	client         *Client
	ID             string `json:"id"`
	Name           string `json:"name"`
	Desc           string `json:"desc"`
	Closed         bool   `json:"closed"`
	IdOrganization string `json:"idOrganization"`
	Pinned         bool   `json:"pinned"`
	Url            string `json:"url"`
	ShortUrl       string `json:"shortUrl"`
	Prefs          struct {
		PermissionLevel       string            `json:"permissionLevel"`
		Voting                string            `json:"voting"`
		Comments              string            `json:"comments"`
		Invitations           string            `json:"invitations"`
		SelfJoin              bool              `json:"selfjoin"`
		CardCovers            bool              `json:"cardCovers"`
		CardAging             string            `json:"cardAging"`
		CalendarFeedEnabled   bool              `json:"calendarFeedEnabled"`
		Background            string            `json:"background"`
		BackgroundColor       string            `json:"backgroundColor"`
		BackgroundImage       string            `json:"backgroundImage"`
		BackgroundImageScaled []BackgroundImage `json:"backgroundImageScaled"`
		BackgroundTile        bool              `json:"backgroundTile"`
		BackgroundBrightness  string            `json:"backgroundBrightness"`
		CanBePublic           bool              `json:"canBePublic"`
		CanBeOrg              bool              `json:"canBeOrg"`
		CanBePrivate          bool              `json:"canBePrivate"`
		CanInvite             bool              `json:"canInvite"`
	} `json:"prefs"`
	LabelNames struct {
		Black  string `json:"black,omitempty"`
		Blue   string `json:"blue,omitempty"`
		Green  string `json:"green,omitempty"`
		Lime   string `json:"lime,omitempty"`
		Orange string `json:"orange,omitempty"`
		Pink   string `json:"pink,omitempty"`
		Purple string `json:"purple",omitempty"`
		Red    string `json:"red,omitempty"`
		Sky    string `json:"sky,omitempty"`
		Yellow string `json:"yellow,omitempty"`
	} `json:"labelNames"`
}

type BackgroundImage struct {
	width  int    `json:"width"`
	height int    `json:"height"`
	url    string `json:"url"`
}

func (b *Board) CreatedAt() time.Time {
	t, _ := IDToTime(b.ID)
	return t
}

/**
 * Board retrieves a Trello board by its ID.
 */
func (c *Client) GetBoard(boardID string, args Arguments) (board *Board, err error) {
	path := fmt.Sprintf("boards/%s", boardID)
	err = c.Get(path, args, &board)
	if board != nil {
		board.client = c
	}
	return
}

func (m *Member) GetBoards(args Arguments) (boards []*Board, err error) {
	path := fmt.Sprintf("members/%s/boards", m.ID)
	err = m.client.Get(path, args, &boards)
	for i := range boards {
		boards[i].client = m.client
	}
	return
}
<commit_msg>More go_vet fixes.<commit_after>// Copyright © 2016 Aaron Longwell
//
// Use of this source code is governed by an MIT licese.
// Details in the LICENSE file.

package trello

import (
	"fmt"
	"time"
)

type Board struct {
	client         *Client
	ID             string `json:"id"`
	Name           string `json:"name"`
	Desc           string `json:"desc"`
	Closed         bool   `json:"closed"`
	IdOrganization string `json:"idOrganization"`
	Pinned         bool   `json:"pinned"`
	Url            string `json:"url"`
	ShortUrl       string `json:"shortUrl"`
	Prefs          struct {
		PermissionLevel       string            `json:"permissionLevel"`
		Voting                string            `json:"voting"`
		Comments              string            `json:"comments"`
		Invitations           string            `json:"invitations"`
		SelfJoin              bool              `json:"selfjoin"`
		CardCovers            bool              `json:"cardCovers"`
		CardAging             string            `json:"cardAging"`
		CalendarFeedEnabled   bool              `json:"calendarFeedEnabled"`
		Background            string            `json:"background"`
		BackgroundColor       string            `json:"backgroundColor"`
		BackgroundImage       string            `json:"backgroundImage"`
		BackgroundImageScaled []BackgroundImage `json:"backgroundImageScaled"`
		BackgroundTile        bool              `json:"backgroundTile"`
		BackgroundBrightness  string            `json:"backgroundBrightness"`
		CanBePublic           bool              `json:"canBePublic"`
		CanBeOrg              bool              `json:"canBeOrg"`
		CanBePrivate          bool              `json:"canBePrivate"`
		CanInvite             bool              `json:"canInvite"`
	} `json:"prefs"`
	LabelNames struct {
		Black  string `json:"black,omitempty"`
		Blue   string `json:"blue,omitempty"`
		Green  string `json:"green,omitempty"`
		Lime   string `json:"lime,omitempty"`
		Orange string `json:"orange,omitempty"`
		Pink   string `json:"pink,omitempty"`
		Purple string `json:"purple,omitempty"`
		Red    string `json:"red,omitempty"`
		Sky    string `json:"sky,omitempty"`
		Yellow string `json:"yellow,omitempty"`
	} `json:"labelNames"`
}

type BackgroundImage struct {
	Width  int    `json:"width"`
	Height int    `json:"height"`
	URL    string `json:"url"`
}

func (b *Board) CreatedAt() time.Time {
	t, _ := IDToTime(b.ID)
	return t
}

/**
 * Board retrieves a Trello board by its ID.
 */
func (c *Client) GetBoard(boardID string, args Arguments) (board *Board, err error) {
	path := fmt.Sprintf("boards/%s", boardID)
	err = c.Get(path, args, &board)
	if board != nil {
		board.client = c
	}
	return
}

func (m *Member) GetBoards(args Arguments) (boards []*Board, err error) {
	path := fmt.Sprintf("members/%s/boards", m.ID)
	err = m.client.Get(path, args, &boards)
	for i := range boards {
		boards[i].client = m.client
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package tailer

import (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/google/mtail/watcher"

	"github.com/spf13/afero"
)

func makeTestTail(t *testing.T) (*Tailer, chan *LogLine, *watcher.FakeWatcher, afero.Fs) {
	fs := afero.NewMemMapFs()
	w := watcher.NewFakeWatcher()
	lines := make(chan *LogLine, 1)
	o := Options{lines, false, w, fs}
	ta, err := New(o)
	if err != nil {
		t.Fatal(err)
	}
	return ta, lines, w, fs
}

func makeTestTailReal(t *testing.T, prefix string) (*Tailer, chan *LogLine, *watcher.LogWatcher, afero.Fs, string) {
	dir, err := ioutil.TempDir("", prefix)
	if err != nil {
		t.Fatalf("can't create tempdir: %v", err)
	}

	fs := afero.NewOsFs()
	w, err := watcher.NewLogWatcher()
	if err != nil {
		t.Fatalf("can't create watcher: %v", err)
	}
	lines := make(chan *LogLine, 1)
	o := Options{lines, false, w, fs}
	ta, err := New(o)
	if err != nil {
		t.Fatal(err)
	}
	return ta, lines, w, fs, dir
}

func TestTail(t *testing.T) {
	ta, _, w, fs := makeTestTail(t)
	fs.Mkdir("tail_test", os.ModePerm)
	logfile := "/tmp/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Error(err)
	}
	defer f.Close()
	defer w.Close()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}
	// Tail also causes the log to be read, so no need to inject an event.

	if _, ok := ta.files[logfile]; !ok {
		t.Errorf("path not found in files map: %+#v", ta.files)
	}
}

func TestHandleLogUpdate(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a\nb\nc\nd\n")
	if err != nil {
		t.Fatal(err)
	}
	f.Seek(0, 0) // In memory files share the same offset
	wg.Add(4)
	w.InjectUpdate(logfile)

	// ugh
	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "a"},
		{logfile, "b"},
		{logfile, "c"},
		{logfile, "d"},
	}
	if diff := cmp.Diff(result, expected); diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}
}

// TestHandleLogTruncate writes to a file, waits for those
// writes to be seen, then truncates the file and writes some more.
// At the end all lines written must be reported by the tailer.
func TestHandleLogTruncate(t *testing.T) {
	ta, lines, w, fs, dir := makeTestTailReal(t, "trunc")
	defer os.RemoveAll(dir) // clean up

	logfile := filepath.Join(dir, "log")
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a\nb\nc\n")
	if err != nil {
		t.Fatal(err)
	}
	wg.Add(3)
	wg.Wait()

	err = f.Truncate(0)
	if err != nil {
		t.Fatal(err)
	}

	// This is potentially racy.  Unlike in the case where we've got new
	// lines that we can verify were seen with the WaitGroup, here nothing
	// ensures that this update-due-to-truncate is seen by the Tailer before
	// we write new data to the file.  In order to avoid the race we'll make
	// sure that the total data size written post-truncate is less than
	// pre-truncate, so that the post-truncate offset is always smaller
	// than the offset seen after wg.Add(3); wg.Wait() above.

	_, err = f.WriteString("d\ne\n")
	if err != nil {
		t.Fatal(err)
	}
	wg.Add(2)

	// ugh
	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "a"},
		{logfile, "b"},
		{logfile, "c"},
		{logfile, "d"},
		{logfile, "e"},
	}
	if diff := cmp.Diff(result, expected); diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}
}

func TestHandleLogUpdatePartialLine(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a")
	if err != nil {
		t.Fatal(err)
	}
	f.Seek(0, 0)
	w.InjectUpdate(logfile)

	f.Seek(1, 0)
	_, err = f.WriteString("b")
	if err != nil {
		t.Error(err)
	}
	f.Seek(1, 0)
	w.InjectUpdate(logfile)

	f.Seek(2, 0)
	_, err = f.WriteString("\n")
	if err != nil {
		t.Error(err)
	}
	f.Seek(2, 0)
	w.InjectUpdate(logfile)

	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "ab"},
	}
	diff := cmp.Diff(result, expected)
	if diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}

}

func TestReadPartial(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)
	defer w.Close()

	f, err := fs.Create("t")
	if err != nil {
		t.Fatal(err)
	}
	p := bytes.NewBufferString("")
	err = ta.read(f, p)
	if p.String() != "" {
		t.Errorf("partial line returned not empty: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	p.Reset()
	p.WriteString("o")
	f.WriteString("hi")
	f.Seek(0, 0)
	err = ta.read(f, p)
	if p.String() != "ohi" {
		t.Errorf("partial line returned not expected: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	p.Reset()
	err = ta.read(f, p)
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	f.WriteString("\n")
	f.Seek(-1, os.SEEK_END)
	p.Reset()
	p.WriteString("ohi")
	err = ta.read(f, p)
	l := <-lines
	if l.Line != "ohi" {
		t.Errorf("line emitted not ohi: %q", l)
	}
	if p.String() != "" {
		t.Errorf("partial not empty: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
}

func TestReadPipe(t *testing.T) {
	ta, lines, wa, _ := makeTestTail(t)
	defer wa.Close()

	r, w, err := os.Pipe()
	if err != nil {
		t.Fatal(err)
	}

	err = ta.TailFile(r)
	if err != nil {
		t.Fatal(err)
	}
	n, err := w.WriteString("hi\n")
	if err != nil {
		t.Fatal(err)
	}
	if n < 2 {
		t.Fatalf("Didn't write enough bytes: %d", n)
	}
	l := <-lines
	if l.Line != "hi" {
		t.Errorf("line not expected: %q", l)
	}
}
<commit_msg>Swap order of diff inputs.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package tailer

import (
	"bytes"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"sync"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/google/mtail/watcher"

	"github.com/spf13/afero"
)

func makeTestTail(t *testing.T) (*Tailer, chan *LogLine, *watcher.FakeWatcher, afero.Fs) {
	fs := afero.NewMemMapFs()
	w := watcher.NewFakeWatcher()
	lines := make(chan *LogLine, 1)
	o := Options{lines, false, w, fs}
	ta, err := New(o)
	if err != nil {
		t.Fatal(err)
	}
	return ta, lines, w, fs
}

func makeTestTailReal(t *testing.T, prefix string) (*Tailer, chan *LogLine, *watcher.LogWatcher, afero.Fs, string) {
	dir, err := ioutil.TempDir("", prefix)
	if err != nil {
		t.Fatalf("can't create tempdir: %v", err)
	}

	fs := afero.NewOsFs()
	w, err := watcher.NewLogWatcher()
	if err != nil {
		t.Fatalf("can't create watcher: %v", err)
	}
	lines := make(chan *LogLine, 1)
	o := Options{lines, false, w, fs}
	ta, err := New(o)
	if err != nil {
		t.Fatal(err)
	}
	return ta, lines, w, fs, dir
}

func TestTail(t *testing.T) {
	ta, _, w, fs := makeTestTail(t)
	fs.Mkdir("tail_test", os.ModePerm)
	logfile := "/tmp/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Error(err)
	}
	defer f.Close()
	defer w.Close()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}
	// Tail also causes the log to be read, so no need to inject an event.

	if _, ok := ta.files[logfile]; !ok {
		t.Errorf("path not found in files map: %+#v", ta.files)
	}
}

func TestHandleLogUpdate(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a\nb\nc\nd\n")
	if err != nil {
		t.Fatal(err)
	}
	f.Seek(0, 0) // In memory files share the same offset
	wg.Add(4)
	w.InjectUpdate(logfile)

	// ugh
	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "a"},
		{logfile, "b"},
		{logfile, "c"},
		{logfile, "d"},
	}
	if diff := cmp.Diff(expected, result); diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}
}

// TestHandleLogTruncate writes to a file, waits for those
// writes to be seen, then truncates the file and writes some more.
// At the end all lines written must be reported by the tailer.
func TestHandleLogTruncate(t *testing.T) {
	ta, lines, w, fs, dir := makeTestTailReal(t, "trunc")
	defer os.RemoveAll(dir) // clean up

	logfile := filepath.Join(dir, "log")
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a\nb\nc\n")
	if err != nil {
		t.Fatal(err)
	}
	wg.Add(3)
	wg.Wait()

	err = f.Truncate(0)
	if err != nil {
		t.Fatal(err)
	}

	// This is potentially racy.  Unlike in the case where we've got new
	// lines that we can verify were seen with the WaitGroup, here nothing
	// ensures that this update-due-to-truncate is seen by the Tailer before
	// we write new data to the file.  In order to avoid the race we'll make
	// sure that the total data size written post-truncate is less than
	// pre-truncate, so that the post-truncate offset is always smaller
	// than the offset seen after wg.Add(3); wg.Wait() above.

	_, err = f.WriteString("d\ne\n")
	if err != nil {
		t.Fatal(err)
	}
	wg.Add(2)

	// ugh
	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "a"},
		{logfile, "b"},
		{logfile, "c"},
		{logfile, "d"},
		{logfile, "e"},
	}
	if diff := cmp.Diff(expected, result); diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}
}

func TestHandleLogUpdatePartialLine(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a")
	if err != nil {
		t.Fatal(err)
	}
	f.Seek(0, 0)
	w.InjectUpdate(logfile)

	f.Seek(1, 0)
	_, err = f.WriteString("b")
	if err != nil {
		t.Error(err)
	}
	f.Seek(1, 0)
	w.InjectUpdate(logfile)

	f.Seek(2, 0)
	_, err = f.WriteString("\n")
	if err != nil {
		t.Error(err)
	}
	f.Seek(2, 0)
	w.InjectUpdate(logfile)

	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "ab"},
	}
	diff := cmp.Diff(expected, result)
	if diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}

}

func TestReadPartial(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)
	defer w.Close()

	f, err := fs.Create("t")
	if err != nil {
		t.Fatal(err)
	}
	p := bytes.NewBufferString("")
	err = ta.read(f, p)
	if p.String() != "" {
		t.Errorf("partial line returned not empty: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	p.Reset()
	p.WriteString("o")
	f.WriteString("hi")
	f.Seek(0, 0)
	err = ta.read(f, p)
	if p.String() != "ohi" {
		t.Errorf("partial line returned not expected: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	p.Reset()
	err = ta.read(f, p)
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	f.WriteString("\n")
	f.Seek(-1, os.SEEK_END)
	p.Reset()
	p.WriteString("ohi")
	err = ta.read(f, p)
	l := <-lines
	if l.Line != "ohi" {
		t.Errorf("line emitted not ohi: %q", l)
	}
	if p.String() != "" {
		t.Errorf("partial not empty: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
}

func TestReadPipe(t *testing.T) {
	ta, lines, wa, _ := makeTestTail(t)
	defer wa.Close()

	r, w, err := os.Pipe()
	if err != nil {
		t.Fatal(err)
	}

	err = ta.TailFile(r)
	if err != nil {
		t.Fatal(err)
	}
	n, err := w.WriteString("hi\n")
	if err != nil {
		t.Fatal(err)
	}
	if n < 2 {
		t.Fatalf("Didn't write enough bytes: %d", n)
	}
	l := <-lines
	if l.Line != "hi" {
		t.Errorf("line not expected: %q", l)
	}
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package tailer

import (
	"bytes"
	"io"
	"os"
	"sync"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/google/mtail/watcher"

	"github.com/spf13/afero"
)

func makeTestTail(t *testing.T) (*Tailer, chan *LogLine, *watcher.FakeWatcher, afero.Fs) {
	fs := afero.NewMemMapFs()
	w := watcher.NewFakeWatcher()
	lines := make(chan *LogLine, 1)
	o := Options{lines, false, w, fs}
	ta, err := New(o)
	if err != nil {
		t.Fatal(err)
	}
	return ta, lines, w, fs
}

func TestTail(t *testing.T) {
	ta, _, w, fs := makeTestTail(t)
	fs.Mkdir("tail_test", os.ModePerm)
	logfile := "/tmp/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Error(err)
	}
	defer f.Close()
	defer w.Close()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}
	// Tail also causes the log to be read, so no need to inject an event.

	if _, ok := ta.files[logfile]; !ok {
		t.Errorf("path not found in files map: %+#v", ta.files)
	}
}

func TestHandleLogUpdate(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a\nb\nc\nd\n")
	if err != nil {
		t.Fatal(err)
	}
	f.Seek(0, 0) // In memory files share the same offset
	wg.Add(4)
	w.InjectUpdate(logfile)

	// ugh
	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "a"},
		{logfile, "b"},
		{logfile, "c"},
		{logfile, "d"},
	}
	if diff := cmp.Diff(result, expected); diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}
}

func TestHandleLogUpdatePartialLine(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a")
	if err != nil {
		t.Fatal(err)
	}
	f.Seek(0, 0)
	w.InjectUpdate(logfile)

	f.Seek(1, 0)
	_, err = f.WriteString("b")
	if err != nil {
		t.Error(err)
	}
	f.Seek(1, 0)
	w.InjectUpdate(logfile)

	f.Seek(2, 0)
	_, err = f.WriteString("\n")
	if err != nil {
		t.Error(err)
	}
	f.Seek(2, 0)
	w.InjectUpdate(logfile)

	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "ab"},
	}
	diff := cmp.Diff(result, expected)
	if diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}

}

func TestReadPartial(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)
	defer w.Close()

	f, err := fs.Create("t")
	if err != nil {
		t.Fatal(err)
	}
	p := bytes.NewBufferString("")
	err = ta.read(f, p)
	if p.String() != "" {
		t.Errorf("partial line returned not empty: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	p.Reset()
	p.WriteString("o")
	f.WriteString("hi")
	f.Seek(0, 0)
	err = ta.read(f, p)
	if p.String() != "ohi" {
		t.Errorf("partial line returned not expected: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	p.Reset()
	err = ta.read(f, p)
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	f.WriteString("\n")
	f.Seek(-1, os.SEEK_END)
	p.Reset()
	p.WriteString("ohi")
	err = ta.read(f, p)
	l := <-lines
	if l.Line != "ohi" {
		t.Errorf("line emitted not ohi: %q", l)
	}
	if p.String() != "" {
		t.Errorf("partial not empty: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
}

func TestReadPipe(t *testing.T) {
	ta, lines, wa, _ := makeTestTail(t)
	defer wa.Close()

	r, w, err := os.Pipe()
	if err != nil {
		t.Fatal(err)
	}

	err = ta.TailFile(r)
	if err != nil {
		t.Fatal(err)
	}
	n, err := w.WriteString("hi\n")
	if err != nil {
		t.Fatal(err)
	}
	if n < 2 {
		t.Fatalf("Didn't write enough bytes: %d", n)
	}
	l := <-lines
	if l.Line != "hi" {
		t.Errorf("line not expected: %q", l)
	}
}
<commit_msg>Add test for log truncation followed by more updates.<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package tailer

import (
	"bytes"
	"io"
	"os"
	"sync"
	"testing"

	"github.com/google/go-cmp/cmp"
	"github.com/google/mtail/watcher"

	"github.com/spf13/afero"
)

func makeTestTail(t *testing.T) (*Tailer, chan *LogLine, *watcher.FakeWatcher, afero.Fs) {
	fs := afero.NewMemMapFs()
	w := watcher.NewFakeWatcher()
	lines := make(chan *LogLine, 1)
	o := Options{lines, false, w, fs}
	ta, err := New(o)
	if err != nil {
		t.Fatal(err)
	}
	return ta, lines, w, fs
}

func TestTail(t *testing.T) {
	ta, _, w, fs := makeTestTail(t)
	fs.Mkdir("tail_test", os.ModePerm)
	logfile := "/tmp/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Error(err)
	}
	defer f.Close()
	defer w.Close()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}
	// Tail also causes the log to be read, so no need to inject an event.

	if _, ok := ta.files[logfile]; !ok {
		t.Errorf("path not found in files map: %+#v", ta.files)
	}
}

func TestHandleLogUpdate(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a\nb\nc\nd\n")
	if err != nil {
		t.Fatal(err)
	}
	f.Seek(0, 0) // In memory files share the same offset
	wg.Add(4)
	w.InjectUpdate(logfile)

	// ugh
	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "a"},
		{logfile, "b"},
		{logfile, "c"},
		{logfile, "d"},
	}
	if diff := cmp.Diff(result, expected); diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}
}

func TestHandleLogTruncate(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a\nb\n")
	if err != nil {
		t.Fatal(err)
	}
	wg.Add(2)
	w.InjectUpdate(logfile)
	wg.Wait()

	err = f.Truncate(0)
	if err != nil {
		t.Fatal(err)
	}
	w.InjectUpdate(logfile)

	_, err = f.WriteString("c\nd\n")
	if err != nil {
		t.Fatal(err)
	}
	wg.Add(2)
	w.InjectUpdate(logfile)

	// ugh
	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "a"},
		{logfile, "b"},
		{logfile, "c"},
		{logfile, "d"},
	}
	if diff := cmp.Diff(result, expected); diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}
}

func TestHandleLogUpdatePartialLine(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)

	err := fs.Mkdir("/tail_test", os.ModePerm)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	logfile := "/tail_test/log"
	f, err := fs.Create(logfile)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	result := []*LogLine{}
	done := make(chan struct{})
	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		for line := range lines {
			result = append(result, line)
			wg.Done()
		}
		close(done)
	}()

	err = ta.TailPath(logfile)
	if err != nil {
		t.Fatal(err)
	}

	_, err = f.WriteString("a")
	if err != nil {
		t.Fatal(err)
	}
	f.Seek(0, 0)
	w.InjectUpdate(logfile)

	f.Seek(1, 0)
	_, err = f.WriteString("b")
	if err != nil {
		t.Error(err)
	}
	f.Seek(1, 0)
	w.InjectUpdate(logfile)

	f.Seek(2, 0)
	_, err = f.WriteString("\n")
	if err != nil {
		t.Error(err)
	}
	f.Seek(2, 0)
	w.InjectUpdate(logfile)

	wg.Wait()
	w.Close()
	<-done

	expected := []*LogLine{
		{logfile, "ab"},
	}
	diff := cmp.Diff(result, expected)
	if diff != "" {
		t.Errorf("result didn't match:\n%s", diff)
	}

}

func TestReadPartial(t *testing.T) {
	ta, lines, w, fs := makeTestTail(t)
	defer w.Close()

	f, err := fs.Create("t")
	if err != nil {
		t.Fatal(err)
	}
	p := bytes.NewBufferString("")
	err = ta.read(f, p)
	if p.String() != "" {
		t.Errorf("partial line returned not empty: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	p.Reset()
	p.WriteString("o")
	f.WriteString("hi")
	f.Seek(0, 0)
	err = ta.read(f, p)
	if p.String() != "ohi" {
		t.Errorf("partial line returned not expected: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	p.Reset()
	err = ta.read(f, p)
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
	f.WriteString("\n")
	f.Seek(-1, os.SEEK_END)
	p.Reset()
	p.WriteString("ohi")
	err = ta.read(f, p)
	l := <-lines
	if l.Line != "ohi" {
		t.Errorf("line emitted not ohi: %q", l)
	}
	if p.String() != "" {
		t.Errorf("partial not empty: %q", p)
	}
	if err != io.EOF {
		t.Errorf("error returned not EOF: %v", err)
	}
}

func TestReadPipe(t *testing.T) {
	ta, lines, wa, _ := makeTestTail(t)
	defer wa.Close()

	r, w, err := os.Pipe()
	if err != nil {
		t.Fatal(err)
	}

	err = ta.TailFile(r)
	if err != nil {
		t.Fatal(err)
	}
	n, err := w.WriteString("hi\n")
	if err != nil {
		t.Fatal(err)
	}
	if n < 2 {
		t.Fatalf("Didn't write enough bytes: %d", n)
	}
	l := <-lines
	if l.Line != "hi" {
		t.Errorf("line not expected: %q", l)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"math/rand"

	"github.com/codahale/graphicfarts"
)

func main() {
	var (
		nSites = flag.Int("sites", 10, "number of sites")
	)

	canvas, rect := graphicfarts.Setup()

	var sx, sy []int
	var sc []string
	for i := 0; i < *nSites; i++ {
		x := rand.Intn(rect.Dx())
		y := rand.Intn(rect.Dy())

		r := uint8(rand.Intn(256))
		g := uint8(rand.Intn(256))
		b := uint8(rand.Intn(256))

		sx = append(sx, x)
		sy = append(sy, y)
		sc = append(sc, fmt.Sprintf("fill:none;stroke:#%02x%02x%02x", r, g, b))
	}

	// BUG(coda): holy shit this is the wrong way to do this

	for x := 0; x < rect.Dx(); x++ {
		for y := 0; y < rect.Dy(); y++ {
			dMin := dot(rect.Dx(), rect.Dy())
			var sMin int
			for s := 0; s < *nSites; s++ {
				if d := dot(sx[s]-x, sy[s]-y); d < dMin {
					sMin = s
					dMin = d
				}
			}
			canvas.Rect(x, y, 1, 1, sc[sMin])
		}
	}

	canvas.End()
}

func dot(x, y int) int {
	return x*x + y*y
}
<commit_msg>Punt and use a Voronoi library.<commit_after>package main

import (
	"flag"
	"fmt"
	"math/rand"

	"github.com/codahale/graphicfarts"
	"github.com/pzsz/voronoi"
)

func main() {
	var (
		nSites = flag.Int("sites", 10, "number of sites")
	)

	canvas, rect := graphicfarts.Setup()

	var sites []voronoi.Vertex
	for i := 0; i < *nSites; i++ {
		x := rand.Intn(rect.Dx())
		y := rand.Intn(rect.Dy())

		sites = append(sites, voronoi.Vertex{X: float64(x), Y: float64(y)})
	}

	bbox := voronoi.NewBBox(0, float64(rect.Max.X), 0, float64(rect.Max.Y))
	diagram := voronoi.ComputeDiagram(sites, bbox, true)

	for _, cell := range diagram.Cells {
		var x, y []int
		for _, halfedge := range cell.Halfedges {
			start := halfedge.GetStartpoint()
			x = append(x, int(start.X))
			y = append(y, int(start.Y))

			end := halfedge.GetEndpoint()
			x = append(x, int(end.X))
			y = append(y, int(end.Y))
		}

		x = append(x, x[0])
		y = append(y, y[0])

		r := rand.Intn(256)
		g := rand.Intn(256)
		b := rand.Intn(256)

		style := fmt.Sprintf("fill:#%02x%02x%02x;stroke:black", r, g, b)
		canvas.Polygon(x, y, style)
	}

	for _, site := range sites {
		canvas.Circle(int(site.X), int(site.Y), 5, "fill:black")
	}

	canvas.End()
}
<|endoftext|>


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

package walk

import . "github.com/lxn/go-winapi"

type HatchStyle int

const (
	HatchHorizontal       HatchStyle = HS_HORIZONTAL
	HatchVertical         HatchStyle = HS_VERTICAL
	HatchForwardDiagonal  HatchStyle = HS_FDIAGONAL
	HatchBackwardDiagonal HatchStyle = HS_BDIAGONAL
	HatchCross            HatchStyle = HS_CROSS
	HatchDiagonalCross    HatchStyle = HS_DIAGCROSS
)

type Brush interface {
	Dispose()
	handle() HBRUSH
	logbrush() *LOGBRUSH
}

type nullBrush struct {
	hBrush HBRUSH
}

func newNullBrush() *nullBrush {
	lb := &LOGBRUSH{LbStyle: BS_NULL}

	hBrush := CreateBrushIndirect(lb)
	if hBrush == 0 {
		panic("failed to create null brush")
	}

	return &nullBrush{hBrush: hBrush}
}

func (b *nullBrush) Dispose() {
	if b.hBrush != 0 {
		DeleteObject(HGDIOBJ(b.hBrush))

		b.hBrush = 0
	}
}

func (b *nullBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *nullBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{LbStyle: BS_NULL}
}

var nullBrushSingleton Brush = newNullBrush()

func NullBrush() Brush {
	return nullBrushSingleton
}

type SolidColorBrush struct {
	hBrush HBRUSH
	color  Color
}

func NewSolidColorBrush(color Color) (*SolidColorBrush, error) {
	lb := &LOGBRUSH{LbStyle: BS_SOLID, LbColor: COLORREF(color)}

	hBrush := CreateBrushIndirect(lb)
	if hBrush == 0 {
		return nil, newError("CreateBrushIndirect failed")
	}

	return &SolidColorBrush{hBrush: hBrush, color: color}, nil
}

func (b *SolidColorBrush) Color() Color {
	return b.color
}

func (b *SolidColorBrush) Dispose() {
	if b.hBrush != 0 {
		DeleteObject(HGDIOBJ(b.hBrush))

		b.hBrush = 0
	}
}

func (b *SolidColorBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *SolidColorBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{LbStyle: BS_SOLID, LbColor: COLORREF(b.color)}
}

type HatchBrush struct {
	hBrush HBRUSH
	color  Color
	style  HatchStyle
}

func NewHatchBrush(color Color, style HatchStyle) (*HatchBrush, error) {
	lb := &LOGBRUSH{LbStyle: BS_HATCHED, LbColor: COLORREF(color), LbHatch: uintptr(style)}

	hBrush := CreateBrushIndirect(lb)
	if hBrush == 0 {
		return nil, newError("CreateBrushIndirect failed")
	}

	return &HatchBrush{hBrush: hBrush, color: color, style: style}, nil
}

func (b *HatchBrush) Color() Color {
	return b.color
}

func (b *HatchBrush) Dispose() {
	if b.hBrush != 0 {
		DeleteObject(HGDIOBJ(b.hBrush))

		b.hBrush = 0
	}
}

func (b *HatchBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *HatchBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{LbStyle: BS_HATCHED, LbColor: COLORREF(b.color), LbHatch: uintptr(b.style)}
}

func (b *HatchBrush) Style() HatchStyle {
	return b.style
}

type BitmapBrush struct {
	hBrush HBRUSH
	bitmap *Bitmap
}

func NewBitmapBrush(bitmap *Bitmap) (*BitmapBrush, error) {
	if bitmap == nil {
		return nil, newError("bitmap cannot be nil")
	}

	lb := &LOGBRUSH{LbStyle: BS_DIBPATTERN, LbColor: DIB_RGB_COLORS, LbHatch: uintptr(bitmap.hPackedDIB)}

	hBrush := CreateBrushIndirect(lb)
	if hBrush == 0 {
		return nil, newError("CreateBrushIndirect failed")
	}

	return &BitmapBrush{hBrush: hBrush, bitmap: bitmap}, nil
}

func (b *BitmapBrush) Dispose() {
	if b.hBrush != 0 {
		DeleteObject(HGDIOBJ(b.hBrush))

		b.hBrush = 0
	}
}

func (b *BitmapBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *BitmapBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{LbStyle: BS_DIBPATTERN, LbColor: DIB_RGB_COLORS, LbHatch: uintptr(b.bitmap.hPackedDIB)}
}

func (b *BitmapBrush) Bitmap() *Bitmap {
	return b.bitmap
}
<commit_msg>Add SystemColorBrush<commit_after>// Copyright 2010 The Walk Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package walk

import . "github.com/lxn/go-winapi"

type HatchStyle int

const (
	HatchHorizontal       HatchStyle = HS_HORIZONTAL
	HatchVertical         HatchStyle = HS_VERTICAL
	HatchForwardDiagonal  HatchStyle = HS_FDIAGONAL
	HatchBackwardDiagonal HatchStyle = HS_BDIAGONAL
	HatchCross            HatchStyle = HS_CROSS
	HatchDiagonalCross    HatchStyle = HS_DIAGCROSS
)

type Brush interface {
	Dispose()
	handle() HBRUSH
	logbrush() *LOGBRUSH
}

type nullBrush struct {
	hBrush HBRUSH
}

func newNullBrush() *nullBrush {
	lb := &LOGBRUSH{LbStyle: BS_NULL}

	hBrush := CreateBrushIndirect(lb)
	if hBrush == 0 {
		panic("failed to create null brush")
	}

	return &nullBrush{hBrush: hBrush}
}

func (b *nullBrush) Dispose() {
	if b.hBrush != 0 {
		DeleteObject(HGDIOBJ(b.hBrush))

		b.hBrush = 0
	}
}

func (b *nullBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *nullBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{LbStyle: BS_NULL}
}

var nullBrushSingleton Brush = newNullBrush()

func NullBrush() Brush {
	return nullBrushSingleton
}

type SystemColorBrush struct {
	hBrush     HBRUSH
	colorIndex int
}

func NewSystemColorBrush(colorIndex int) (*SystemColorBrush, error) {
	hBrush := GetSysColorBrush(colorIndex)
	if hBrush == 0 {
		return nil, newError("GetSysColorBrush failed")
	}

	return &SystemColorBrush{hBrush, colorIndex}, nil
}

func (b *SystemColorBrush) ColorIndex() int {
	return b.colorIndex
}

func (b *SystemColorBrush) Dispose() {
	// nop
}

func (b *SystemColorBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *SystemColorBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{
		LbStyle: BS_SOLID,
		LbColor: COLORREF(GetSysColor(b.colorIndex)),
	}
}

type SolidColorBrush struct {
	hBrush HBRUSH
	color  Color
}

func NewSolidColorBrush(color Color) (*SolidColorBrush, error) {
	lb := &LOGBRUSH{LbStyle: BS_SOLID, LbColor: COLORREF(color)}

	hBrush := CreateBrushIndirect(lb)
	if hBrush == 0 {
		return nil, newError("CreateBrushIndirect failed")
	}

	return &SolidColorBrush{hBrush: hBrush, color: color}, nil
}

func (b *SolidColorBrush) Color() Color {
	return b.color
}

func (b *SolidColorBrush) Dispose() {
	if b.hBrush != 0 {
		DeleteObject(HGDIOBJ(b.hBrush))

		b.hBrush = 0
	}
}

func (b *SolidColorBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *SolidColorBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{LbStyle: BS_SOLID, LbColor: COLORREF(b.color)}
}

type HatchBrush struct {
	hBrush HBRUSH
	color  Color
	style  HatchStyle
}

func NewHatchBrush(color Color, style HatchStyle) (*HatchBrush, error) {
	lb := &LOGBRUSH{LbStyle: BS_HATCHED, LbColor: COLORREF(color), LbHatch: uintptr(style)}

	hBrush := CreateBrushIndirect(lb)
	if hBrush == 0 {
		return nil, newError("CreateBrushIndirect failed")
	}

	return &HatchBrush{hBrush: hBrush, color: color, style: style}, nil
}

func (b *HatchBrush) Color() Color {
	return b.color
}

func (b *HatchBrush) Dispose() {
	if b.hBrush != 0 {
		DeleteObject(HGDIOBJ(b.hBrush))

		b.hBrush = 0
	}
}

func (b *HatchBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *HatchBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{LbStyle: BS_HATCHED, LbColor: COLORREF(b.color), LbHatch: uintptr(b.style)}
}

func (b *HatchBrush) Style() HatchStyle {
	return b.style
}

type BitmapBrush struct {
	hBrush HBRUSH
	bitmap *Bitmap
}

func NewBitmapBrush(bitmap *Bitmap) (*BitmapBrush, error) {
	if bitmap == nil {
		return nil, newError("bitmap cannot be nil")
	}

	lb := &LOGBRUSH{LbStyle: BS_DIBPATTERN, LbColor: DIB_RGB_COLORS, LbHatch: uintptr(bitmap.hPackedDIB)}

	hBrush := CreateBrushIndirect(lb)
	if hBrush == 0 {
		return nil, newError("CreateBrushIndirect failed")
	}

	return &BitmapBrush{hBrush: hBrush, bitmap: bitmap}, nil
}

func (b *BitmapBrush) Dispose() {
	if b.hBrush != 0 {
		DeleteObject(HGDIOBJ(b.hBrush))

		b.hBrush = 0
	}
}

func (b *BitmapBrush) handle() HBRUSH {
	return b.hBrush
}

func (b *BitmapBrush) logbrush() *LOGBRUSH {
	return &LOGBRUSH{LbStyle: BS_DIBPATTERN, LbColor: DIB_RGB_COLORS, LbHatch: uintptr(b.bitmap.hPackedDIB)}
}

func (b *BitmapBrush) Bitmap() *Bitmap {
	return b.bitmap
}
<|endoftext|>


<commit_before>package misspell

import (
	"testing"
)

func TestFalsePositives(t *testing.T) {
	cases := []string{
		"  http.Redirect(w, req, req.URL.Path, http.StatusFound) ",
		"url is http://zeebra.com ",
		"path is /zeebra?zeebra=zeebra ",
		"Malcom_McLean",
		"implementor", // alt spelling, see https://github.com/client9/misspell/issues/46
		"searchtypes",
		" witness",
		"returndata",
		"UNDERSTOOD",
		"textinterface",
		" committed ",
		"committed",
		"Bengali",
		"Portuguese",
		"scientists",
		"causally",
		"embarrassing",
		"setuptools", // python package
		"committing",
		"guises",
		"disguise",
		"begging",
		"cmo",
		"cmos",
		"borked",
		"hadn't",
		"Iceweasel",
		"summarised",
		"autorenew",
		"travelling",
		"republished",
		"fallthru",
		"pruning",
		"deb.VersionDontCare",
		"authtag",
		"intrepid",
		"usefully",
		"there",
		"definite",
		"earliest",
		"Japanese",
		"international",
		"excellent",
		"gracefully",
		"carefully",
		"class",
		"include",
		"process",
		"address",
		"attempt",
		"large",
		"although",
		"specific",
		"taste",
		"against",
		"successfully",
		"unsuccessfully",
		"occurred",
		"agree",
		"controlled",
		"publisher",
		"strategy",
		"geoposition",
		"paginated",
		"happened",
		"relative",
		"computing",
		"language",
		"manual",
		"token",
		"into",
		"nothing",
		"datatool",
		"propose",
		"learnt",
		"tolerant",
		"whitehat",
		"monotonic",
		"comprised",
		"indemnity",
		"flattened",
		"interrupted",
		"inotify",
		"occasional",
		"forging",
		"ampersand",
		"decomposition",
		"commit",
		"programmer", // "grammer"
		//		"requestsinserted",
		"seeked",      // technical word
		"bodyreader",  // variable name
		"cantPrepare", // variable name
		"dontPrepare", // variable name
	}
	r := New()
	r.Debug = true
	for casenum, tt := range cases {
		got, _ := r.Replace(tt)
		if got != tt {
			t.Errorf("%d: %q got converted to %q", casenum, tt, got)
		}
	}
}
<commit_msg>future false positive<commit_after>package misspell

import (
	"testing"
)

func TestFalsePositives(t *testing.T) {
	cases := []string{
		"cleaner", // triggered by "cleane->cleanser" and partial word FP
		"  http.Redirect(w, req, req.URL.Path, http.StatusFound) ",
		"url is http://zeebra.com ",
		"path is /zeebra?zeebra=zeebra ",
		"Malcom_McLean",
		"implementor", // alt spelling, see https://github.com/client9/misspell/issues/46
		"searchtypes",
		" witness",
		"returndata",
		"UNDERSTOOD",
		"textinterface",
		" committed ",
		"committed",
		"Bengali",
		"Portuguese",
		"scientists",
		"causally",
		"embarrassing",
		"setuptools", // python package
		"committing",
		"guises",
		"disguise",
		"begging",
		"cmo",
		"cmos",
		"borked",
		"hadn't",
		"Iceweasel",
		"summarised",
		"autorenew",
		"travelling",
		"republished",
		"fallthru",
		"pruning",
		"deb.VersionDontCare",
		"authtag",
		"intrepid",
		"usefully",
		"there",
		"definite",
		"earliest",
		"Japanese",
		"international",
		"excellent",
		"gracefully",
		"carefully",
		"class",
		"include",
		"process",
		"address",
		"attempt",
		"large",
		"although",
		"specific",
		"taste",
		"against",
		"successfully",
		"unsuccessfully",
		"occurred",
		"agree",
		"controlled",
		"publisher",
		"strategy",
		"geoposition",
		"paginated",
		"happened",
		"relative",
		"computing",
		"language",
		"manual",
		"token",
		"into",
		"nothing",
		"datatool",
		"propose",
		"learnt",
		"tolerant",
		"whitehat",
		"monotonic",
		"comprised",
		"indemnity",
		"flattened",
		"interrupted",
		"inotify",
		"occasional",
		"forging",
		"ampersand",
		"decomposition",
		"commit",
		"programmer", // "grammer"
		//		"requestsinserted",
		"seeked",      // technical word
		"bodyreader",  // variable name
		"cantPrepare", // variable name
		"dontPrepare", // variable name
	}
	r := New()
	r.Debug = true
	for casenum, tt := range cases {
		got, _ := r.Replace(tt)
		if got != tt {
			t.Errorf("%d: %q got converted to %q", casenum, tt, got)
		}
	}
}
<|endoftext|>


<commit_before>package dfversions

const (
    max_uint32 = ^uint32(0)
    min_uint32 = uint32(0)
)

var (
    min_version = max_uint32
    max_version = min_uint32
)

var save_versions = map[uint32]string{
    1107: "0.21.93.19a",
    1108: "0.21.95.19b",
    1110: "0.21.100.19a",
    1113: "0.21.101.19a",
    1114: "0.21.101.19d",
    1117: "0.21.102.19a",
    1119: "0.21.104.19b",
    1121: "0.21.104.19d",
    1123: "0.21.104.21a",
    1125: "0.21.104.21b",
    1128: "0.22.107.21a",
    1131: "0.22.110.22b",
    1133: "0.22.110.22d",
    1134: "0.22.110.22e",
    1137: "0.22.110.22f",
    1148: "0.22.110.23c",
    1151: "0.22.120.23a",
    1159: "0.22.120.23b",
    1160: "0.22.121.23a",
    1161: "0.22.121.23b",
    1165: "0.22.123.23a",
    1167: "0.23.125.23a",
    1168: "0.23.125.23b",
    1169: "0.23.130.23a",
    1205: "0.27.169.32a",
    1206: "0.27.169.33a",
    1209: "0.27.169.33b",
    1211: "0.27.169.33c",
    1212: "0.27.169.33d",
    1213: "0.27.169.33e",
    1215: "0.27.169.33f",
    1216: "0.27.169.33g",
    1223: "0.27.173.38a",
    1231: "0.27.176.38a",
    1234: "0.27.176.38b",
    1235: "0.27.176.38c",
    1254: "0.28.181.39a",
    1255: "0.28.181.39b",
    1256: "0.28.181.39c",
    1259: "0.28.181.39d",
    1260: "0.28.181.39e",
    1261: "0.28.181.39f",
    1265: "0.28.181.40a",
    1266: "0.28.181.40b",
    1267: "0.28.181.40c",
    1268: "0.28.181.40d",
    1287: "0.31.01",
    1288: "0.31.02",
    1289: "0.31.03",
    1292: "0.31.04",
    1295: "0.31.05",
    1297: "0.31.06",
    1300: "0.31.08",
    1304: "0.31.09",
    1305: "0.31.10",
    1310: "0.31.11",
    1311: "0.31.12",
    1323: "0.31.13",
    1325: "0.31.14",
    1326: "0.31.15",
    1327: "0.31.16",
    1340: "0.31.17",
    1341: "0.31.18",
    1351: "0.31.19",
    1353: "0.31.20",
    1354: "0.31.21",
    1359: "0.31.22",
    1360: "0.31.23",
    1361: "0.31.24",
    1362: "0.31.25",
    1372: "0.34.01",
    1374: "0.34.02",
    1376: "0.34.03",
    1377: "0.34.04",
    1378: "0.34.05",
    1382: "0.34.06",
    1383: "0.34.07",
    1400: "0.34.08",
    1402: "0.34.09",
    1403: "0.34.10",
    1404: "0.34.11",
    1441: "0.40.01",
    1442: "0.40.02",
    1443: "0.40.03",
    1444: "0.40.04",
    1445: "0.40.05",
    1446: "0.40.06",
    1448: "0.40.07",
    1449: "0.40.08",
    1451: "0.40.09",
    1452: "0.40.10",
    1456: "0.40.11",
    1459: "0.40.12",
    1462: "0.40.13",
    1469: "0.40.14",
    1470: "0.40.15",
    1471: "0.40.16",
    1472: "0.40.17",
    1473: "0.40.18",
    1474: "0.40.19",
    1477: "0.40.20",
    1478: "0.40.21",
    1479: "0.40.22",
    1480: "0.40.23",
    1481: "0.40.24",
    1531: "0.42.01",
    1532: "0.42.02",
    1533: "0.42.03",
    1534: "0.42.04",
    1537: "0.42.05",
    1542: "0.42.06",
    1551: "0.43.01",
    1552: "0.43.02",
    1553: "0.43.03",
    1555: "0.43.04",
    1556: "0.43.05",
    1596: "0.44.01",
    1597: "0.44.02",
    1600: "0.44.03",
    1603: "0.44.04",
    1604: "0.44.05",
    1611: "0.44.06",
    1612: "0.44.07",
    1613: "0.44.08",
    1614: "0.44.09",
    1620: "0.44.10",
    1623: "0.44.11",
    1625: "0.44.12",
    1710: "0.47.01",
    1711: "0.47.02",
    1713: "0.47.03",
    1715: "0.47.04",
}

func init() {
    for id, _ := range save_versions {
        if id < min_version {
            min_version = id
        }
        if id > max_version {
            max_version = id
        }
    }
}

func IsKnown(id uint32) (ok bool) {
    _, ok = save_versions[id]
    return
}

func Describe(id uint32) string {
    if IsKnown(id) {
        return save_versions[id]
    } else if id < min_version {
        return "before " + save_versions[min_version]
    } else if id > max_version {
        return "after " + save_versions[max_version]
    } else {
        var prev, next uint32
        for prev = id; !IsKnown(prev); prev-- {}
        for next = id; !IsKnown(next); next++ {}
        return "between " + Describe(prev) + " and " + Describe(next)
    }
}
<commit_msg>Add 0.47.05<commit_after>package dfversions

const (
    max_uint32 = ^uint32(0)
    min_uint32 = uint32(0)
)

var (
    min_version = max_uint32
    max_version = min_uint32
)

var save_versions = map[uint32]string{
    1107: "0.21.93.19a",
    1108: "0.21.95.19b",
    1110: "0.21.100.19a",
    1113: "0.21.101.19a",
    1114: "0.21.101.19d",
    1117: "0.21.102.19a",
    1119: "0.21.104.19b",
    1121: "0.21.104.19d",
    1123: "0.21.104.21a",
    1125: "0.21.104.21b",
    1128: "0.22.107.21a",
    1131: "0.22.110.22b",
    1133: "0.22.110.22d",
    1134: "0.22.110.22e",
    1137: "0.22.110.22f",
    1148: "0.22.110.23c",
    1151: "0.22.120.23a",
    1159: "0.22.120.23b",
    1160: "0.22.121.23a",
    1161: "0.22.121.23b",
    1165: "0.22.123.23a",
    1167: "0.23.125.23a",
    1168: "0.23.125.23b",
    1169: "0.23.130.23a",
    1205: "0.27.169.32a",
    1206: "0.27.169.33a",
    1209: "0.27.169.33b",
    1211: "0.27.169.33c",
    1212: "0.27.169.33d",
    1213: "0.27.169.33e",
    1215: "0.27.169.33f",
    1216: "0.27.169.33g",
    1223: "0.27.173.38a",
    1231: "0.27.176.38a",
    1234: "0.27.176.38b",
    1235: "0.27.176.38c",
    1254: "0.28.181.39a",
    1255: "0.28.181.39b",
    1256: "0.28.181.39c",
    1259: "0.28.181.39d",
    1260: "0.28.181.39e",
    1261: "0.28.181.39f",
    1265: "0.28.181.40a",
    1266: "0.28.181.40b",
    1267: "0.28.181.40c",
    1268: "0.28.181.40d",
    1287: "0.31.01",
    1288: "0.31.02",
    1289: "0.31.03",
    1292: "0.31.04",
    1295: "0.31.05",
    1297: "0.31.06",
    1300: "0.31.08",
    1304: "0.31.09",
    1305: "0.31.10",
    1310: "0.31.11",
    1311: "0.31.12",
    1323: "0.31.13",
    1325: "0.31.14",
    1326: "0.31.15",
    1327: "0.31.16",
    1340: "0.31.17",
    1341: "0.31.18",
    1351: "0.31.19",
    1353: "0.31.20",
    1354: "0.31.21",
    1359: "0.31.22",
    1360: "0.31.23",
    1361: "0.31.24",
    1362: "0.31.25",
    1372: "0.34.01",
    1374: "0.34.02",
    1376: "0.34.03",
    1377: "0.34.04",
    1378: "0.34.05",
    1382: "0.34.06",
    1383: "0.34.07",
    1400: "0.34.08",
    1402: "0.34.09",
    1403: "0.34.10",
    1404: "0.34.11",
    1441: "0.40.01",
    1442: "0.40.02",
    1443: "0.40.03",
    1444: "0.40.04",
    1445: "0.40.05",
    1446: "0.40.06",
    1448: "0.40.07",
    1449: "0.40.08",
    1451: "0.40.09",
    1452: "0.40.10",
    1456: "0.40.11",
    1459: "0.40.12",
    1462: "0.40.13",
    1469: "0.40.14",
    1470: "0.40.15",
    1471: "0.40.16",
    1472: "0.40.17",
    1473: "0.40.18",
    1474: "0.40.19",
    1477: "0.40.20",
    1478: "0.40.21",
    1479: "0.40.22",
    1480: "0.40.23",
    1481: "0.40.24",
    1531: "0.42.01",
    1532: "0.42.02",
    1533: "0.42.03",
    1534: "0.42.04",
    1537: "0.42.05",
    1542: "0.42.06",
    1551: "0.43.01",
    1552: "0.43.02",
    1553: "0.43.03",
    1555: "0.43.04",
    1556: "0.43.05",
    1596: "0.44.01",
    1597: "0.44.02",
    1600: "0.44.03",
    1603: "0.44.04",
    1604: "0.44.05",
    1611: "0.44.06",
    1612: "0.44.07",
    1613: "0.44.08",
    1614: "0.44.09",
    1620: "0.44.10",
    1623: "0.44.11",
    1625: "0.44.12",
    1710: "0.47.01",
    1711: "0.47.02",
    1713: "0.47.03",
    1715: "0.47.04",
    1716: "0.47.05",
}

func init() {
    for id, _ := range save_versions {
        if id < min_version {
            min_version = id
        }
        if id > max_version {
            max_version = id
        }
    }
}

func IsKnown(id uint32) (ok bool) {
    _, ok = save_versions[id]
    return
}

func Describe(id uint32) string {
    if IsKnown(id) {
        return save_versions[id]
    } else if id < min_version {
        return "before " + save_versions[min_version]
    } else if id > max_version {
        return "after " + save_versions[max_version]
    } else {
        var prev, next uint32
        for prev = id; !IsKnown(prev); prev-- {}
        for next = id; !IsKnown(next); next++ {}
        return "between " + Describe(prev) + " and " + Describe(next)
    }
}
<|endoftext|>


<commit_before>package version

import "fmt"

const (
	// VersionMajor is for an API incompatible changes
	VersionMajor = 5
	// VersionMinor is for functionality in a backwards-compatible manner
	VersionMinor = 20
	// VersionPatch is for backwards-compatible bug fixes
	VersionPatch = 1

	// VersionDev indicates development branch. Releases will be empty string.
	VersionDev = "-dev"
)

// Version is the specification version that the package types support.
var Version = fmt.Sprintf("%d.%d.%d%s", VersionMajor, VersionMinor, VersionPatch, VersionDev)
<commit_msg>Release v5.21.0<commit_after>package version

import "fmt"

const (
	// VersionMajor is for an API incompatible changes
	VersionMajor = 5
	// VersionMinor is for functionality in a backwards-compatible manner
	VersionMinor = 21
	// VersionPatch is for backwards-compatible bug fixes
	VersionPatch = 0

	// VersionDev indicates development branch. Releases will be empty string.
	VersionDev = ""
)

// Version is the specification version that the package types support.
var Version = fmt.Sprintf("%d.%d.%d%s", VersionMajor, VersionMinor, VersionPatch, VersionDev)
<|endoftext|>


<commit_before>// Copyright 2017 Istio 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 version for fortio holds version information and build information.
package version // import "fortio.org/fortio/version"
import (
	"fmt"
	"runtime"

	"fortio.org/fortio/log"
)

const (
	major = 1
	minor = 6
	patch = 1

	debug = false // turn on to debug init()
)

var (
	// The following are set by Dockerfile during link time:
	tag       = "n/a"
	buildInfo = "unknown"
	// Number of lines in git status --porcelain; 0 means clean
	gitstatus = "0" // buildInfo default is unknown so no need to add -dirty
	// computed in init()
	version     = ""
	longVersion = ""
)

// Major returns the numerical major version number (first digit of version.Short()).
func Major() int {
	return major
}

// Minor returns the numerical minor version number (second digit of version.Short()).
func Minor() int {
	return minor
}

// Patch returns the numerical patch level (third digit of version.Short()).
func Patch() int {
	return patch
}

// Short returns the 3 digit short version string Major.Minor.Patch[-pre]
// version.Short() is the overall project version (used to version json
// output too). "-pre" is added when the version doesn't match exactly
// a git tag or the build isn't from a clean source tree. (only standard
// dockerfile based build of a clean, tagged source tree should print "X.Y.Z"
// as short version).
func Short() string {
	return version
}

// Long returns the full version and build information.
// Format is "X.Y.X[-pre] YYYY-MM-DD HH:MM SHA[-dirty]" date and time is
// the build date (UTC), sha is the git sha of the source tree.
func Long() string {
	return longVersion
}

// Carefully manually tested all the combinations in pair with Dockerfile
func init() {
	if debug {
		log.SetLogLevel(log.Debug)
	}
	version = fmt.Sprintf("%d.%d.%d", major, minor, patch)
	clean := (gitstatus == "0")
	// The docker build will pass the git tag to the build, if it is clean
	// from a tag it will look like v0.7.0
	if tag != "v"+version || !clean {
		log.Debugf("tag is %v, clean is %v marking as pre release", tag, clean)
		version += "-pre"
	}
	if !clean {
		buildInfo += "-dirty"
		log.Debugf("gitstatus is %q, marking buildinfo as dirty: %v", gitstatus, buildInfo)
	}
	longVersion = version + " " + buildInfo + " " + runtime.Version()
}
<commit_msg>forgot to bump version, skipping 1.6.2 for 1.6.3<commit_after>// Copyright 2017 Istio 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 version for fortio holds version information and build information.
package version // import "fortio.org/fortio/version"
import (
	"fmt"
	"runtime"

	"fortio.org/fortio/log"
)

const (
	major = 1
	minor = 6
	patch = 3

	debug = false // turn on to debug init()
)

var (
	// The following are set by Dockerfile during link time:
	tag       = "n/a"
	buildInfo = "unknown"
	// Number of lines in git status --porcelain; 0 means clean
	gitstatus = "0" // buildInfo default is unknown so no need to add -dirty
	// computed in init()
	version     = ""
	longVersion = ""
)

// Major returns the numerical major version number (first digit of version.Short()).
func Major() int {
	return major
}

// Minor returns the numerical minor version number (second digit of version.Short()).
func Minor() int {
	return minor
}

// Patch returns the numerical patch level (third digit of version.Short()).
func Patch() int {
	return patch
}

// Short returns the 3 digit short version string Major.Minor.Patch[-pre]
// version.Short() is the overall project version (used to version json
// output too). "-pre" is added when the version doesn't match exactly
// a git tag or the build isn't from a clean source tree. (only standard
// dockerfile based build of a clean, tagged source tree should print "X.Y.Z"
// as short version).
func Short() string {
	return version
}

// Long returns the full version and build information.
// Format is "X.Y.X[-pre] YYYY-MM-DD HH:MM SHA[-dirty]" date and time is
// the build date (UTC), sha is the git sha of the source tree.
func Long() string {
	return longVersion
}

// Carefully manually tested all the combinations in pair with Dockerfile
func init() {
	if debug {
		log.SetLogLevel(log.Debug)
	}
	version = fmt.Sprintf("%d.%d.%d", major, minor, patch)
	clean := (gitstatus == "0")
	// The docker build will pass the git tag to the build, if it is clean
	// from a tag it will look like v0.7.0
	if tag != "v"+version || !clean {
		log.Debugf("tag is %v, clean is %v marking as pre release", tag, clean)
		version += "-pre"
	}
	if !clean {
		buildInfo += "-dirty"
		log.Debugf("gitstatus is %q, marking buildinfo as dirty: %v", gitstatus, buildInfo)
	}
	longVersion = version + " " + buildInfo + " " + runtime.Version()
}
<|endoftext|>


<commit_before>package version

var (
	// The full version string
	Version = "1.0.1"
	// GitCommit is set with --ldflags "-X main.gitCommit=$(git rev-parse HEAD)"
	GitCommit string
)

func init() {
	if GitCommit != "" {
		Version += "-" + GitCommit[:8]
	}
}
<commit_msg>edit version for prod<commit_after>package version

var (
	// The full version string
	Version = "1.0.2"
	// GitCommit is set with --ldflags "-X main.gitCommit=$(git rev-parse HEAD)"
	GitCommit string
)

func init() {
	if GitCommit != "" {
		Version += "-" + GitCommit[:8]
	}
}
<|endoftext|>


<commit_before>package server

import (
	"database/sql"
	"gopkg.in/gin-gonic/gin.v1"
	"log"
	"net/http"
	"net/url"
	"path/filepath"
)

type Login struct {
	User     string `form:"username" json:"username" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

type Signup struct {
	User     string `form:"username" json:"username" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
	Email    string `form:"email" json:"email" binding:"required"`
}

type AddSite struct {
	SiteName  string `form:"site_name" json:"site_name" binding:"required"`
	SiteUrl   string `form:"site_url" json:"site_url" binding:"required"`
	SiteGroup string `form:"site_group" json:"email"`
}

type favInfo struct {
	SiteName string
	SiteIcon string
	SiteUrl string
}

type favCtt struct {
	FavName string
	FavData []favInfo
}

type rsFav []favCtt

type test []int

func routers(r *gin.Engine) {

	r.LoadHTMLGlob(filepath.Join(staticPrefix, "views/*"))

	db := getDB()

	// 主页
	r.GET("/", func(c *gin.Context) {
		var siteName, siteIcon, siteUrl, tagName string
		uname := 1
		rows, err := db.Query("select sites.site_name,sites.site_icon,sites.site_url, tags.tag_name from sites, tags, users WHERE sites.tag = tags.id and users.id = ? GROUP BY sites.tag, sites.id", uname)
		defer rows.Close()

		var prefix = ""
		var isPush = false
		fav := favCtt{}
		//dataArr := fav.data
		rsFavIns := rsFav{}
		for rows.Next() {
			err := rows.Scan(&siteName, &siteIcon, &siteUrl, &tagName)
			checkErr(err)
			isPush = false
			if prefix != tagName {
				if prefix != "" {
					rsFavIns = append(rsFavIns, fav)
					isPush = true
				}
				fav = favCtt{}
				fav.FavName = tagName
				prefix = tagName
			}
			favInfoIns := favInfo{siteName, siteIcon, siteUrl,}
			fav.FavData = append(fav.FavData, favInfoIns)
		}

		if !isPush {
			rsFavIns = append(rsFavIns, fav)
		}
		err = rows.Err()
		checkErr(err)

		c.HTML(http.StatusOK, "main.tmpl", gin.H{
			"title":    "psfe",
			"username": "schoeu",
			"favData": rsFavIns,
		})
	})

	// 注册GET
	r.GET("/signup", func(c *gin.Context) {
		c.HTML(http.StatusOK, "signup.tmpl", gin.H{
			"title":   "Sign up",
			"isLogin": false,
		})
	})

	// 注册POST
	r.POST("/signup", func(c *gin.Context) {
		var form Signup
		if c.Bind(&form) == nil {
			var id string
			uname := form.User
			rows, err := db.Query("select id from users where username = ?", uname)
			defer rows.Close()

			for rows.Next() {
				err := rows.Scan(&id)
				checkErr(err)
			}

			err = rows.Err()
			checkErr(err)

			// 表中无记录
			if id == "" {
				stmt, err := db.Prepare("insert into users(username, password, email)values(?,?,?)")
				checkErr(err)

				defer stmt.Close()

				_, err = stmt.Exec(uname, form.Password, form.Email)
				if err != sql.ErrNoRows {
					c.JSON(http.StatusOK, gin.H{
						"errorNo":  0,
						"has":      0,
						"username": uname,
					})
				} else {
					checkErr(err)
				}
			} else {
				checkErr(err)
				c.JSON(http.StatusOK, gin.H{
					"errorNo": 0,
					"has":     1,
				})
			}

			checkErr(err)
		}
	})

	// 登录GET
	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"title":   "Sign in",
			"isLogin": false,
		})
	})

	// 登录POST
	r.POST("/login", func(c *gin.Context) {
		var form Login
		if c.Bind(&form) == nil {
			var psw string
			rows := db.QueryRow("select password from users where username = ?", form.User)

			err := rows.Scan(&psw)
			if err == sql.ErrNoRows {
				c.JSON(http.StatusOK, gin.H{
					"errorNo": 0,
					"issigup": 0,
				})
				return
			}

			checkErr(err)

			if form.Password == psw {
				c.Redirect(http.StatusFound, "/")
			} else {
				c.JSON(http.StatusOK, gin.H{
					"errorNo": 0,
					"issigup": 1,
					"msg":     "wrong password.",
				})
			}
		}
	})

	// 注册POST
	r.POST("/addsite", func(c *gin.Context) {
		var form AddSite
		if c.Bind(&form) == nil {

			var id string
			siteInfo, err := url.Parse(form.SiteUrl)
			checkErr(err)
			scheme := siteInfo.Scheme
			if scheme == "" {
				scheme = "http"
			}
			scheme = scheme + "://"

			siteUrl := scheme + siteInfo.Host
			host := siteInfo.Host

			siteFullUrl := scheme + siteInfo.Host + siteInfo.Path

			siteIcon := siteUrl + "/favicon.ico"

			rows, err := db.Query("select id from sites where site_name = ?", host)
			defer rows.Close()

			for rows.Next() {
				err := rows.Scan(&id)
				checkErr(err)
			}

			err = rows.Err()
			checkErr(err)

			// 表中无记录
			if id == "" {
				stmt, err := db.Prepare("insert into sites(site_url, site_name, tag, site_icon)values(?,?,?,?)")
				checkErr(err)

				defer stmt.Close()

				_, err = stmt.Exec(siteFullUrl, form.SiteName, form.SiteGroup, siteIcon)
				if err != sql.ErrNoRows {
					c.JSON(http.StatusOK, gin.H{
						"errorNo": 0,
						"ok":      1,
					})
				} else {
					checkErr(err)
				}
			} else {
				checkErr(err)
				c.JSON(http.StatusOK, gin.H{
					"errorNo": 0,
					"has":     1,
				})
			}

			checkErr(err)
		}
	})
}

func checkErr(err error) {
	if err != nil {
		log.Fatal(err)
	}

}
<commit_msg>update fixed coleection tags bug<commit_after>package server

import (
	"database/sql"
	"gopkg.in/gin-gonic/gin.v1"
	"log"
	"net/http"
	"net/url"
	"path/filepath"
	"regexp"
)

type Login struct {
	User     string `form:"username" json:"username" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
}

type Signup struct {
	User     string `form:"username" json:"username" binding:"required"`
	Password string `form:"password" json:"password" binding:"required"`
	Email    string `form:"email" json:"email" binding:"required"`
}

type AddSite struct {
	SiteName  string `form:"site_name" json:"site_name" binding:"required"`
	SiteUrl   string `form:"site_url" json:"site_url" binding:"required"`
	SiteGroup string `form:"site_group" json:"email"`
}

type favInfo struct {
	SiteName string
	SiteIcon string
	SiteUrl string
}

type favCtt struct {
	FavName string
	FavData []favInfo
}

type rsFav []favCtt

type test []int

func routers(r *gin.Engine) {

	r.LoadHTMLGlob(filepath.Join(staticPrefix, "views/*"))

	db := getDB()

	// 主页
	r.GET("/", func(c *gin.Context) {
		var siteName, siteIcon, siteUrl, tagName string
		uname := 1
		rows, err := db.Query("select sites.site_name,sites.site_icon,sites.site_url, tags.tag_name from sites, tags, users WHERE sites.tag = tags.id and users.id = ? GROUP BY sites.tag, sites.id", uname)
		defer rows.Close()

		var prefix = ""
		var isPush = false
		fav := favCtt{}
		//dataArr := fav.data
		rsFavIns := rsFav{}
		for rows.Next() {
			err := rows.Scan(&siteName, &siteIcon, &siteUrl, &tagName)
			checkErr(err)
			isPush = false
			if prefix != tagName {
				if prefix != "" {
					rsFavIns = append(rsFavIns, fav)
					isPush = true
				}
				fav = favCtt{}
				fav.FavName = tagName
				prefix = tagName
			}
			favInfoIns := favInfo{siteName, siteIcon, siteUrl,}
			fav.FavData = append(fav.FavData, favInfoIns)
		}

		if !isPush {
			rsFavIns = append(rsFavIns, fav)
		}
		err = rows.Err()
		checkErr(err)

		c.HTML(http.StatusOK, "main.tmpl", gin.H{
			"title":    "psfe",
			"username": "schoeu",
			"favData": rsFavIns,
		})
	})

	// 注册GET
	r.GET("/signup", func(c *gin.Context) {
		c.HTML(http.StatusOK, "signup.tmpl", gin.H{
			"title":   "Sign up",
			"isLogin": false,
		})
	})

	// 注册POST
	r.POST("/signup", func(c *gin.Context) {
		var form Signup
		if c.Bind(&form) == nil {
			var id string
			uname := form.User
			rows, err := db.Query("select id from users where username = ?", uname)
			defer rows.Close()

			for rows.Next() {
				err := rows.Scan(&id)
				checkErr(err)
			}

			err = rows.Err()
			checkErr(err)

			// 表中无记录
			if id == "" {
				stmt, err := db.Prepare("insert into users(username, password, email)values(?,?,?)")
				checkErr(err)

				defer stmt.Close()

				_, err = stmt.Exec(uname, form.Password, form.Email)
				if err != sql.ErrNoRows {
					c.JSON(http.StatusOK, gin.H{
						"errorNo":  0,
						"has":      0,
						"username": uname,
					})
				} else {
					checkErr(err)
				}
			} else {
				checkErr(err)
				c.JSON(http.StatusOK, gin.H{
					"errorNo": 0,
					"has":     1,
				})
			}

			checkErr(err)
		}
	})

	// 登录GET
	r.GET("/login", func(c *gin.Context) {
		c.HTML(http.StatusOK, "login.tmpl", gin.H{
			"title":   "Sign in",
			"isLogin": false,
		})
	})

	// 登录POST
	r.POST("/login", func(c *gin.Context) {
		var form Login
		if c.Bind(&form) == nil {
			var psw string
			rows := db.QueryRow("select password from users where username = ?", form.User)

			err := rows.Scan(&psw)
			if err == sql.ErrNoRows {
				c.JSON(http.StatusOK, gin.H{
					"errorNo": 0,
					"issigup": 0,
				})
				return
			}

			checkErr(err)

			if form.Password == psw {
				c.Redirect(http.StatusFound, "/")
			} else {
				c.JSON(http.StatusOK, gin.H{
					"errorNo": 0,
					"issigup": 1,
					"msg":     "wrong password.",
				})
			}
		}
	})

	// 注册POST
	r.POST("/addsite", func(c *gin.Context) {
		var form AddSite
		if c.Bind(&form) == nil {

			var id string
			siteInfo, err := url.Parse(form.SiteUrl)
			checkErr(err)
			scheme := siteInfo.Scheme
			if scheme == "" {
				scheme = "http"
			}

			host := siteInfo.Host

			if host == "" {
				host = siteInfo.Path
			}

			siteFullUrl := form.SiteUrl

			siteIcon := filepath.Join(host, "/favicon.ico")

			matched, err := regexp.MatchString("://", siteIcon)
			if !matched {
				siteIcon = scheme + "://" + siteIcon
			}

			rows, err := db.Query("select id from sites where site_name = ?", host)
			defer rows.Close()

			for rows.Next() {
				err := rows.Scan(&id)
				checkErr(err)
			}

			err = rows.Err()
			checkErr(err)

			// 表中无记录
			if id == "" {
				stmt, err := db.Prepare("insert into sites(site_url, site_name, tag, site_icon)values(?,?,?,?)")
				checkErr(err)

				defer stmt.Close()

				_, err = stmt.Exec(siteFullUrl, form.SiteName, form.SiteGroup, siteIcon)
				if err != sql.ErrNoRows {
					c.JSON(http.StatusOK, gin.H{
						"errorNo": 0,
						"ok":      1,
					})
				} else {
					checkErr(err)
				}
			} else {
				checkErr(err)
				c.JSON(http.StatusOK, gin.H{
					"errorNo": 0,
					"has":     1,
				})
			}

			checkErr(err)
		}
	})
}

func checkErr(err error) {
	if err != nil {
		log.Fatal(err)
	}

}
<|endoftext|>


<commit_before>package pointer

import (
	"github.com/github/git-lfs/lfs"
	"github.com/technoweenie/go-contentaddressable"
	"io"
	"os"
)

func Smudge(writer io.Writer, ptr *Pointer, cb lfs.CopyCallback) error {
	mediafile, err := lfs.LocalMediaPath(ptr.Oid)
	if err != nil {
		return err
	}

	var wErr *lfs.WrappedError
	if stat, statErr := os.Stat(mediafile); statErr != nil || stat == nil {
		wErr = downloadFile(writer, ptr, mediafile, cb)
	} else {
		wErr = readLocalFile(writer, ptr, mediafile, cb)
	}

	if wErr != nil {
		return &SmudgeError{ptr.Oid, mediafile, wErr}
	} else {
		return nil
	}
}

func downloadFile(writer io.Writer, ptr *Pointer, mediafile string, cb lfs.CopyCallback) *lfs.WrappedError {
	reader, size, wErr := lfs.Download(mediafile)
	if reader != nil {
		defer reader.Close()
	}

	if wErr != nil {
		wErr.Errorf("Error downloading %s.", mediafile)
		return wErr
	}

	if ptr.Size == 0 {
		ptr.Size = size
	}

	mediaFile, err := contentaddressable.NewFile(mediafile)
	if err != nil {
		return lfs.Errorf(err, "Error opening media file buffer.")
	}

	_, err = lfs.CopyWithCallback(mediaFile, reader, ptr.Size, cb)
	if err == nil {
		err = mediaFile.Accept()
	}
	mediaFile.Close()

	if err != nil {
		return lfs.Errorf(err, "Error buffering media file.")
	}

	return readLocalFile(writer, ptr, mediafile, nil)
}

func readLocalFile(writer io.Writer, ptr *Pointer, mediafile string, cb lfs.CopyCallback) *lfs.WrappedError {
	reader, err := os.Open(mediafile)
	if err != nil {
		return lfs.Errorf(err, "Error opening media file.")
	}
	defer reader.Close()

	if ptr.Size == 0 {
		if stat, _ := os.Stat(mediafile); stat != nil {
			ptr.Size = stat.Size()
		}
	}

	_, err = lfs.CopyWithCallback(writer, reader, ptr.Size, cb)
	return lfs.Errorf(err, "Error reading from media file.")
}

type SmudgeError struct {
	Oid      string
	Filename string
	*lfs.WrappedError
}
<commit_msg>pass just the oid to Download()<commit_after>package pointer

import (
	"github.com/github/git-lfs/lfs"
	"github.com/technoweenie/go-contentaddressable"
	"io"
	"os"
	"path/filepath"
)

func Smudge(writer io.Writer, ptr *Pointer, cb lfs.CopyCallback) error {
	mediafile, err := lfs.LocalMediaPath(ptr.Oid)
	if err != nil {
		return err
	}

	var wErr *lfs.WrappedError
	if stat, statErr := os.Stat(mediafile); statErr != nil || stat == nil {
		wErr = downloadFile(writer, ptr, mediafile, cb)
	} else {
		wErr = readLocalFile(writer, ptr, mediafile, cb)
	}

	if wErr != nil {
		return &SmudgeError{ptr.Oid, mediafile, wErr}
	} else {
		return nil
	}
}

func downloadFile(writer io.Writer, ptr *Pointer, mediafile string, cb lfs.CopyCallback) *lfs.WrappedError {
	reader, size, wErr := lfs.Download(filepath.Base(mediafile))
	if reader != nil {
		defer reader.Close()
	}

	if wErr != nil {
		wErr.Errorf("Error downloading %s.", mediafile)
		return wErr
	}

	if ptr.Size == 0 {
		ptr.Size = size
	}

	mediaFile, err := contentaddressable.NewFile(mediafile)
	if err != nil {
		return lfs.Errorf(err, "Error opening media file buffer.")
	}

	_, err = lfs.CopyWithCallback(mediaFile, reader, ptr.Size, cb)
	if err == nil {
		err = mediaFile.Accept()
	}
	mediaFile.Close()

	if err != nil {
		return lfs.Errorf(err, "Error buffering media file.")
	}

	return readLocalFile(writer, ptr, mediafile, nil)
}

func readLocalFile(writer io.Writer, ptr *Pointer, mediafile string, cb lfs.CopyCallback) *lfs.WrappedError {
	reader, err := os.Open(mediafile)
	if err != nil {
		return lfs.Errorf(err, "Error opening media file.")
	}
	defer reader.Close()

	if ptr.Size == 0 {
		if stat, _ := os.Stat(mediafile); stat != nil {
			ptr.Size = stat.Size()
		}
	}

	_, err = lfs.CopyWithCallback(writer, reader, ptr.Size, cb)
	return lfs.Errorf(err, "Error reading from media file.")
}

type SmudgeError struct {
	Oid      string
	Filename string
	*lfs.WrappedError
}
<|endoftext|>