<commit_before>package html // import "github.com/tdewolff/parse/html"

import (
	"io"
	"strconv"

	"github.com/tdewolff/parse"
)

////////////////////////////////////////////////////////////////

// TokenType determines the type of token, eg. a number or a semicolon.
type TokenType uint32

// TokenType values.
const (
	ErrorToken TokenType = iota // extra token when errors occur
	CommentToken
	DoctypeToken
	StartTagToken
	StartTagCloseToken
	StartTagVoidToken
	EndTagToken
	AttributeToken
	TextToken
)

// String returns the string representation of a TokenType.
func (tt TokenType) String() string {
	switch tt {
	case ErrorToken:
		return "Error"
	case CommentToken:
		return "Comment"
	case DoctypeToken:
		return "Doctype"
	case StartTagToken:
		return "StartTag"
	case StartTagCloseToken:
		return "StartTagClose"
	case StartTagVoidToken:
		return "StartTagVoid"
	case EndTagToken:
		return "EndTag"
	case AttributeToken:
		return "Attribute"
	case TextToken:
		return "Text"
	}
	return "Invalid(" + strconv.Itoa(int(tt)) + ")"
}

////////////////////////////////////////////////////////////////

// Tokenizer is the state for the tokenizer.
type Tokenizer struct {
	r   *parse.ShiftBuffer

	rawTag  Hash
	inTag   bool
	attrVal []byte
}

// NewTokenizer returns a new Tokenizer for a given io.Reader.
func NewTokenizer(r io.Reader) *Tokenizer {
	return &Tokenizer{
		r:    parse.NewShiftBuffer(r),
	}
}

// Err returns the error encountered during tokenization, this is often io.EOF but also other errors can be returned.
func (z Tokenizer) Err() error {
	return z.r.Err()
}

// IsEOF returns true when it has encountered EOF and thus loaded the last buffer in memory.
func (z Tokenizer) IsEOF() bool {
	return z.r.IsEOF()
}

// Next returns the next Token. It returns ErrorToken when an error was encountered. Using Err() one can retrieve the error message.
func (z *Tokenizer) Next() (TokenType, []byte) {
	var c byte
	if z.inTag {
		z.attrVal = nil
		c = z.r.Peek(0)
		if c != '>' && c != '/' {
			return AttributeToken, z.shiftAttribute()
		}
		z.inTag = false
		if c == '/' {
			z.r.Move(2)
			return StartTagVoidToken, z.r.Shift()
		} else {
			z.r.Move(1)
			return StartTagCloseToken, z.r.Shift()
		}
	}

	if z.rawTag != 0 {
		if rawText := z.shiftRawText(); len(rawText) > 0 {
			z.rawTag = 0
			return TextToken, rawText
		}
		z.rawTag = 0
	}

	for {
		c = z.r.Peek(0)
		if c == 0 {
			if z.r.Pos() > 0 {
				return TextToken, z.r.Shift()
			} else {
				return ErrorToken, []byte{}
			}
		} else if c == '<' {
			c = z.r.Peek(1)
			if z.r.Pos() > 0 {
				if c == '/' && z.r.Peek(2) != 0 || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '!' || c == '?' {
					return TextToken, z.r.Shift()
				}
			} else if c == '/' && z.r.Peek(2) != 0 {
				z.r.Move(2)
				z.r.Skip()
				if c = z.r.Peek(0); c != '>' && !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
					return CommentToken, z.shiftBogusComment()
				}
				return EndTagToken, z.shiftEndTag()
			} else if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
				z.r.Move(1)
				z.r.Skip()
				z.inTag = true
				return StartTagToken, z.shiftStartTag()
			} else if c == '!' {
				z.r.Move(2)
				z.r.Skip()
				return z.readMarkup()
			} else if c == '?' {
				z.r.Move(1)
				z.r.Skip()
				return CommentToken, z.shiftBogusComment()
			}
		}
		z.r.Move(1)
	}
	return ErrorToken, []byte{}
}

func (z *Tokenizer) AttrVal() []byte {
	return z.attrVal
}

func (z *Tokenizer) RawTag() Hash {
	return z.rawTag
}

////////////////////////////////////////////////////////////////

/*
The following functions follow the specifications at http://www.w3.org/html/wg/drafts/html/master/syntax.html
*/

func (z *Tokenizer) shiftRawText() []byte {
	if z.rawTag == Plaintext {
		for {
			if z.r.Peek(0) == 0 {
				return z.r.Shift()
			}
			z.r.Move(1)
		}
	} else { // RCDATA, RAWTEXT and SCRIPT
		for {
			c := z.r.Peek(0)
			if c == 0 {
				return z.r.Shift()
			} else if c == '<' && z.r.Peek(1) == '/' {
				nPos := z.r.Pos()
				z.r.Move(2)
				for {
					if c = z.r.Peek(0); !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
						break
					}
					z.r.Move(1)
				}
				if h := ToHash(parse.CopyToLower(z.r.Bytes()[nPos+2:])); h == z.rawTag {
					z.r.MoveTo(nPos)
					return z.r.Shift()
				}
			} else if z.rawTag == Script && z.at([]byte("<!--")) {
				z.r.Move(4)
				inScript := false
				for {
					if z.at([]byte("-->")) {
						z.r.Move(3)
						break
					} else if z.at([]byte("<script")) {
						z.r.Move(7)
						inScript = true
					} else if z.at([]byte("</script")) {
						if inScript {
							z.r.Move(8)
							inScript = false
						} else {
							return z.r.Shift()
						}
					}
					z.r.Move(1)
				}
			} else {
				z.r.Move(1)
			}
		}
	}
}

func (z *Tokenizer) readMarkup() (TokenType, []byte) {
	if z.at([]byte("--")) {
		z.r.Move(2)
		z.r.Skip()
		for {
			if z.r.Peek(0) == 0 {
				return CommentToken, z.r.Shift()
			} else if z.at([]byte("-->")) {
				comment := z.r.Shift()
				z.r.Move(3)
				z.r.Skip()
				return CommentToken, comment
			} else if z.at([]byte("--!>")) {
				comment := z.r.Shift()
				z.r.Move(4)
				z.r.Skip()
				return CommentToken, comment
			}
			z.r.Move(1)
		}
	} else if z.at([]byte("[CDATA[")) {
		z.r.Move(7)
		z.r.Skip()
		for {
			if z.r.Peek(0) == 0 {
				return TextToken, z.r.Shift()
			} else if z.at([]byte("]]>")) {
				text := z.r.Shift()
				z.r.Move(3)
				z.r.Skip()
				return TextToken, text
			}
			z.r.Move(1)
		}
	} else {
		z.r.Skip()
		if z.atCaseInsensitive([]byte("doctype")) {
			z.r.Move(7)
			for {
				if c := z.r.Peek(0); c == '>' || c == 0 {
					doctype := z.r.Shift()
					z.r.Move(1)
					z.r.Skip()
					return DoctypeToken, doctype
				}
				z.r.Move(1)
			}
		}
	}
	bogus := z.shiftBogusComment()
	return CommentToken, bogus
}

func (z *Tokenizer) shiftBogusComment() []byte {
	for {
		if c := z.r.Peek(0); c == '>' || c == 0 {
			bogus := z.r.Shift()
			z.r.Move(1)
			z.r.Skip()
			return bogus
		}
		z.r.Move(1)
	}
}

func (z *Tokenizer) shiftStartTag() []byte {
	for {
		if c := z.r.Peek(0); c == ' ' || c == '>' || c == '/' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 {
			break
		}
		z.r.Move(1)
	}
	name := parse.ToLower(z.r.Shift())
	if h := ToHash(name); h == Textarea || h == Title || h == Style || h == Xmp || h == Iframe || h == Noembed || h == Noframes || h == Noscript || h == Script || h == Plaintext {
		z.rawTag = h
	}
	z.skipWhitespace() // before attribute name state
	return name
}

func (z *Tokenizer) shiftAttribute() []byte {
	for { // attribute name state
		if c := z.r.Peek(0); c == ' ' || c == '=' || c == '>' || c == '/' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 {
			break
		}
		z.r.Move(1)
	}
	name := parse.ToLower(z.r.Shift())
	z.skipWhitespace() // after attribute name state
	if z.r.Peek(0) == '=' {
		z.r.Move(1)
		z.skipWhitespace() // before attribute value state
		delim := z.r.Peek(0)
		if delim == '"' || delim == '\'' { // attribute value single- and double-quoted state
			z.r.Move(1)
			for {
				if z.r.Peek(0) == delim {
					break
				}
				z.r.Move(1)
			}
			z.r.Move(1)
		} else { // attribute value unquoted state
			for {
				if c := z.r.Peek(0); c == ' ' || c == '>' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 {
					break
				}
				z.r.Move(1)
			}
		}
		z.attrVal = z.r.Shift()
		z.skipWhitespace() // before attribute name state or after attribute quoted value state
	} else {
		z.attrVal = nil
	}
	return name
}

func (z *Tokenizer) shiftEndTag() []byte {
	for {
		c := z.r.Peek(0)
		if c == 0 {
			return z.r.Shift()
		} else if c == '>' {
			name := parse.ToLower(z.r.Shift())
			z.r.Move(1)
			z.r.Skip()
			return name
		}
		z.r.Move(1)
	}
}

func (z *Tokenizer) skipWhitespace() {
	for {
		c := z.r.Peek(0)
		if c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != '\f' || c == 0 {
			break
		}
		z.r.Move(1)
	}
	z.r.Skip()
}

func (z *Tokenizer) at(b []byte) bool {
	for i, c := range b {
		if z.r.Peek(i) != c {
			return false
		}
	}
	return true
}

func (z *Tokenizer) atCaseInsensitive(b []byte) bool {
	for i, c := range b {
		if z.r.Peek(i) != c && (z.r.Peek(i) | ('a' - 'A')) != c {
			return false
		}
	}
	return true
}
<commit_msg>Aesthetic change<commit_after>package html // import "github.com/tdewolff/parse/html"

import (
	"io"
	"strconv"

	"github.com/tdewolff/parse"
)

////////////////////////////////////////////////////////////////

// TokenType determines the type of token, eg. a number or a semicolon.
type TokenType uint32

// TokenType values.
const (
	ErrorToken TokenType = iota // extra token when errors occur
	CommentToken
	DoctypeToken
	StartTagToken
	StartTagCloseToken
	StartTagVoidToken
	EndTagToken
	AttributeToken
	TextToken
)

// String returns the string representation of a TokenType.
func (tt TokenType) String() string {
	switch tt {
	case ErrorToken:
		return "Error"
	case CommentToken:
		return "Comment"
	case DoctypeToken:
		return "Doctype"
	case StartTagToken:
		return "StartTag"
	case StartTagCloseToken:
		return "StartTagClose"
	case StartTagVoidToken:
		return "StartTagVoid"
	case EndTagToken:
		return "EndTag"
	case AttributeToken:
		return "Attribute"
	case TextToken:
		return "Text"
	}
	return "Invalid(" + strconv.Itoa(int(tt)) + ")"
}

////////////////////////////////////////////////////////////////

// Tokenizer is the state for the tokenizer.
type Tokenizer struct {
	r   *parse.ShiftBuffer

	rawTag  Hash
	inTag   bool
	attrVal []byte
}

// NewTokenizer returns a new Tokenizer for a given io.Reader.
func NewTokenizer(r io.Reader) *Tokenizer {
	return &Tokenizer{
		r:    parse.NewShiftBuffer(r),
	}
}

// Err returns the error encountered during tokenization, this is often io.EOF but also other errors can be returned.
func (z Tokenizer) Err() error {
	return z.r.Err()
}

// IsEOF returns true when it has encountered EOF and thus loaded the last buffer in memory.
func (z Tokenizer) IsEOF() bool {
	return z.r.IsEOF()
}

// Next returns the next Token. It returns ErrorToken when an error was encountered. Using Err() one can retrieve the error message.
func (z *Tokenizer) Next() (TokenType, []byte) {
	var c byte
	if z.inTag {
		z.attrVal = nil
		c = z.r.Peek(0)
		if c != '>' && c != '/' {
			return AttributeToken, z.shiftAttribute()
		}
		z.inTag = false
		if c == '/' {
			z.r.Move(2)
			return StartTagVoidToken, z.r.Shift()
		} else {
			z.r.Move(1)
			return StartTagCloseToken, z.r.Shift()
		}
	}

	if z.rawTag != 0 {
		if rawText := z.shiftRawText(); len(rawText) > 0 {
			z.rawTag = 0
			return TextToken, rawText
		}
		z.rawTag = 0
	}

	for {
		c = z.r.Peek(0)
		if c == 0 {
			if z.r.Pos() > 0 {
				return TextToken, z.r.Shift()
			} else {
				return ErrorToken, []byte{}
			}
		} else if c == '<' {
			c = z.r.Peek(1)
			if z.r.Pos() > 0 {
				if c == '/' && z.r.Peek(2) != 0 || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '!' || c == '?' {
					return TextToken, z.r.Shift()
				}
			} else if c == '/' && z.r.Peek(2) != 0 {
				z.r.Move(2)
				z.r.Skip()
				if c = z.r.Peek(0); c != '>' && !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
					return CommentToken, z.shiftBogusComment()
				}
				return EndTagToken, z.shiftEndTag()
			} else if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
				z.r.Move(1)
				z.r.Skip()
				z.inTag = true
				return StartTagToken, z.shiftStartTag()
			} else if c == '!' {
				z.r.Move(2)
				z.r.Skip()
				return z.readMarkup()
			} else if c == '?' {
				z.r.Move(1)
				z.r.Skip()
				return CommentToken, z.shiftBogusComment()
			}
		}
		z.r.Move(1)
	}
	return ErrorToken, []byte{}
}

