<commit_before>// Unfancy resources embedding with Go.

package resources

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"text/template"
)

type File interface {
	io.Reader
	Stat() (os.FileInfo, error)
}

//Create a new Package.
func New() *Package {
	return &Package{
		Config: Config{
			Pkg:     "resources",
			Var:     "FS",
			Declare: true,
		},
		Files: make(map[string]File),
	}
}

//Configuration defines some details about the output Go file.
type Config struct {
	Pkg     string // Package name
	Var     string // Variable name to assign the file system to.
	Tag     string // Build tag, leave empty for no tag.
	Declare bool   // Dictates whatever there should be a defintion Variable
}

type Package struct {
	Config
	Files map[string]File
}

//Add a file to the package at the give path.
func (p *Package) Add(path string, file File) {
	p.Files[path] = file
}

//Add a file to the package at the give path, the files is the location of a file on the filesystem.
func (p *Package) AddFile(path string, file string) error {
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	p.Files[path] = f
	return nil
}

//Build the package
func (p *Package) Build(out io.Writer) error {
	return pkg.Execute(out, p)
}

//Write the build to a file, you don't need to call Build.
func (p *Package) Write(path string) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()

	return p.Build(f)
}

//Template

var pkg *template.Template

func reader(input io.Reader) (string, error) {

	var (
		buff       bytes.Buffer
		err        error
		blockwidth int = 12
		curblock   int = 0
	)

	b := make([]byte, blockwidth)

	for n, err := input.Read(b); err == nil; n, err = input.Read(b) {
		for i := 0; i < n; i++ {
			fmt.Fprintf(&buff, "0x%02x,", b[i])
			curblock++
			if curblock < blockwidth {
				continue
			}
			buff.WriteByte('\n')
			buff.Write([]byte{'\t', '\t'})
			curblock = 0
		}
	}

	return buff.String(), err
}

func init() {

	pkg = template.Must(template.New("file").Funcs(template.FuncMap{"reader": reader}).Parse(` File{
	  data: []byte{
	{{ reader . }}
  },
  fi: FileInfo {
	name:    "{{ .Stat.Name }}",
    size:    {{ .Stat.Size }},
	modTime: time.Unix({{ .Stat.ModTime.Unix }},{{ .Stat.ModTime.UnixNano }}),
    isDir:   {{ .Stat.IsDir }},
  },
}`))

	pkg = template.Must(pkg.New("pkg").Parse(`{{ if .Tag }}// +build {{ .Tag }}

{{ end }}//Generated by github.com/omeid/go-resources
package {{ .Pkg }}

import (
  "net/http"
  "time"
  "bytes"
  "os"
  "path/filepath"
  "strings"
  "errors"
)

{{ if .Declare }}
var {{ .Var }} http.FileSystem
{{ end }}

// http.FileSystem implementation.
type FileSystem struct {
	files map[string]File
}

func (fs *FileSystem) Open(name string) (http.File, error) {
	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
	    strings.Contains(name, "\x00") {
		return nil, errors.New("http: invalid character in file path")
	}
	file, ok := fs.files[name]
	if !ok {
		files := []os.FileInfo{}
		for path, file := range fs.files {
			if strings.HasPrefix(path, name) {
				s, _ := file.Stat()
				files = append(files, s)
			}
		}

		if len(files) == 0 {
			return nil, os.ErrNotExist
		}

		//We have a directory.
		return &File{
		  fi: FileInfo{
				isDir: true,
				files: files,
			}}, nil
	}
	file.Reader = bytes.NewReader(file.data)
	return &file, nil
}

type File struct {
	*bytes.Reader
	data []byte
	fi FileInfo
}

// A noop-closer.
func (f *File) Close() error {
	return nil
}

func (f *File) Readdir(count int) ([]os.FileInfo, error) {
  return nil, os.ErrNotExist
}

func (f *File) Stat() (os.FileInfo, error) {
  return &f.fi, nil
}

type FileInfo struct {
	name    string
	size    int64
	mode    os.FileMode
	modTime time.Time
	isDir   bool
	sys     interface{}

	files []os.FileInfo
}

func (f *FileInfo) Name() string {
	return f.name
}
func (f *FileInfo) Size() int64 {
	return f.size
}

func (f *FileInfo) Mode() os.FileMode {
	return f.mode
}

func (f *FileInfo) ModTime() time.Time {
	return f.modTime
}

func (f *FileInfo) IsDir() bool {
	return f.isDir
}

func (f *FileInfo) Readdir(count int) ([]os.FileInfo, error) {
	return f.files, nil
}

func (f *FileInfo) Sys() interface{} {
	return f.sys
}

func init() {
  {{ .Var }} = &FileSystem{
		files: map[string]File{
		  {{range $path, $file := .Files }} "/{{ $path }}": {{ template "file" $file }}, {{ end }}
		},
	  }
}
`))
}
<commit_msg>Copy files correctly. Close #5<commit_after>// Unfancy resources embedding with Go.

package resources

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"text/template"
)

type File interface {
	io.Reader
	Stat() (os.FileInfo, error)
}

//Create a new Package.
func New() *Package {
	return &Package{
		Config: Config{
			Pkg:     "resources",
			Var:     "FS",
			Declare: true,
		},
		Files: make(map[string]File),
	}
}

//Configuration defines some details about the output Go file.
type Config struct {
	Pkg     string // Package name
	Var     string // Variable name to assign the file system to.
	Tag     string // Build tag, leave empty for no tag.
	Declare bool   // Dictates whatever there should be a defintion Variable
}

type Package struct {
	Config
	Files map[string]File
}

//Add a file to the package at the give path.
func (p *Package) Add(path string, file File) {
	p.Files[path] = file
}

//Add a file to the package at the give path, the files is the location of a file on the filesystem.
func (p *Package) AddFile(path string, file string) error {
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	p.Files[path] = f
	return nil
}

//Build the package
func (p *Package) Build(out io.Writer) error {
	return pkg.Execute(out, p)
}

//Write the build to a file, you don't need to call Build.
func (p *Package) Write(path string) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()

	return p.Build(f)
}

//Template

var pkg *template.Template

func reader(input io.Reader) (string, error) {

	var (
		buff       bytes.Buffer
		err        error
		blockwidth int = 12
		curblock   int = 0
	)

	b := make([]byte, blockwidth)

	for n, err := input.Read(b); err == nil; n, err = input.Read(b) {
		for i := 0; i < n; i++ {
			fmt.Fprintf(&buff, "0x%02x,", b[i])
			curblock++
			if curblock < blockwidth {
				continue
			}
			buff.WriteByte('\n')
			buff.Write([]byte{'\t', '\t'})
			curblock = 0
		}
	}

	return buff.String(), err
}

func init() {

	pkg = template.Must(template.New("file").Funcs(template.FuncMap{"reader": reader}).Parse(` File{
	  data: []byte{
	{{ reader . }}
  },
  fi: FileInfo {
	name:    "{{ .Stat.Name }}",
    size:    {{ .Stat.Size }},
	modTime: time.Unix({{ .Stat.ModTime.Unix }},{{ .Stat.ModTime.UnixNano }}),
    isDir:   {{ .Stat.IsDir }},
  },
}`))

	pkg = template.Must(pkg.New("pkg").Parse(`{{ if .Tag }}// +build {{ .Tag }}

{{ end }}//Generated by github.com/omeid/go-resources
package {{ .Pkg }}

import (
  "net/http"
  "time"
  "bytes"
  "os"
  "path/filepath"
  "strings"
  "errors"
)

{{ if .Declare }}
var {{ .Var }} http.FileSystem
{{ end }}

// http.FileSystem implementation.
type FileSystem struct {
	files map[string]File
}

func (fs *FileSystem) Open(name string) (http.File, error) {
	if filepath.Separator != '/' && strings.IndexRune(name, filepath.Separator) >= 0 ||
	    strings.Contains(name, "\x00") {
		return nil, errors.New("http: invalid character in file path")
	}
	file, ok := fs.files[name]
	if !ok {
		files := []os.FileInfo{}
		for path, file := range fs.files {
			if strings.HasPrefix(path, name) {
				fi := file.fi
				files = append(files, &fi)
			}
		}

		if len(files) == 0 {
			return nil, os.ErrNotExist
		}

		//We have a directory.
		return &File{
		  fi: FileInfo{
				isDir: true,
				files: files,
			}}, nil
	}
	file.Reader = bytes.NewReader(file.data)
	return &file, nil
}

type File struct {
	*bytes.Reader
	data []byte
	fi FileInfo
}

// A noop-closer.
func (f *File) Close() error {
	return nil
}

func (f *File) Readdir(count int) ([]os.FileInfo, error) {
  return nil, os.ErrNotExist
}

func (f *File) Stat() (os.FileInfo, error) {
  return &f.fi, nil
}

type FileInfo struct {
	name    string
	size    int64
	mode    os.FileMode
	modTime time.Time
	isDir   bool
	sys     interface{}

	files []os.FileInfo
}

func (f *FileInfo) Name() string {
	return f.name
}
func (f *FileInfo) Size() int64 {
	return f.size
}

func (f *FileInfo) Mode() os.FileMode {
	return f.mode
}

func (f *FileInfo) ModTime() time.Time {
	return f.modTime
}

func (f *FileInfo) IsDir() bool {
	return f.isDir
}

func (f *FileInfo) Readdir(count int) ([]os.FileInfo, error) {
	return f.files, nil
}

func (f *FileInfo) Sys() interface{} {
	return f.sys
}

func init() {
  {{ .Var }} = &FileSystem{
		files: map[string]File{
		  {{range $path, $file := .Files }} "/{{ $path }}": {{ template "file" $file }}, {{ end }}
		},
	  }
}
`))
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package txscript_test

import (
	"encoding/hex"
	"fmt"

	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
)

// This example demonstrates creating a script which pays to a bitcoin address.
// It also prints the created script hex and uses the DisasmString function to
// display the disassembled script.
func ExamplePayToAddrScript() {
	// Parse the address to send the coins to into a btcutil.Address
	// which is useful to ensure the accuracy of the address and determine
	// the address type.  It is also required for the upcoming call to
	// PayToAddrScript.
	addressStr := "12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV"
	address, err := btcutil.DecodeAddress(addressStr, &chaincfg.MainNetParams)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Create a public key script that pays to the address.
	script, err := txscript.PayToAddrScript(address)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("Script Hex: %x\n", script)

	disasm, err := txscript.DisasmString(script)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Script Disassembly:", disasm)

	// Output:
	// Script Hex: 76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac
	// Script Disassembly: OP_DUP OP_HASH160 128004ff2fcaf13b2b91eb654b1dc2b674f7ec61 OP_EQUALVERIFY OP_CHECKSIG
}

// This example demonstrates extracting information from a standard public key
// script.
func ExampleExtractPkScriptAddrs() {
	// Start with a standard pay-to-pubkey-hash script.
	scriptHex := "76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac"
	script, err := hex.DecodeString(scriptHex)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Extract and print details from the script.
	scriptClass, addresses, reqSigs, err := txscript.ExtractPkScriptAddrs(
		script, &chaincfg.MainNetParams)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Script Class:", scriptClass)
	fmt.Println("Addresses:", addresses)
	fmt.Println("Required Signatures:", reqSigs)

	// Output:
	// Script Class: pubkeyhash
	// Addresses: [12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV]
	// Required Signatures: 1
}

// This example demonstrates manually creating and signing a redeem transaction.
func ExampleSignTxOutput() {
	// Ordinarily the private key would come from whatever storage mechanism
	// is being used, but for this example just hard code it.
	privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" +
		"d4f8720ee63e502ee2869afab7de234b80c")
	if err != nil {
		fmt.Println(err)
		return
	}
	privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
	pubKeyHash := btcutil.Hash160(pubKey.SerializeCompressed())
	addr, err := btcutil.NewAddressPubKeyHash(pubKeyHash,
		&chaincfg.MainNetParams)
	if err != nil {
		fmt.Println(err)
		return
	}

	// For this example, create a fake transaction that represents what
	// would ordinarily be the real transaction that is being spent.  It
	// contains a single output that pays to address in the amount of 1 BTC.
	originTx := wire.NewMsgTx()
	prevOut := wire.NewOutPoint(&wire.ShaHash{}, ^uint32(0))
	txIn := wire.NewTxIn(prevOut, []byte{txscript.OP_0, txscript.OP_0})
	originTx.AddTxIn(txIn)
	pkScript, err := txscript.PayToAddrScript(addr)
	if err != nil {
		fmt.Println(err)
		return
	}
	txOut := wire.NewTxOut(100000000, pkScript)
	originTx.AddTxOut(txOut)
	originTxHash := originTx.TxSha()

	// Create the transaction to redeem the fake transaction.
	redeemTx := wire.NewMsgTx()

	// Add the input(s) the redeeming transaction will spend.  There is no
	// signature script at this point since it hasn't been created or signed
	// yet, hence nil is provided for it.
	prevOut = wire.NewOutPoint(&originTxHash, 0)
	txIn = wire.NewTxIn(prevOut, nil)
	redeemTx.AddTxIn(txIn)

	// Ordinarily this would contain that actual destination of the funds,
	// but for this example don't bother.
	txOut = wire.NewTxOut(0, nil)
	redeemTx.AddTxOut(txOut)

	// Sign the redeeming transaction.
	lookupKey := func(a btcutil.Address) (*btcec.PrivateKey, bool, error) {
		// Ordinarily this function would involve looking up the private
		// key for the provided address, but since the only thing being
		// signed in this example uses the address associated with the
		// private key from above, simply return it with the compressed
		// flag set since the address is using the associated compressed
		// public key.
		//
		// NOTE: If you want to prove the code is actually signing the
		// transaction properly, uncomment the following line which
		// intentionally returns an invalid key to sign with, which in
		// turn will result in a failure during the script execution
		// when verifying the signature.
		//
		// privKey.D.SetInt64(12345)
		//
		return privKey, true, nil
	}
	// Notice that the script database parameter is nil here since it isn't
	// used.  It must be specified when pay-to-script-hash transactions are
	// being signed.
	sigScript, err := txscript.SignTxOutput(&chaincfg.MainNetParams,
		redeemTx, 0, originTx.TxOut[0].PkScript, txscript.SigHashAll,
		txscript.KeyClosure(lookupKey), nil, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	redeemTx.TxIn[0].SignatureScript = sigScript

	// Prove that the transaction has been validly signed by executing the
	// script pair.
	flags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures |
		txscript.ScriptStrictMultiSig |
		txscript.ScriptDiscourageUpgradableNops
	vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0,
		flags, nil, nil, -1)
	if err != nil {
		fmt.Println(err)
		return
	}
	if err := vm.Execute(); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Transaction successfully signed")

	// Output:
	// Transaction successfully signed
}
<commit_msg>txscript: add basic test for segwit sighash calculation<commit_after>// Copyright (c) 2014-2015 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package txscript_test