func (z *Tokenizer) AttrVal() []byte {
	return z.attrVal
}

func (z *Tokenizer) RawTag() Hash {
	return z.rawTag
}

////////////////////////////////////////////////////////////////

/*
The following functions follow the specifications at http://www.w3.org/html/wg/drafts/html/master/syntax.html
*/

func (z *Tokenizer) shiftRawText() []byte {
	if z.rawTag == Plaintext {
		for {
			if z.r.Peek(0) == 0 {
				return z.r.Shift()
			}
			z.r.Move(1)
		}
	} else { // RCDATA, RAWTEXT and SCRIPT
		for {
			c := z.r.Peek(0)
			if c == 0 {
				return z.r.Shift()
			} else if c == '<' && z.r.Peek(1) == '/' {
				nPos := z.r.Pos()
				z.r.Move(2)
				for {
					if c = z.r.Peek(0); !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
						break
					}
					z.r.Move(1)
				}
				if h := ToHash(parse.CopyToLower(z.r.Bytes()[nPos+2:])); h == z.rawTag {
					z.r.MoveTo(nPos)
					return z.r.Shift()
				}
			} else if z.rawTag == Script && z.at([]byte("<!--")) {
				z.r.Move(4)
				inScript := false
				for {
					if z.at([]byte("-->")) {
						z.r.Move(3)
						break
					} else if z.at([]byte("<script")) {
						z.r.Move(7)
						inScript = true
					} else if z.at([]byte("</script")) {
						if inScript {
							z.r.Move(8)
							inScript = false
						} else {
							return z.r.Shift()
						}
					}
					z.r.Move(1)
				}
			} else {
				z.r.Move(1)
			}
		}
	}
}

func (z *Tokenizer) readMarkup() (TokenType, []byte) {
	if z.at([]byte("--")) {
		z.r.Move(2)
		z.r.Skip()
		for {
			if z.r.Peek(0) == 0 {
				return CommentToken, z.r.Shift()
			} else if z.at([]byte("-->")) {
				comment := z.r.Shift()
				z.r.Move(3)
				z.r.Skip()
				return CommentToken, comment
			} else if z.at([]byte("--!>")) {
				comment := z.r.Shift()
				z.r.Move(4)
				z.r.Skip()
				return CommentToken, comment
			}
			z.r.Move(1)
		}
	} else if z.at([]byte("[CDATA[")) {
		z.r.Move(7)
		z.r.Skip()
		for {
			if z.r.Peek(0) == 0 {
				return TextToken, z.r.Shift()
			} else if z.at([]byte("]]>")) {
				text := z.r.Shift()
				z.r.Move(3)
				z.r.Skip()
				return TextToken, text
			}
			z.r.Move(1)
		}
	} else {
		z.r.Skip()
		if z.atCaseInsensitive([]byte("doctype")) {
			z.r.Move(7)
			for {
				if c := z.r.Peek(0); c == '>' || c == 0 {
					doctype := z.r.Shift()
					z.r.Move(1)
					z.r.Skip()
					return DoctypeToken, doctype
				}
				z.r.Move(1)
			}
		}
	}
	bogus := z.shiftBogusComment()
	return CommentToken, bogus
}

func (z *Tokenizer) shiftBogusComment() []byte {
	for {
		if c := z.r.Peek(0); c == '>' || c == 0 {
			bogus := z.r.Shift()
			z.r.Move(1)
			z.r.Skip()
			return bogus
		}
		z.r.Move(1)
	}
}

func (z *Tokenizer) shiftStartTag() []byte {
	for {
		if c := z.r.Peek(0); c == ' ' || c == '>' || c == '/' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 {
			break
		}
		z.r.Move(1)
	}
	name := parse.ToLower(z.r.Shift())
	if h := ToHash(name); h == Textarea || h == Title || h == Style || h == Xmp || h == Iframe || h == Noembed || h == Noframes || h == Noscript || h == Script || h == Plaintext {
		z.rawTag = h
	}
	z.skipWhitespace() // before attribute name state
	return name
}

func (z *Tokenizer) shiftAttribute() []byte {
	for { // attribute name state
		if c := z.r.Peek(0); c == ' ' || c == '=' || c == '>' || c == '/' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 {
			break
		}
		z.r.Move(1)
	}
	name := parse.ToLower(z.r.Shift())
	z.skipWhitespace() // after attribute name state
	if z.r.Peek(0) == '=' {
		z.r.Move(1)
		z.skipWhitespace() // before attribute value state
		delim := z.r.Peek(0)
		if delim == '"' || delim == '\'' { // attribute value single- and double-quoted state
			z.r.Move(1)
			for {
				if z.r.Peek(0) == delim {
					break
				}
				z.r.Move(1)
			}
			z.r.Move(1)
		} else { // attribute value unquoted state
			for {
				if c := z.r.Peek(0); c == ' ' || c == '>' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 {
					break
				}
				z.r.Move(1)
			}
		}
		z.attrVal = z.r.Shift()
		z.skipWhitespace() // before attribute name state or after attribute quoted value state
	} else {
		z.attrVal = nil
	}
	return name
}

func (z *Tokenizer) shiftEndTag() []byte {
	for {
		c := z.r.Peek(0)
		if c == 0 {
			return z.r.Shift()
		} else if c == '>' {
			name := parse.ToLower(z.r.Shift())
			z.r.Move(1)
			z.r.Skip()
			return name
		}
		z.r.Move(1)
	}
}

func (z *Tokenizer) skipWhitespace() {
	for {
		c := z.r.Peek(0)
		if c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != '\f' || c == 0 {
			break
		}
		z.r.Move(1)
	}
	z.r.Skip()
}

func (z *Tokenizer) at(b []byte) bool {
	for i, c := range b {
		if z.r.Peek(i) != c {
			return false
		}
	}
	return true
}

func (z *Tokenizer) atCaseInsensitive(b []byte) bool {
	for i, c := range b {
		if z.r.Peek(i) != c && (z.r.Peek(i) + ('a' - 'A')) != c {
			return false
		}
	}
	return true
}
<|endoftext|>


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

package main

import (
	"image"
	"image/color"
	"tour/pic"
)

type Image [][]uint8

func (m Image) ColorModel() color.Model {
	return color.RGBAModel
}

func (m Image) Bounds() image.Rectangle {
	dx, dy := len(m), 0
	if dx > 0 {
		dy = len(m[0])
	}

	return image.Rect(0, 0, dx, dy)
}

func (m Image) At(x, y int) color.Color {
	v := m[x][y]
	return color.RGBA{v, v, 255, 255}
}

func NewImage(x, y int, f func(int, int) uint8) Image {
	m := make([][]uint8, x)
	for i := range m {
		m[i] = make([]uint8, y)
		for j := range m[i] {
			m[i][j] = f(i, j)
		}
	}
	return m
}

func main() {
	m := NewImage(255, 255, func(a, b int) uint8 { return uint8(a * b) })
	pic.ShowImage(m)
}
<commit_msg>go-tour/gotour/solution: Adding alternative solution to the image exercise.<commit_after>// Copyright 2012 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"image"
	"image/color"
	"tour/pic"
)

type Image struct {
	Height, Width int
}

func (m Image) ColorModel() color.Model {
	return color.RGBAModel
}

func (m Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, m.Height, m.Width)
}

func (m Image) At(x, y int) color.Color {
	c := uint8(x ^ y)
	return color.RGBA{c, c, 255, 255}
}

func main() {
	m := Image{256, 256}
	pic.ShowImage(m)
}
<|endoftext|>


<commit_before>package i18n

import (
	"strconv"
)

const (
	// These are the possible values for *strconv.NumError
	_ String = "value out of range"
	_ String = "invalid syntax"
)

// Error represents an error which can be translated to
// another language. Keep in mind that Error also implements
// error, so you can return an Error from any function that
// returns error. You can later use FromError() to get back
// an Error again.
type Error interface {
	// Error returns the untranslated error message.
	Error() string
	// TranslatedError returns the translated error message.
	TranslatedError(languager Languager) string
}

// translatableError implements the Error interface.
type translatableError struct {
	Format string
	Args   []interface{}
}

func (e *translatableError) Error() string {
	return Sprintf(e.Format, nil, e.Args...)
}

func (e *translatableError) TranslatedError(languager Languager) string {
	return Sprintf(e.Format, languager, e.Args...)
}

func (e *translatableError) TranslatedString(languager Languager) string {
	return e.TranslatedError(languager)
}

// Errorf returns a error with the given format and arguments. The
// returned Error uses Sprintf internally, which means it will
// translate any argument which supports translation.
func Errorf(format string, args ...interface{}) Error {
	return &translatableError{format, args}
}

// NewError returns an Error with the given message.
func NewError(message string) Error {
	return &translatableError{Format: message}
}

// FromError returns an Error from an error, translating
// it when possible. If e already implements Error, the received
// value is returned.
func FromError(e error) Error {
	if err, ok := e.(Error); ok {
		return err
	}
	if err, ok := e.(*strconv.NumError); ok {
		return Errorf("could not parse %q: %s", err.Num, String(err.Err.Error()))
	}
	return NewError(e.Error())
}
<commit_msg>Add support for converting a i18n.Error into a translated error<commit_after>package i18n

import (
	"errors"
	"strconv"
)

const (
	// These are the possible values for *strconv.NumError
	_ String = "value out of range"
	_ String = "invalid syntax"
)

// Error represents an error which can be translated to
// another language. Keep in mind that Error also implements
// error, so you can return an Error from any function that
// returns error. You can later use FromError() to get back
// an Error again or TranslatedError, to get an error with
// the translated message.
type Error interface {
	// Error returns the untranslated error message.
	Error() string
	// Err translates the Error and returns it as an error.
	Err(languager Languager) error
	// TranslatedError returns the translated error message.
	TranslatedError(languager Languager) string
}

// translatableError implements the Error interface.
type translatableError struct {
	Format string
	Args   []interface{}
}

func (e *translatableError) Error() string {
	return Sprintf(e.Format, nil, e.Args...)
}

func (e *translatableError) Err(languager Languager) error {
	return errors.New(e.TranslatedError(languager))
}

func (e *translatableError) TranslatedError(languager Languager) string {
	return Sprintf(e.Format, languager, e.Args...)
}

func (e *translatableError) TranslatedString(languager Languager) string {
	return e.TranslatedError(languager)
}

// Errorf returns a error with the given format and arguments. The
// returned Error uses Sprintf internally, which means it will
// translate any argument which supports translation.
func Errorf(format string, args ...interface{}) Error {
	return &translatableError{format, args}
}

// NewError returns an Error with the given message.
func NewError(message string) Error {
	return &translatableError{Format: message}
}

// FromError returns an Error from an error, translating
// it when possible. If e already implements Error, the received
// value is returned.
func FromError(e error) Error {
	if err, ok := e.(Error); ok {
		return err
	}
	if err, ok := e.(*strconv.NumError); ok {
		return Errorf("could not parse %q: %s", err.Num, String(err.Err.Error()))
	}
	return NewError(e.Error())
}

func TranslatedError(err error, languager Languager) error {
	terr := FromError(err)
	if terr != nil {
		return terr.Err(languager)
	}
	return nil
}
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	"strings"

	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"

	"google.golang.org/api/cloudresourcemanager/v1"
)

func dataSourceGoogleOrganization() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceOrganizationRead,
		Schema: map[string]*schema.Schema{
			"domain": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ConflictsWith: []string{"organization"},
			},
			"organization": {
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"domain"},
			},
			"org_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"name": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"directory_customer_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"create_time": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"lifecycle_state": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func dataSourceOrganizationRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	var organization *cloudresourcemanager.Organization
	if v, ok := d.GetOk("domain"); ok {
		filter := fmt.Sprintf("domain=%s", v.(string))
		resp, err := config.clientResourceManager.Organizations.Search(&cloudresourcemanager.SearchOrganizationsRequest{
			Filter: filter,
		}).Do()
		if err != nil {
			return fmt.Errorf("Error reading organization: %s", err)
		}

		if len(resp.Organizations) == 0 {
			return fmt.Errorf("Organization not found: %s", v)
		}
		if len(resp.Organizations) > 1 {
			return fmt.Errorf("More than one matching organization found")
		}

		organization = resp.Organizations[0]
	} else if v, ok := d.GetOk("organization"); ok {
		resp, err := config.clientResourceManager.Organizations.Get(canonicalOrganizationName(v.(string))).Do()
		if err != nil {
			return handleNotFoundError(err, d, fmt.Sprintf("Organization Not Found : %s", v))
		}

		organization = resp
	} else {
		return fmt.Errorf("one of domain or organization must be set")
	}

	d.SetId(organization.Name)
	d.Set("name", organization.Name)
	d.Set("org_id", GetResourceNameFromSelfLink(organization.Name))
	d.Set("domain", organization.DisplayName)
	d.Set("create_time", organization.CreationTime)
	d.Set("lifecycle_state", organization.LifecycleState)
	if organization.Owner != nil {
		d.Set("directory_customer_id", organization.Owner.DirectoryCustomerId)
	}

	return nil
}