import (
	"encoding/hex"
	"fmt"

	"github.com/btcsuite/btcd/btcec"
	"github.com/btcsuite/btcd/chaincfg"
	"github.com/btcsuite/btcd/txscript"
	"github.com/btcsuite/btcd/wire"
	"github.com/btcsuite/btcutil"
)

// This example demonstrates creating a script which pays to a bitcoin address.
// It also prints the created script hex and uses the DisasmString function to
// display the disassembled script.
func ExamplePayToAddrScript() {
	// Parse the address to send the coins to into a btcutil.Address
	// which is useful to ensure the accuracy of the address and determine
	// the address type.  It is also required for the upcoming call to
	// PayToAddrScript.
	addressStr := "12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV"
	address, err := btcutil.DecodeAddress(addressStr, &chaincfg.MainNetParams)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Create a public key script that pays to the address.
	script, err := txscript.PayToAddrScript(address)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("Script Hex: %x\n", script)

	disasm, err := txscript.DisasmString(script)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Script Disassembly:", disasm)

	// Output:
	// Script Hex: 76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac
	// Script Disassembly: OP_DUP OP_HASH160 128004ff2fcaf13b2b91eb654b1dc2b674f7ec61 OP_EQUALVERIFY OP_CHECKSIG
}

// This example demonstrates extracting information from a standard public key
// script.
func ExampleExtractPkScriptAddrs() {
	// Start with a standard pay-to-pubkey-hash script.
	scriptHex := "76a914128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac"
	script, err := hex.DecodeString(scriptHex)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Extract and print details from the script.
	scriptClass, addresses, reqSigs, err := txscript.ExtractPkScriptAddrs(
		script, &chaincfg.MainNetParams)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Script Class:", scriptClass)
	fmt.Println("Addresses:", addresses)
	fmt.Println("Required Signatures:", reqSigs)

	// Output:
	// Script Class: pubkeyhash
	// Addresses: [12gpXQVcCL2qhTNQgyLVdCFG2Qs2px98nV]
	// Required Signatures: 1
}

// TODO(roasbeef): segwit sign exxample

// This example demonstrates manually creating and signing a redeem transaction.
func ExampleSignTxOutput() {
	// Ordinarily the private key would come from whatever storage mechanism
	// is being used, but for this example just hard code it.
	privKeyBytes, err := hex.DecodeString("22a47fa09a223f2aa079edf85a7c2" +
		"d4f8720ee63e502ee2869afab7de234b80c")
	if err != nil {
		fmt.Println(err)
		return
	}
	privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), privKeyBytes)
	pubKeyHash := btcutil.Hash160(pubKey.SerializeCompressed())
	addr, err := btcutil.NewAddressPubKeyHash(pubKeyHash,
		&chaincfg.MainNetParams)
	if err != nil {
		fmt.Println(err)
		return
	}

	// For this example, create a fake transaction that represents what
	// would ordinarily be the real transaction that is being spent.  It
	// contains a single output that pays to address in the amount of 1 BTC.
	originTx := wire.NewMsgTx()
	prevOut := wire.NewOutPoint(&wire.ShaHash{}, ^uint32(0))
	txIn := wire.NewTxIn(prevOut, []byte{txscript.OP_0, txscript.OP_0}, nil)
	originTx.AddTxIn(txIn)
	pkScript, err := txscript.PayToAddrScript(addr)
	if err != nil {
		fmt.Println(err)
		return
	}
	txOut := wire.NewTxOut(100000000, pkScript)
	originTx.AddTxOut(txOut)
	originTxHash := originTx.TxSha()

	// Create the transaction to redeem the fake transaction.
	redeemTx := wire.NewMsgTx()

	// Add the input(s) the redeeming transaction will spend.  There is no
	// signature script at this point since it hasn't been created or signed
	// yet, hence nil is provided for it.
	prevOut = wire.NewOutPoint(&originTxHash, 0)
	txIn = wire.NewTxIn(prevOut, nil, nil)
	redeemTx.AddTxIn(txIn)

	// Ordinarily this would contain that actual destination of the funds,
	// but for this example don't bother.
	txOut = wire.NewTxOut(0, nil)
	redeemTx.AddTxOut(txOut)

	// Sign the redeeming transaction.
	lookupKey := func(a btcutil.Address) (*btcec.PrivateKey, bool, error) {
		// Ordinarily this function would involve looking up the private
		// key for the provided address, but since the only thing being
		// signed in this example uses the address associated with the
		// private key from above, simply return it with the compressed
		// flag set since the address is using the associated compressed
		// public key.
		//
		// NOTE: If you want to prove the code is actually signing the
		// transaction properly, uncomment the following line which
		// intentionally returns an invalid key to sign with, which in
		// turn will result in a failure during the script execution
		// when verifying the signature.
		//
		// privKey.D.SetInt64(12345)
		//
		return privKey, true, nil
	}
	// Notice that the script database parameter is nil here since it isn't
	// used.  It must be specified when pay-to-script-hash transactions are
	// being signed.
	sigScript, err := txscript.SignTxOutput(&chaincfg.MainNetParams,
		redeemTx, 0, originTx.TxOut[0].PkScript, txscript.SigHashAll,
		txscript.KeyClosure(lookupKey), nil, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	redeemTx.TxIn[0].SignatureScript = sigScript

	// Prove that the transaction has been validly signed by executing the
	// script pair.
	flags := txscript.ScriptBip16 | txscript.ScriptVerifyDERSignatures |
		txscript.ScriptStrictMultiSig |
		txscript.ScriptDiscourageUpgradableNops
	vm, err := txscript.NewEngine(originTx.TxOut[0].PkScript, redeemTx, 0,
		flags, nil, nil, -1)
	if err != nil {
		fmt.Println(err)
		return
	}
	if err := vm.Execute(); err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println("Transaction successfully signed")

	// Output:
	// Transaction successfully signed
}
<|endoftext|>


<commit_before>package taggolib

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"time"
)

const (
	// These constants represent the built-in tags
	tagAlbum       = "ALBUM"
	tagAlbumArtist = "ALBUMARTIST"
	tagArtist      = "ARTIST"
	tagComment     = "COMMENT"
	tagDate        = "DATE"
	tagDiscNumber  = "DISCNUMBER"
	tagGenre       = "GENRE"
	tagTitle       = "TITLE"
	tagTrackNumber = "TRACKNUMBER"
)

var (
	// errInvalidStream is returned when taggolib encounters a broken input stream, but
	// does recognize the input stream format
	errInvalidStream = errors.New("invalid input stream")
	// errUnknownFormat is returned when taggolib cannot recognize the input stream format
	errUnknownFormat = errors.New("unknown format")
	// errUnsupportedVersion is returned when taggolib recognizes an input stream format, but
	// can not currently handle the version specified by the input stream
	errUnsupportedVersion = errors.New("unsupported version")
)

// TagError represents an error which occurs during the metadata parsing process
type TagError struct {
	Err     error
	Format  string
	Details string
}

// Error returns a detailed description of an error during the the metadata parsing process
func (e TagError) Error() string {
	return fmt.Sprintf("%s - %s: %s", e.Err.Error(), e.Format, e.Details)
}

// IsInvalidStream is a convenience method which checks if an error is caused by an invalid stream
// of a known format
func IsInvalidStream(err error) bool {
	// Attempt to type-assert to TagError
	tagErr, ok := err.(TagError)
	if !ok {
		return false
	}

	// Return if error matches errInvalidStream
	return tagErr.Err == errInvalidStream
}

// IsUnknownFormat is a convenience method which checks if an error is caused by an unknown format
func IsUnknownFormat(err error) bool {
	// Attempt to type-assert to TagError
	tagErr, ok := err.(TagError)
	if !ok {
		return false
	}

	// Return if error matches errUnknownFormat
	return tagErr.Err == errUnknownFormat
}