func canonicalOrganizationName(ba string) string {
	if strings.HasPrefix(ba, "organizations/") {
		return ba
	}

	return "organizations/" + ba
}
<commit_msg>Retry reads of organization datasource (#1553)<commit_after>package google

import (
	"fmt"
	"strings"

	"github.com/hashicorp/terraform-plugin-sdk/helper/schema"

	"google.golang.org/api/cloudresourcemanager/v1"
)

func dataSourceGoogleOrganization() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceOrganizationRead,
		Schema: map[string]*schema.Schema{
			"domain": {
				Type:          schema.TypeString,
				Optional:      true,
				Computed:      true,
				ConflictsWith: []string{"organization"},
			},
			"organization": {
				Type:          schema.TypeString,
				Optional:      true,
				ConflictsWith: []string{"domain"},
			},
			"org_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"name": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"directory_customer_id": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"create_time": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"lifecycle_state": {
				Type:     schema.TypeString,
				Computed: true,
			},
		},
	}
}

func dataSourceOrganizationRead(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)

	var organization *cloudresourcemanager.Organization
	if v, ok := d.GetOk("domain"); ok {
		filter := fmt.Sprintf("domain=%s", v.(string))
		var resp *cloudresourcemanager.SearchOrganizationsResponse
		err := retryTimeDuration(func() (err error) {
			resp, err = config.clientResourceManager.Organizations.Search(&cloudresourcemanager.SearchOrganizationsRequest{
				Filter: filter,
			}).Do()
			return err
		}, d.Timeout(schema.TimeoutRead))
		if err != nil {
			return fmt.Errorf("Error reading organization: %s", err)
		}

		if len(resp.Organizations) == 0 {
			return fmt.Errorf("Organization not found: %s", v)
		}

		if len(resp.Organizations) > 1 {
			return fmt.Errorf("More than one matching organization found")
		}

		organization = resp.Organizations[0]
	} else if v, ok := d.GetOk("organization"); ok {
		var resp *cloudresourcemanager.Organization
		err := retryTimeDuration(func() (err error) {
			resp, err = config.clientResourceManager.Organizations.Get(canonicalOrganizationName(v.(string))).Do()
			return err
		}, d.Timeout(schema.TimeoutRead))
		if err != nil {
			return handleNotFoundError(err, d, fmt.Sprintf("Organization Not Found : %s", v))
		}

		organization = resp
	} else {
		return fmt.Errorf("one of domain or organization must be set")
	}

	d.SetId(organization.Name)
	d.Set("name", organization.Name)
	d.Set("org_id", GetResourceNameFromSelfLink(organization.Name))
	d.Set("domain", organization.DisplayName)
	d.Set("create_time", organization.CreationTime)
	d.Set("lifecycle_state", organization.LifecycleState)
	if organization.Owner != nil {
		d.Set("directory_customer_id", organization.Owner.DirectoryCustomerId)
	}

	return nil
}

func canonicalOrganizationName(ba string) string {
	if strings.HasPrefix(ba, "organizations/") {
		return ba
	}

	return "organizations/" + ba
}
<|endoftext|>


<commit_before>// Copyright 2016 Hajime Hoshi
//
// 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 ebiten_test

import (
	"errors"
	"image"
	"image/color"
	"image/draw"
	_ "image/png"
	"math"
	"os"
	"testing"

	. "github.com/hajimehoshi/ebiten"
)

func TestMain(m *testing.M) {
	code := 0
	// Run an Ebiten process so that (*Image).At is available.
	f := func(screen *Image) error {
		code = m.Run()
		return errors.New("regular termination")
	}
	Run(f, 320, 240, 1, "Test")
	os.Exit(code)
}

var ebitenImageBin = ""

func openImage(path string) (image.Image, error) {
	file, err := readFile(path)
	if err != nil {
		return nil, err
	}

	img, _, err := image.Decode(file)
	if err != nil {
		return nil, err
	}
	return img, nil
}

func openEbitenImage(path string) (*Image, image.Image, error) {
	img, err := openImage(path)
	if err != nil {
		return nil, nil, err
	}

	eimg, err := NewImageFromImage(img, FilterNearest)
	if err != nil {
		return nil, nil, err
	}
	return eimg, img, nil
}

func diff(x, y uint8) uint8 {
	if x <= y {
		return y - x
	}
	return x - y
}

func TestImagePixels(t *testing.T) {
	img0, img, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}

	if got := img0.Bounds().Size(); got != img.Bounds().Size() {
		t.Errorf("img size: got %d; want %d", got, img.Bounds().Size())
	}

	for j := 0; j < img0.Bounds().Size().Y; j++ {
		for i := 0; i < img0.Bounds().Size().X; i++ {
			got := img0.At(i, j)
			want := color.RGBAModel.Convert(img.At(i, j))
			if got != want {
				t.Errorf("img0 At(%d, %d): got %#v; want %#v", i, j, got, want)
			}
		}
	}
}

func TestImageComposition(t *testing.T) {
	img2Color := color.NRGBA{0x24, 0x3f, 0x6a, 0x88}
	img3Color := color.NRGBA{0x85, 0xa3, 0x08, 0xd3}

	// TODO: Rename this to img0
	img1, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}

	w, h := img1.Bounds().Size().X, img1.Bounds().Size().Y

	img2, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}

	img3, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}

	img2.Fill(img2Color)
	img3.Fill(img3Color)
	img_12_3, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	img2.DrawImage(img1, nil)
	img3.DrawImage(img2, nil)
	img_12_3.DrawImage(img3, nil)

	img2.Fill(img2Color)
	img3.Fill(img3Color)
	img_1_23, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	img3.DrawImage(img2, nil)
	img3.DrawImage(img1, nil)
	img_1_23.DrawImage(img3, nil)

	for j := 0; j < h; j++ {
		for i := 0; i < w; i++ {
			c1 := img_12_3.At(i, j).(color.RGBA)
			c2 := img_1_23.At(i, j).(color.RGBA)
			if 1 < diff(c1.R, c2.R) || 1 < diff(c1.G, c2.G) || 1 < diff(c1.B, c2.B) || 1 < diff(c1.A, c2.A) {
				t.Errorf("img_12_3.At(%d, %d) = %#v; img_1_23.At(%[1]d, %[2]d) = %#[4]v", i, j, c1, c2)
			}
			if c1.A == 0 {
				t.Fatalf("img_12_3.At(%d, %d).A = 0; nothing is rendered?", i, j)
			}
			if c2.A == 0 {
				t.Fatalf("img_1_23.At(%d, %d).A = 0; nothing is rendered?", i, j)
			}
		}
	}
}

func TestImageSelf(t *testing.T) {
	img, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}
	if err := img.DrawImage(img, nil); err == nil {
		t.Fatalf("img.DrawImage(img, nil) doesn't return error; an error should be returned")
	}
}

func TestImageDotByDotInversion(t *testing.T) {
	img0, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}
	w, h := img0.Size()
	img1, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	op := &DrawImageOptions{}
	op.GeoM.Rotate(math.Pi)
	op.GeoM.Translate(float64(w), float64(h))
	img1.DrawImage(img0, op)

	for j := 0; j < h; j++ {
		for i := 0; i < w; i++ {
			c0 := img0.At(i, j).(color.RGBA)
			c1 := img1.At(w-i-1, h-j-1).(color.RGBA)
			if c0 != c1 {
				t.Errorf("img0.At(%[1]d, %[2]d) should equal to img1.At(%[3]d, %[4]d) but not: %[5]v vs %[6]v", i, j, w-i-1, h-j-1, c0, c1)
			}
		}
	}
}

func TestReplacePixels(t *testing.T) {
	origImg, err := openImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}
	// Convert to RGBA
	img := image.NewRGBA(origImg.Bounds())
	draw.Draw(img, img.Bounds(), origImg, image.ZP, draw.Src)

	size := img.Bounds().Size()
	img0, err := NewImage(size.X, size.Y, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}

	img0.ReplacePixels(img.Pix)
	for j := 0; j < img0.Bounds().Size().Y; j++ {
		for i := 0; i < img0.Bounds().Size().X; i++ {
			got := img0.At(i, j)
			want := img.At(i, j)
			if got != want {
				t.Errorf("img0 At(%d, %d): got %#v; want %#v", i, j, got, want)
			}
		}
	}

	p := make([]uint8, 4*size.X*size.Y)
	for i, _ := range p {
		p[i] = 0x80
	}
	img0.ReplacePixels(p)
	for j := 0; j < img0.Bounds().Size().Y; j++ {
		for i := 0; i < img0.Bounds().Size().X; i++ {
			got := img0.At(i, j)
			want := color.RGBA{p[4*i], p[4*i+1], p[4*i+2], p[4*i+3]}
			if got != want {
				t.Errorf("img0 At(%d, %d): got %#v; want %#v", i, j, got, want)
			}
		}
	}
}

func TestImageDispose(t *testing.T) {
	img, err := NewImage(16, 16, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	if err := img.Dispose(); err != nil {
		t.Errorf("img.Dipose() returns error: %v", err)
	}
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func TestImageCompositeModeLighter(t *testing.T) {
	img0, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}

	w, h := img0.Size()
	img1, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	img1.Fill(color.RGBA{0x01, 0x02, 0x03, 0x04})
	op := &DrawImageOptions{}
	op.CompositeMode = CompositeModeLighter
	img1.DrawImage(img0, op)
	for j := 0; j < img1.Bounds().Size().Y; j++ {
		for i := 0; i < img1.Bounds().Size().X; i++ {
			got := img1.At(i, j).(color.RGBA)
			want := img0.At(i, j).(color.RGBA)
			want.R = uint8(min(0xff, int(want.R)+1))
			want.G = uint8(min(0xff, int(want.G)+2))
			want.B = uint8(min(0xff, int(want.B)+3))
			want.A = uint8(min(0xff, int(want.A)+4))
			if got != want {
				t.Errorf("img1 At(%d, %d): got %#v; want %#v", i, j, got, want)
			}
		}
	}
}

func TestNewImageFromEbitenImage(t *testing.T) {
	img, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}
	if _, err := NewImageFromImage(img, FilterNearest); err != nil {
		t.Errorf("NewImageFromImage returns error: %v", err)
	}
}
<commit_msg>gofmt -s -w<commit_after>// Copyright 2016 Hajime Hoshi
//
// 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 ebiten_test

import (
	"errors"
	"image"
	"image/color"
	"image/draw"
	_ "image/png"
	"math"
	"os"
	"testing"

	. "github.com/hajimehoshi/ebiten"
)

func TestMain(m *testing.M) {
	code := 0
	// Run an Ebiten process so that (*Image).At is available.
	f := func(screen *Image) error {
		code = m.Run()
		return errors.New("regular termination")
	}
	Run(f, 320, 240, 1, "Test")
	os.Exit(code)
}

var ebitenImageBin = ""

func openImage(path string) (image.Image, error) {
	file, err := readFile(path)
	if err != nil {
		return nil, err
	}

	img, _, err := image.Decode(file)
	if err != nil {
		return nil, err
	}
	return img, nil
}

func openEbitenImage(path string) (*Image, image.Image, error) {
	img, err := openImage(path)
	if err != nil {
		return nil, nil, err
	}

	eimg, err := NewImageFromImage(img, FilterNearest)
	if err != nil {
		return nil, nil, err
	}
	return eimg, img, nil
}

func diff(x, y uint8) uint8 {
	if x <= y {
		return y - x
	}
	return x - y
}

func TestImagePixels(t *testing.T) {
	img0, img, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}

	if got := img0.Bounds().Size(); got != img.Bounds().Size() {
		t.Errorf("img size: got %d; want %d", got, img.Bounds().Size())
	}

	for j := 0; j < img0.Bounds().Size().Y; j++ {
		for i := 0; i < img0.Bounds().Size().X; i++ {
			got := img0.At(i, j)
			want := color.RGBAModel.Convert(img.At(i, j))
			if got != want {
				t.Errorf("img0 At(%d, %d): got %#v; want %#v", i, j, got, want)
			}
		}
	}
}