// IsUnsupportedVersion is a convenience method which checks if an error is caused by an unsupported version
// of a known format
func IsUnsupportedVersion(err error) bool {
	// Attempt to type-assert to TagError
	tagErr, ok := err.(TagError)
	if !ok {
		return false
	}

	// Return if error matches errUnsupportedVersion
	return tagErr.Err == errUnsupportedVersion
}

// Parser represents an audio metadata tag parser
type Parser interface {
	Album() string
	AlbumArtist() string
	Artist() string
	BitDepth() int
	Bitrate() int
	Channels() int
	Comment() string
	Date() string
	DiscNumber() int
	Duration() time.Duration
	Encoder() string
	Format() string
	Genre() string
	SampleRate() int
	Tag(name string) string
	Title() string
	TrackNumber() int
}

// New creates a new Parser depending on the magic number detected in the input reader
func New(reader io.ReadSeeker) (Parser, error) {
	// Check for magic numbers
	magicBuf := make([]byte, 8)

	// Read first byte to begin checking magic number
	if _, err := reader.Read(magicBuf[:1]); err != nil {
		return nil, err
	}

	// Check for FLAC magic number
	if magicBuf[0] == byte('f') {
		// Read next 3 bytes for magic number
		if _, err := reader.Read(magicBuf[1:len(flacMagicNumber)]); err != nil {
			return nil, err
		}

		// Verify FLAC magic number
		if bytes.Equal(magicBuf[:len(flacMagicNumber)], flacMagicNumber) {
			return newFLACParser(reader)
		}
	}

	// Check for MP3 magic number
	if magicBuf[0] == byte('I') {
		// Read next 2 bytes for magic number
		if _, err := reader.Read(magicBuf[1:len(mp3MagicNumber)]); err != nil {
			return nil, err
		}

		// Verify MP3 magic number
		if bytes.Equal(magicBuf[:len(mp3MagicNumber)], mp3MagicNumber) {
			return newMP3Parser(reader)
		}
	}

	// Check for OGG magic number
	if magicBuf[0] == byte('O') {
		// Read next 3 bytes for magic number
		if _, err := reader.Read(magicBuf[1:len(oggMagicNumber)]); err != nil {
			return nil, err
		}

		// Verify OGG magic number
		if bytes.Equal(magicBuf[:len(oggMagicNumber)], oggMagicNumber) {
			return newOGGVorbisParser(reader)
		}
	}

	// Unrecognized magic number
	return nil, TagError{
		Err:     errUnknownFormat,
		Format:  "unknown",
		Details: "unrecognized magic number, cannot parse this stream",
	}
}
<commit_msg>Beef up taggolib documentation for GoDoc<commit_after>package taggolib

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"time"
)

const (
	// These constants represent the built-in tags
	tagAlbum       = "ALBUM"
	tagAlbumArtist = "ALBUMARTIST"
	tagArtist      = "ARTIST"
	tagComment     = "COMMENT"
	tagDate        = "DATE"
	tagDiscNumber  = "DISCNUMBER"
	tagGenre       = "GENRE"
	tagTitle       = "TITLE"
	tagTrackNumber = "TRACKNUMBER"
)

var (
	// errInvalidStream is returned when taggolib encounters a broken input stream, but
	// does recognize the input stream format
	errInvalidStream = errors.New("invalid input stream")
	// errUnknownFormat is returned when taggolib cannot recognize the input stream format
	errUnknownFormat = errors.New("unknown format")
	// errUnsupportedVersion is returned when taggolib recognizes an input stream format, but
	// can not currently handle the version specified by the input stream
	errUnsupportedVersion = errors.New("unsupported version")
)

// TagError represents an error which occurs during the metadata parsing process.  It is used internally to
// note several types of errors, and may be used to retrieve detailed information regarding an error.
type TagError struct {
	Err     error
	Format  string
	Details string
}

// Error returns a detailed description of an error during the the metadata parsing process, including the
// internal taggolib error, the detected stream format, and a short description of exactly why the error occurred.
func (e TagError) Error() string {
	return fmt.Sprintf("%s - %s: %s", e.Err.Error(), e.Format, e.Details)
}

// IsInvalidStream is a convenience method which checks if an error is caused by an invalid stream
// of a known format.  This may happen if the input stream is corrupt, or if the input stream contains flags which
// should not be present in a valid input stream.
func IsInvalidStream(err error) bool {
	// Attempt to type-assert to TagError
	tagErr, ok := err.(TagError)
	if !ok {
		return false
	}

	// Return if error matches errInvalidStream
	return tagErr.Err == errInvalidStream
}

// IsUnknownFormat is a convenience method which checks if an error is caused by an unknown format.  This may happen
// if the input stream contains a magic number which taggolib cannot handle, such as an unsupported audio format,
// or any kind of file which is not an audio file.
func IsUnknownFormat(err error) bool {
	// Attempt to type-assert to TagError
	tagErr, ok := err.(TagError)
	if !ok {
		return false
	}

	// Return if error matches errUnknownFormat
	return tagErr.Err == errUnknownFormat
}

// IsUnsupportedVersion is a convenience method which checks if an error is caused by an unsupported version
// of a known format.  This may happen if the input stream is recognized by taggolib, but taggolib does not support
// parsing a certain version of the metadata, such as ID3v1.
func IsUnsupportedVersion(err error) bool {
	// Attempt to type-assert to TagError
	tagErr, ok := err.(TagError)
	if !ok {
		return false
	}

	// Return if error matches errUnsupportedVersion
	return tagErr.Err == errUnsupportedVersion
}

// Parser represents an audio metadata tag parser.  It is the interface which all other parsers implement, and it
// contains all the standard methods which must be present in an audio parser.
type Parser interface {
	// Methods which access the data stored in a typical audio metadata tag
	Album() string
	AlbumArtist() string
	Artist() string
	Comment() string
	Date() string
	DiscNumber() int
	Genre() string
	Title() string
	TrackNumber() int

	// Tag is a special method which will attempt to retrieve an audio metadata tag with the input name. Tag will
	// attempt to return a metadata tag's raw contents, or will return an empty string on failure.
	// Using Tag, the following two calls are functionally equivalent:
	//   - parser.Artist()
	//   - parser.Tag("ARTIST")
	Tag(name string) string

	// Methods which access properties of an audio file, which are typically calculated at runtime
	BitDepth() int
	Bitrate() int
	Channels() int
	Duration() time.Duration
	Encoder() string
	Format() string
	SampleRate() int
}

// New creates a new audio metadata parser, depending on the magic number detected in the input reader.  If New
// recognizes the magic number, it will delegate parsing to the appropriate parser.  If it does not recognize the
// input format, it will return errUnknownFormat, which can be checked using IsUnknownFormat.
func New(reader io.ReadSeeker) (Parser, error) {
	// Check for magic numbers
	magicBuf := make([]byte, 8)

	// Read first byte to begin checking magic number
	if _, err := reader.Read(magicBuf[:1]); err != nil {
		return nil, err
	}

	// Check for FLAC magic number
	if magicBuf[0] == byte('f') {
		// Read next 3 bytes for magic number
		if _, err := reader.Read(magicBuf[1:len(flacMagicNumber)]); err != nil {
			return nil, err
		}

		// Verify FLAC magic number
		if bytes.Equal(magicBuf[:len(flacMagicNumber)], flacMagicNumber) {
			return newFLACParser(reader)
		}
	}

	// Check for MP3 magic number
	if magicBuf[0] == byte('I') {
		// Read next 2 bytes for magic number
		if _, err := reader.Read(magicBuf[1:len(mp3MagicNumber)]); err != nil {
			return nil, err
		}

		// Verify MP3 magic number
		if bytes.Equal(magicBuf[:len(mp3MagicNumber)], mp3MagicNumber) {
			return newMP3Parser(reader)
		}
	}

	// Check for OGG magic number
	if magicBuf[0] == byte('O') {
		// Read next 3 bytes for magic number
		if _, err := reader.Read(magicBuf[1:len(oggMagicNumber)]); err != nil {
			return nil, err
		}

		// Verify OGG magic number
		if bytes.Equal(magicBuf[:len(oggMagicNumber)], oggMagicNumber) {
			return newOGGVorbisParser(reader)
		}
	}

	// Unrecognized magic number
	return nil, TagError{
		Err:     errUnknownFormat,
		Format:  "unknown",
		Details: "unrecognized magic number, cannot parse this stream",
	}
}
<|endoftext|>


<commit_before>package base

import (
	"fmt"
	"gopkg.in/orivil/orivil.v0"
)

type Controller struct {
	*orivil.App
}