func TestImageComposition(t *testing.T) {
	img2Color := color.NRGBA{0x24, 0x3f, 0x6a, 0x88}
	img3Color := color.NRGBA{0x85, 0xa3, 0x08, 0xd3}

	// TODO: Rename this to img0
	img1, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}

	w, h := img1.Bounds().Size().X, img1.Bounds().Size().Y

	img2, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}

	img3, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}

	img2.Fill(img2Color)
	img3.Fill(img3Color)
	img_12_3, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	img2.DrawImage(img1, nil)
	img3.DrawImage(img2, nil)
	img_12_3.DrawImage(img3, nil)

	img2.Fill(img2Color)
	img3.Fill(img3Color)
	img_1_23, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	img3.DrawImage(img2, nil)
	img3.DrawImage(img1, nil)
	img_1_23.DrawImage(img3, nil)

	for j := 0; j < h; j++ {
		for i := 0; i < w; i++ {
			c1 := img_12_3.At(i, j).(color.RGBA)
			c2 := img_1_23.At(i, j).(color.RGBA)
			if 1 < diff(c1.R, c2.R) || 1 < diff(c1.G, c2.G) || 1 < diff(c1.B, c2.B) || 1 < diff(c1.A, c2.A) {
				t.Errorf("img_12_3.At(%d, %d) = %#v; img_1_23.At(%[1]d, %[2]d) = %#[4]v", i, j, c1, c2)
			}
			if c1.A == 0 {
				t.Fatalf("img_12_3.At(%d, %d).A = 0; nothing is rendered?", i, j)
			}
			if c2.A == 0 {
				t.Fatalf("img_1_23.At(%d, %d).A = 0; nothing is rendered?", i, j)
			}
		}
	}
}

func TestImageSelf(t *testing.T) {
	img, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}
	if err := img.DrawImage(img, nil); err == nil {
		t.Fatalf("img.DrawImage(img, nil) doesn't return error; an error should be returned")
	}
}

func TestImageDotByDotInversion(t *testing.T) {
	img0, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}
	w, h := img0.Size()
	img1, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	op := &DrawImageOptions{}
	op.GeoM.Rotate(math.Pi)
	op.GeoM.Translate(float64(w), float64(h))
	img1.DrawImage(img0, op)

	for j := 0; j < h; j++ {
		for i := 0; i < w; i++ {
			c0 := img0.At(i, j).(color.RGBA)
			c1 := img1.At(w-i-1, h-j-1).(color.RGBA)
			if c0 != c1 {
				t.Errorf("img0.At(%[1]d, %[2]d) should equal to img1.At(%[3]d, %[4]d) but not: %[5]v vs %[6]v", i, j, w-i-1, h-j-1, c0, c1)
			}
		}
	}
}

func TestReplacePixels(t *testing.T) {
	origImg, err := openImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}
	// Convert to RGBA
	img := image.NewRGBA(origImg.Bounds())
	draw.Draw(img, img.Bounds(), origImg, image.ZP, draw.Src)

	size := img.Bounds().Size()
	img0, err := NewImage(size.X, size.Y, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}

	img0.ReplacePixels(img.Pix)
	for j := 0; j < img0.Bounds().Size().Y; j++ {
		for i := 0; i < img0.Bounds().Size().X; i++ {
			got := img0.At(i, j)
			want := img.At(i, j)
			if got != want {
				t.Errorf("img0 At(%d, %d): got %#v; want %#v", i, j, got, want)
			}
		}
	}

	p := make([]uint8, 4*size.X*size.Y)
	for i := range p {
		p[i] = 0x80
	}
	img0.ReplacePixels(p)
	for j := 0; j < img0.Bounds().Size().Y; j++ {
		for i := 0; i < img0.Bounds().Size().X; i++ {
			got := img0.At(i, j)
			want := color.RGBA{p[4*i], p[4*i+1], p[4*i+2], p[4*i+3]}
			if got != want {
				t.Errorf("img0 At(%d, %d): got %#v; want %#v", i, j, got, want)
			}
		}
	}
}

func TestImageDispose(t *testing.T) {
	img, err := NewImage(16, 16, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	if err := img.Dispose(); err != nil {
		t.Errorf("img.Dipose() returns error: %v", err)
	}
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func TestImageCompositeModeLighter(t *testing.T) {
	img0, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}

	w, h := img0.Size()
	img1, err := NewImage(w, h, FilterNearest)
	if err != nil {
		t.Fatal(err)
		return
	}
	img1.Fill(color.RGBA{0x01, 0x02, 0x03, 0x04})
	op := &DrawImageOptions{}
	op.CompositeMode = CompositeModeLighter
	img1.DrawImage(img0, op)
	for j := 0; j < img1.Bounds().Size().Y; j++ {
		for i := 0; i < img1.Bounds().Size().X; i++ {
			got := img1.At(i, j).(color.RGBA)
			want := img0.At(i, j).(color.RGBA)
			want.R = uint8(min(0xff, int(want.R)+1))
			want.G = uint8(min(0xff, int(want.G)+2))
			want.B = uint8(min(0xff, int(want.B)+3))
			want.A = uint8(min(0xff, int(want.A)+4))
			if got != want {
				t.Errorf("img1 At(%d, %d): got %#v; want %#v", i, j, got, want)
			}
		}
	}
}

func TestNewImageFromEbitenImage(t *testing.T) {
	img, _, err := openEbitenImage("testdata/ebiten.png")
	if err != nil {
		t.Fatal(err)
		return
	}
	if _, err := NewImageFromImage(img, FilterNearest); err != nil {
		t.Errorf("NewImageFromImage returns error: %v", err)
	}
}
<|endoftext|>


<commit_before>package xkcd_test

import (
	"github.com/rkoesters/xkcd"
	"testing"
)

func TestGetImage(t *testing.T) {
	img, err := xkcd.GetImage(1)
	if err != nil {
		t.Error(err)
	}

	if img == nil {
		t.Error("img == nil")
	}
}
<commit_msg>Add more tests to image_test.go.<commit_after>package xkcd_test

import (
	"github.com/rkoesters/xkcd"
	"testing"
)

func TestGetImage1(t *testing.T) {
	testGetImage(t, 1,
		"https://imgs.xkcd.com/comics/barrel_cropped_(1).jpg",
		"barrel_cropped_(1).jpg",
		"jpeg",
	)
}

func TestGetImage1000(t *testing.T) {
	testGetImage(t, 1000,
		"https://imgs.xkcd.com/comics/1000_comics.png",
		"1000_comics.png",
		"png",
	)
}

func TestGetImage1116(t *testing.T) {
	testGetImage(t, 1116,
		"https://imgs.xkcd.com/comics/traffic_lights.gif",
		"traffic_lights.gif",
		"gif",
	)
}

func testGetImage(t *testing.T, num int, url, name, format string) {
	img, err := xkcd.GetImage(num)
	if err != nil {
		t.Error(err)
	}

	if img == nil {
		t.Fatal("img == nil")
	}

	if url != img.SourceURL() {
		t.Errorf("url: expected=%v actual=%v", url, img.SourceURL())
	}

	if name != img.SourceName() {
		t.Errorf("name: expected=%v actual=%v", name, img.SourceName())
	}

	if format != img.SourceFormat() {
		t.Errorf("format: expected=%v actual=%v", format, img.SourceFormat())
	}
}
<|endoftext|>


<commit_before>package in

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"sync"

	"github.com/concourse/concourse-pipeline-resource/concourse"
	"github.com/concourse/concourse-pipeline-resource/fly"
	"github.com/concourse/concourse-pipeline-resource/logger"
)

const (
	apiPrefix = "/api/v1"
)

type Command struct {
	logger      logger.Logger
	flyCommand  fly.Command
	downloadDir string
}

func NewCommand(
	logger logger.Logger,
	flyCommand fly.Command,
	downloadDir string,
) *Command {
	return &Command{
		logger:      logger,
		flyCommand:  flyCommand,
		downloadDir: downloadDir,
	}
}

func (c *Command) Run(input concourse.InRequest) (concourse.InResponse, error) {
	c.logger.Debugf("Received input: %+v\n", input)

	insecure := false
	if input.Source.Insecure != "" {
		var err error
		insecure, err = strconv.ParseBool(input.Source.Insecure)
		if err != nil {
			return concourse.InResponse{}, err
		}
	}

	teams := make(map[string]concourse.Team)

	for _, team := range input.Source.Teams {
		teams[team.Name] = team
	}

	for teamName, team := range teams {
		c.logger.Debugf("Performing login\n")
		_, err := c.flyCommand.Login(
			input.Source.Target,
			teamName,
			team.Username,
			team.Password,
			insecure,
		)
		if err != nil {
			return concourse.InResponse{}, err
		}

		c.logger.Debugf("Login successful\n")

		pipelines, err := c.flyCommand.Pipelines()
		if err != nil {
			return concourse.InResponse{}, err
		}
		c.logger.Debugf("Found pipelines (%s): %+v\n", teamName, pipelines)

		var wg sync.WaitGroup
		wg.Add(len(pipelines))

		errChan := make(chan error, len(pipelines))

		for _, p := range pipelines {
			go func(pipelineName string) {
				defer wg.Done()

				outContents, err := c.flyCommand.GetPipeline(pipelineName)
				if err != nil {
					errChan <- err
				}
				pipelineContentsFilepath := filepath.Join(
					c.downloadDir,
					fmt.Sprintf(
						"%s-%s.yml",
						teamName,
						pipelineName,
					),
				)
				c.logger.Debugf(
					"Writing pipeline contents to: %s\n",
					pipelineContentsFilepath,
				)
				err = ioutil.WriteFile(pipelineContentsFilepath, outContents, os.ModePerm)
				// Untested as it is too hard to force ioutil.WriteFile to error
				if err != nil {
					errChan <- err
				}
			}(p)
		}

		c.logger.Debugf("Waiting for all pipelines\n")
		wg.Wait()
		c.logger.Debugf("Waiting for all pipelines complete\n")

		close(errChan)
		for err := range errChan {
			if err != nil {
				return concourse.InResponse{}, err
			}
		}
	}

	response := concourse.InResponse{
		Version:  input.Version,
		Metadata: []concourse.Metadata{},
	}

	return response, nil
}

type pipelineWithContent struct {
	name     string
	contents []byte
}
<commit_msg>46 Download pipelines serially in the get step (rather than in parallel)<commit_after>package in

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"

	"github.com/concourse/concourse-pipeline-resource/concourse"
	"github.com/concourse/concourse-pipeline-resource/fly"
	"github.com/concourse/concourse-pipeline-resource/logger"
)

const (
	apiPrefix = "/api/v1"
)

type Command struct {
	logger      logger.Logger
	flyCommand  fly.Command
	downloadDir string
}

func NewCommand(
	logger logger.Logger,
	flyCommand fly.Command,
	downloadDir string,
) *Command {
	return &Command{
		logger:      logger,
		flyCommand:  flyCommand,
		downloadDir: downloadDir,
	}
}

func (c *Command) Run(input concourse.InRequest) (concourse.InResponse, error) {
	c.logger.Debugf("Received input: %+v\n", input)

	insecure := false
	if input.Source.Insecure != "" {
		var err error
		insecure, err = strconv.ParseBool(input.Source.Insecure)
		if err != nil {
			return concourse.InResponse{}, err
		}
	}

	teams := make(map[string]concourse.Team)

	for _, team := range input.Source.Teams {
		teams[team.Name] = team
	}

	for teamName, team := range teams {
		c.logger.Debugf("Performing login\n")
		_, err := c.flyCommand.Login(
			input.Source.Target,
			teamName,
			team.Username,
			team.Password,
			insecure,
		)
		if err != nil {
			return concourse.InResponse{}, err
		}

		c.logger.Debugf("Login successful\n")

		pipelines, err := c.flyCommand.Pipelines()
		if err != nil {
			return concourse.InResponse{}, err
		}
		c.logger.Debugf("Found pipelines (%s): %+v\n", teamName, pipelines)

		for _, pipelineName := range pipelines {
			outContents, err := c.flyCommand.GetPipeline(pipelineName)
			if err != nil {
				return concourse.InResponse{}, err
			}
			pipelineContentsFilepath := filepath.Join(
				c.downloadDir,
				fmt.Sprintf(
					"%s-%s.yml",
					teamName,
					pipelineName,
				),
			)
			c.logger.Debugf(
				"Writing pipeline contents to: %s\n",
				pipelineContentsFilepath,
			)
			err = ioutil.WriteFile(pipelineContentsFilepath, outContents, os.ModePerm)
			// Untested as it is too hard to force ioutil.WriteFile to error
			if err != nil {
				return concourse.InResponse{}, err
			}
		}
	}

	response := concourse.InResponse{
		Version:  input.Version,
		Metadata: []concourse.Metadata{},
	}

	return response, nil
}

type pipelineWithContent struct {
	name     string
	contents []byte
}
<|endoftext|>


<commit_before>package trdsql

import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"strings"
)

// LTSVReader provides methods of the Reader interface.
type LTSVReader struct {
	reader    *bufio.Reader
	preRead   []map[string]string
	delimiter string
	names     []string
	types     []string
	limitRead bool
}

// NewLTSVReader returns LTSVReader and error.
func NewLTSVReader(reader io.Reader, opts *ReadOpts) (*LTSVReader, error) {
	r := &LTSVReader{}
	r.reader = bufio.NewReader(reader)
	r.delimiter = "\t"

	if opts.InSkip > 0 {
		skipRead(r, opts.InSkip)
	}

	r.limitRead = opts.InLimitRead

	names := map[string]bool{}
	for i := 0; i < opts.InPreRead; i++ {
		row, keys, err := r.read()
		if err != nil {
			if !errors.Is(err, io.EOF) {
				return r, err
			}
			r.setColumnType()
			debug.Printf(err.Error())
			return r, nil
		}

		// Add only unique column names.
		for k := 0; k < len(keys); k++ {
			if !names[keys[k]] {
				names[keys[k]] = true
				r.names = append(r.names, keys[k])
			}
		}
		r.preRead = append(r.preRead, row)
	}
	r.setColumnType()
	return r, nil
}

func (r *LTSVReader) setColumnType() {
	if r.names == nil {
		return
	}
	r.types = make([]string, len(r.names))
	for i := 0; i < len(r.names); i++ {
		r.types[i] = DefaultDBType
	}
}

// Names returns column names.
func (r *LTSVReader) Names() ([]string, error) {
	return r.names, nil
}

// Types returns column types.
// All LTSV types return the DefaultDBType.
func (r *LTSVReader) Types() ([]string, error) {
	return r.types, nil
}

// PreReadRow is returns only columns that store preread rows.
func (r *LTSVReader) PreReadRow() [][]interface{} {
	rowNum := len(r.preRead)
	rows := make([][]interface{}, rowNum)
	for n := 0; n < rowNum; n++ {
		rows[n] = make([]interface{}, len(r.names))
		for i := range r.names {
			rows[n][i] = r.preRead[n][r.names[i]]
		}
	}
	return rows
}

// ReadRow is read the rest of the row.
func (r *LTSVReader) ReadRow(row []interface{}) ([]interface{}, error) {
	if r.limitRead {
		return nil, io.EOF
	}

	record, _, err := r.read()
	if err != nil {
		return row, err
	}
	for i, name := range r.names {
		row[i] = record[name]
	}
	return row, nil
}

func (r *LTSVReader) read() (map[string]string, []string, error) {
	line, err := r.readline()
	if err != nil {
		return nil, nil, err
	}
	columns := strings.Split(line, r.delimiter)
	lvs := make(map[string]string)
	keys := make([]string, 0, len(columns))
	for _, column := range columns {
		kv := strings.SplitN(column, ":", 2)
		if len(kv) != 2 {
			return nil, nil, ErrInvalidColumn
		}
		lvs[kv[0]] = kv[1]
		keys = append(keys, kv[0])
	}
	return lvs, keys, nil
}

func (r *LTSVReader) readline() (string, error) {
	var buffer bytes.Buffer
	for {
		line, isPrefix, err := r.reader.ReadLine()
		if err != nil {
			return "", err
		}
		buffer.Write(line)
		if isPrefix {
			continue
		}
		str := strings.TrimSpace(buffer.String())
		if len(str) == 0 {
			return str, nil
		}
		buffer.Reset()
	}
}
<commit_msg>Fixed a test mistake<commit_after>package trdsql

import (
	"bufio"
	"bytes"
	"errors"
	"io"
	"strings"
)

// LTSVReader provides methods of the Reader interface.
type LTSVReader struct {
	reader    *bufio.Reader
	preRead   []map[string]string
	delimiter string
	names     []string
	types     []string
	limitRead bool
}

// NewLTSVReader returns LTSVReader and error.
func NewLTSVReader(reader io.Reader, opts *ReadOpts) (*LTSVReader, error) {
	r := &LTSVReader{}
	r.reader = bufio.NewReader(reader)
	r.delimiter = "\t"

	if opts.InSkip > 0 {
		skipRead(r, opts.InSkip)
	}

	r.limitRead = opts.InLimitRead

	names := map[string]bool{}
	for i := 0; i < opts.InPreRead; i++ {
		row, keys, err := r.read()
		if err != nil {
			if !errors.Is(err, io.EOF) {
				return r, err
			}
			r.setColumnType()
			debug.Printf(err.Error())
			return r, nil
		}

		// Add only unique column names.
		for k := 0; k < len(keys); k++ {
			if !names[keys[k]] {
				names[keys[k]] = true
				r.names = append(r.names, keys[k])
			}
		}
		r.preRead = append(r.preRead, row)
	}
	r.setColumnType()
	return r, nil
}

func (r *LTSVReader) setColumnType() {
	if r.names == nil {
		return
	}
	r.types = make([]string, len(r.names))
	for i := 0; i < len(r.names); i++ {
		r.types[i] = DefaultDBType
	}
}

// Names returns column names.
func (r *LTSVReader) Names() ([]string, error) {
	return r.names, nil
}

// Types returns column types.
// All LTSV types return the DefaultDBType.
func (r *LTSVReader) Types() ([]string, error) {
	return r.types, nil
}

// PreReadRow is returns only columns that store preread rows.
func (r *LTSVReader) PreReadRow() [][]interface{} {
	rowNum := len(r.preRead)
	rows := make([][]interface{}, rowNum)
	for n := 0; n < rowNum; n++ {
		rows[n] = make([]interface{}, len(r.names))
		for i := range r.names {
			rows[n][i] = r.preRead[n][r.names[i]]
		}
	}
	return rows
}

// ReadRow is read the rest of the row.
func (r *LTSVReader) ReadRow(row []interface{}) ([]interface{}, error) {
	if r.limitRead {
		return nil, io.EOF
	}

	record, _, err := r.read()
	if err != nil {
		return row, err
	}
	for i, name := range r.names {
		row[i] = record[name]
	}
	return row, nil
}

func (r *LTSVReader) read() (map[string]string, []string, error) {
	line, err := r.readline()
	if err != nil {
		return nil, nil, err
	}
	columns := strings.Split(line, r.delimiter)
	lvs := make(map[string]string)
	keys := make([]string, 0, len(columns))
	for _, column := range columns {
		kv := strings.SplitN(column, ":", 2)
		if len(kv) != 2 {
			return nil, nil, ErrInvalidColumn
		}
		lvs[kv[0]] = kv[1]
		keys = append(keys, kv[0])
	}
	return lvs, keys, nil
}

func (r *LTSVReader) readline() (string, error) {
	var buffer bytes.Buffer
	for {
		line, isPrefix, err := r.reader.ReadLine()
		if err != nil {
			return "", err
		}
		buffer.Write(line)
		if isPrefix {
			continue
		}
		str := strings.TrimSpace(buffer.String())
		if len(str) != 0 {
			return str, nil
		}
		buffer.Reset()
	}
}
<|endoftext|>


<commit_before>package requestclient

import (
	"net"
	"net/http"
)

// DialDialer - is an interface for connecting to an address.
type DialDialer interface {
	Dial(network, address string) (net.Conn, error)
}

// RoundTripper is an interface representing the ability to execute a
// single HTTP transaction, obtaining the Response for a given Request.
//
// A RoundTripper must be safe for concurrent use by multiple
// goroutines.
type RoundTripper interface {
	// RoundTrip executes a single HTTP transaction, returning
	// the Response for the request req.  RoundTrip should not
	// attempt to interpret the response.  In particular,
	// RoundTrip must return err == nil if it obtained a response,
	// regardless of the response's HTTP status code.  A non-nil
	// err should be reserved for failure to obtain a response.
	// Similarly, RoundTrip should not attempt to handle
	// higher-level protocol details such as redirects,
	// authentication, or cookies.
	//
	// RoundTrip should not modify the request, except for
	// consuming and closing the Body, including on errors. The
	// request's URL and Header fields are guaranteed to be
	// initialized.
	RoundTrip(*http.Request) (*http.Response, error)
}

// ClientRequester - higher level API that implements http.Client
type ClientRequester interface {
	Do(req *http.Request) (*http.Response, error)
}
<commit_msg>Add Requester interface<commit_after>package requestclient

import (
	"net"
	"net/http"
)

// DialDialer - is an interface for connecting to an address.
type DialDialer interface {
	Dial(network, address string) (net.Conn, error)
}

// RoundTripper is an interface representing the ability to execute a
// single HTTP transaction, obtaining the Response for a given Request.
//
// A RoundTripper must be safe for concurrent use by multiple
// goroutines.
type RoundTripper interface {
	// RoundTrip executes a single HTTP transaction, returning
	// the Response for the request req.  RoundTrip should not
	// attempt to interpret the response.  In particular,
	// RoundTrip must return err == nil if it obtained a response,
	// regardless of the response's HTTP status code.  A non-nil
	// err should be reserved for failure to obtain a response.
	// Similarly, RoundTrip should not attempt to handle
	// higher-level protocol details such as redirects,
	// authentication, or cookies.
	//
	// RoundTrip should not modify the request, except for
	// consuming and closing the Body, including on errors. The
	// request's URL and Header fields are guaranteed to be
	// initialized.
	RoundTrip(*http.Request) (*http.Response, error)
}

// ClientRequester - higher level API that implements http.Client
type ClientRequester interface {
	Do(req *http.Request) (*http.Response, error)
}

// Requester - wraps RoundTripper & ClientRequester
type Requester interface {
	Do(*http.Request) (*http.Response, error)
	RoundTrip(*http.Request) (*http.Response, error)
}
<|endoftext|>


<commit_before>package gocassa

import (
	"time"
)

// Connection exists because one can not connect to a keyspace if it does not exist, thus having a Create on KeySpace is not possible.
// Use ConnectToKeySpace to acquire an instance of KeySpace without getting a Connection.
type Connection interface {
	CreateKeySpace(name string) error
	DropKeySpace(name string) error
	KeySpace(name string) KeySpace
}