// @route {get}/
func (this *Controller) Index() {

	this.WriteString("
hello orivil!
")
}
<commit_msg>remove not used import<commit_after>package base

import (
	"gopkg.in/orivil/orivil.v0"
)

type Controller struct {
	*orivil.App
}

// @route {get}/
func (this *Controller) Index() {

	this.WriteString("
hello orivil!
")
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"io"
	"io/ioutil"
	"net"
	"strconv"
	"strings"

	"github.com/flynn/strowger/types"
	. "github.com/titanous/gocheck"
)

func NewTCPTestServer(r io.Reader, w io.Writer) *TCPTestServer {
	s := &TCPTestServer{w: w, r: r}
	var err error
	s.l, err = net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	s.Addr = s.l.Addr().String()
	go s.Serve()
	return s
}

type TCPTestServer struct {
	Addr string
	w    io.Writer
	r    io.Reader
	l    net.Listener
}

func (s *TCPTestServer) Serve() {
	for {
		conn, err := s.l.Accept()
		if err != nil {
			return
		}
		go func() {
			defer conn.Close()
			done := make(chan struct{})
			go func() {
				io.Copy(conn, s.r)
				close(done)
			}()
			io.Copy(s.w, conn)
			<-done
		}()
	}
}

func (s *TCPTestServer) Close() error { return s.l.Close() }

func newTCPListener(etcd *fakeEtcd) (*TCPListener, *fakeDiscoverd, error) {
	discoverd := newFakeDiscoverd()
	if etcd == nil {
		etcd = newFakeEtcd()
	}
	l := NewTCPListener("127.0.0.1", NewEtcdDataStore(etcd, "/strowger/tcp/"), discoverd)
	return l, discoverd, l.Start()
}

func assertTCPConn(c *C, addr, expected string, rcvd *bytes.Buffer) {
	conn, err := net.Dial("tcp", addr)
	c.Assert(err, IsNil)
	conn.Write([]byte("asdf"))
	conn.(*net.TCPConn).CloseWrite()
	res, err := ioutil.ReadAll(conn)
	conn.Close()

	c.Assert(err, IsNil)
	c.Assert(string(res), Equals, expected)
	c.Assert(rcvd.String(), Equals, "asdf")
	rcvd.Reset()
}

func (s *S) TestAddTCPRoute(c *C) {
	const addr, port, portInt = "127.0.0.1:45000", "45000", 45000
	buf := &bytes.Buffer{}
	srv1 := NewTCPTestServer(strings.NewReader("1"), buf)
	srv2 := NewTCPTestServer(strings.NewReader("2"), buf)
	defer srv1.Close()
	defer srv2.Close()

	l, discoverd, err := newTCPListener(nil)
	c.Assert(err, IsNil)
	defer l.Close()

	discoverd.Register("test", srv1.Addr)
	defer discoverd.UnregisterAll()

	wait := waitForEvent(c, l, "add", port)
	err = l.AddRoute(&strowger.TCPRoute{Port: portInt, Service: "test"})
	c.Assert(err, IsNil)
	wait()

	assertTCPConn(c, addr, "1", buf)

	discoverd.Unregister("test", srv1.Addr)
	discoverd.Register("test", srv2.Addr)

	assertTCPConn(c, addr, "2", buf)

	wait = waitForEvent(c, l, "remove", port)
	err = l.RemoveRoute(port)
	c.Assert(err, IsNil)
	wait()

	_, err = net.Dial("tcp", addr)
	c.Assert(err, Not(IsNil))
}

func (s *S) TestInitialTCPSync(c *C) {
	const addr, port = "127.0.0.1:45000", 45000
	etcd := newFakeEtcd()
	l, _, err := newTCPListener(etcd)
	c.Assert(err, IsNil)
	wait := waitForEvent(c, l, "add", strconv.Itoa(port))
	err = l.AddRoute(&strowger.TCPRoute{Service: "test", Port: port})
	c.Assert(err, IsNil)
	wait()
	l.Close()

	buf := &bytes.Buffer{}
	srv := NewTCPTestServer(strings.NewReader("1"), buf)
	defer srv.Close()

	l, discoverd, err := newTCPListener(etcd)
	c.Assert(err, IsNil)
	defer l.Close()

	discoverd.Register("test", srv.Addr)
	defer discoverd.UnregisterAll()

	assertTCPConn(c, addr, "1", buf)
}
<commit_msg>router: Fix race in test, simplify<commit_after>package main

import (
	"io"
	"io/ioutil"
	"net"
	"strconv"

	"github.com/flynn/strowger/types"
	. "github.com/titanous/gocheck"
)

func NewTCPTestServer(prefix string) *TCPTestServer {
	s := &TCPTestServer{prefix: prefix}
	var err error
	s.l, err = net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		panic(err)
	}
	s.Addr = s.l.Addr().String()
	go s.Serve()
	return s
}

type TCPTestServer struct {
	Addr   string
	prefix string
	l      net.Listener
}

func (s *TCPTestServer) Serve() {
	for {
		conn, err := s.l.Accept()
		if err != nil {
			return
		}
		go func() {
			conn.Write([]byte(s.prefix))
			io.Copy(conn, conn)
			conn.Close()
		}()
	}
}

func (s *TCPTestServer) Close() error { return s.l.Close() }

func newTCPListener(etcd *fakeEtcd) (*TCPListener, *fakeDiscoverd, error) {
	discoverd := newFakeDiscoverd()
	if etcd == nil {
		etcd = newFakeEtcd()
	}
	l := NewTCPListener("127.0.0.1", NewEtcdDataStore(etcd, "/strowger/tcp/"), discoverd)
	return l, discoverd, l.Start()
}

func assertTCPConn(c *C, addr, prefix string) {
	conn, err := net.Dial("tcp", addr)
	c.Assert(err, IsNil)
	conn.Write([]byte("asdf"))
	conn.(*net.TCPConn).CloseWrite()
	res, err := ioutil.ReadAll(conn)
	conn.Close()

	c.Assert(err, IsNil)
	c.Assert(string(res), Equals, prefix+"asdf")
}

func (s *S) TestAddTCPRoute(c *C) {
	const addr, port, portInt = "127.0.0.1:45000", "45000", 45000
	srv1 := NewTCPTestServer("1")
	srv2 := NewTCPTestServer("2")
	defer srv1.Close()
	defer srv2.Close()

	l, discoverd, err := newTCPListener(nil)
	c.Assert(err, IsNil)
	defer l.Close()

	discoverd.Register("test", srv1.Addr)
	defer discoverd.UnregisterAll()

	wait := waitForEvent(c, l, "add", port)
	err = l.AddRoute(&strowger.TCPRoute{Port: portInt, Service: "test"})
	c.Assert(err, IsNil)
	wait()

	assertTCPConn(c, addr, "1")

	discoverd.Unregister("test", srv1.Addr)
	discoverd.Register("test", srv2.Addr)

	assertTCPConn(c, addr, "2")

	wait = waitForEvent(c, l, "remove", port)
	err = l.RemoveRoute(port)
	c.Assert(err, IsNil)
	wait()

	_, err = net.Dial("tcp", addr)
	c.Assert(err, Not(IsNil))
}

func (s *S) TestInitialTCPSync(c *C) {
	const addr, port = "127.0.0.1:45000", 45000
	etcd := newFakeEtcd()
	l, _, err := newTCPListener(etcd)
	c.Assert(err, IsNil)
	wait := waitForEvent(c, l, "add", strconv.Itoa(port))
	err = l.AddRoute(&strowger.TCPRoute{Service: "test", Port: port})
	c.Assert(err, IsNil)
	wait()
	l.Close()

	srv := NewTCPTestServer("1")
	defer srv.Close()

	l, discoverd, err := newTCPListener(etcd)
	c.Assert(err, IsNil)
	defer l.Close()

	discoverd.Register("test", srv.Addr)
	defer discoverd.UnregisterAll()

	assertTCPConn(c, addr, "1")
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"testing"
	"github.com/TheJumpCloud/jcapi"
)

const (
	testUrlBase string = "https://console.jumpcloud.com/api"
	authUrlBase string = "https://auth.jumpcloud.com"
)

var testAPIKey string = os.Getenv("JUMPCLOUD_APIKEY")
var testSystemID string = os.Getenv("JUMPCLOUD_SYSTEMID")

func TestCSVImporter(t *testing.T) {
	// Attach to JumpCloud
	jc := jcapi.NewJCAPI(testAPIKey, testUrlBase)

	// Fetch all users in JumpCloud
	userList, err := jc.GetSystemUsers(false)

	if err != nil {
		t.Fatalf("Could not read system users, err='%s'\n", err)
		return
	}

	// Fetch our system from JumpCloud
	system, err := jc.GetSystemById(testSystemID, true)

	if err != nil {
		t.Fatalf("Could not read system info for ID='%s', err='%s'\n", testSystemID, err)
		return
	}

	if system.Hostname == "" {
		t.Fatalf("Could not read system info for ID='%s', err='%s'\n", testSystemID, err)
		return
	}

	// Create a CSV record to add a test user
	csvrec := []string{"Joe", "Smith", "js", "TheMan@jumpcloud.com", "", "", "T", "", ""}

	// Process this request record
	ProcessCSVRecord(jc, userList, csvrec)

	// Fetch our freshly minted user
	ourUserList, err := jc.GetSystemUserByEmail("TheMan@jumpcloud.com", true)

	if err != nil {
		t.Fatalf("Could not read system user, err='%s'\n", err)
		return
	}

	tempUserId := GetUserIdFromUserName(ourUserList, "js")

	if tempUserId == "" {
		t.Fatalf("Could not read system user, err='%s'\n", err)
		return
	}

	tempUser, err := jc.GetSystemUserById(tempUserId, true)

	if err != nil {
		t.Fatalf("Could not read system user, err='%s'\n", err)
		return
	}

	// Ensure the user has no associated tags
	if len(tempUser.Tags) > 0 {
		t.Fatalf("Unexpectedly found tags associated with user\n")
		return
	}

	// Re-fetch all users in JumpCloud
	userList, err = jc.GetSystemUsers(false)

	if err != nil {
		t.Fatalf("Could not re-read system users, err='%s'\n", err)
		return
	}

	// Update our user to add a tag
	csvrec = []string{"Joe", "Smith", "js", "TheMan@jumpcloud.com", "", "", "T", "", system.Hostname}

	ProcessCSVRecord(jc, userList, csvrec)

	// Refetch our user...they should now have a tag associated with the host and tag name we provided
	tempUser, err = jc.GetSystemUserById(tempUserId, true)

	if err != nil {
		t.Fatalf("Could not read system user, err='%s'\n", err)
		return
	}

	if len(tempUser.Tags) <= 0 {
		t.Fatalf("No tags associated with user\n")
		return
	}

	foundIt := false
	testTagName := system.Hostname + " - Joe Smith (js)"

	for _, checkTag := range tempUser.Tags {
		if checkTag.Name == testTagName {
			for _, checkTagHost := range checkTag.Systems {
				if checkTagHost == testSystemID {
					foundIt = true
				}
			}
		}
	}

	if !foundIt {
		t.Fatalf("Did not find expected tag associated with user\n")
		return
	}

	return
}
<commit_msg>Added checking to tell the user to set up their environment variables if they aren't setup in the tests<commit_after>package main

import (
	"github.com/TheJumpCloud/jcapi"
	"os"
	"testing"
)

const (
	testUrlBase string = "https://console.jumpcloud.com/api"
	authUrlBase string = "https://auth.jumpcloud.com"
)

var testAPIKey string = os.Getenv("JUMPCLOUD_APIKEY")
var testSystemID string = os.Getenv("JUMPCLOUD_SYSTEMID")

func checkEnv(t *testing.T) {
	if testAPIKey == "" || testSystemID == "" {
		t.Fatalf("Environment not set, you need to:\n\texport JUMPCLOUD_APIKEY=<your-API-key>\n\texport JUMPCLOUD_SYSTEMID=<some-system-ID-on-your-acct>\n")
	}
}

func TestCSVImporter(t *testing.T) {
	checkEnv(t)

	// Attach to JumpCloud
	jc := jcapi.NewJCAPI(testAPIKey, testUrlBase)

	// Fetch all users in JumpCloud
	userList, err := jc.GetSystemUsers(false)

	if err != nil {
		t.Fatalf("Could not read system users, err='%s'\n", err)
		return
	}

	// Fetch our system from JumpCloud
	system, err := jc.GetSystemById(testSystemID, true)

	if err != nil {
		t.Fatalf("Could not read system info for ID='%s', err='%s'\n", testSystemID, err)
		return
	}

	if system.Hostname == "" {
		t.Fatalf("Could not read system info for ID='%s', err='%s'\n", testSystemID, err)
		return
	}

	// Create a CSV record to add a test user
	csvrec := []string{"Joe", "Smith", "js", "TheMan@jumpcloud.com", "", "", "T", "", ""}

	// Process this request record
	ProcessCSVRecord(jc, userList, csvrec)

	// Fetch our freshly minted user
	ourUserList, err := jc.GetSystemUserByEmail("TheMan@jumpcloud.com", true)

	if err != nil {
		t.Fatalf("Could not read system user, err='%s'\n", err)
		return
	}

	tempUserId := GetUserIdFromUserName(ourUserList, "js")

	if tempUserId == "" {
		t.Fatalf("Could not read system user, err='%s'\n", err)
		return
	}

	tempUser, err := jc.GetSystemUserById(tempUserId, true)

	if err != nil {
		t.Fatalf("Could not read system user, err='%s'\n", err)
		return
	}

	// Ensure the user has no associated tags
	if len(tempUser.Tags) > 0 {
		t.Fatalf("Unexpectedly found tags associated with user\n")
		return
	}

	// Re-fetch all users in JumpCloud
	userList, err = jc.GetSystemUsers(false)

	if err != nil {
		t.Fatalf("Could not re-read system users, err='%s'\n", err)
		return
	}

	// Update our user to add a tag
	csvrec = []string{"Joe", "Smith", "js", "TheMan@jumpcloud.com", "", "", "T", "", system.Hostname}

	ProcessCSVRecord(jc, userList, csvrec)

	// Refetch our user...they should now have a tag associated with the host and tag name we provided
	tempUser, err = jc.GetSystemUserById(tempUserId, true)

	if err != nil {
		t.Fatalf("Could not read system user, err='%s'\n", err)
		return
	}

	if len(tempUser.Tags) <= 0 {
		t.Fatalf("No tags associated with user\n")
		return
	}

	foundIt := false
	testTagName := system.Hostname + " - Joe Smith (js)"

	for _, checkTag := range tempUser.Tags {
		if checkTag.Name == testTagName {
			for _, checkTagHost := range checkTag.Systems {
				if checkTagHost == testSystemID {
					foundIt = true
				}
			}
		}
	}

	if !foundIt {
		t.Fatalf("Did not find expected tag associated with user\n")
		return
	}

	return
}
<|endoftext|>


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

package main

import (
	"bytes"
	"io/ioutil"
	"path/filepath"
	"text/template"

	"fmt"
	"k8s.io/kubernetes/pkg/api"
)

const (
	DEFAULT_NAMESPACE = api.NamespaceDefault
	DEFAULT_SELECTOR  = ""
)

type Template struct {
	// Template descriptor from configuration
	desc *TemplateDescriptor

	// Template name (base file name)
	name string

	// Template last output (in case of successfully rendered template)
	lastOutput string
}

func newTemplate(d *TemplateDescriptor) *Template {
	// Get last template output, if present
	o, err := ioutil.ReadFile(d.Output)
	if err != nil {
		o = nil
	}
	// Create template
	return &Template{
		desc:       d,
		name:       filepath.Base(d.Path),
		lastOutput: string(o),
	}
}

func (t *Template) Process(dm *DependencyManager, dryRun bool) (bool, error) {
	if r, err := t.Render(dm); err == nil {
		if changed := !(r == t.lastOutput); changed {
			// Template output changed
			if !dryRun {
				// TODO file mode from config
				// TODO atomic write
				if err := ioutil.WriteFile(t.desc.Output, []byte(r), 0644); err != nil {
					return false, err
				}
			}
			t.lastOutput = r
			return true, nil
		}
		// Template output not changed
		return false, nil
	} else {
		// Can't render template
		return false, err
	}
}

func (t *Template) Render(dm *DependencyManager) (string, error) {
	// Read template data
	data, err := ioutil.ReadFile(t.desc.Path)
	if err != nil {
		return "", err
	}
	s := string(data)
	// Create template from read data
	template, err := template.New(t.name).Funcs(funcMap(dm)).Parse(s)
	if err != nil {
		return "", err
	}
	// Render template to buffer
	buf := new(bytes.Buffer)
	if err := template.Execute(buf, nil); err != nil {
		return "", err
	}

	return buf.String(), nil
}

func funcMap(dm *DependencyManager) template.FuncMap {
	return template.FuncMap{
		// Kubernetes objects
		"pods":                   pods(dm),
		"services":               services(dm),
		"replicationcontrollers": replicationcontrollers(dm),
		"events":                 events(dm),
		"endpoints":              endpoints(dm),
		"nodes":                  nodes(dm),
		"namespaces":             namespaces(dm),
		// Utils
		"add": add,
		"sub": sub,
	}
}

// Parse template tag with max 1 argument - selector
func parseSelector(s ...string) (string, error) {
	selector := DEFAULT_SELECTOR
	switch len(s) {
	case 0:
		break
	case 1:
		selector = s[0]
	default:
		return "", fmt.Errorf("expected max 1 argument, got %d", len(s))
	}
	return selector, nil
}

// Parse template tag with max 2 arguments - selector and namespace (in given order)
func parseNamespaceSelector(s ...string) (string, string, error) {
	namespace, selector := DEFAULT_NAMESPACE, DEFAULT_SELECTOR
	switch len(s) {
	case 0:
		break
	case 1:
		selector = s[0]
	case 2:
		selector = s[0]
		namespace = s[1]
	default:
		return "", "", fmt.Errorf("expected max 2 arguments, got %d", len(s))
	}
	return namespace, selector, nil
}

// {{pods "selector" "namespace"}}
func pods(dm *DependencyManager) func(...string) ([]api.Pod, error) {
	return func(s ...string) ([]api.Pod, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.Pods(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{services "selector" "namespace"}}
func services(dm *DependencyManager) func(...string) ([]api.Service, error) {
	return func(s ...string) ([]api.Service, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.Services(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{replicationcontrollers "selector" "namespace"}}
func replicationcontrollers(dm *DependencyManager) func(...string) ([]api.ReplicationController, error) {
	return func(s ...string) ([]api.ReplicationController, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.ReplicationControllers(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{events "selector" "namespace"}}
func events(dm *DependencyManager) func(...string) ([]api.Event, error) {
	return func(s ...string) ([]api.Event, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.Events(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{endpoints "selector" "namespace"}}
func endpoints(dm *DependencyManager) func(...string) ([]api.Endpoints, error) {
	return func(s ...string) ([]api.Endpoints, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.Endpoints(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{nodes "selector"}}
func nodes(dm *DependencyManager) func(...string) ([]api.Node, error) {
	return func(s ...string) ([]api.Node, error) {
		if selector, err := parseSelector(s...); err == nil {
			return dm.Nodes(selector)
		} else {
			return nil, err
		}
	}
}

// {{namespaces "selector"}}
func namespaces(dm *DependencyManager) func(...string) ([]api.Namespace, error) {
	return func(s ...string) ([]api.Namespace, error) {
		if selector, err := parseSelector(s...); err == nil {
			return dm.Namespaces(selector)
		} else {
			return nil, err
		}
	}
}

// {{add a b}}
func add(a, b int) int {
	return a + b
}

// {{sub a b}}
func sub(a, b int) int {
	return a - b
}
<commit_msg>Atomic template output file update<commit_after>// Copyright © 2015 Victor Antonovich <victor@antonovich.me>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"bytes"
	"io/ioutil"
	"path/filepath"
	"text/template"

	"fmt"
	"k8s.io/kubernetes/pkg/api"
	"os"
)

const (
	DEFAULT_NAMESPACE = api.NamespaceDefault
	DEFAULT_SELECTOR  = ""
)

type Template struct {
	// Template descriptor from configuration
	desc *TemplateDescriptor

	// Template name (base file name)
	name string

	// Template last output (in case of successfully rendered template)
	lastOutput string
}

func newTemplate(d *TemplateDescriptor) *Template {
	// Get last template output, if present
	o, err := ioutil.ReadFile(d.Output)
	if err != nil {
		o = nil
	}
	// Create template
	return &Template{
		desc:       d,
		name:       filepath.Base(d.Path),
		lastOutput: string(o),
	}
}

func (t *Template) Process(dm *DependencyManager, dryRun bool) (bool, error) {
	if r, err := t.Render(dm); err == nil {
		if changed := !(r == t.lastOutput); changed {
			// Template output changed
			if !dryRun {
				if err := t.Write([]byte(r)); err != nil {
					// Can't write template output
					return false, err
				}
			}
			t.lastOutput = r
			return true, nil
		}
		// Template output not changed
		return false, nil
	} else {
		// Can't render template
		return false, err
	}
}

func (t *Template) Write(content []byte) error {
	dir := filepath.Dir(t.desc.Output)
	name := filepath.Base(t.desc.Output)
	if _, err := os.Stat(t.desc.Output); os.IsNotExist(err) {
		// Output file does not exist, create intermediate dirs and write directly
		if err := os.MkdirAll(dir, 0755); err != nil {
			return err
		}
		// TODO file mode from config
		if err := ioutil.WriteFile(t.desc.Output, content, 0644); err != nil {
			return err
		}
	} else {
		// Output file exist, update atomically using temp file
		var f *os.File
		if f, err = ioutil.TempFile(dir, name); err != nil {
			return err
		}
		defer os.Remove(f.Name())
		// Write template output to temp file
		if _, err := f.Write(content); err != nil {
			return err
		}
		if err := f.Sync(); err != nil {
			return err
		}
		if err := f.Close(); err != nil {
			return err
		}
		// TODO file mode from config
		if err := os.Chmod(f.Name(), 0644); err != nil {
			return err
		}
		// Rename temp file to output file
		if err := os.Rename(f.Name(), t.desc.Output); err != nil {
			return err
		}
	}
	return nil
}

func (t *Template) Render(dm *DependencyManager) (string, error) {
	// Read template data
	data, err := ioutil.ReadFile(t.desc.Path)
	if err != nil {
		return "", err
	}
	s := string(data)
	// Create template from read data
	template, err := template.New(t.name).Funcs(funcMap(dm)).Parse(s)
	if err != nil {
		return "", err
	}
	// Render template to buffer
	buf := new(bytes.Buffer)
	if err := template.Execute(buf, nil); err != nil {
		return "", err
	}

	return buf.String(), nil
}

func funcMap(dm *DependencyManager) template.FuncMap {
	return template.FuncMap{
		// Kubernetes objects
		"pods":                   pods(dm),
		"services":               services(dm),
		"replicationcontrollers": replicationcontrollers(dm),
		"events":                 events(dm),
		"endpoints":              endpoints(dm),
		"nodes":                  nodes(dm),
		"namespaces":             namespaces(dm),
		// Utils
		"add": add,
		"sub": sub,
	}
}

// Parse template tag with max 1 argument - selector
func parseSelector(s ...string) (string, error) {
	selector := DEFAULT_SELECTOR
	switch len(s) {
	case 0:
		break
	case 1:
		selector = s[0]
	default:
		return "", fmt.Errorf("expected max 1 argument, got %d", len(s))
	}
	return selector, nil
}

// Parse template tag with max 2 arguments - selector and namespace (in given order)
func parseNamespaceSelector(s ...string) (string, string, error) {
	namespace, selector := DEFAULT_NAMESPACE, DEFAULT_SELECTOR
	switch len(s) {
	case 0:
		break
	case 1:
		selector = s[0]
	case 2:
		selector = s[0]
		namespace = s[1]
	default:
		return "", "", fmt.Errorf("expected max 2 arguments, got %d", len(s))
	}
	return namespace, selector, nil
}

// {{pods "selector" "namespace"}}
func pods(dm *DependencyManager) func(...string) ([]api.Pod, error) {
	return func(s ...string) ([]api.Pod, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.Pods(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{services "selector" "namespace"}}
func services(dm *DependencyManager) func(...string) ([]api.Service, error) {
	return func(s ...string) ([]api.Service, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.Services(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{replicationcontrollers "selector" "namespace"}}
func replicationcontrollers(dm *DependencyManager) func(...string) ([]api.ReplicationController, error) {
	return func(s ...string) ([]api.ReplicationController, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.ReplicationControllers(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{events "selector" "namespace"}}
func events(dm *DependencyManager) func(...string) ([]api.Event, error) {
	return func(s ...string) ([]api.Event, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.Events(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{endpoints "selector" "namespace"}}
func endpoints(dm *DependencyManager) func(...string) ([]api.Endpoints, error) {
	return func(s ...string) ([]api.Endpoints, error) {
		if namespace, selector, err := parseNamespaceSelector(s...); err == nil {
			return dm.Endpoints(namespace, selector)
		} else {
			return nil, err
		}
	}
}

// {{nodes "selector"}}
func nodes(dm *DependencyManager) func(...string) ([]api.Node, error) {
	return func(s ...string) ([]api.Node, error) {
		if selector, err := parseSelector(s...); err == nil {
			return dm.Nodes(selector)
		} else {
			return nil, err
		}
	}
}

// {{namespaces "selector"}}
func namespaces(dm *DependencyManager) func(...string) ([]api.Namespace, error) {
	return func(s ...string) ([]api.Namespace, error) {
		if selector, err := parseSelector(s...); err == nil {
			return dm.Namespaces(selector)
		} else {
			return nil, err
		}
	}
}

// {{add a b}}
func add(a, b int) int {
	return a + b
}

// {{sub a b}}
func sub(a, b int) int {
	return a - b
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"crypto/sha1"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"syscall"
	"text/template"
)

func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func getArrayValues(funcName string, entries interface{}) (reflect.Value, error) {
	entriesVal := reflect.ValueOf(entries)

	kind := entriesVal.Kind()

	if kind == reflect.Ptr {
		entriesVal = reflect.Indirect(entriesVal)
		kind = entriesVal.Kind()
	}

	switch entriesVal.Kind() {
	case reflect.Array, reflect.Slice:
		break
	default:
		return entriesVal, fmt.Errorf("Must pass an array or slice to '%v'; received %v; kind %v", funcName, entries, kind)
	}
	return entriesVal, nil
}

// Generalized groupBy function
func generalizedGroupBy(funcName string, entries interface{}, key string, addEntry func(map[string][]interface{}, interface{}, interface{})) (map[string][]interface{}, error) {
	entriesVal, err := getArrayValues(funcName, entries)

	if err != nil {
		return nil, err
	}

	groups := make(map[string][]interface{})
	for i := 0; i < entriesVal.Len(); i++ {
		v := reflect.Indirect(entriesVal.Index(i)).Interface()
		value := deepGet(v, key)
		if value != nil {
			addEntry(groups, value, v)
		}
	}
	return groups, nil
}

func groupByMulti(entries interface{}, key, sep string) (map[string][]interface{}, error) {
	return generalizedGroupBy("groupByMulti", entries, key, func(groups map[string][]interface{}, value interface{}, v interface{}) {
		items := strings.Split(value.(string), sep)
		for _, item := range items {
			groups[item] = append(groups[item], v)
		}
	})
}

// groupBy groups a generic array or slice by the path property key
func groupBy(entries interface{}, key string) (map[string][]interface{}, error) {
	return generalizedGroupBy("groupBy", entries, key, func(groups map[string][]interface{}, value interface{}, v interface{}) {
		groups[value.(string)] = append(groups[value.(string)], v)
	})
}

// groupByKeys is the same as groupBy but only returns a list of keys
func groupByKeys(entries interface{}, key string) ([]string, error) {
	keys, err := generalizedGroupBy("groupByKeys", entries, key, func(groups map[string][]interface{}, value interface{}, v interface{}) {
		groups[value.(string)] = append(groups[value.(string)], v)
	})

	if err != nil {
		return nil, err
	}

	ret := []string{}
	for k := range keys {
		ret = append(ret, k)
	}
	return ret, nil
}

// Generalized where function
func generalizedWhere(funcName string, entries interface{}, key string, test func(interface{}) bool) (interface{}, error) {

	entriesVal, err := getArrayValues(funcName, entries)

	if err != nil {
		return nil, err
	}

	selection := make([]interface{}, 0)
	for i := 0; i < entriesVal.Len(); i++ {
		v := reflect.Indirect(entriesVal.Index(i)).Interface()

		value := deepGet(v, key)
		if test(value) {
			selection = append(selection, v)
		}
	}

	return selection, nil
}

// selects entries based on key
func where(entries interface{}, key string, cmp interface{}) (interface{}, error) {
	return generalizedWhere("where", entries, key, func(value interface{}) bool {
		return reflect.DeepEqual(value, cmp)
	})
}

// selects entries where a key exists
func whereExist(entries interface{}, key string) (interface{}, error) {
	return generalizedWhere("whereExist", entries, key, func(value interface{}) bool {
		return value != nil
	})
}

// selects entries where a key does not exist
func whereNotExist(entries interface{}, key string) (interface{}, error) {
	return generalizedWhere("whereNotExist", entries, key, func(value interface{}) bool {
		return value == nil
	})
}

// selects entries based on key.  Assumes key is delimited and breaks it apart before comparing
func whereAny(entries interface{}, key, sep string, cmp []string) (interface{}, error) {
	return generalizedWhere("whereAny", entries, key, func(value interface{}) bool {
		if value == nil {
			return false
		} else {
			items := strings.Split(value.(string), sep)
			return len(intersect(cmp, items)) > 0
		}
	})
}

// selects entries based on key.  Assumes key is delimited and breaks it apart before comparing
func whereAll(entries interface{}, key, sep string, cmp []string) (interface{}, error) {
	req_count := len(cmp)
	return generalizedWhere("whereAll", entries, key, func(value interface{}) bool {
		if value == nil {
			return false
		} else {
			items := strings.Split(value.(string), sep)
			return len(intersect(cmp, items)) == req_count
		}
	})
}

// hasPrefix returns whether a given string is a prefix of another string
func hasPrefix(prefix, s string) bool {
	return strings.HasPrefix(s, prefix)
}

// hasSuffix returns whether a given string is a suffix of another string
func hasSuffix(suffix, s string) bool {
	return strings.HasSuffix(s, suffix)
}

func keys(input interface{}) (interface{}, error) {
	if input == nil {
		return nil, nil
	}

	val := reflect.ValueOf(input)
	if val.Kind() != reflect.Map {
		return nil, fmt.Errorf("Cannot call keys on a non-map value: %v", input)
	}

	vk := val.MapKeys()
	k := make([]interface{}, val.Len())
	for i, _ := range k {
		k[i] = vk[i].Interface()
	}

	return k, nil
}

func intersect(l1, l2 []string) []string {
	m := make(map[string]bool)
	m2 := make(map[string]bool)
	for _, v := range l2 {
		m2[v] = true
	}
	for _, v := range l1 {
		if m2[v] {
			m[v] = true
		}
	}
	keys := make([]string, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}
	return keys
}

func contains(item map[string]string, key string) bool {
	if _, ok := item[key]; ok {
		return true
	}
	return false
}

func dict(values ...interface{}) (map[string]interface{}, error) {
	if len(values)%2 != 0 {
		return nil, errors.New("invalid dict call")
	}
	dict := make(map[string]interface{}, len(values)/2)
	for i := 0; i < len(values); i += 2 {
		key, ok := values[i].(string)
		if !ok {
			return nil, errors.New("dict keys must be strings")
		}
		dict[key] = values[i+1]
	}
	return dict, nil
}

func hashSha1(input string) string {
	h := sha1.New()
	io.WriteString(h, input)
	return fmt.Sprintf("%x", h.Sum(nil))
}

func marshalJson(input interface{}) (string, error) {
	var buf bytes.Buffer
	enc := json.NewEncoder(&buf)
	if err := enc.Encode(input); err != nil {
		return "", err
	}
	return strings.TrimSuffix(buf.String(), "\n"), nil
}

func unmarshalJson(input string) (interface{}, error) {
	var v interface{}
	if err := json.Unmarshal([]byte(input), &v); err != nil {
		return nil, err
	}
	return v, nil
}

// arrayFirst returns first item in the array or nil if the
// input is nil or empty
func arrayFirst(input interface{}) interface{} {
	if input == nil {
		return nil
	}

	arr := reflect.ValueOf(input)

	if arr.Len() == 0 {
		return nil
	}

	return arr.Index(0).Interface()
}

// arrayLast returns last item in the array
func arrayLast(input interface{}) interface{} {
	arr := reflect.ValueOf(input)
	return arr.Index(arr.Len() - 1).Interface()
}

// arrayClosest find the longest matching substring in values
// that matches input
func arrayClosest(values []string, input string) string {
	best := ""
	for _, v := range values {
		if strings.Contains(input, v) && len(v) > len(best) {
			best = v
		}
	}
	return best
}

// dirList returns a list of files in the specified path
func dirList(path string) ([]string, error) {
	names := []string{}
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return names, err
	}
	for _, f := range files {
		names = append(names, f.Name())
	}
	return names, nil
}

// coalesce returns the first non nil argument
func coalesce(input ...interface{}) interface{} {
	for _, v := range input {
		if v != nil {
			return v
		}
	}
	return nil
}

// trimPrefix returns whether a given string is a prefix of another string
func trimPrefix(prefix, s string) string {
	return strings.TrimPrefix(s, prefix)
}

// trimSuffix returns whether a given string is a suffix of another string
func trimSuffix(suffix, s string) string {
	return strings.TrimSuffix(s, suffix)
}

func newTemplate(name string) *template.Template {
	tmpl := template.New(name).Funcs(template.FuncMap{
		"closest":       arrayClosest,
		"coalesce":      coalesce,
		"contains":      contains,
		"dict":          dict,
		"dir":           dirList,
		"exists":        exists,
		"first":         arrayFirst,
		"groupBy":       groupBy,
		"groupByKeys":   groupByKeys,
		"groupByMulti":  groupByMulti,
		"hasPrefix":     hasPrefix,
		"hasSuffix":     hasSuffix,
		"json":          marshalJson,
		"intersect":     intersect,
		"keys":          keys,
		"last":          arrayLast,
		"replace":       strings.Replace,
		"parseJson":     unmarshalJson,
		"queryEscape":   url.QueryEscape,
		"sha1":          hashSha1,
		"split":         strings.Split,
		"trimPrefix":    trimPrefix,
		"trimSuffix":    trimSuffix,
		"where":         where,
		"whereExist":    whereExist,
		"whereNotExist": whereNotExist,
		"whereAny":      whereAny,
		"whereAll":      whereAll,
	})
	return tmpl
}

func generateFile(config Config, containers Context) bool {
	templatePath := config.Template
	tmpl, err := newTemplate(filepath.Base(templatePath)).ParseFiles(templatePath)
	if err != nil {
		log.Fatalf("unable to parse template: %s", err)
	}

	filteredContainers := Context{}
	if config.OnlyPublished {
		for _, container := range containers {
			if len(container.PublishedAddresses()) > 0 {
				filteredContainers = append(filteredContainers, container)
			}
		}
	} else if config.OnlyExposed {
		for _, container := range containers {
			if len(container.Addresses) > 0 {
				filteredContainers = append(filteredContainers, container)
			}
		}
	} else {
		filteredContainers = containers
	}

	dest := os.Stdout
	if config.Dest != "" {
		dest, err = ioutil.TempFile(filepath.Dir(config.Dest), "docker-gen")
		defer func() {
			dest.Close()
			os.Remove(dest.Name())
		}()
		if err != nil {
			log.Fatalf("unable to create temp file: %s\n", err)
		}
	}

	var buf bytes.Buffer
	bw := bufio.NewWriter(&buf)
	err = tmpl.ExecuteTemplate(bw, filepath.Base(templatePath), &filteredContainers)
	if err != nil {
		log.Fatalf("template error: %s\n", err)
	}
	bw.Flush()

	if config.SkipBlankLines {
		scanner := bufio.NewScanner(bufio.NewReader(&buf))
		for scanner.Scan() {
			line := scanner.Text()
			if !isBlank(line) {
				fmt.Fprintln(dest, line)
			}
		}
	} else {
		buf.WriteTo(dest)
	}

	if config.Dest != "" {

		contents := []byte{}
		if fi, err := os.Stat(config.Dest); err == nil {
			if err := dest.Chmod(fi.Mode()); err != nil {
				log.Fatalf("unable to chmod temp file: %s\n", err)
			}
			if err := dest.Chown(int(fi.Sys().(*syscall.Stat_t).Uid), int(fi.Sys().(*syscall.Stat_t).Gid)); err != nil {
				log.Fatalf("unable to chown temp file: %s\n", err)
			}
			contents, err = ioutil.ReadFile(config.Dest)
			if err != nil {
				log.Fatalf("unable to compare current file contents: %s: %s\n", config.Dest, err)
			}
		}

		if bytes.Compare(contents, buf.Bytes()) != 0 {
			err = os.Rename(dest.Name(), config.Dest)
			if err != nil {
				log.Fatalf("unable to create dest file %s: %s\n", config.Dest, err)
			}
			log.Printf("Generated '%s' from %d containers", config.Dest, len(filteredContainers))
			return true
		}
		return false
	}
	return true
}
<commit_msg>fixed compare with old contents regression bug<commit_after>package main

import (
	"bufio"
	"bytes"
	"crypto/sha1"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/url"
	"os"
	"path/filepath"
	"reflect"
	"strings"
	"syscall"
	"text/template"
)

func exists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func getArrayValues(funcName string, entries interface{}) (reflect.Value, error) {
	entriesVal := reflect.ValueOf(entries)

	kind := entriesVal.Kind()

	if kind == reflect.Ptr {
		entriesVal = reflect.Indirect(entriesVal)
		kind = entriesVal.Kind()
	}

	switch entriesVal.Kind() {
	case reflect.Array, reflect.Slice:
		break
	default:
		return entriesVal, fmt.Errorf("Must pass an array or slice to '%v'; received %v; kind %v", funcName, entries, kind)
	}
	return entriesVal, nil
}

// Generalized groupBy function
func generalizedGroupBy(funcName string, entries interface{}, key string, addEntry func(map[string][]interface{}, interface{}, interface{})) (map[string][]interface{}, error) {
	entriesVal, err := getArrayValues(funcName, entries)

	if err != nil {
		return nil, err
	}

	groups := make(map[string][]interface{})
	for i := 0; i < entriesVal.Len(); i++ {
		v := reflect.Indirect(entriesVal.Index(i)).Interface()
		value := deepGet(v, key)
		if value != nil {
			addEntry(groups, value, v)
		}
	}
	return groups, nil
}

func groupByMulti(entries interface{}, key, sep string) (map[string][]interface{}, error) {
	return generalizedGroupBy("groupByMulti", entries, key, func(groups map[string][]interface{}, value interface{}, v interface{}) {
		items := strings.Split(value.(string), sep)
		for _, item := range items {
			groups[item] = append(groups[item], v)
		}
	})
}

// groupBy groups a generic array or slice by the path property key
func groupBy(entries interface{}, key string) (map[string][]interface{}, error) {
	return generalizedGroupBy("groupBy", entries, key, func(groups map[string][]interface{}, value interface{}, v interface{}) {
		groups[value.(string)] = append(groups[value.(string)], v)
	})
}

// groupByKeys is the same as groupBy but only returns a list of keys
func groupByKeys(entries interface{}, key string) ([]string, error) {
	keys, err := generalizedGroupBy("groupByKeys", entries, key, func(groups map[string][]interface{}, value interface{}, v interface{}) {
		groups[value.(string)] = append(groups[value.(string)], v)
	})

	if err != nil {
		return nil, err
	}

	ret := []string{}
	for k := range keys {
		ret = append(ret, k)
	}
	return ret, nil
}

// Generalized where function
func generalizedWhere(funcName string, entries interface{}, key string, test func(interface{}) bool) (interface{}, error) {

	entriesVal, err := getArrayValues(funcName, entries)

	if err != nil {
		return nil, err
	}

	selection := make([]interface{}, 0)
	for i := 0; i < entriesVal.Len(); i++ {
		v := reflect.Indirect(entriesVal.Index(i)).Interface()

		value := deepGet(v, key)
		if test(value) {
			selection = append(selection, v)
		}
	}

	return selection, nil
}

// selects entries based on key
func where(entries interface{}, key string, cmp interface{}) (interface{}, error) {
	return generalizedWhere("where", entries, key, func(value interface{}) bool {
		return reflect.DeepEqual(value, cmp)
	})
}

// selects entries where a key exists
func whereExist(entries interface{}, key string) (interface{}, error) {
	return generalizedWhere("whereExist", entries, key, func(value interface{}) bool {
		return value != nil
	})
}

// selects entries where a key does not exist
func whereNotExist(entries interface{}, key string) (interface{}, error) {
	return generalizedWhere("whereNotExist", entries, key, func(value interface{}) bool {
		return value == nil
	})
}

// selects entries based on key.  Assumes key is delimited and breaks it apart before comparing
func whereAny(entries interface{}, key, sep string, cmp []string) (interface{}, error) {
	return generalizedWhere("whereAny", entries, key, func(value interface{}) bool {
		if value == nil {
			return false
		} else {
			items := strings.Split(value.(string), sep)
			return len(intersect(cmp, items)) > 0
		}
	})
}

// selects entries based on key.  Assumes key is delimited and breaks it apart before comparing
func whereAll(entries interface{}, key, sep string, cmp []string) (interface{}, error) {
	req_count := len(cmp)
	return generalizedWhere("whereAll", entries, key, func(value interface{}) bool {
		if value == nil {
			return false
		} else {
			items := strings.Split(value.(string), sep)
			return len(intersect(cmp, items)) == req_count
		}
	})
}

// hasPrefix returns whether a given string is a prefix of another string
func hasPrefix(prefix, s string) bool {
	return strings.HasPrefix(s, prefix)
}

// hasSuffix returns whether a given string is a suffix of another string
func hasSuffix(suffix, s string) bool {
	return strings.HasSuffix(s, suffix)
}

func keys(input interface{}) (interface{}, error) {
	if input == nil {
		return nil, nil
	}

	val := reflect.ValueOf(input)
	if val.Kind() != reflect.Map {
		return nil, fmt.Errorf("Cannot call keys on a non-map value: %v", input)
	}

	vk := val.MapKeys()
	k := make([]interface{}, val.Len())
	for i, _ := range k {
		k[i] = vk[i].Interface()
	}

	return k, nil
}

func intersect(l1, l2 []string) []string {
	m := make(map[string]bool)
	m2 := make(map[string]bool)
	for _, v := range l2 {
		m2[v] = true
	}
	for _, v := range l1 {
		if m2[v] {
			m[v] = true
		}
	}
	keys := make([]string, 0, len(m))
	for k := range m {
		keys = append(keys, k)
	}
	return keys
}

func contains(item map[string]string, key string) bool {
	if _, ok := item[key]; ok {
		return true
	}
	return false
}

func dict(values ...interface{}) (map[string]interface{}, error) {
	if len(values)%2 != 0 {
		return nil, errors.New("invalid dict call")
	}
	dict := make(map[string]interface{}, len(values)/2)
	for i := 0; i < len(values); i += 2 {
		key, ok := values[i].(string)
		if !ok {
			return nil, errors.New("dict keys must be strings")
		}
		dict[key] = values[i+1]
	}
	return dict, nil
}

func hashSha1(input string) string {
	h := sha1.New()
	io.WriteString(h, input)
	return fmt.Sprintf("%x", h.Sum(nil))
}

func marshalJson(input interface{}) (string, error) {
	var buf bytes.Buffer
	enc := json.NewEncoder(&buf)
	if err := enc.Encode(input); err != nil {
		return "", err
	}
	return strings.TrimSuffix(buf.String(), "\n"), nil
}

func unmarshalJson(input string) (interface{}, error) {
	var v interface{}
	if err := json.Unmarshal([]byte(input), &v); err != nil {
		return nil, err
	}
	return v, nil
}

// arrayFirst returns first item in the array or nil if the
// input is nil or empty
func arrayFirst(input interface{}) interface{} {
	if input == nil {
		return nil
	}

	arr := reflect.ValueOf(input)

	if arr.Len() == 0 {
		return nil
	}

	return arr.Index(0).Interface()
}

// arrayLast returns last item in the array
func arrayLast(input interface{}) interface{} {
	arr := reflect.ValueOf(input)
	return arr.Index(arr.Len() - 1).Interface()
}

// arrayClosest find the longest matching substring in values
// that matches input
func arrayClosest(values []string, input string) string {
	best := ""
	for _, v := range values {
		if strings.Contains(input, v) && len(v) > len(best) {
			best = v
		}
	}
	return best
}

// dirList returns a list of files in the specified path
func dirList(path string) ([]string, error) {
	names := []string{}
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return names, err
	}
	for _, f := range files {
		names = append(names, f.Name())
	}
	return names, nil
}

// coalesce returns the first non nil argument
func coalesce(input ...interface{}) interface{} {
	for _, v := range input {
		if v != nil {
			return v
		}
	}
	return nil
}

// trimPrefix returns whether a given string is a prefix of another string
func trimPrefix(prefix, s string) string {
	return strings.TrimPrefix(s, prefix)
}

// trimSuffix returns whether a given string is a suffix of another string
func trimSuffix(suffix, s string) string {
	return strings.TrimSuffix(s, suffix)
}

func newTemplate(name string) *template.Template {
	tmpl := template.New(name).Funcs(template.FuncMap{
		"closest":       arrayClosest,
		"coalesce":      coalesce,
		"contains":      contains,
		"dict":          dict,
		"dir":           dirList,
		"exists":        exists,
		"first":         arrayFirst,
		"groupBy":       groupBy,
		"groupByKeys":   groupByKeys,
		"groupByMulti":  groupByMulti,
		"hasPrefix":     hasPrefix,
		"hasSuffix":     hasSuffix,
		"json":          marshalJson,
		"intersect":     intersect,
		"keys":          keys,
		"last":          arrayLast,
		"replace":       strings.Replace,
		"parseJson":     unmarshalJson,
		"queryEscape":   url.QueryEscape,
		"sha1":          hashSha1,
		"split":         strings.Split,
		"trimPrefix":    trimPrefix,
		"trimSuffix":    trimSuffix,
		"where":         where,
		"whereExist":    whereExist,
		"whereNotExist": whereNotExist,
		"whereAny":      whereAny,
		"whereAll":      whereAll,
	})
	return tmpl
}

func generateFile(config Config, containers Context) bool {
	filteredContainers := Context{}
	if config.OnlyPublished {
		for _, container := range containers {
			if len(container.PublishedAddresses()) > 0 {
				filteredContainers = append(filteredContainers, container)
			}
		}
	} else if config.OnlyExposed {
		for _, container := range containers {
			if len(container.Addresses) > 0 {
				filteredContainers = append(filteredContainers, container)
			}
		}
	} else {
		filteredContainers = containers
	}

	contents := executeTemplate(config.Template, filteredContainers)

	if config.SkipBlankLines {
		contents = removeBlankLines(contents)
	}

	if config.Dest != "" {
		dest, err := ioutil.TempFile(filepath.Dir(config.Dest), "docker-gen")
		defer func() {
			dest.Close()
			os.Remove(dest.Name())
		}()
		if err != nil {
			log.Fatalf("unable to create temp file: %s\n", err)
		}

		dest.Write(contents)

		oldContents := []byte{}
		if fi, err := os.Stat(config.Dest); err == nil {
			if err := dest.Chmod(fi.Mode()); err != nil {
				log.Fatalf("unable to chmod temp file: %s\n", err)
			}
			if err := dest.Chown(int(fi.Sys().(*syscall.Stat_t).Uid), int(fi.Sys().(*syscall.Stat_t).Gid)); err != nil {
				log.Fatalf("unable to chown temp file: %s\n", err)
			}
			oldContents, err = ioutil.ReadFile(config.Dest)
			if err != nil {
				log.Fatalf("unable to compare current file contents: %s: %s\n", config.Dest, err)
			}
		}

		if bytes.Compare(oldContents, contents) != 0 {
			err = os.Rename(dest.Name(), config.Dest)
			if err != nil {
				log.Fatalf("unable to create dest file %s: %s\n", config.Dest, err)
			}
			log.Printf("Generated '%s' from %d containers", config.Dest, len(filteredContainers))
			return true
		}
		return false
	} else {
		os.Stdout.Write(contents)
	}
	return true
}

func executeTemplate(templatePath string, containers Context) []byte {
	tmpl, err := newTemplate(filepath.Base(templatePath)).ParseFiles(templatePath)
	if err != nil {
		log.Fatalf("unable to parse template: %s", err)
	}

	var buf bytes.Buffer
	err = tmpl.ExecuteTemplate(&buf, filepath.Base(templatePath), &containers)
	if err != nil {
		log.Fatalf("template error: %s\n", err)
	}
	return buf.Bytes()
}

func removeBlankLines(buf []byte) []byte {
	filtered := new(bytes.Buffer)
	scanner := bufio.NewScanner(bytes.NewReader(buf))
	for scanner.Scan() {
		line := scanner.Text()
		if !isBlank(line) {
			fmt.Fprintln(filtered, line)
		}
	}
	return filtered.Bytes()
}
<|endoftext|>


<commit_before>package swgohgg

import (
	"fmt"
	"time"

	"github.com/PuerkitoBio/goquery"
)

// Arena returns basic information about the player Arena team.
// If authorized, attempts to fetch more information from character stats
func (c *Client) Arena() (team []*CharacterStats, lastUpdate time.Time, err error) {
	doc, err := c.Get(fmt.Sprintf("https://swgoh.gg/u/%s/", c.profile))
	if err != nil {
		return
	}
	basicStats := make(map[string]CharacterStats)
	doc.Find(".current-rank-team").First().Find(".static-char-portrait").Each(func(i int, s *goquery.Selection) {
		charName := s.AttrOr("title", "UNKOWN")
		charBasicStats := CharacterStats{
			Name:  charName,
			Level: atoi(s.Find(".char-portrait-full-level").Text()),
			Stars: stars(s),
		}
		basicStats[charName] = charBasicStats
	})
	fmt.Printf("basicStats => %#v", basicStats)
	for name := range basicStats {
		basic := basicStats[name]
		if c.authorized {
			var stat *CharacterStats
			stat, err = c.CharacterStats(name)
			if err != nil {
				return
			}
			if stat.GearLevel < 0 {
				stat.Name = basic.Name
				stat.Level = basic.GearLevel
				stat.Stars = basic.Stars
			}
			team = append(team, stat)
		} else {
			team = append(team, &basic)
		}
	}
	timestamp := doc.Find(".user-last-updated .datetime").First().AttrOr("data-datetime", "0000-00-00T00:00:00Z")
	lastUpdate, err = time.Parse(time.RFC3339, timestamp)
	return
}
<commit_msg>Removed fmt.Printf message<commit_after>package swgohgg

import (
	"fmt"
	"time"

	"github.com/PuerkitoBio/goquery"
)

// Arena returns basic information about the player Arena team.
// If authorized, attempts to fetch more information from character stats
func (c *Client) Arena() (team []*CharacterStats, lastUpdate time.Time, err error) {
	doc, err := c.Get(fmt.Sprintf("https://swgoh.gg/u/%s/", c.profile))
	if err != nil {
		return
	}
	basicStats := make(map[string]CharacterStats)
	doc.Find(".current-rank-team").First().Find(".static-char-portrait").Each(func(i int, s *goquery.Selection) {
		charName := s.AttrOr("title", "UNKOWN")
		charBasicStats := CharacterStats{
			Name:  charName,
			Level: atoi(s.Find(".char-portrait-full-level").Text()),
			Stars: stars(s),
		}
		basicStats[charName] = charBasicStats
	})
	for name := range basicStats {
		basic := basicStats[name]
		if c.authorized {
			var stat *CharacterStats
			stat, err = c.CharacterStats(name)
			if err != nil {
				return
			}
			if stat.GearLevel < 0 {
				stat.Name = basic.Name
				stat.Level = basic.GearLevel
				stat.Stars = basic.Stars
			}
			team = append(team, stat)
		} else {
			team = append(team, &basic)
		}
	}
	timestamp := doc.Find(".user-last-updated .datetime").First().AttrOr("data-datetime", "0000-00-00T00:00:00Z")
	lastUpdate, err = time.Parse(time.RFC3339, timestamp)
	return
}
<|endoftext|>


<commit_before>package terminal

import "fmt"

func Println(text string) {
    fmt.Println(text)
}<commit_msg>updates<commit_after>package terminal

import (
    "os"
    "bufio"
)

const RESET = "\033[2J"

var Output *bufio.Writer = bufio.NewWriter(os.Stdout)

func Clear() {
    Output.WriteString(RESET)
}
<|endoftext|>


<commit_before>// Package sendgrid provides a simple interface to interact with the SendGrid API
package sendgrid

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"time"
)

func timeoutHandler(network, address string) (net.Conn, error) {
	return net.DialTimeout(network, address, time.Duration(5*time.Second))
}

// SGClient will contain the credentials and default values
type SGClient struct {
	apiUser string
	apiPwd  string
	APIMail string
	Client  *http.Client
}

// NewSendGridClient will return a new SGClient.
func NewSendGridClient(apiUser, apiPwd string) *SGClient {
	apiMail := "https://api.sendgrid.com/api/mail.send.json?"
	return &SGClient{
		apiUser: apiUser,
		apiPwd:  apiPwd,
		APIMail: apiMail,
	}
}

func (sg *SGClient) buildURL(m *SGMail) (url.Values, error) {
	values := url.Values{}
	values.Set("api_user", sg.apiUser)
	values.Set("api_key", sg.apiPwd)
	values.Set("subject", m.Subject)
	values.Set("html", m.HTML)
	values.Set("text", m.Text)
	values.Set("from", m.From)
	values.Set("replyto", m.ReplyTo)
	apiHeaders, apiError := m.JsonString()
	if apiError != nil {
		return nil, fmt.Errorf("sendgrid.go: error:%v", apiError)
	}
	values.Set("x-smtpapi", apiHeaders)
	values.Set("headers", m.Headers)
	if len(m.FromName) != 0 {
		values.Set("fromname", m.FromName)
	}
	for i := 0; i < len(m.Mail.To); i++ {
		values.Add("to[]", m.Mail.To[i])
	}
	for i := 0; i < len(m.Bcc); i++ {
		values.Add("bcc[]", m.Bcc[i])
	}
	for i := 0; i < len(m.ToName); i++ {
		values.Add("toname[]", m.ToName[i])
	}
	for k, v := range m.Files {
		values.Set("files["+k+"]", v)
	}
	return values, nil
}

// Send will send mail using SG web API
func (sg *SGClient) Send(m *SGMail) error {
	if sg.Client == nil {
		transport := http.Transport{
			Dial: timeoutHandler,
		}
		sg.Client = &http.Client{
			Transport: &transport,
		}
	}
	var e error
	values, e := sg.buildUrl(m)
	if e != nil {
		return e
	}
	r, e := sg.Client.PostForm(sg.APIMail, values)
	if e == nil { // errors can contain nil Body responses
		defer r.Body.Close()
	}
	if r.StatusCode == http.StatusOK && e == nil {
		return nil
	}
	body, _ := ioutil.ReadAll(r.Body)
	return fmt.Errorf("sendgrid.go: code:%d error:%v body:%s", r.StatusCode, e, body)
}
<commit_msg>Better error handling and support for headers<commit_after>// Package sendgrid provides a simple interface to interact with the SendGrid API
package sendgrid

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"net/url"
	"time"
)

func timeoutHandler(network, address string) (net.Conn, error) {
	return net.DialTimeout(network, address, time.Duration(5*time.Second))
}

// SGClient will contain the credentials and default values
type SGClient struct {
	apiUser string
	apiPwd  string
	APIMail string
	Client  *http.Client
}

// NewSendGridClient will return a new SGClient.
func NewSendGridClient(apiUser, apiPwd string) *SGClient {
	apiMail := "https://api.sendgrid.com/api/mail.send.json?"
	return &SGClient{
		apiUser: apiUser,
		apiPwd:  apiPwd,
		APIMail: apiMail,
	}
}

func (sg *SGClient) buildURL(m *SGMail) (url.Values, error) {
	values := url.Values{}
	values.Set("api_user", sg.apiUser)
	values.Set("api_key", sg.apiPwd)
	values.Set("subject", m.Subject)
	values.Set("html", m.HTML)
	values.Set("text", m.Text)
	values.Set("from", m.From)
	values.Set("replyto", m.ReplyTo)
	apiHeaders, err := m.SMTPAPIHeader.JSONString()
	if err != nil {
		return nil, fmt.Errorf("sendgrid.go: error:%v", err)
	}
	values.Set("x-smtpapi", apiHeaders)
	headers, err := m.HeadersString()
	if err != nil {
		return nil, fmt.Errorf("sendgrid.go: error: %v", err)
	}
	values.Set("headers", headers)
	if len(m.FromName) != 0 {
		values.Set("fromname", m.FromName)
	}
	for i := 0; i < len(m.To); i++ {
		values.Add("to[]", m.To[i])
	}
	for i := 0; i < len(m.Bcc); i++ {
		values.Add("bcc[]", m.Bcc[i])
	}
	for i := 0; i < len(m.ToName); i++ {
		values.Add("toname[]", m.ToName[i])
	}
	for k, v := range m.Files {
		values.Set("files["+k+"]", v)
	}
	return values, nil
}

// Send will send mail using SG web API
func (sg *SGClient) Send(m *SGMail) error {
	if sg.Client == nil {
		transport := http.Transport{
			Dial: timeoutHandler,
		}
		sg.Client = &http.Client{
			Transport: &transport,
		}
	}
	var e error
	values, e := sg.buildURL(m)
	if e != nil {
		return e
	}
	r, e := sg.Client.PostForm(sg.APIMail, values)
	if e == nil { // errors can contain nil Body responses
		defer r.Body.Close()
	}
	if r.StatusCode == http.StatusOK && e == nil {
		return nil
	}
	body, _ := ioutil.ReadAll(r.Body)
	return fmt.Errorf("sendgrid.go: code:%d error:%v body:%s", r.StatusCode, e, body)
}
<|endoftext|>