// KeySpace is used to obtain tables from.
type KeySpace interface {
	MapTable(tableName, id string, row interface{}) MapTable
	MultimapTable(tableName, fieldToIndexBy, uniqueKey string, row interface{}) MultimapTable
	MultimapMultiKeyTable(tableName string, fieldToIndexBy, uniqueKey []string, row interface{}) MultimapMkTable
	TimeSeriesTable(tableName, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesTable
	MultiTimeSeriesTable(tableName, fieldToIndexByField, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) MultiTimeSeriesTable
	Table(tableName string, row interface{}, keys Keys) Table
	// DebugMode enables/disables debug mode depending on the value of the input boolean.
	// When DebugMode is enabled, all built CQL statements are printe to stdout.
	DebugMode(bool)
	// Name returns the keyspace name as in C*
	Name() string
	// Tables returns the name of all configured column families in this keyspace
	Tables() ([]string, error)
	// Exists returns whether the specified column family exists within the keyspace
	Exists(string) (bool, error)
}

//
// Map recipe
//

// MapTable gives you basic CRUD functionality. If you need fancier ways to query your data set have a look at the other tables.
type MapTable interface {
	Set(v interface{}) Op
	Update(id interface{}, m map[string]interface{}) Op
	Delete(id interface{}) Op
	Read(id, pointer interface{}) Op
	MultiRead(ids []interface{}, pointerToASlice interface{}) Op
	WithOptions(Options) MapTable
	TableChanger
}

//
// Multimap recipe
//

// MultimapTable lets you list rows based on a field equality, eg. 'list all sales where seller id = v'.
type MultimapTable interface {
	Set(v interface{}) Op
	Update(v, id interface{}, m map[string]interface{}) Op
	Delete(v, id interface{}) Op
	DeleteAll(v interface{}) Op
	List(v, startId interface{}, limit int, pointerToASlice interface{}) Op
	Read(v, id, pointer interface{}) Op
	MultiRead(v interface{}, ids []interface{}, pointerToASlice interface{}) Op
	WithOptions(Options) MultimapTable
	TableChanger
}

// MultimapMkTable lets you list rows based on several fields equality, eg. 'list all sales where seller id = v and name = 'john'.
type MultimapMkTable interface {
	Set(v interface{}) Op
	Update(v, id map[string]interface{}, m map[string]interface{}) Op
	Delete(v, id map[string]interface{}) Op
	DeleteAll(v map[string]interface{}) Op
	List(v, startId map[string]interface{}, limit int, pointerToASlice interface{}) Op
	Read(v, id map[string]interface{}, pointer interface{}) Op
	MultiRead(v, id map[string]interface{}, pointerToASlice interface{}) Op
	WithOptions(Options) MultimapMkTable
	TableChanger
}

//
// TimeSeries recipe
//

// TimeSeriesTable lets you list rows which have a field value between two date ranges.
type TimeSeriesTable interface {
	// timeField and idField must be present
	Set(v interface{}) Op
	Update(timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(timeStamp time.Time, id interface{}) Op
	Read(timeStamp time.Time, id, pointer interface{}) Op
	List(start, end time.Time, pointerToASlice interface{}) Op
	WithOptions(Options) TimeSeriesTable
	TableChanger
}

//
// TimeSeries B recipe
//

// MultiTimeSeriesTable is a cross between TimeSeries and Multimap tables.
type MultiTimeSeriesTable interface {
	// timeField and idField must be present
	Set(v interface{}) Op
	Update(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(v interface{}, timeStamp time.Time, id interface{}) Op
	Read(v interface{}, timeStamp time.Time, id, pointer interface{}) Op
	List(v interface{}, start, end time.Time, pointerToASlice interface{}) Op
	WithOptions(Options) MultiTimeSeriesTable
	TableChanger
}

//
// Raw CQL
//

// Filter is a subset of a Table, filtered by Relations.
// You can do writes or reads on a filter.
type Filter interface {
	// Updates does a partial update. Use this if you don't want to overwrite your whole row, but you want to modify fields atomically.
	Update(m map[string]interface{}) Op // Probably this is danger zone (can't be implemented efficiently) on a selectuinb with more than 1 document
	// Delete all rows matching the filter.
	Delete() Op
	// Read the results. Make sure you pass in a pointer to a slice.
	Read(pointerToASlice interface{}) Op
	// Read one result. Make sure you pass in a pointer.
	ReadOne(pointer interface{}) Op
}

// Keys is used with the raw CQL Table type. It is implicit when using recipe tables.
type Keys struct {
	PartitionKeys     []string
	ClusteringColumns []string
	Compound          bool //indicates if the partitions keys are gereated as compound key when no clustering columns are set
}

// Op is returned by both read and write methods, you have to run them explicitly to take effect.
// It represents one or more operations.
type Op interface {
	// Run the operation.
	Run() error
	// You do not need this in 95% of the use cases, use Run!
	// Using atomic batched writes (logged batches in Cassandra terminology) comes at a high performance cost!
	RunAtomically() error
	// Add an other Op to this one.
	Add(...Op) Op
	// WithOptions lets you specify `Op` level `Options`.
	// The `Op` level Options and the `Table` level `Options` will be merged in a way that Op level takes precedence.
	// All queries in an `Op` will have the specified `Options`.
	// When using Add(), the existing options are preserved.
	// For example:
	//
	//    op1.WithOptions(Options{Limit:3}).Add(op2.WithOptions(Options{Limit:2})) // op1 has a limit of 3, op2 has a limit of 2
	//    op1.WithOptions(Options{Limit:3}).Add(op2).WithOptions(Options{Limit:2}) // op1 and op2 both have a limit of 2
	//
	WithOptions(Options) Op
	// Preflight performs any pre-execution validation that confirms the op considers itself "valid".
	// NOTE: Run() and RunAtomically() should call this method before execution, and abort if any errors are returned.
	Preflight() error
	// GenerateStatement generates the statment and params to perform the operation
	GenerateStatement() (string, []interface{})
	// QueryExecutor returns the QueryExecutor
	QueryExecutor() QueryExecutor
}

// Danger zone! Do not use this interface unless you really know what you are doing
type TableChanger interface {
	// Create creates the table in the keySpace, but only if it does not exist already.
	// If the table already exists, it returns an error.
	Create() error
	// CreateStatement returns you the CQL query which can be used to create the tably manually in cqlsh
	CreateStatement() (string, error)
	// Recreate drops the table if exists and creates it again.
	// This is useful for test purposes only.
	Recreate() error
	// Name returns the name of the table, as in C*
	Name() string
	//Drop() error
	//CreateIfDoesNotExist() error
}

// Table is the only non-recipe table, it is the "raw CQL table", it lets you do pretty much whatever you want
// with the downside that you have to know what you are doing - eg. you have to know what queries can you make
// on a certain partition key - clustering column combination.
type Table interface {
	// Set Inserts, or Replaces your row with the supplied struct. Be aware that what is not in your struct
	// will be deleted. To only overwrite some of the fields, use Query.Update.
	Set(v interface{}) Op
	// Where accepts a bunch of realtions and returns a filter. See the documentation for Relation and Filter to understand what that means.
	Where(relations ...Relation) Filter // Because we provide selections
	// Name returns the underlying table name, as stored in C*
	WithOptions(Options) Table
	TableChanger
}

// QueryExecutor actually executes the queries - this is mostly useful for testing/mocking purposes,
// ignore this otherwise. This library is using github.com/gocql/gocql as the query executor by default.
type QueryExecutor interface {
	// Query executes a query and returns the results.  It also takes Options to do things like set consistency
	QueryWithOptions(opts Options, stmt string, params ...interface{}) ([]map[string]interface{}, error)
	// Query executes a query and returns the results
	Query(stmt string, params ...interface{}) ([]map[string]interface{}, error)
	// Execute executes a DML query. It also takes Options to do things like set consistency
	ExecuteWithOptions(opts Options, stmt string, params ...interface{}) error
	// Execute executes a DML query
	Execute(stmt string, params ...interface{}) error
	// ExecuteAtomically executs multiple DML queries with a logged batch
	ExecuteAtomically(stmt []string, params [][]interface{}) error
}

type Counter int
<commit_msg>Fix function missing in interface<commit_after>package gocassa

import (
	"time"
)

// Connection exists because one can not connect to a keyspace if it does not exist, thus having a Create on KeySpace is not possible.
// Use ConnectToKeySpace to acquire an instance of KeySpace without getting a Connection.
type Connection interface {
	CreateKeySpace(name string) error
	DropKeySpace(name string) error
	KeySpace(name string) KeySpace
}

// KeySpace is used to obtain tables from.
type KeySpace interface {
	MapTable(tableName, id string, row interface{}) MapTable
	MultimapTable(tableName, fieldToIndexBy, uniqueKey string, row interface{}) MultimapTable
	MultimapMultiKeyTable(tableName string, fieldToIndexBy, uniqueKey []string, row interface{}) MultimapMkTable
	TimeSeriesTable(tableName, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) TimeSeriesTable
	MultiTimeSeriesTable(tableName, fieldToIndexByField, timeField, uniqueKey string, bucketSize time.Duration, row interface{}) MultiTimeSeriesTable
	Table(tableName string, row interface{}, keys Keys) Table
	// DebugMode enables/disables debug mode depending on the value of the input boolean.
	// When DebugMode is enabled, all built CQL statements are printe to stdout.
	DebugMode(bool)
	// Name returns the keyspace name as in C*
	Name() string
	// Tables returns the name of all configured column families in this keyspace
	Tables() ([]string, error)
	// Exists returns whether the specified column family exists within the keyspace
	Exists(string) (bool, error)
}

//
// Map recipe
//

// MapTable gives you basic CRUD functionality. If you need fancier ways to query your data set have a look at the other tables.
type MapTable interface {
	Set(v interface{}) Op
	Update(id interface{}, m map[string]interface{}) Op
	Delete(id interface{}) Op
	Read(id, pointer interface{}) Op
	MultiRead(ids []interface{}, pointerToASlice interface{}) Op
	WithOptions(Options) MapTable
	TableChanger
}

//
// Multimap recipe
//

// MultimapTable lets you list rows based on a field equality, eg. 'list all sales where seller id = v'.
type MultimapTable interface {
	Set(v interface{}) Op
	Update(v, id interface{}, m map[string]interface{}) Op
	Delete(v, id interface{}) Op
	DeleteAll(v interface{}) Op
	List(v, startId interface{}, limit int, pointerToASlice interface{}) Op
	Read(v, id, pointer interface{}) Op
	MultiRead(v interface{}, ids []interface{}, pointerToASlice interface{}) Op
	WithOptions(Options) MultimapTable
	TableChanger
}

// MultimapMkTable lets you list rows based on several fields equality, eg. 'list all sales where seller id = v and name = 'john'.
type MultimapMkTable interface {
	Set(v interface{}) Op
	Update(v, id map[string]interface{}, m map[string]interface{}) Op
	Delete(v, id map[string]interface{}) Op
	DeleteAll(v map[string]interface{}) Op
	List(v, startId map[string]interface{}, limit int, pointerToASlice interface{}) Op
	Read(v, id map[string]interface{}, pointer interface{}) Op
	MultiRead(v, id map[string]interface{}, pointerToASlice interface{}) Op
	WithOptions(Options) MultimapMkTable
	TableChanger
}

//
// TimeSeries recipe
//

// TimeSeriesTable lets you list rows which have a field value between two date ranges.
type TimeSeriesTable interface {
	// timeField and idField must be present
	Set(v interface{}) Op
	Update(timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(timeStamp time.Time, id interface{}) Op
	Read(timeStamp time.Time, id, pointer interface{}) Op
	List(start, end time.Time, pointerToASlice interface{}) Op
	WithOptions(Options) TimeSeriesTable
	TableChanger
}

//
// TimeSeries B recipe
//

// MultiTimeSeriesTable is a cross between TimeSeries and Multimap tables.
type MultiTimeSeriesTable interface {
	// timeField and idField must be present
	Set(v interface{}) Op
	Update(v interface{}, timeStamp time.Time, id interface{}, m map[string]interface{}) Op
	Delete(v interface{}, timeStamp time.Time, id interface{}) Op
	Read(v interface{}, timeStamp time.Time, id, pointer interface{}) Op
	List(v interface{}, start, end time.Time, pointerToASlice interface{}) Op
	WithOptions(Options) MultiTimeSeriesTable
	TableChanger
}

//
// Raw CQL
//

// Filter is a subset of a Table, filtered by Relations.
// You can do writes or reads on a filter.
type Filter interface {
	// Updates does a partial update. Use this if you don't want to overwrite your whole row, but you want to modify fields atomically.
	Update(m map[string]interface{}) Op // Probably this is danger zone (can't be implemented efficiently) on a selectuinb with more than 1 document
	// Delete all rows matching the filter.
	Delete() Op
	// Read the results. Make sure you pass in a pointer to a slice.
	Read(pointerToASlice interface{}) Op
	// Read one result. Make sure you pass in a pointer.
	ReadOne(pointer interface{}) Op
}

// Keys is used with the raw CQL Table type. It is implicit when using recipe tables.
type Keys struct {
	PartitionKeys     []string
	ClusteringColumns []string
	Compound          bool //indicates if the partitions keys are gereated as compound key when no clustering columns are set
}

// Op is returned by both read and write methods, you have to run them explicitly to take effect.
// It represents one or more operations.
type Op interface {
	// Run the operation.
	Run() error
	// You do not need this in 95% of the use cases, use Run!
	// Using atomic batched writes (logged batches in Cassandra terminology) comes at a high performance cost!
	RunAtomically() error
	// Add an other Op to this one.
	Add(...Op) Op
	// WithOptions lets you specify `Op` level `Options`.
	// The `Op` level Options and the `Table` level `Options` will be merged in a way that Op level takes precedence.
	// All queries in an `Op` will have the specified `Options`.
	// When using Add(), the existing options are preserved.
	// For example:
	//
	//    op1.WithOptions(Options{Limit:3}).Add(op2.WithOptions(Options{Limit:2})) // op1 has a limit of 3, op2 has a limit of 2
	//    op1.WithOptions(Options{Limit:3}).Add(op2).WithOptions(Options{Limit:2}) // op1 and op2 both have a limit of 2
	//
	WithOptions(Options) Op
	// Preflight performs any pre-execution validation that confirms the op considers itself "valid".
	// NOTE: Run() and RunAtomically() should call this method before execution, and abort if any errors are returned.
	Preflight() error
	// GenerateStatement generates the statment and params to perform the operation
	GenerateStatement() (string, []interface{})
	// QueryExecutor returns the QueryExecutor
	QueryExecutor() QueryExecutor
}

// Danger zone! Do not use this interface unless you really know what you are doing
type TableChanger interface {
	// Create creates the table in the keySpace, but only if it does not exist already.
	// If the table already exists, it returns an error.
	Create() error
	// CreateStatement returns you the CQL query which can be used to create the table manually in cqlsh
	CreateStatement() (string, error)
	// Create creates the table in the keySpace, but only if it does not exist already.
	// If the table already exists, then nothing is creted.
	CreateIfNotExist() error
	// CreateStatement returns you the CQL query which can be used to create the table manually in cqlsh
	CreateIfNotExistStatement() (string, error)
	// Recreate drops the table if exists and creates it again.
	// This is useful for test purposes only.
	Recreate() error
	// Name returns the name of the table, as in C*
	Name() string
	//Drop() error
	//CreateIfDoesNotExist() error
}

// Table is the only non-recipe table, it is the "raw CQL table", it lets you do pretty much whatever you want
// with the downside that you have to know what you are doing - eg. you have to know what queries can you make
// on a certain partition key - clustering column combination.
type Table interface {
	// Set Inserts, or Replaces your row with the supplied struct. Be aware that what is not in your struct
	// will be deleted. To only overwrite some of the fields, use Query.Update.
	Set(v interface{}) Op
	// Where accepts a bunch of realtions and returns a filter. See the documentation for Relation and Filter to understand what that means.
	Where(relations ...Relation) Filter // Because we provide selections
	// Name returns the underlying table name, as stored in C*
	WithOptions(Options) Table
	TableChanger
}

// QueryExecutor actually executes the queries - this is mostly useful for testing/mocking purposes,
// ignore this otherwise. This library is using github.com/gocql/gocql as the query executor by default.
type QueryExecutor interface {
	// Query executes a query and returns the results.  It also takes Options to do things like set consistency
	QueryWithOptions(opts Options, stmt string, params ...interface{}) ([]map[string]interface{}, error)
	// Query executes a query and returns the results
	Query(stmt string, params ...interface{}) ([]map[string]interface{}, error)
	// Execute executes a DML query. It also takes Options to do things like set consistency
	ExecuteWithOptions(opts Options, stmt string, params ...interface{}) error
	// Execute executes a DML query
	Execute(stmt string, params ...interface{}) error
	// ExecuteAtomically executs multiple DML queries with a logged batch
	ExecuteAtomically(stmt []string, params [][]interface{}) error
}

type Counter int
<|endoftext|>


<commit_before>package wireless

import (
	"os"
	"path"
	"path/filepath"
)

// Interfaces is a shortcut to the best known method for gathering the wireless
// interfaces from the current system
var Interfaces = SysFSInterfaces

// SysFSInterfaces returns the wireless interfaces found in the SysFS (/sys/class/net)
func SysFSInterfaces() []string {
	s := []string{}
	base := "/sys/class/net"
	matches, _ := filepath.Glob(path.Join(base, "*"))

	//  look for the wireless folder in each interfces directory to determine if it is a wireless device
	for _, iface := range matches {
		if _, err := os.Stat(path.Join(iface, "wireless")); err == nil {
			s = append(s, path.Base(iface))
		}
	}

	return s
}
<commit_msg>add DefaultInterface method to return the first interface found<commit_after>package wireless

import (
	"os"
	"path"
	"path/filepath"
)

// Interfaces is a shortcut to the best known method for gathering the wireless
// interfaces from the current system
var Interfaces = SysFSInterfaces

// DefaultInterface will return the default wireless interface, being the first
// one returned from the Interfaces method
func DefaultInterface() (string, bool) {
	ifs := Interfaces()
	if len(ifs) == 0 {
		return "", false
	}

	return ifs[0], true
}

// SysFSInterfaces returns the wireless interfaces found in the SysFS (/sys/class/net)
func SysFSInterfaces() []string {
	s := []string{}
	base := "/sys/class/net"
	matches, _ := filepath.Glob(path.Join(base, "*"))

	//  look for the wireless folder in each interfces directory to determine if it is a wireless device
	for _, iface := range matches {
		if _, err := os.Stat(path.Join(iface, "wireless")); err == nil {
			s = append(s, path.Base(iface))
		}
	}

	return s
}
<|endoftext|>


<commit_before>package cluster

import (
	log "code.google.com/p/log4go"
	"errors"
	"fmt"
	"net"
	"protocol"
	"time"
)

const (
	DEFAULT_BACKOFF   = time.Second
	MAX_BACKOFF       = 10 * time.Second
	HEARTBEAT_TIMEOUT = 200 * time.Millisecond
)

type ClusterServer struct {
	Id                       uint32
	RaftName                 string
	State                    ServerState
	RaftConnectionString     string
	ProtobufConnectionString string
	connection               ServerConnection
	HeartbeatInterval        time.Duration
	Backoff                  time.Duration
	isUp                     bool
	writeBuffer              *WriteBuffer
	heartbeatStarted         bool
}

type ServerConnection interface {
	Connect()
	MakeRequest(request *protocol.Request, responseStream chan *protocol.Response) error
}

type ServerState int

const (
	LoadingRingData ServerState = iota
	SendingRingData
	DeletingOldData
	Running
	Potential
)

func NewClusterServer(raftName, raftConnectionString, protobufConnectionString string, connection ServerConnection, heartbeatInterval time.Duration) *ClusterServer {
	if heartbeatInterval.Nanoseconds() < 1000 {
		heartbeatInterval = time.Millisecond * 10
	}

	s := &ClusterServer{
		RaftName:                 raftName,
		RaftConnectionString:     raftConnectionString,
		ProtobufConnectionString: protobufConnectionString,
		connection:               connection,
		HeartbeatInterval:        heartbeatInterval,
		Backoff:                  DEFAULT_BACKOFF,
		heartbeatStarted:         false,
	}

	return s
}

func (self *ClusterServer) StartHeartbeat() {
	if self.heartbeatStarted {
		return
	}

	self.heartbeatStarted = true
	self.isUp = true
	go self.heartbeat()
}

func (self *ClusterServer) SetWriteBuffer(writeBuffer *WriteBuffer) {
	self.writeBuffer = writeBuffer
}

func (self *ClusterServer) GetId() uint32 {
	return self.Id
}

func (self *ClusterServer) Connect() {
	if !shouldConnect(self.ProtobufConnectionString) {
		return
	}

	log.Info("ClusterServer: %d connecting to: %s", self.Id, self.ProtobufConnectionString)
	self.connection.Connect()
}

func (self *ClusterServer) MakeRequest(request *protocol.Request, responseStream chan *protocol.Response) error {
	err := self.connection.MakeRequest(request, responseStream)
	if err != nil {
		self.isUp = false
	}
	return err
}

func (self *ClusterServer) Write(request *protocol.Request) error {
	responseChan := make(chan *protocol.Response)
	err := self.connection.MakeRequest(request, responseChan)
	if err != nil {
		return err
	}
	response := <-responseChan
	if response.ErrorMessage != nil {
		return errors.New(*response.ErrorMessage)
	}
	return nil
}

func (self *ClusterServer) BufferWrite(request *protocol.Request) {
	self.writeBuffer.Write(request)
}

func (self *ClusterServer) IsUp() bool {
	return self.isUp
}

// private methods

var HEARTBEAT_TYPE = protocol.Request_HEARTBEAT

func (self *ClusterServer) heartbeat() {
	defer func() {
		self.heartbeatStarted = false
	}()

	responseChan := make(chan *protocol.Response)
	heartbeatRequest := &protocol.Request{
		Type:     &HEARTBEAT_TYPE,
		Database: protocol.String(""),
	}
	for {
		heartbeatRequest.Id = nil
		err := self.MakeRequest(heartbeatRequest, responseChan)
		if err != nil {
			self.handleHeartbeatError(err)
			continue
		}
		err = self.getHeartbeatResponse(responseChan)
		if err != nil {
			self.handleHeartbeatError(err)
			continue
		}

		// otherwise, reset the backoff and mark the server as up
		self.isUp = true
		self.Backoff = DEFAULT_BACKOFF
		<-time.After(self.HeartbeatInterval)
	}
}

func (self *ClusterServer) getHeartbeatResponse(responseChan <-chan *protocol.Response) error {
	select {
	case response := <-responseChan:
		if response.ErrorMessage != nil {
			return fmt.Errorf("Server returned error to heartbeat: %s", *response.ErrorMessage)
		}

		if *response.Type != protocol.Response_HEARTBEAT {
			return fmt.Errorf("Server returned a non heartbeat response")
		}
	case <-time.After(HEARTBEAT_TIMEOUT):
		return fmt.Errorf("Server failed to return heartbeat in 100ms", "")
	}

	return nil
}

func (self *ClusterServer) handleHeartbeatError(err error) {
	self.isUp = false
	self.Backoff *= 2
	if self.Backoff > MAX_BACKOFF {
		self.Backoff = MAX_BACKOFF
	}
	<-time.After(self.Backoff)
}

// in the coordinator test we don't want to create protobuf servers,
// so we just ignore creating a protobuf client when the connection
// string has a 0 port
func shouldConnect(addr string) bool {
	log.Debug("SHOULD CONNECT: ", addr)
	_, port, err := net.SplitHostPort(addr)
	if err != nil {
		log.Error("Error parsing address '%s': %s", addr, err)
		return false
	}

	if port == "0" {
		log.Warn("Cannot connect to port 0. Not creating a protobuf client")
		return false
	}
	return true
}
<commit_msg>Make an error on request to another server send the message down the response channel (non-blocking) so that go routines monitoring the channel and not the method return can stop.<commit_after>package cluster

import (
	log "code.google.com/p/log4go"
	"errors"
	"fmt"
	"net"
	"protocol"
	"time"
)

const (
	DEFAULT_BACKOFF   = time.Second
	MAX_BACKOFF       = 10 * time.Second
	HEARTBEAT_TIMEOUT = 100 * time.Millisecond
)

type ClusterServer struct {
	Id                       uint32
	RaftName                 string
	State                    ServerState
	RaftConnectionString     string
	ProtobufConnectionString string
	connection               ServerConnection
	HeartbeatInterval        time.Duration
	Backoff                  time.Duration
	isUp                     bool
	writeBuffer              *WriteBuffer
	heartbeatStarted         bool
}

type ServerConnection interface {
	Connect()
	MakeRequest(request *protocol.Request, responseStream chan *protocol.Response) error
}

type ServerState int

const (
	LoadingRingData ServerState = iota
	SendingRingData
	DeletingOldData
	Running
	Potential
)

func NewClusterServer(raftName, raftConnectionString, protobufConnectionString string, connection ServerConnection, heartbeatInterval time.Duration) *ClusterServer {
	if heartbeatInterval.Nanoseconds() < 1000 {
		heartbeatInterval = time.Millisecond * 10
	}

	s := &ClusterServer{
		RaftName:                 raftName,
		RaftConnectionString:     raftConnectionString,
		ProtobufConnectionString: protobufConnectionString,
		connection:               connection,
		HeartbeatInterval:        heartbeatInterval,
		Backoff:                  DEFAULT_BACKOFF,
		heartbeatStarted:         false,
	}

	return s
}

func (self *ClusterServer) StartHeartbeat() {
	if self.heartbeatStarted {
		return
	}

	self.heartbeatStarted = true
	self.isUp = true
	go self.heartbeat()
}

func (self *ClusterServer) SetWriteBuffer(writeBuffer *WriteBuffer) {
	self.writeBuffer = writeBuffer
}

func (self *ClusterServer) GetId() uint32 {
	return self.Id
}

func (self *ClusterServer) Connect() {
	if !shouldConnect(self.ProtobufConnectionString) {
		return
	}

	log.Info("ClusterServer: %d connecting to: %s", self.Id, self.ProtobufConnectionString)
	self.connection.Connect()
}

func (self *ClusterServer) MakeRequest(request *protocol.Request, responseStream chan *protocol.Response) error {
	err := self.connection.MakeRequest(request, responseStream)
	if err != nil {
		self.isUp = false
		message := err.Error()
		select {
		case responseStream <- &protocol.Response{Type: &endStreamResponse, ErrorMessage: &message}:
		default:
		}
	}
	return err
}

func (self *ClusterServer) Write(request *protocol.Request) error {
	responseChan := make(chan *protocol.Response)
	err := self.connection.MakeRequest(request, responseChan)
	if err != nil {
		return err
	}
	response := <-responseChan
	if response.ErrorMessage != nil {
		return errors.New(*response.ErrorMessage)
	}
	return nil
}

func (self *ClusterServer) BufferWrite(request *protocol.Request) {
	self.writeBuffer.Write(request)
}

func (self *ClusterServer) IsUp() bool {
	return self.isUp
}

// private methods

var HEARTBEAT_TYPE = protocol.Request_HEARTBEAT

func (self *ClusterServer) heartbeat() {
	defer func() {
		self.heartbeatStarted = false
	}()

	responseChan := make(chan *protocol.Response)
	heartbeatRequest := &protocol.Request{
		Type:     &HEARTBEAT_TYPE,
		Database: protocol.String(""),
	}
	for {
		heartbeatRequest.Id = nil
		err := self.MakeRequest(heartbeatRequest, responseChan)
		if err != nil {
			self.handleHeartbeatError(err)
			continue
		}
		err = self.getHeartbeatResponse(responseChan)
		if err != nil {
			self.handleHeartbeatError(err)
			continue
		}

		// otherwise, reset the backoff and mark the server as up
		self.isUp = true
		self.Backoff = DEFAULT_BACKOFF
		<-time.After(self.HeartbeatInterval)
	}
}

func (self *ClusterServer) getHeartbeatResponse(responseChan <-chan *protocol.Response) error {
	select {
	case response := <-responseChan:
		if response.ErrorMessage != nil {
			return fmt.Errorf("Server %d returned error to heartbeat: %s", self.Id, *response.ErrorMessage)
		}

		if *response.Type != protocol.Response_HEARTBEAT {
			return fmt.Errorf("Server returned a non heartbeat response")
		}
	case <-time.After(HEARTBEAT_TIMEOUT):
		return fmt.Errorf("Server failed to return heartbeat in 100ms: %d", self.Id)
	}

	return nil
}

func (self *ClusterServer) handleHeartbeatError(err error) {
	self.isUp = false
	self.Backoff *= 2
	if self.Backoff > MAX_BACKOFF {
		self.Backoff = MAX_BACKOFF
	}
	<-time.After(self.Backoff)
}

// in the coordinator test we don't want to create protobuf servers,
// so we just ignore creating a protobuf client when the connection
// string has a 0 port
func shouldConnect(addr string) bool {
	log.Debug("SHOULD CONNECT: ", addr)
	_, port, err := net.SplitHostPort(addr)
	if err != nil {
		log.Error("Error parsing address '%s': %s", addr, err)
		return false
	}

	if port == "0" {
		log.Warn("Cannot connect to port 0. Not creating a protobuf client")
		return false
	}
	return true
}
<|endoftext|>


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

// Download remote packages.

package main

import (
	"http"
	"os"
	"path"
	"regexp"
	"strings"
)

const dashboardURL = "http://godashboard.appspot.com/package"

// maybeReportToDashboard reports path to dashboard unless
// -dashboard=false is on command line.  It ignores errors.
func maybeReportToDashboard(path string) {
	// if -dashboard=false was on command line, do nothing
	if !*reportToDashboard {
		return
	}

	// otherwise lob url to dashboard
	r, _ := http.Post(dashboardURL, "application/x-www-form-urlencoded", strings.NewReader("path="+path))
	if r != nil && r.Body != nil {
		r.Body.Close()
	}
}

var googlecode = regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`)
var github = regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
var launchpad = regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`)

// download checks out or updates pkg from the remote server.
func download(pkg string) (string, os.Error) {
	if strings.Index(pkg, "..") >= 0 {
		return "", os.ErrorString("invalid path (contains ..)")
	}
	if m := bitbucket.FindStringSubmatch(pkg); m != nil {
		if err := vcsCheckout(&hg, root+m[1], "http://"+m[1], m[1]); err != nil {
			return "", err
		}
		return root + pkg, nil
	}
	if m := googlecode.FindStringSubmatch(pkg); m != nil {
		var v *vcs
		switch m[2] {
		case "hg":
			v = &hg
		case "svn":
			v = &svn
		default:
			// regexp only allows hg, svn to get through
			panic("missing case in download: " + pkg)
		}
		if err := vcsCheckout(v, root+m[1], "http://"+m[1], m[1]); err != nil {
			return "", err
		}
		return root + pkg, nil
	}
	if m := github.FindStringSubmatch(pkg); m != nil {
		if strings.HasSuffix(m[1], ".git") {
			return "", os.ErrorString("repository " + pkg + " should not have .git suffix")
		}
		if err := vcsCheckout(&git, root+m[1], "http://"+m[1]+".git", m[1]); err != nil {
			return "", err
		}
		return root + pkg, nil
	}
	if m := launchpad.FindStringSubmatch(pkg); m != nil {
		// Either lp.net/<project>[/<series>[/<path>]]
		//	 or lp.net/~<user or team>/<project>/<branch>[/<path>]
		if err := vcsCheckout(&bzr, root+m[1], "https://"+m[1], m[1]); err != nil {
			return "", err
		}
		return root + pkg, nil
	}
	return "", os.ErrorString("unknown repository: " + pkg)
}

// a vcs represents a version control system
// like Mercurial, Git, or Subversion.
type vcs struct {
	cmd               string
	metadir           string
	clone             string
	update            string
	updateReleaseFlag string
	pull              string
	pullForceFlag     string
	log               string
	logLimitFlag      string
	logReleaseFlag    string
}

var hg = vcs{
	cmd:               "hg",
	metadir:           ".hg",
	clone:             "clone",
	update:            "update",
	updateReleaseFlag: "release",
	pull:              "pull",
	log:               "log",
	logLimitFlag:      "-l1",
	logReleaseFlag:    "-rrelease",
}

var git = vcs{
	cmd:               "git",
	metadir:           ".git",
	clone:             "clone",
	update:            "pull",
	updateReleaseFlag: "release",
	pull:              "fetch",
	log:               "log",
	logLimitFlag:      "-n1",
	logReleaseFlag:    "release",
}

var svn = vcs{
	cmd:               "svn",
	metadir:           ".svn",
	clone:             "checkout",
	update:            "update",
	updateReleaseFlag: "release",
	log:               "log",
	logLimitFlag:      "-l1",
	logReleaseFlag:    "release",
}

var bzr = vcs{
	cmd:               "bzr",
	metadir:           ".bzr",
	clone:             "branch",
	update:            "update",
	updateReleaseFlag: "-rrelease",
	pull:              "pull",
	pullForceFlag:     "--overwrite",
	log:               "log",
	logLimitFlag:      "-l1",
	logReleaseFlag:    "-rrelease",
}

// vcsCheckout checks out repo into dst using vcs.
// It tries to check out (or update, if the dst already
// exists and -u was specified on the command line)
// the repository at tag/branch "release".  If there is no
// such tag or branch, it falls back to the repository tip.
func vcsCheckout(vcs *vcs, dst, repo, dashpath string) os.Error {
	dir, err := os.Stat(dst + "/" + vcs.metadir)
	if err == nil && !dir.IsDirectory() {
		return os.ErrorString("not a directory: " + dst)
	}
	if err != nil {
		parent, _ := path.Split(dst)
		if err := os.MkdirAll(parent, 0777); err != nil {
			return err
		}
		if err := run("/", nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
			return err
		}
		quietRun(dst, nil, vcs.cmd, vcs.update, vcs.updateReleaseFlag)

		// success on first installation - report
		maybeReportToDashboard(dashpath)
	} else if *update {
		// Retrieve new revisions from the remote branch, if the VCS
		// supports this operation independently (e.g. svn doesn't)
		if vcs.pull != "" {
			if vcs.pullForceFlag != "" {
				if err := run(dst, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil {
					return err
				}
			} else if err := run(dst, nil, vcs.cmd, vcs.pull); err != nil {
				return err
			}
		}

		// Try to detect if a "release" tag exists.  If it does, update
		// to the tagged version.  If no tag is found, then update to the
		// tip afterwards.
		// NOTE(gustavo@niemeyer.net): What is the expected behavior with
		// svn here? "svn log -l1 release" doesn't make sense in this
		// context and will probably fail.
		if err := quietRun(dst, nil, vcs.cmd, vcs.log, vcs.logLimitFlag, vcs.logReleaseFlag); err == nil {
			if err := run(dst, nil, vcs.cmd, vcs.update, vcs.updateReleaseFlag); err != nil {
				// The VCS supports tagging, has the "release" tag, but
				// something else went wrong.  Report.
				return err
			}
		} else if err := run(dst, nil, vcs.cmd, vcs.update); err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>goinstall: use https for Google Code checkouts<commit_after>// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Download remote packages.

package main

import (
	"http"
	"os"
	"path"
	"regexp"
	"strings"
)

const dashboardURL = "http://godashboard.appspot.com/package"

// maybeReportToDashboard reports path to dashboard unless
// -dashboard=false is on command line.  It ignores errors.
func maybeReportToDashboard(path string) {
	// if -dashboard=false was on command line, do nothing
	if !*reportToDashboard {
		return
	}

	// otherwise lob url to dashboard
	r, _ := http.Post(dashboardURL, "application/x-www-form-urlencoded", strings.NewReader("path="+path))
	if r != nil && r.Body != nil {
		r.Body.Close()
	}
}

var googlecode = regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`)
var github = regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
var launchpad = regexp.MustCompile(`^(launchpad\.net/([a-z0-9A-Z_.\-]+(/[a-z0-9A-Z_.\-]+)?|~[a-z0-9A-Z_.\-]+/(\+junk|[a-z0-9A-Z_.\-]+)/[a-z0-9A-Z_.\-]+))(/[a-z0-9A-Z_.\-/]+)?$`)

// download checks out or updates pkg from the remote server.
func download(pkg string) (string, os.Error) {
	if strings.Index(pkg, "..") >= 0 {
		return "", os.ErrorString("invalid path (contains ..)")
	}
	if m := bitbucket.FindStringSubmatch(pkg); m != nil {
		if err := vcsCheckout(&hg, root+m[1], "http://"+m[1], m[1]); err != nil {
			return "", err
		}
		return root + pkg, nil
	}
	if m := googlecode.FindStringSubmatch(pkg); m != nil {
		var v *vcs
		switch m[2] {
		case "hg":
			v = &hg
		case "svn":
			v = &svn
		default:
			// regexp only allows hg, svn to get through
			panic("missing case in download: " + pkg)
		}
		if err := vcsCheckout(v, root+m[1], "https://"+m[1], m[1]); err != nil {
			return "", err
		}
		return root + pkg, nil
	}
	if m := github.FindStringSubmatch(pkg); m != nil {
		if strings.HasSuffix(m[1], ".git") {
			return "", os.ErrorString("repository " + pkg + " should not have .git suffix")
		}
		if err := vcsCheckout(&git, root+m[1], "http://"+m[1]+".git", m[1]); err != nil {
			return "", err
		}
		return root + pkg, nil
	}
	if m := launchpad.FindStringSubmatch(pkg); m != nil {
		// Either lp.net/<project>[/<series>[/<path>]]
		//	 or lp.net/~<user or team>/<project>/<branch>[/<path>]
		if err := vcsCheckout(&bzr, root+m[1], "https://"+m[1], m[1]); err != nil {
			return "", err
		}
		return root + pkg, nil
	}
	return "", os.ErrorString("unknown repository: " + pkg)
}

// a vcs represents a version control system
// like Mercurial, Git, or Subversion.
type vcs struct {
	cmd               string
	metadir           string
	clone             string
	update            string
	updateReleaseFlag string
	pull              string
	pullForceFlag     string
	log               string
	logLimitFlag      string
	logReleaseFlag    string
}

var hg = vcs{
	cmd:               "hg",
	metadir:           ".hg",
	clone:             "clone",
	update:            "update",
	updateReleaseFlag: "release",
	pull:              "pull",
	log:               "log",
	logLimitFlag:      "-l1",
	logReleaseFlag:    "-rrelease",
}

var git = vcs{
	cmd:               "git",
	metadir:           ".git",
	clone:             "clone",
	update:            "pull",
	updateReleaseFlag: "release",
	pull:              "fetch",
	log:               "log",
	logLimitFlag:      "-n1",
	logReleaseFlag:    "release",
}

var svn = vcs{
	cmd:               "svn",
	metadir:           ".svn",
	clone:             "checkout",
	update:            "update",
	updateReleaseFlag: "release",
	log:               "log",
	logLimitFlag:      "-l1",
	logReleaseFlag:    "release",
}

var bzr = vcs{
	cmd:               "bzr",
	metadir:           ".bzr",
	clone:             "branch",
	update:            "update",
	updateReleaseFlag: "-rrelease",
	pull:              "pull",
	pullForceFlag:     "--overwrite",
	log:               "log",
	logLimitFlag:      "-l1",
	logReleaseFlag:    "-rrelease",
}

// vcsCheckout checks out repo into dst using vcs.
// It tries to check out (or update, if the dst already
// exists and -u was specified on the command line)
// the repository at tag/branch "release".  If there is no
// such tag or branch, it falls back to the repository tip.
func vcsCheckout(vcs *vcs, dst, repo, dashpath string) os.Error {
	dir, err := os.Stat(dst + "/" + vcs.metadir)
	if err == nil && !dir.IsDirectory() {
		return os.ErrorString("not a directory: " + dst)
	}
	if err != nil {
		parent, _ := path.Split(dst)
		if err := os.MkdirAll(parent, 0777); err != nil {
			return err
		}
		if err := run("/", nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
			return err
		}
		quietRun(dst, nil, vcs.cmd, vcs.update, vcs.updateReleaseFlag)

		// success on first installation - report
		maybeReportToDashboard(dashpath)
	} else if *update {
		// Retrieve new revisions from the remote branch, if the VCS
		// supports this operation independently (e.g. svn doesn't)
		if vcs.pull != "" {
			if vcs.pullForceFlag != "" {
				if err := run(dst, nil, vcs.cmd, vcs.pull, vcs.pullForceFlag); err != nil {
					return err
				}
			} else if err := run(dst, nil, vcs.cmd, vcs.pull); err != nil {
				return err
			}
		}

		// Try to detect if a "release" tag exists.  If it does, update
		// to the tagged version.  If no tag is found, then update to the
		// tip afterwards.
		// NOTE(gustavo@niemeyer.net): What is the expected behavior with
		// svn here? "svn log -l1 release" doesn't make sense in this
		// context and will probably fail.
		if err := quietRun(dst, nil, vcs.cmd, vcs.log, vcs.logLimitFlag, vcs.logReleaseFlag); err == nil {
			if err := run(dst, nil, vcs.cmd, vcs.update, vcs.updateReleaseFlag); err != nil {
				// The VCS supports tagging, has the "release" tag, but
				// something else went wrong.  Report.
				return err
			}
		} else if err := run(dst, nil, vcs.cmd, vcs.update); err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>