<commit_before>package main

import (
	"html/template"
	"log"
	"net/http"

	"github.com/dchest/uniuri"
	"github.com/gorilla/mux"
)

const (
	PORT   = ":8080"
	LENGTH = 12
)

var templates = template.Must(template.ParseFiles("static/index.html", "static/login.html", "static/register.html", "static/todo.html", "static/edit.html", "static/add.html"))

type User struct {
	ID       int
	Email    string
	Password string
}

type Tasks struct {
	ID      int    `json:"id"`
	Title   string `json:"title"`
	Task    string `json:"task"`
	Created string `json:"created"`
	DueDate string `json:"duedate"`
	Email   string `json:"email"`
}

type Page struct {
	Tasks []Tasks
}

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

func genName() string {
	name := uniuri.NewLen(LENGTH)

	return name
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	err := templates.ExecuteTemplate(w, "index.html", "")
	checkErr(err)

}

func todoHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	todo := vars["id"]
	err := templates.ExecuteTemplate(w, "todo.html", "")
	checkErr(err)

}

func addHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		err := templates.ExecuteTemplate(w, "add.html", "")
		checkErr(err)

	case "POST":
		title := r.FormValue("title")
		task := r.FormValue("task")
		duedate := r.FormValue("duedate")

	}

}

func editHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	todo := vars["id"]

}

func delHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	todo := vars["id"]

}

func finishHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	todo := vars["id"]

}

func userHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["id"]

}

func userDelHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["id"]

}

func loginHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		err := templates.ExecuteTemplate(w, "login.html", "")
		checkErr(err)
	case "POST":
		email := r.FormValue("email")
		pass := r.FormValue("pass")
	}

}

func registerHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		err := templates.ExecuteTemplate(w, "login.html", "")
		checkErr(err)
	case "POST":
		email := r.FormValue("email")
		pass := r.FormValue("pass")
	}

}

func logoutHandler(w http.ResponseWriter, r *http.Request) {
	cookie := &http.Cookie{
		Name:   "session",
		Value:  "",
		Path:   "/",
		MaxAge: -1,
	}
	http.SetCookie(w, cookie)
	http.Redirect(w, r, "/", 301)

}

func resetHandler(w http.ResponseWriter, r *http.Request) {

}

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/", rootHandler)

	router.HandleFunc("/todo", todoHandler)
	router.HandleFunc("/todo/{id}", todoHandler)
	router.HandleFunc("/todo/add", addHandler)
	router.HandleFunc("/todo/edit/{id}", editHandler)
	router.HandleFunc("/todo/del/{id}", delHandler)

	router.HandleFunc("/finish/{id}", finishHandler)

	router.HandleFunc("/user", userHandler)
	router.HandleFunc("/user/{id}", userHandler)
	router.HandleFunc("/user/del/{id}", userDelHandler)

	router.HandleFunc("/register", registerHandler)
	router.HandleFunc("/login", loginHandler)
	router.HandleFunc("/logout", logoutHandler)
	router.HandleFunc("/resetpass", resetHandler)
	err := http.ListenAndServe(PORT, router)
	if err != nil {
		log.Fatal(err)
	}

}
<commit_msg>Make registerhandler<commit_after>package main

import (
	"database/sql"
	"html"
	"html/template"
	"log"
	"net/http"

	"golang.org/x/crypto/bcrypt"

	"github.com/dchest/uniuri"
	"github.com/gorilla/mux"
)

const (
	PORT   = ":8080"
	LENGTH = 12
)

var templates = template.Must(template.ParseFiles("static/index.html", "static/login.html", "static/register.html", "static/todo.html", "static/edit.html", "static/add.html"))

type User struct {
	ID       int
	Email    string
	Password string
}

type Tasks struct {
	ID      int    `json:"id"`
	Title   string `json:"title"`
	Task    string `json:"task"`
	Created string `json:"created"`
	DueDate string `json:"duedate"`
	Email   string `json:"email"`
}

type Page struct {
	Tasks []Tasks
}

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

func genName() string {
	name := uniuri.NewLen(LENGTH)

	return name
}

func rootHandler(w http.ResponseWriter, r *http.Request) {
	err := templates.ExecuteTemplate(w, "index.html", "")
	checkErr(err)

}

func todoHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	todo := vars["id"]
	p := Page{}
	err := templates.ExecuteTemplate(w, "todo.html", &p)
	checkErr(err)

}

func addHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		err := templates.ExecuteTemplate(w, "add.html", "")
		checkErr(err)

	case "POST":
		title := r.FormValue("title")
		task := r.FormValue("task")
		duedate := r.FormValue("duedate")

	}

}

func editHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	todo := vars["id"]

}

func delHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	todo := vars["id"]

}

func finishHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	todo := vars["id"]

}

func userHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["id"]

}

func userDelHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	id := vars["id"]

}

func loginHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		err := templates.ExecuteTemplate(w, "login.html", "")
		checkErr(err)
	case "POST":
		email := r.FormValue("email")
		pass := r.FormValue("pass")
	}

}

func registerHandler(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case "GET":
		err := templates.ExecuteTemplate(w, "login.html", "")
		checkErr(err)
	case "POST":
		email := r.FormValue("email")
		pass := r.FormValue("pass")
		db, err := sql.Open("mysql", DATABASE)
		checkErr(err)

		defer db.Close()
		query, err := db.Prepare("INSERT into users(email, password) values(?, ?)")
		checkErr(err)
		hashedPassword, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost)
		checkErr(err)

		_, err = query.Exec(html.EscapeString(email), hashedPassword)
		checkErr(err)
		http.Redirect(w, r, "/login", 302)
	}

}

func logoutHandler(w http.ResponseWriter, r *http.Request) {
	cookie := &http.Cookie{
		Name:   "session",
		Value:  "",
		Path:   "/",
		MaxAge: -1,
	}
	http.SetCookie(w, cookie)
	http.Redirect(w, r, "/", 301)

}

func resetHandler(w http.ResponseWriter, r *http.Request) {

}

func main() {
	router := mux.NewRouter()
	router.HandleFunc("/", rootHandler)

	router.HandleFunc("/todo", todoHandler)
	router.HandleFunc("/todo/{id}", todoHandler)
	router.HandleFunc("/todo/add", addHandler)
	router.HandleFunc("/todo/edit/{id}", editHandler)
	router.HandleFunc("/todo/del/{id}", delHandler)

	router.HandleFunc("/finish/{id}", finishHandler)

	router.HandleFunc("/user", userHandler)
	router.HandleFunc("/user/{id}", userHandler)
	router.HandleFunc("/user/del/{id}", userDelHandler)

	router.HandleFunc("/register", registerHandler)
	router.HandleFunc("/login", loginHandler)
	router.HandleFunc("/logout", logoutHandler)
	router.HandleFunc("/resetpass", resetHandler)
	err := http.ListenAndServe(PORT, router)
	if err != nil {
		log.Fatal(err)
	}

}
<|endoftext|>


<commit_before>// Copyright 2011 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 (
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
)

var cmdTool = &Command{
	Run:       runTool,
	UsageLine: "tool [-n] command [args...]",
	Short:     "run specified go tool",
	Long: `
Tool runs the go tool command identified by the arguments.
With no arguments it prints the list of known tools.

The -n flag causes tool to print the command that would be
executed but not execute it.

For more about each tool command, see 'go tool command -h'.
`,
}

var (
	toolGOOS      = runtime.GOOS
	toolGOARCH    = runtime.GOARCH
	toolIsWindows = toolGOOS == "windows"
	toolDir       = build.ToolDir

	toolN bool
)

func init() {
	cmdTool.Flag.BoolVar(&toolN, "n", false, "")
}

const toolWindowsExtension = ".exe"

func tool(toolName string) string {
	toolPath := filepath.Join(toolDir, toolName)
	if toolIsWindows && toolName != "pprof" {
		toolPath += toolWindowsExtension
	}
	// Give a nice message if there is no tool with that name.
	if _, err := os.Stat(toolPath); err != nil {
		if isInGoToolsRepo(toolName) {
			fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo install code.google.com/p/go.tools/cmd/%s\n", toolName, toolName)
		} else {
			fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
		}
		setExitStatus(3)
		exit()
	}
	return toolPath
}

func isInGoToolsRepo(toolName string) bool {
	switch toolName {
	case "vet":
		return true
	}
	return false
}

func runTool(cmd *Command, args []string) {
	if len(args) == 0 {
		listTools()
		return
	}
	toolName := args[0]
	// The tool name must be lower-case letters, numbers or underscores.
	for _, c := range toolName {
		switch {
		case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
		default:
			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
			setExitStatus(2)
			return
		}
	}
	toolPath := tool(toolName)
	if toolPath == "" {
		return
	}
	if toolIsWindows && toolName == "pprof" {
		args = append([]string{"perl", toolPath}, args[1:]...)
		var err error
		toolPath, err = exec.LookPath("perl")
		if err != nil {
			fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
			setExitStatus(3)
			return
		}
	}
	if toolN {
		fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
		return
	}
	toolCmd := &exec.Cmd{
		Path:   toolPath,
		Args:   args,
		Stdin:  os.Stdin,
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	err := toolCmd.Run()
	if err != nil {
		// Only print about the exit status if the command
		// didn't even run (not an ExitError) or it didn't exit cleanly
		// or we're printing command lines too (-x mode).
		// Assume if command exited cleanly (even with non-zero status)
		// it printed any messages it wanted to print.
		if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX {
			fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
		}
		setExitStatus(1)
		return
	}
}

// listTools prints a list of the available tools in the tools directory.
func listTools() {
	f, err := os.Open(toolDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
		setExitStatus(2)
		return
	}
	defer f.Close()
	names, err := f.Readdirnames(-1)
	if err != nil {
		fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
		setExitStatus(2)
		return
	}

	sort.Strings(names)
	for _, name := range names {
		// Unify presentation by going to lower case.
		name = strings.ToLower(name)
		// If it's windows, don't show the .exe suffix.
		if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) {
			name = name[:len(name)-len(toolWindowsExtension)]
		}
		fmt.Println(name)
	}
}
<commit_msg>cmd/go: use "go get" instead of "go install" to install vet<commit_after>// Copyright 2011 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 (
	"fmt"
	"go/build"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"sort"
	"strings"
)

var cmdTool = &Command{
	Run:       runTool,
	UsageLine: "tool [-n] command [args...]",
	Short:     "run specified go tool",
	Long: `
Tool runs the go tool command identified by the arguments.
With no arguments it prints the list of known tools.

The -n flag causes tool to print the command that would be
executed but not execute it.

For more about each tool command, see 'go tool command -h'.
`,
}

var (
	toolGOOS      = runtime.GOOS
	toolGOARCH    = runtime.GOARCH
	toolIsWindows = toolGOOS == "windows"
	toolDir       = build.ToolDir

	toolN bool
)

func init() {
	cmdTool.Flag.BoolVar(&toolN, "n", false, "")
}

const toolWindowsExtension = ".exe"

func tool(toolName string) string {
	toolPath := filepath.Join(toolDir, toolName)
	if toolIsWindows && toolName != "pprof" {
		toolPath += toolWindowsExtension
	}
	// Give a nice message if there is no tool with that name.
	if _, err := os.Stat(toolPath); err != nil {
		if isInGoToolsRepo(toolName) {
			fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get code.google.com/p/go.tools/cmd/%s\n", toolName, toolName)
		} else {
			fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
		}
		setExitStatus(3)
		exit()
	}
	return toolPath
}

func isInGoToolsRepo(toolName string) bool {
	switch toolName {
	case "vet":
		return true
	}
	return false
}

func runTool(cmd *Command, args []string) {
	if len(args) == 0 {
		listTools()
		return
	}
	toolName := args[0]
	// The tool name must be lower-case letters, numbers or underscores.
	for _, c := range toolName {
		switch {
		case 'a' <= c && c <= 'z', '0' <= c && c <= '9', c == '_':
		default:
			fmt.Fprintf(os.Stderr, "go tool: bad tool name %q\n", toolName)
			setExitStatus(2)
			return
		}
	}
	toolPath := tool(toolName)
	if toolPath == "" {
		return
	}
	if toolIsWindows && toolName == "pprof" {
		args = append([]string{"perl", toolPath}, args[1:]...)
		var err error
		toolPath, err = exec.LookPath("perl")
		if err != nil {
			fmt.Fprintf(os.Stderr, "go tool: perl not found\n")
			setExitStatus(3)
			return
		}
	}
	if toolN {
		fmt.Printf("%s %s\n", toolPath, strings.Join(args[1:], " "))
		return
	}
	toolCmd := &exec.Cmd{
		Path:   toolPath,
		Args:   args,
		Stdin:  os.Stdin,
		Stdout: os.Stdout,
		Stderr: os.Stderr,
	}
	err := toolCmd.Run()
	if err != nil {
		// Only print about the exit status if the command
		// didn't even run (not an ExitError) or it didn't exit cleanly
		// or we're printing command lines too (-x mode).
		// Assume if command exited cleanly (even with non-zero status)
		// it printed any messages it wanted to print.
		if e, ok := err.(*exec.ExitError); !ok || !e.Exited() || buildX {
			fmt.Fprintf(os.Stderr, "go tool %s: %s\n", toolName, err)
		}
		setExitStatus(1)
		return
	}
}

// listTools prints a list of the available tools in the tools directory.
func listTools() {
	f, err := os.Open(toolDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "go tool: no tool directory: %s\n", err)
		setExitStatus(2)
		return
	}
	defer f.Close()
	names, err := f.Readdirnames(-1)
	if err != nil {
		fmt.Fprintf(os.Stderr, "go tool: can't read directory: %s\n", err)
		setExitStatus(2)
		return
	}

	sort.Strings(names)
	for _, name := range names {
		// Unify presentation by going to lower case.
		name = strings.ToLower(name)
		// If it's windows, don't show the .exe suffix.
		if toolIsWindows && strings.HasSuffix(name, toolWindowsExtension) {
			name = name[:len(name)-len(toolWindowsExtension)]
		}
		fmt.Println(name)
	}
}
<|endoftext|>


<commit_before>package aero

import (
	"fmt"
	"io"
	"strings"

	"github.com/akyoto/color"
)

// node types
const (
	separator = '/'
	parameter = ':'
	wildcard  = '*'
)

// controlFlow tells the main loop what it should do next.
type controlFlow int

// controlFlow values.
const (
	controlStop  controlFlow = 0
	controlBegin controlFlow = 1
	controlNext  controlFlow = 2
)

// dataType specifies which type of data we are going to save for each node.
type dataType = Handler

// tree represents a radix tree.
type tree struct {
	prefix    string
	children  [224]*tree
	data      dataType
	parameter *tree
	wildcard  *tree
	kind      byte
}

// add adds a new element to the tree.
func (node *tree) add(path string, data dataType) {
	// Search tree for equal parts until we can no longer proceed
	i := 0
	offset := 0

	for {
	begin:
		switch node.kind {
		case parameter:
			// This only occurs when the same parameter based route is added twice.
			// node: /post/:id|
			// path: /post/:id|
			if i == len(path) {
				node.data = data
				return
			}

			// When we hit a separator, we'll search for a fitting child.
			if path[i] == separator {
				var control controlFlow
				node, offset, control = node.end(path, data, i, offset)

				switch control {
				case controlStop:
					return
				case controlBegin:
					goto begin
				case controlNext:
					goto next
				}
			}

		default:
			if i == len(path) {
				// The path already exists.
				// node: /blog|
				// path: /blog|
				if i-offset == len(node.prefix) {
					node.data = data
					return
				}

				// The path ended but the node prefix is longer.
				// node: /blog|feed
				// path: /blog|
				node.split(i-offset, "", data)
				return
			}

			// The node we just checked is entirely included in our path.
			// node: /|
			// path: /|blog
			if i-offset == len(node.prefix) {
				var control controlFlow
				node, offset, control = node.end(path, data, i, offset)

				switch control {
				case controlStop:
					return
				case controlBegin:
					goto begin
				case controlNext:
					goto next
				}
			}

			// We got a conflict.
			// node: /b|ag
			// path: /b|riefcase
			if path[i] != node.prefix[i-offset] {
				node.split(i-offset, path[i:], data)
				return
			}
		}

	next:
		i++
	}
}

// split splits the node at the given index and inserts
// a new child node with the given path and data.
// If path is empty, it will not create another child node
// and instead assign the data directly to the node.
func (node *tree) split(index int, path string, data dataType) {
	// Create split node with the remaining string
	splitNode := node.clone(node.prefix[index:])

	/// The existing data must be removed
	node.reset(node.prefix[:index])

	// If the path is empty, it means we don't create a 2nd child node.
	// Just assign the data for the existing node and store a single child node.
	if path == "" {
		node.data = data
		node.children[splitNode.prefix[0]-32] = splitNode
		return
	}

	node.children[splitNode.prefix[0]-32] = splitNode

	// Create new nodes with the remaining path
	node.append(path, data)
}

// clone clones the node with a new prefix.
func (node *tree) clone(prefix string) *tree {
	return &tree{
		prefix:    prefix,
		data:      node.data,
		children:  node.children,
		parameter: node.parameter,
		wildcard:  node.wildcard,
		kind:      node.kind,
	}
}

// reset resets the existing node data.
func (node *tree) reset(prefix string) {
	node.prefix = prefix
	node.data = nil
	node.parameter = nil
	node.wildcard = nil
	node.kind = 0
	node.children = [224]*tree{}
}

// addTrailingSlash adds a trailing slash with the same data.
func (node *tree) addTrailingSlash(data dataType) {
	if strings.HasSuffix(node.prefix, "/") || node.children[separator-32] != nil || node.kind == wildcard {
		return
	}

	node.children[separator-32] = &tree{
		prefix: "/",
		data:   data,
	}
}

// append appends the given path to the tree.
func (node *tree) append(path string, data dataType) {
	// At this point, all we know is that somewhere
	// in the remaining string we have parameters.
	// node: /user|
	// path: /user|/:userid
	for {
		if path == "" {
			node.data = data
			return
		}

		paramStart := strings.IndexByte(path, parameter)

		if paramStart == -1 {
			paramStart = strings.IndexByte(path, wildcard)
		}

		// If it's a static route we are adding,
		// just add the remainder as a normal node.
		if paramStart == -1 {
			// If the node itself doesn't have a prefix (root node),
			// don't add a child and use the node itself.
			if node.prefix == "" {
				node.prefix = path
				node.data = data
				return
			}

			child := &tree{
				prefix: path,
				data:   data,
			}

			node.children[path[0]-32] = child
			child.addTrailingSlash(data)
			return
		}

		// If we're directly in front of a parameter,
		// add a parameter node.
		if paramStart == 0 {
			paramEnd := strings.IndexByte(path, separator)

			if paramEnd == -1 {
				paramEnd = len(path)
			}

			child := &tree{
				prefix: path[1:paramEnd],
				kind:   path[paramStart],
			}

			switch child.kind {
			case parameter:
				child.addTrailingSlash(data)
				node.parameter = child
				node = child
				path = path[paramEnd:]
				continue

			case wildcard:
				child.data = data
				node.wildcard = child
				return
			}
		}

		// We know there's a parameter, but not directly at the start.

		// If the node itself doesn't have a prefix (root node),
		// don't add a child and use the node itself.
		if node.prefix == "" {
			node.prefix = path[:paramStart]
			path = path[paramStart:]
			continue
		}

		// Add a normal node with the path before the parameter start.
		child := &tree{
			prefix: path[:paramStart],
		}

		// Allow trailing slashes to return
		// the same content as their parent node.
		if child.prefix == "/" {
			child.data = node.data
		}

		node.children[path[0]-32] = child
		node = child
		path = path[paramStart:]
	}
}

// end is called when the node was fully parsed
// and needs to decide the next control flow.
func (node *tree) end(path string, data dataType, i int, offset int) (*tree, int, controlFlow) {
	child := node.children[path[i]-32]

	if child != nil {
		node = child
		offset = i
		return node, offset, controlNext
	}

	// No fitting children found, does this node even contain a prefix yet?
	// If no prefix is set, this is the starting node.
	if node.prefix == "" {
		node.append(path[i:], data)
		return node, offset, controlStop
	}

	// node: /user/|:id
	// path: /user/|:id/profile
	if node.parameter != nil {
		node = node.parameter
		offset = i
		return node, offset, controlBegin
	}

	node.append(path[i:], data)
	return node, offset, controlStop
}

// find finds the data for the given path and assigns it to ctx.handler, if available.
func (node *tree) find(path string, ctx *context) {
	var (
		i                  uint
		offset             uint
		lastWildcardOffset uint
		lastWildcard       *tree
	)

	// Search tree for equal parts until we can no longer proceed
	for {
		if node.kind == parameter {
			// We reached the end.
			if i == uint(len(path)) {
				ctx.addParameter(node.prefix, path[offset:i])
				ctx.handler = node.data
				return
			}

			// node: /:xxx|/:yyy
			// path: /blog|/post
			if path[i] == separator {
				ctx.addParameter(node.prefix, path[offset:i])
				node = node.children[separator-32]
				offset = i
				i++
				continue
			}

			i++
			continue
		}

		// We reached the end.
		if i == uint(len(path)) {
			// node: /blog|
			// path: /blog|
			if i-offset == uint(len(node.prefix)) {
				ctx.handler = node.data
				return
			}

			// node: /blog|feed
			// path: /blog|
			ctx.handler = nil
			return
		}

		// The node we just checked is entirely included in our path.
		// node: /|
		// path: /|blog
		if i-offset == uint(len(node.prefix)) {
			if node.wildcard != nil {
				lastWildcard = node.wildcard
				lastWildcardOffset = i
			}

			child := node.children[path[i]-32]

			if child != nil {
				node = child
				offset = i
				i++
				continue
			}

			// node: /|:id
			// path: /|blog
			if node.parameter != nil {
				node = node.parameter
				offset = i
				continue
			}

			// node: /|*any
			// path: /|image.png
			if node.wildcard != nil {
				ctx.addParameter(node.wildcard.prefix, path[i:])
				ctx.handler = node.wildcard.data
				return
			}

			ctx.handler = nil
			return
		}

		// We got a conflict.
		// node: /b|ag
		// path: /b|riefcase
		if path[i] != node.prefix[i-offset] {
			if lastWildcard != nil {
				ctx.addParameter(lastWildcard.prefix, path[lastWildcardOffset:])
				ctx.handler = lastWildcard.data
				return
			}

			ctx.handler = nil
			return
		}

		i++
	}
}

// each traverses the tree and calls the given function on every node.
func (node *tree) each(callback func(*tree)) {
	callback(node)

	for _, child := range node.children {
		if child == nil {
			continue
		}

		child.each(callback)
	}

	if node.parameter != nil {
		node.parameter.each(callback)
	}

	if node.wildcard != nil {
		node.wildcard.each(callback)
	}
}

// PrettyPrint prints a human-readable form of the tree to the given writer.
func (node *tree) PrettyPrint(writer io.Writer) {
	node.prettyPrint(writer, -1)
}

// prettyPrint
func (node *tree) prettyPrint(writer io.Writer, level int) {
	prefix := ""

	if level >= 0 {
		prefix = strings.Repeat("  ", level) + "|_ "
	}

	colorFunc := color.CyanString

	switch node.kind {
	case ':':
		prefix += ":"
		colorFunc = color.YellowString
	case '*':
		prefix += "*"
		colorFunc = color.GreenString
	}

	fmt.Fprintf(writer, "%s%s [%t]\n", prefix, colorFunc(node.prefix), node.data != nil)

	for _, child := range node.children {
		if child == nil {
			continue
		}

		child.prettyPrint(writer, level+1)
	}

	if node.parameter != nil {
		node.parameter.prettyPrint(writer, level+1)
	}

	if node.wildcard != nil {
		node.wildcard.prettyPrint(writer, level+1)
	}
}
<commit_msg>Further improved performance<commit_after>package aero

import (
	"fmt"
	"io"
	"strings"

	"github.com/akyoto/color"
)

// node types
const (
	separator = '/'
	parameter = ':'
	wildcard  = '*'
)

// controlFlow tells the main loop what it should do next.
type controlFlow int

// controlFlow values.
const (
	controlStop  controlFlow = 0
	controlBegin controlFlow = 1
	controlNext  controlFlow = 2
)

// dataType specifies which type of data we are going to save for each node.
type dataType = Handler

// tree represents a radix tree.
type tree struct {
	prefix    string
	children  [224]*tree
	data      dataType
	parameter *tree
	wildcard  *tree
	kind      byte
}

// add adds a new element to the tree.
func (node *tree) add(path string, data dataType) {
	// Search tree for equal parts until we can no longer proceed
	i := 0
	offset := 0

	for {
	begin:
		switch node.kind {
		case parameter:
			// This only occurs when the same parameter based route is added twice.
			// node: /post/:id|
			// path: /post/:id|
			if i == len(path) {
				node.data = data
				return
			}

			// When we hit a separator, we'll search for a fitting child.
			if path[i] == separator {
				var control controlFlow
				node, offset, control = node.end(path, data, i, offset)

				switch control {
				case controlStop:
					return
				case controlBegin:
					goto begin
				case controlNext:
					goto next
				}
			}

		default:
			if i == len(path) {
				// The path already exists.
				// node: /blog|
				// path: /blog|
				if i-offset == len(node.prefix) {
					node.data = data
					return
				}

				// The path ended but the node prefix is longer.
				// node: /blog|feed
				// path: /blog|
				node.split(i-offset, "", data)
				return
			}

			// The node we just checked is entirely included in our path.
			// node: /|
			// path: /|blog
			if i-offset == len(node.prefix) {
				var control controlFlow
				node, offset, control = node.end(path, data, i, offset)

				switch control {
				case controlStop:
					return
				case controlBegin:
					goto begin
				case controlNext:
					goto next
				}
			}

			// We got a conflict.
			// node: /b|ag
			// path: /b|riefcase
			if path[i] != node.prefix[i-offset] {
				node.split(i-offset, path[i:], data)
				return
			}
		}

	next:
		i++
	}
}

// split splits the node at the given index and inserts
// a new child node with the given path and data.
// If path is empty, it will not create another child node
// and instead assign the data directly to the node.
func (node *tree) split(index int, path string, data dataType) {
	// Create split node with the remaining string
	splitNode := node.clone(node.prefix[index:])

	/// The existing data must be removed
	node.reset(node.prefix[:index])

	// If the path is empty, it means we don't create a 2nd child node.
	// Just assign the data for the existing node and store a single child node.
	if path == "" {
		node.data = data
		node.children[splitNode.prefix[0]-32] = splitNode
		return
	}

	node.children[splitNode.prefix[0]-32] = splitNode

	// Create new nodes with the remaining path
	node.append(path, data)
}

// clone clones the node with a new prefix.
func (node *tree) clone(prefix string) *tree {
	return &tree{
		prefix:    prefix,
		data:      node.data,
		children:  node.children,
		parameter: node.parameter,
		wildcard:  node.wildcard,
		kind:      node.kind,
	}
}

// reset resets the existing node data.
func (node *tree) reset(prefix string) {
	node.prefix = prefix
	node.data = nil
	node.parameter = nil
	node.wildcard = nil
	node.kind = 0
	node.children = [224]*tree{}
}

// addTrailingSlash adds a trailing slash with the same data.
func (node *tree) addTrailingSlash(data dataType) {
	if strings.HasSuffix(node.prefix, "/") || node.children[separator-32] != nil || node.kind == wildcard {
		return
	}

	node.children[separator-32] = &tree{
		prefix: "/",
		data:   data,
	}
}

// append appends the given path to the tree.
func (node *tree) append(path string, data dataType) {
	// At this point, all we know is that somewhere
	// in the remaining string we have parameters.
	// node: /user|
	// path: /user|/:userid
	for {
		if path == "" {
			node.data = data
			return
		}

		paramStart := strings.IndexByte(path, parameter)

		if paramStart == -1 {
			paramStart = strings.IndexByte(path, wildcard)
		}

		// If it's a static route we are adding,
		// just add the remainder as a normal node.
		if paramStart == -1 {
			// If the node itself doesn't have a prefix (root node),
			// don't add a child and use the node itself.
			if node.prefix == "" {
				node.prefix = path
				node.data = data
				return
			}

			child := &tree{
				prefix: path,
				data:   data,
			}

			node.children[path[0]-32] = child
			child.addTrailingSlash(data)
			return
		}

		// If we're directly in front of a parameter,
		// add a parameter node.
		if paramStart == 0 {
			paramEnd := strings.IndexByte(path, separator)

			if paramEnd == -1 {
				paramEnd = len(path)
			}

			child := &tree{
				prefix: path[1:paramEnd],
				kind:   path[paramStart],
			}

			switch child.kind {
			case parameter:
				child.addTrailingSlash(data)
				node.parameter = child
				node = child
				path = path[paramEnd:]
				continue

			case wildcard:
				child.data = data
				node.wildcard = child
				return
			}
		}

		// We know there's a parameter, but not directly at the start.

		// If the node itself doesn't have a prefix (root node),
		// don't add a child and use the node itself.
		if node.prefix == "" {
			node.prefix = path[:paramStart]
			path = path[paramStart:]
			continue
		}

		// Add a normal node with the path before the parameter start.
		child := &tree{
			prefix: path[:paramStart],
		}

		// Allow trailing slashes to return
		// the same content as their parent node.
		if child.prefix == "/" {
			child.data = node.data
		}

		node.children[path[0]-32] = child
		node = child
		path = path[paramStart:]
	}
}

// end is called when the node was fully parsed
// and needs to decide the next control flow.
func (node *tree) end(path string, data dataType, i int, offset int) (*tree, int, controlFlow) {
	child := node.children[path[i]-32]

	if child != nil {
		node = child
		offset = i
		return node, offset, controlNext
	}

	// No fitting children found, does this node even contain a prefix yet?
	// If no prefix is set, this is the starting node.
	if node.prefix == "" {
		node.append(path[i:], data)
		return node, offset, controlStop
	}

	// node: /user/|:id
	// path: /user/|:id/profile
	if node.parameter != nil {
		node = node.parameter
		offset = i
		return node, offset, controlBegin
	}

	node.append(path[i:], data)
	return node, offset, controlStop
}

// find finds the data for the given path and assigns it to ctx.handler, if available.
func (node *tree) find(path string, ctx *context) {
	var (
		i                  uint
		offset             uint
		lastWildcardOffset uint
		lastWildcard       *tree
	)

	// Search tree for equal parts until we can no longer proceed
	for {
		if node.kind == parameter {
			for {
				// We reached the end.
				if i == uint(len(path)) {
					ctx.addParameter(node.prefix, path[offset:i])
					ctx.handler = node.data
					return
				}

				// node: /:xxx|/:yyy
				// path: /blog|/post
				if path[i] == separator {
					ctx.addParameter(node.prefix, path[offset:i])
					node = node.children[separator-32]
					offset = i
					i++
					break
				}

				i++
			}

			continue
		}

		// We reached the end.
		if i == uint(len(path)) {
			// node: /blog|
			// path: /blog|
			if i-offset == uint(len(node.prefix)) {
				ctx.handler = node.data
				return
			}

			// node: /blog|feed
			// path: /blog|
			ctx.handler = nil
			return
		}

		// The node we just checked is entirely included in our path.
		// node: /|
		// path: /|blog
		if i-offset == uint(len(node.prefix)) {
			if node.wildcard != nil {
				lastWildcard = node.wildcard
				lastWildcardOffset = i
			}

			child := node.children[path[i]-32]

			if child != nil {
				node = child
				offset = i
				i++
				continue
			}

			// node: /|:id
			// path: /|blog
			if node.parameter != nil {
				node = node.parameter
				offset = i
				continue
			}

			// node: /|*any
			// path: /|image.png
			if node.wildcard != nil {
				ctx.addParameter(node.wildcard.prefix, path[i:])
				ctx.handler = node.wildcard.data
				return
			}

			ctx.handler = nil
			return
		}

		// We got a conflict.
		// node: /b|ag
		// path: /b|riefcase
		if path[i] != node.prefix[i-offset] {
			if lastWildcard != nil {
				ctx.addParameter(lastWildcard.prefix, path[lastWildcardOffset:])
				ctx.handler = lastWildcard.data
				return
			}

			ctx.handler = nil
			return
		}

		i++
	}
}

// each traverses the tree and calls the given function on every node.
func (node *tree) each(callback func(*tree)) {
	callback(node)

	for _, child := range node.children {
		if child == nil {
			continue
		}

		child.each(callback)
	}

	if node.parameter != nil {
		node.parameter.each(callback)
	}

	if node.wildcard != nil {
		node.wildcard.each(callback)
	}
}

// PrettyPrint prints a human-readable form of the tree to the given writer.
func (node *tree) PrettyPrint(writer io.Writer) {
	node.prettyPrint(writer, -1)
}

// prettyPrint
func (node *tree) prettyPrint(writer io.Writer, level int) {
	prefix := ""

	if level >= 0 {
		prefix = strings.Repeat("  ", level) + "|_ "
	}

	colorFunc := color.CyanString

	switch node.kind {
	case ':':
		prefix += ":"
		colorFunc = color.YellowString
	case '*':
		prefix += "*"
		colorFunc = color.GreenString
	}

	fmt.Fprintf(writer, "%s%s [%t]\n", prefix, colorFunc(node.prefix), node.data != nil)

	for _, child := range node.children {
		if child == nil {
			continue
		}

		child.prettyPrint(writer, level+1)
	}

	if node.parameter != nil {
		node.parameter.prettyPrint(writer, level+1)
	}

	if node.wildcard != nil {
		node.wildcard.prettyPrint(writer, level+1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"
)

// Goのflagパッケージで同名の引数を複数受け取る - Qiita
// http://qiita.com/hironobu_s/items/96e8397ec453dfb976d4
type strslice []string

func (s *strslice) String() string {
    return fmt.Sprintf("%v", *s)
}

func (s *strslice) Set(v string) error {
    *s = append(*s, v)
    return nil
}

func main() {
	var ignore_dirs strslice
	var empty_dirs strslice
	input_dir := flag.String( "top", ".", "tree TOP directory" )
	flag.Var( &ignore_dirs,  "xd", "eXclude Directory" )
	file_display := flag.Bool( "f", false, "Dispaly files" )
	flag.Var( &empty_dirs, "emd", "Behavior as empty directory" )
	flag.Parse()

	fmt.Println(*input_dir)
	tree(*input_dir, *input_dir, 0, "", *file_display, ignore_dirs, empty_dirs)
}

func tree(rootPath, searchPath string, depth int, parent string, file_display bool, ignore_dirs []string, empty_dirs []string) {

	searchName := filepath.Base(searchPath)
	for _, emd := range empty_dirs {
		if searchName == emd {
			// 空ディレクトリ扱いの場合、以降の処理は不要
			return
		}
	}

	fis, err := ioutil.ReadDir(searchPath)

	if err != nil {
		//fmt.Println( searchPath, " is error" )
		//panic(err)
		return
	}

	dirlist  := make([]string, 0)
	filelist := make([]string, 0)
	for _, fi := range fis {
		fullPath := filepath.Join(searchPath, fi.Name())

		if fi.IsDir() {
			ignore := false
			for _, ignore_dir := range ignore_dirs {
				if ignore_dir == fi.Name() {
					ignore = true
					break
				}
			}
			if !ignore {
				dirlist = append(dirlist, fullPath)
			}
		} else if file_display {
			filelist = append(filelist, fullPath)
		}
	}

	has_dir := ( 0 < len(dirlist) )
	for _, file := range filelist {
		rel, err := filepath.Rel(rootPath, file)

		if err != nil {
			//panic(err)
			return
		}

		base := filepath.Base(rel)

		if has_dir {
			fmt.Println(parent + "│  ", base )
		} else {
			fmt.Println(parent + "    ", base )
		}
	}
	if 0 < len(filelist) {
		if has_dir {
			fmt.Println(parent + "│" )
		} else {
			fmt.Println(strings.TrimRight(parent, " "))
		}
	}

	for idx, dir := range dirlist {
		rel, err := filepath.Rel(rootPath, dir)
		has_young_brother := ( 0 < len(dirlist[idx+1:]) )
		next := ""

		if err != nil {
			//panic(err)
			return
		}

		base := filepath.Base(rel)

		if has_young_brother {
			fmt.Println(parent + "├─", base )
			next += "│  "
		} else {
			fmt.Println(parent + "└─", base )
			next += "    "
		}
		tree(rootPath, dir, depth + 1, parent + next, file_display, ignore_dirs, empty_dirs)
	}

}
<commit_msg>Add comments<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"path/filepath"
	"strings"
)

// Goのflagパッケージで同名の引数を複数受け取る - Qiita
// http://qiita.com/hironobu_s/items/96e8397ec453dfb976d4
type strslice []string

func (s *strslice) String() string {
    return fmt.Sprintf("%v", *s)
}

func (s *strslice) Set(v string) error {
    *s = append(*s, v)
    return nil
}

func main() {
	var ignore_dirs strslice
	var empty_dirs strslice
	input_dir := flag.String( "top", ".", "tree TOP directory" )
	flag.Var( &ignore_dirs,  "xd", "eXclude Directory" )
	file_display := flag.Bool( "f", false, "Dispaly files" )
	flag.Var( &empty_dirs, "emd", "Behavior as empty directory" )
	flag.Parse()

	fmt.Println(*input_dir)
	tree(*input_dir, *input_dir, 0, "", *file_display, ignore_dirs, empty_dirs)
}

func tree(rootPath, searchPath string, depth int, parent string, file_display bool, ignore_dirs []string, empty_dirs []string) {

	searchName := filepath.Base(searchPath)
	for _, emd := range empty_dirs {
		if searchName == emd {
			// 空ディレクトリ扱いの場合、以降の処理は不要
			return
		}
	}

	fis, err := ioutil.ReadDir(searchPath)

	if err != nil {
		//fmt.Println( searchPath, " is error" )
		//panic(err)
		return
	}

	dirlist  := make([]string, 0)
	filelist := make([]string, 0)
	for _, fi := range fis {
		fullPath := filepath.Join(searchPath, fi.Name())

		if fi.IsDir() {
			// 無視ディレクトリチェック
			ignore := false
			for _, ignore_dir := range ignore_dirs {
				if ignore_dir == fi.Name() {
					ignore = true
					break
				}
			}
			if !ignore {
				// ディレクトリ追加
				dirlist = append(dirlist, fullPath)
			}
		} else if file_display {
			// ファイル追加
			filelist = append(filelist, fullPath)
		}
	}

	// ファイル処理
	has_dir := ( 0 < len(dirlist) )
	for _, file := range filelist {
		rel, err := filepath.Rel(rootPath, file)

		if err != nil {
			//panic(err)
			return
		}

		base := filepath.Base(rel)

		if has_dir {
			fmt.Println(parent + "│  ", base )
		} else {
			fmt.Println(parent + "    ", base )
		}
	}
	if 0 < len(filelist) {
		// ファイル名を出力すれば空行を追加
		if has_dir {
			fmt.Println(parent + "│" )
		} else {
			fmt.Println(strings.TrimRight(parent, " "))
		}
	}

	// ディレクトリ処理
	for idx, dir := range dirlist {
		rel, err := filepath.Rel(rootPath, dir)
		has_young_brother := ( 0 < len(dirlist[idx+1:]) )
		next := ""

		if err != nil {
			//panic(err)
			return
		}

		base := filepath.Base(rel)

		if has_young_brother {
			fmt.Println(parent + "├─", base )
			next += "│  "
		} else {
			fmt.Println(parent + "└─", base )
			next += "    "
		}
		tree(rootPath, dir, depth + 1, parent + next, file_display, ignore_dirs, empty_dirs)
	}

}
<|endoftext|>


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

// Package trie implements a byte trie with edge compression.
package trie

import (
	"bytes"
	"fmt"
)

// A Trie maintains a sorted collection of values keyed on a string.
// Insertion is O(len(key)). Unlike Go's built-in map there is no
// distinction between a nil and a non-existent value.
// The zero value for Trie is an empty trie ready to use.
type Trie struct {
	suffix   string
	value    interface{}
	children []Trie
	base     byte
}

// Find the largest i such that a[:i] == b[:i]
func commonPrefix(a, b string) int {
	l := len(a)
	if l > len(b) {
		l = len(b)
	}
	for i := 0; i < l; i++ {
		if a[i] != b[i] {
			return i
		}
	}
	return l
}

// Put inserts or replaces a value in the trie.  To remove a value
// insert nil.
func (t *Trie) Put(key string, value interface{}) {
	if t.children == nil && t.value == nil { // empty node
		t.suffix = key
		t.value = value
		return
	}

	s := commonPrefix(t.suffix, key)

	if s < len(t.suffix) {
		// split on s: turn t into a node with suffix[:s]
		// and move the contents to child[suffix[s]-t.base] with suffix[s+1:]
		// we save the extra alloc on the common case that we'd insert a subtrie
		// on key[s] immediately below by making children large enough
		newbase := t.suffix[s]
		newlen := 1
		if s < len(key) {
			for key[s] < newbase || int(key[s]) >= int(newbase)+newlen {
				newlen *= 2
				newbase &= ^byte(newlen - 1)
			}
		}
		newch := make([]Trie, newlen)
		newch[t.suffix[s]-newbase] = Trie{
			suffix:   t.suffix[s+1:],
			value:    t.value,
			children: t.children,
			base:     t.base,
		}

		t.suffix = t.suffix[:s]
		t.value = nil
		t.children = newch
		t.base = newbase
	}

	if s == len(key) {
		t.value = value
		return
	}

	if len(t.children) == 0 {
		t.children = make([]Trie, 1)
		t.base = key[s]
	} else {
		newbase := t.base
		newlen := len(t.children)
		for key[s] < newbase || int(key[s]) >= int(newbase)+newlen {
			newlen *= 2
			newbase &= ^byte(newlen - 1)
		}
		if newlen != len(t.children) {
			newch := make([]Trie, newlen)
			copy(newch[t.base-newbase:], t.children)
			t.children = newch
			t.base = newbase
		}
	}

	t.children[key[s]-t.base].Put(key[s+1:], value)

	return
}

// Get retrieves an element from the trie if it exists, or nil if it does not.
func (t *Trie) Get(key string) interface{} {
	s := commonPrefix(t.suffix, key)

	if s < len(t.suffix) {
		return nil
	}

	if s == len(key) {
		return t.value
	}

	if key[s] < t.base || int(key[s]) > int(t.base)+len(t.children) {
		return nil
	}

	return t.children[key[s]-t.base].Get(key[s+1:])
}

// FindPfx finds the longest prefix of key in the trie that has a non-nil value.
func (t *Trie) FindPfx(key string) (pfx string, val interface{}) {
	s := commonPrefix(t.suffix, key)

	if s < len(t.suffix) {
		return "", nil
	}

	if s == len(key) { // and s == len(t.suffix) , so key = t.suffix
		if t.value != nil {
			return t.suffix, t.value
		}
		return "", nil
	}
	// there's a bit of key left over.  if it is out of range, we're the longest prefix

	if key[s] < t.base || int(key[s]) > int(t.base)+len(t.children) {
		if t.value != nil {
			return t.suffix, t.value
		}
		return "", nil
	}

	p, v := t.children[key[s]-t.base].FindPfx(key[s+1:])
	if v != nil {
		return key[:s+1] + p, v
	}

	if t.value != nil {
		return t.suffix, t.value
	}
	return "", nil
}

// subtrie retrieves the part of t that has key as a prefix.
// and the part of its suffix that should be tacked on to key
func (t *Trie) subtrie(key string) (*Trie, int) {
	s := commonPrefix(t.suffix, key)

	if s == len(key) {
		return t, s
	}

	if s < len(t.suffix) {
		return nil, 0
	}

	// s == len(suffix) but s < len(key): there's a bit of key left over

	if key[s] < t.base || int(key[s]) > int(t.base)+len(t.children) {
		return nil, 0
	}

	return t.children[key[s]-t.base].subtrie(key[s+1:])
}

func (t *Trie) forEach(f func([]byte, interface{}) bool, buf *bytes.Buffer) bool {
	if t.value == nil && t.children == nil {
		return true
	}

	pfx := buf.Len()
	buf.WriteString(t.suffix)

	if t.value != nil && !f(buf.Bytes(), t.value) { // this is the alloc (probably)
		return false
	}

	if t.children != nil {
		l := buf.Len()
		buf.WriteByte(t.base)
		for _, v := range t.children {
			if !v.forEach(f, buf) {
				return false
			}
			buf.Bytes()[l]++
		}
	}

	buf.Truncate(pfx)

	return true
}

// ForEach will apply the function f to each key, value pair in the
// Trie in sorted (depth-first pre-)order.  if f returns false, the
// iteration will stop.
func (t *Trie) ForEach(f func(string, interface{}) bool) {
	var buf bytes.Buffer
	t.forEach(func(b []byte, v interface{}) bool { return f(string(b), v) }, &buf)
}

// ForEachB will apply the function f to each key, value pair in the
// Trie in sorted (depth-first pre-)order.  if f returns false, the
// iteration will stop.
func (t *Trie) ForEachB(f func([]byte, interface{}) bool) {
	var buf bytes.Buffer
	t.forEach(f, &buf)
}

// ForEachPfx applies ForEach to the sub-trie that starts with the given prefix.
func (t *Trie) ForEachPfx(pfx string, f func(string, interface{}) bool) {
	t, sfx := t.subtrie(pfx)
	if t == nil {
		return
	}
	var buf bytes.Buffer
	buf.Grow(len(pfx))
	buf.WriteString(pfx[:len(pfx)-sfx])
	t.forEach(func(b []byte, v interface{}) bool { return f(string(b), v) }, &buf)
}

// String returns a multiline string representation of the trie
// in the form
//    trie[
//       key1: value1
//       key2: value2
//       ....
//    ]
func (t *Trie) String() string {
	var buf bytes.Buffer
	buf.WriteString("trie{\n")
	t.ForEach(func(key string, val interface{}) bool {
		fmt.Fprintf(&buf, "\t%s:%v\n", key, val)
		return true
	})
	buf.WriteString("}")
	return buf.String()
}

// debug
const spaces = "                                                                                "

func (t *Trie) dump(level int) {
	if level > len(spaces) {
		level = len(spaces)
	}
	fmt.Printf("%s: %v\n", t.suffix, t.value)
	if t.children != nil {
		fmt.Printf("%s<%d>\n", spaces[:4*level], len(t.children))
	}
	c := t.base
	for _, ch := range t.children {
		if ch.value != nil || ch.children != nil {
			if c >= 32 && c < 128 {
				fmt.Printf("%s['%c']", spaces[:4*level], c)
			} else {
				fmt.Printf("%s[%d]", spaces[:4*level], c)
			}
			ch.dump(level + 1)
		}
		c++
	}
}

func (t *Trie) shape() (ln, sz int) {
	if t.value != nil {
		ln++
	}
	sz++
	for _, c := range t.children {
		l, s := c.shape()
		ln += l
		sz += s
	}
	return
}
<commit_msg>Fixed embarrasing bug<commit_after>// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package trie implements a byte trie with edge compression.
package trie

import (
	"bytes"
	"fmt"
)

// A Trie maintains a sorted collection of values keyed on a string.
// Insertion is O(len(key)). Unlike Go's built-in map there is no
// distinction between a nil and a non-existent value.
// The zero value for Trie is an empty trie ready to use.
type Trie struct {
	suffix   string
	value    interface{}
	children []Trie
	base     byte
}

// Find the largest i such that a[:i] == b[:i]
func commonPrefix(a, b string) int {
	l := len(a)
	if l > len(b) {
		l = len(b)
	}
	for i := 0; i < l; i++ {
		if a[i] != b[i] {
			return i
		}
	}
	return l
}

// Put inserts or replaces a value in the trie.  To remove a value
// insert nil.
func (t *Trie) Put(key string, value interface{}) {
	if t.children == nil && t.value == nil { // empty node
		t.suffix = key
		t.value = value
		return
	}

	s := commonPrefix(t.suffix, key)

	if s < len(t.suffix) {
		// split on s: turn t into a node with suffix[:s]
		// and move the contents to child[suffix[s]-t.base] with suffix[s+1:]
		// we save the extra alloc on the common case that we'd insert a subtrie
		// on key[s] immediately below by making children large enough
		newbase := t.suffix[s]
		newlen := 1
		if s < len(key) {
			for key[s] < newbase || int(key[s]) >= int(newbase)+newlen {
				newlen *= 2
				newbase &= ^byte(newlen - 1)
			}
		}
		newch := make([]Trie, newlen)
		newch[t.suffix[s]-newbase] = Trie{
			suffix:   t.suffix[s+1:],
			value:    t.value,
			children: t.children,
			base:     t.base,
		}

		t.suffix = t.suffix[:s]
		t.value = nil
		t.children = newch
		t.base = newbase
	}

	if s == len(key) {
		t.value = value
		return
	}

	if len(t.children) == 0 {
		t.children = make([]Trie, 1)
		t.base = key[s]
	} else {
		newbase := t.base
		newlen := len(t.children)
		for key[s] < newbase || int(key[s]) >= int(newbase)+newlen {
			newlen *= 2
			newbase &= ^byte(newlen - 1)
		}
		if newlen != len(t.children) {
			newch := make([]Trie, newlen)
			copy(newch[t.base-newbase:], t.children)
			t.children = newch
			t.base = newbase
		}
	}

	t.children[key[s]-t.base].Put(key[s+1:], value)

	return
}

// Get retrieves an element from the trie if it exists, or nil if it does not.
func (t *Trie) Get(key string) interface{} {
	s := commonPrefix(t.suffix, key)

	if s < len(t.suffix) {
		return nil
	}

	if s == len(key) {
		return t.value
	}

	if key[s] < t.base || int(key[s]) >= int(t.base)+len(t.children) {
		return nil
	}

	return t.children[key[s]-t.base].Get(key[s+1:])
}

// FindPfx finds the longest prefix of key in the trie that has a non-nil value.
func (t *Trie) FindPfx(key string) (pfx string, val interface{}) {
	s := commonPrefix(t.suffix, key)

	if s < len(t.suffix) {
		return "", nil
	}

	if s == len(key) { // and s == len(t.suffix) , so key = t.suffix
		if t.value != nil {
			return t.suffix, t.value
		}
		return "", nil
	}
	// there's a bit of key left over.  if it is out of range, we're the longest prefix

	if key[s] < t.base || int(key[s]) >= int(t.base)+len(t.children) {
		if t.value != nil {
			return t.suffix, t.value
		}
		return "", nil
	}

	p, v := t.children[key[s]-t.base].FindPfx(key[s+1:])
	if v != nil {
		return key[:s+1] + p, v
	}

	if t.value != nil {
		return t.suffix, t.value
	}
	return "", nil
}

// subtrie retrieves the part of t that has key as a prefix.
// and the part of its suffix that should be tacked on to key
func (t *Trie) subtrie(key string) (*Trie, int) {
	s := commonPrefix(t.suffix, key)

	if s == len(key) {
		return t, s
	}

	if s < len(t.suffix) {
		return nil, 0
	}

	// s == len(suffix) but s < len(key): there's a bit of key left over

	if key[s] < t.base || int(key[s]) >= int(t.base)+len(t.children) {
		return nil, 0
	}

	return t.children[key[s]-t.base].subtrie(key[s+1:])
}

func (t *Trie) forEach(f func([]byte, interface{}) bool, buf *bytes.Buffer) bool {
	if t.value == nil && t.children == nil {
		return true
	}

	pfx := buf.Len()
	buf.WriteString(t.suffix)

	if t.value != nil && !f(buf.Bytes(), t.value) { // this is the alloc (probably)
		return false
	}

	if t.children != nil {
		l := buf.Len()
		buf.WriteByte(t.base)
		for _, v := range t.children {
			if !v.forEach(f, buf) {
				return false
			}
			buf.Bytes()[l]++
		}
	}

	buf.Truncate(pfx)

	return true
}

// ForEach will apply the function f to each key, value pair in the
// Trie in sorted (depth-first pre-)order.  if f returns false, the
// iteration will stop.
func (t *Trie) ForEach(f func(string, interface{}) bool) {
	var buf bytes.Buffer
	t.forEach(func(b []byte, v interface{}) bool { return f(string(b), v) }, &buf)
}

// ForEachB will apply the function f to each key, value pair in the
// Trie in sorted (depth-first pre-)order.  if f returns false, the
// iteration will stop.
func (t *Trie) ForEachB(f func([]byte, interface{}) bool) {
	var buf bytes.Buffer
	t.forEach(f, &buf)
}

// ForEachPfx applies ForEach to the sub-trie that starts with the given prefix.
func (t *Trie) ForEachPfx(pfx string, f func(string, interface{}) bool) {
	t, sfx := t.subtrie(pfx)
	if t == nil {
		return
	}
	var buf bytes.Buffer
	buf.Grow(len(pfx))
	buf.WriteString(pfx[:len(pfx)-sfx])
	t.forEach(func(b []byte, v interface{}) bool { return f(string(b), v) }, &buf)
}

// String returns a multiline string representation of the trie
// in the form
//    trie[
//       key1: value1
//       key2: value2
//       ....
//    ]
func (t *Trie) String() string {
	var buf bytes.Buffer
	buf.WriteString("trie{\n")
	t.ForEach(func(key string, val interface{}) bool {
		fmt.Fprintf(&buf, "\t%s:%v\n", key, val)
		return true
	})
	buf.WriteString("}")
	return buf.String()
}

// debug
const spaces = "                                                                                "

func (t *Trie) dump(level int) {
	if level > len(spaces) {
		level = len(spaces)
	}
	fmt.Printf("%s: %v\n", t.suffix, t.value)
	if t.children != nil {
		fmt.Printf("%s<%d>\n", spaces[:4*level], len(t.children))
	}
	c := t.base
	for _, ch := range t.children {
		if ch.value != nil || ch.children != nil {
			if c >= 32 && c < 128 {
				fmt.Printf("%s['%c']", spaces[:4*level], c)
			} else {
				fmt.Printf("%s[%d]", spaces[:4*level], c)
			}
			ch.dump(level + 1)
		}
		c++
	}
}

func (t *Trie) shape() (ln, sz int) {
	if t.value != nil {
		ln++
	}
	sz++
	for _, c := range t.children {
		l, s := c.shape()
		ln += l
		sz += s
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 conn

import (
	"fmt"
	"github.com/jacobsa/aws"
	"github.com/jacobsa/aws/time"
)

const (
	iso8601Format = "2006-01-02T15:04:05Z"
)

// A connection to the SimpleDB service.
type Conn interface {
	// Send the supplied request to the service, taking care of adding
	// appropriate authentication info.
	SendRequest(req Request) (resp []byte, err error)
}

// Create a connection using the supplied dependencies.
func NewConn(
	key aws.AccessKey,
	httpConn HttpConn,
	signer Signer,
	clock time.Clock) (Conn, error) {
	return &conn{key, httpConn, signer, clock}, nil
}

type conn struct {
	key aws.AccessKey
	httpConn HttpConn
	signer Signer
	clock time.Clock
}

func (c *conn) SendRequest(req Request) (resp []byte, err error) {
	// Make a copy of the request that we can modify below.
	originalReq := req
	req = Request{}
	for key, val := range originalReq {
		req[key] = val
	}

	// Set authentication info.
	req["AWSAccessKeyId"] = c.key.Id
	req["Timestamp"] = c.clock.Now().Format(iso8601Format)
	req["SignatureVersion"] = "2"
	req["SignatureMethod"] = "HmacSHA1"

	// Sign the request.
	if err = c.signer.SignRequest(req); err != nil {
		err = fmt.Errorf("SignRequest: %v", err)
		return
	}

	// Send the request.
	httpResp, err := c.httpConn.SendRequest(req)
	if err != nil {
		err = fmt.Errorf("SendRequest: %v", err)
		return
	}

	// Did the server return an error?
	if httpResp.StatusCode != 200 {
		err = fmt.Errorf(
			"Error from server (%d): %s",
			httpResp.StatusCode,
			httpResp.Body)

		return
	}

	return httpResp.Body, nil
}
<commit_msg>Fixed formatting.<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// 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 conn

import (
	"fmt"
	"github.com/jacobsa/aws"
	"github.com/jacobsa/aws/time"
)

const (
	iso8601Format = "2006-01-02T15:04:05Z"
)

// A connection to the SimpleDB service.
type Conn interface {
	// Send the supplied request to the service, taking care of adding
	// appropriate authentication info.
	SendRequest(req Request) (resp []byte, err error)
}

// Create a connection using the supplied dependencies.
func NewConn(
	key aws.AccessKey,
	httpConn HttpConn,
	signer Signer,
	clock time.Clock) (Conn, error) {
	return &conn{key, httpConn, signer, clock}, nil
}

type conn struct {
	key      aws.AccessKey
	httpConn HttpConn
	signer   Signer
	clock    time.Clock
}

func (c *conn) SendRequest(req Request) (resp []byte, err error) {
	// Make a copy of the request that we can modify below.
	originalReq := req
	req = Request{}
	for key, val := range originalReq {
		req[key] = val
	}

	// Set authentication info.
	req["AWSAccessKeyId"] = c.key.Id
	req["Timestamp"] = c.clock.Now().Format(iso8601Format)
	req["SignatureVersion"] = "2"
	req["SignatureMethod"] = "HmacSHA1"

	// Sign the request.
	if err = c.signer.SignRequest(req); err != nil {
		err = fmt.Errorf("SignRequest: %v", err)
		return
	}

	// Send the request.
	httpResp, err := c.httpConn.SendRequest(req)
	if err != nil {
		err = fmt.Errorf("SendRequest: %v", err)
		return
	}

	// Did the server return an error?
	if httpResp.StatusCode != 200 {
		err = fmt.Errorf(
			"Error from server (%d): %s",
			httpResp.StatusCode,
			httpResp.Body)

		return
	}

	return httpResp.Body, nil
}
<|endoftext|>


<commit_before>package evacuation

import (
	"errors"
	"os"
	"time"

	"code.cloudfoundry.org/bbs"
	"code.cloudfoundry.org/bbs/models"
	"code.cloudfoundry.org/clock"
	loggingclient "code.cloudfoundry.org/diego-logging-client"
	"code.cloudfoundry.org/executor"
	"code.cloudfoundry.org/lager"
)

const (
	ExitTimeout = 15 * time.Second
)

var strandedEvacuatingActualLRPs = "StrandedEvacuatingActualLRPs"

type EvacuationCleanup struct {
	clock          clock.Clock
	logger         lager.Logger
	cellID         string
	bbsClient      bbs.InternalClient
	executorClient executor.Client
	metronClient   loggingclient.IngressClient
}

func NewEvacuationCleanup(
	logger lager.Logger,
	cellID string,
	bbsClient bbs.InternalClient,
	executorClient executor.Client,
	clock clock.Clock,
	metronClient loggingclient.IngressClient,
) *EvacuationCleanup {
	return &EvacuationCleanup{
		logger:         logger,
		cellID:         cellID,
		bbsClient:      bbsClient,
		executorClient: executorClient,
		clock:          clock,
		metronClient:   metronClient,
	}
}

func (e *EvacuationCleanup) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := e.logger.Session("evacuation-cleanup")

	logger.Info("started")
	defer logger.Info("complete")

	close(ready)

	select {
	case signal := <-signals:
		logger.Info("signalled", lager.Data{"signal": signal})
	}

	actualLRPGroups, err := e.bbsClient.ActualLRPGroups(logger, models.ActualLRPFilter{CellID: e.cellID})
	if err != nil {
		logger.Error("failed-fetching-actual-lrp-groups", err)
		return err
	}

	strandedEvacuationCount := 0
	for _, group := range actualLRPGroups {
		if group.Evacuating == nil {
			continue
		}

		strandedEvacuationCount++
		actualLRP := group.Evacuating
		err = e.bbsClient.RemoveEvacuatingActualLRP(logger, &actualLRP.ActualLRPKey, &actualLRP.ActualLRPInstanceKey)
		if err != nil {
			logger.Error("failed-removing-evacuating-actual-lrp", err, lager.Data{"lrp-key": actualLRP.ActualLRPKey})
		}
	}

	err = e.metronClient.SendMetric(strandedEvacuatingActualLRPs, strandedEvacuationCount)
	if err != nil {
		logger.Error("failed-sending-stranded-evacuating-lrp-metric", err, lager.Data{"count": strandedEvacuationCount})
	}

	logger.Info("finished-evacuating", lager.Data{"stranded-evacuating-actual-lrps": strandedEvacuationCount})

	logger.Info("stopping-all-containers")

	exitTimer := e.clock.NewTimer(ExitTimeout)
	checkRunningContainersTimer := e.clock.NewTicker(1 * time.Second)
	containersSignalled := make(chan struct{})
	containersStopped := make(chan struct{})
	go e.signalRunningContainers(logger, containersSignalled)
	go e.checkRunningContainers(logger, checkRunningContainersTimer.C(), containersSignalled, containersStopped)

	select {
	case <-exitTimer.C():
		// exit after ExitTimeout has passed
		logger.Info("failed-to-cleanup-all-containers")
		return errors.New("failed-to-cleanup-all-containers")
	case <-containersStopped:
		logger.Info("stopped-containers-successfully")
		return nil
	}
}

func (e *EvacuationCleanup) checkRunningContainers(
	logger lager.Logger,
	ticker <-chan time.Time,
	containersSignalled <-chan struct{},
	containersStopped chan<- struct{},
) {
	hasRunningContainers := func() bool {
		containers, err := e.executorClient.ListContainers(logger)
		if err != nil {
			logger.Error("failed-listing-containers", err)
			// assume no container is running if we can't list them
			return false
		}

		for _, container := range containers {
			if container.State == executor.StateRunning {
				return true
			}
		}

		return false
	}

	defer close(containersStopped)

	// wait for all containers to be signalled, this only makes the tests easier
	// to write since they depend on the signalling and checking to happen
	// sequentially, but isn't necessary for the operation of the cleanup
	<-containersSignalled
	for hasRunningContainers() {
		logger.Info("waiting-for-containers-to-stop")
		<-ticker
	}
}

func (e *EvacuationCleanup) signalRunningContainers(logger lager.Logger, containersSignalled chan<- struct{}) {
	defer close(containersSignalled)

	containers, err := e.executorClient.ListContainers(logger)
	if err != nil {
		logger.Error("failed-listing-containers", err)
		return
	}

	logger.Info("sending-signal-to-containers")

	for _, container := range containers {
		e.executorClient.StopContainer(logger, container.Guid)
	}

	logger.Info("sent-signal-to-containers")
}
<commit_msg>Rename metrics constants to follow convention<commit_after>package evacuation

import (
	"errors"
	"os"
	"time"

	"code.cloudfoundry.org/bbs"
	"code.cloudfoundry.org/bbs/models"
	"code.cloudfoundry.org/clock"
	loggingclient "code.cloudfoundry.org/diego-logging-client"
	"code.cloudfoundry.org/executor"
	"code.cloudfoundry.org/lager"
)

const (
	ExitTimeout = 15 * time.Second
)

var strandedEvacuatingActualLRPsMetric = "StrandedEvacuatingActualLRPs"

type EvacuationCleanup struct {
	clock          clock.Clock
	logger         lager.Logger
	cellID         string
	bbsClient      bbs.InternalClient
	executorClient executor.Client
	metronClient   loggingclient.IngressClient
}

func NewEvacuationCleanup(
	logger lager.Logger,
	cellID string,
	bbsClient bbs.InternalClient,
	executorClient executor.Client,
	clock clock.Clock,
	metronClient loggingclient.IngressClient,
) *EvacuationCleanup {
	return &EvacuationCleanup{
		logger:         logger,
		cellID:         cellID,
		bbsClient:      bbsClient,
		executorClient: executorClient,
		clock:          clock,
		metronClient:   metronClient,
	}
}

func (e *EvacuationCleanup) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
	logger := e.logger.Session("evacuation-cleanup")

	logger.Info("started")
	defer logger.Info("complete")

	close(ready)

	select {
	case signal := <-signals:
		logger.Info("signalled", lager.Data{"signal": signal})
	}

	actualLRPGroups, err := e.bbsClient.ActualLRPGroups(logger, models.ActualLRPFilter{CellID: e.cellID})
	if err != nil {
		logger.Error("failed-fetching-actual-lrp-groups", err)
		return err
	}

	strandedEvacuationCount := 0
	for _, group := range actualLRPGroups {
		if group.Evacuating == nil {
			continue
		}

		strandedEvacuationCount++
		actualLRP := group.Evacuating
		err = e.bbsClient.RemoveEvacuatingActualLRP(logger, &actualLRP.ActualLRPKey, &actualLRP.ActualLRPInstanceKey)
		if err != nil {
			logger.Error("failed-removing-evacuating-actual-lrp", err, lager.Data{"lrp-key": actualLRP.ActualLRPKey})
		}
	}

	err = e.metronClient.SendMetric(strandedEvacuatingActualLRPsMetric, strandedEvacuationCount)
	if err != nil {
		logger.Error("failed-sending-stranded-evacuating-lrp-metric", err, lager.Data{"count": strandedEvacuationCount})
	}

	logger.Info("finished-evacuating", lager.Data{"stranded-evacuating-actual-lrps": strandedEvacuationCount})

	logger.Info("stopping-all-containers")

	exitTimer := e.clock.NewTimer(ExitTimeout)
	checkRunningContainersTimer := e.clock.NewTicker(1 * time.Second)
	containersSignalled := make(chan struct{})
	containersStopped := make(chan struct{})
	go e.signalRunningContainers(logger, containersSignalled)
	go e.checkRunningContainers(logger, checkRunningContainersTimer.C(), containersSignalled, containersStopped)

	select {
	case <-exitTimer.C():
		// exit after ExitTimeout has passed
		logger.Info("failed-to-cleanup-all-containers")
		return errors.New("failed-to-cleanup-all-containers")
	case <-containersStopped:
		logger.Info("stopped-containers-successfully")
		return nil
	}
}

func (e *EvacuationCleanup) checkRunningContainers(
	logger lager.Logger,
	ticker <-chan time.Time,
	containersSignalled <-chan struct{},
	containersStopped chan<- struct{},
) {
	hasRunningContainers := func() bool {
		containers, err := e.executorClient.ListContainers(logger)
		if err != nil {
			logger.Error("failed-listing-containers", err)
			// assume no container is running if we can't list them
			return false
		}

		for _, container := range containers {
			if container.State == executor.StateRunning {
				return true
			}
		}

		return false
	}

	defer close(containersStopped)

	// wait for all containers to be signalled, this only makes the tests easier
	// to write since they depend on the signalling and checking to happen
	// sequentially, but isn't necessary for the operation of the cleanup
	<-containersSignalled
	for hasRunningContainers() {
		logger.Info("waiting-for-containers-to-stop")
		<-ticker
	}
}

func (e *EvacuationCleanup) signalRunningContainers(logger lager.Logger, containersSignalled chan<- struct{}) {
	defer close(containersSignalled)

	containers, err := e.executorClient.ListContainers(logger)
	if err != nil {
		logger.Error("failed-listing-containers", err)
		return
	}

	logger.Info("sending-signal-to-containers")

	for _, container := range containers {
		e.executorClient.StopContainer(logger, container.Guid)
	}

	logger.Info("sent-signal-to-containers")
}
<|endoftext|>


<commit_before>package eveConsumer

import (
	"errors"
	"fmt"
	"log"
	"strconv"
	"strings"

	"github.com/antihax/evedata/models"
	"github.com/garyburd/redigo/redis"
)

func init() {
	addConsumer("wallets", walletsConsumer, "EVEDATA_walletQueue")
	addTrigger("wallets", walletsTrigger)
}

// Perform contact sync for wardecs
func walletsTrigger(c *EVEConsumer) (bool, error) {

	// Gather characters for update. Group for optimized updating.
	rows, err := c.ctx.Db.Query(
		`SELECT characterID, tokenCharacterID FROM evedata.crestTokens WHERE
		walletCacheUntil < UTC_TIMESTAMP() AND lastStatus NOT LIKE "%400 Bad Request%" AND
		scopes LIKE "%characterWalletRead%";`)
	if err != nil {
		log.Printf("Wallets: Failed query: %v", err)
		return false, err
	}
	defer rows.Close()

	r := c.ctx.Cache.Get()
	defer r.Close()
	// Loop updatable characters
	for rows.Next() {
		var (
			char      int64 // Source char
			tokenChar int64 // Token Char
		)

		err = rows.Scan(&char, &tokenChar)
		if err != nil {
			log.Printf("Wallets: Failed scan: %v", err)
			continue
		}
		_, err = r.Do("SADD", "EVEDATA_walletQueue", fmt.Sprintf("%d:%d", char, tokenChar))
		if err != nil {
			log.Printf("Wallets: Failed scan: %v", err)
			continue
		}
	}

	return true, err
}

func walletsConsumer(c *EVEConsumer, redisPtr *redis.Conn) (bool, error) {
	r := *redisPtr
	ret, err := r.Do("SPOP", "EVEDATA_walletQueue")
	if err != nil {
		return false, err
	} else if ret == nil {
		return false, nil
	}

	v, err := redis.String(ret, err)
	if err != nil {
		return false, err
	}

	dest := strings.Split(v, ":")

	if len(dest) != 2 {
		return false, errors.New("Invalid wallet string")
	}

	char, err := strconv.ParseInt(dest[0], 10, 64)
	if err != nil {
		return false, err
	}
	tokenChar, err := strconv.ParseInt(dest[1], 10, 64)
	if err != nil {
		return false, err
	}

	token, err := c.getToken(char, tokenChar)
	if err != nil {
		return false, err
	}

	var fromID int64 = 0
	for {
		wallets, err := c.ctx.ESI.EVEAPI.CharacterWalletJournalXML(token, (int64)(tokenChar), fromID)
		if err != nil {
			tokenError(char, tokenChar, nil, err)
			return false, err
		} else {
			tokenSuccess(char, tokenChar, 200, "OK")
		}
		// there are no entries in this journal page.
		if len(wallets.Entries) == 0 {
			break
		}

		tx, err := models.Begin()
		if err != nil {
			return false, err
		}

		var values []string

		for _, wallet := range wallets.Entries {
			if wallet.RefID < fromID || fromID == 0 {
				fromID = wallet.RefID
			}
			values = append(values, fmt.Sprintf("(%d,%d,%d,%d,%d,%d,%q,%f,%f,%q,%d,%f,%q)",
				tokenChar, wallet.RefID, wallet.RefTypeID, wallet.OwnerID1, wallet.OwnerID2,
				wallet.ArgID1, wallet.ArgName1, wallet.Amount, wallet.Balance,
				wallet.Reason, wallet.TaxReceiverID, wallet.TaxAmount, wallet.Date.UTC().Format(models.SQLTimeFormat)))
			if err != nil {
				log.Printf("Wallets: %v %d\n", err, wallet.ArgID1)
				break
			}
		}

		stmt := fmt.Sprintf(`INSERT INTO evedata.walletJournal
								(characterID, refID, refTypeID, ownerID1, ownerID2,
								argID1, argName1, amount, balance,
								reason, taxReceiverID, taxAmount, date)
								VALUES %s ON DUPLICATE KEY UPDATE characterID=characterID;`, strings.Join(values, ",\n"))

		_, err = tx.Exec(stmt)
		if err != nil {
			return false, err
		}

		_, err = tx.Exec(`UPDATE evedata.crestTokens SET walletCacheUntil = ?
							WHERE characterID = ? AND tokenCharacterID = ?`,
			wallets.CachedUntil.UTC(), char, tokenChar)
		if err != nil {
			log.Printf("Wallets: %v\n", err)
			break
		}

		err = models.RetryTransaction(tx)
		if err != nil {
			log.Printf("%s", err)
			return false, err
		}
	}

	fromID = 0
	for {
		transactions, err := c.ctx.ESI.EVEAPI.CharacterWalletTransactionXML(token, (int64)(tokenChar), fromID)
		if err != nil || transactions == nil {
			tokenError(char, tokenChar, nil, err)
			return false, err
		} else {
			tokenSuccess(char, tokenChar, 200, "OK")
		}
		// there are no entries in this journal page.
		if len(transactions.Entries) == 0 {
			break
		}

		tx, err := models.Begin()
		if err != nil {
			return false, err
		}

		var values []string

		for _, transaction := range transactions.Entries {
			if transaction.TransactionID < fromID || fromID == 0 {
				fromID = transaction.TransactionID
			}

			values = append(values, fmt.Sprintf("(%d,%d,%d,%d,%f,%d,%d,%q,%q,%d,%q,%d)",
				tokenChar, transaction.TransactionID, transaction.Quantity, transaction.TypeID, transaction.Price,
				transaction.ClientID, transaction.StationID, transaction.TransactionType,
				transaction.TransactionFor, transaction.JournalTransactionID, transaction.TransactionDateTime.UTC().Format(models.SQLTimeFormat), transaction.ClientTypeID))
		}

		stmt := fmt.Sprintf(`INSERT INTO evedata.walletTransactions
								(characterID, transactionID, quantity, typeID, price,
								clientID,  stationID, transactionType,
								transactionFor, journalTransactionID, transactionDateTime, clientTypeID)
								VALUES %s ON DUPLICATE KEY UPDATE characterID=characterID;`, strings.Join(values, ",\n"))

		_, err = tx.Exec(stmt)
		if err != nil {
			return false, err
		}

		_, err = tx.Exec(`UPDATE evedata.crestTokens SET walletCacheUntil = ?
							WHERE characterID = ? AND tokenCharacterID = ?`,
			transactions.CachedUntil.UTC(), char, tokenChar)
		if err != nil {
			log.Printf("Wallets: %v\n", err)
			break
		}

		err = models.RetryTransaction(tx)
		if err != nil {
			log.Printf("%s", err)
			return false, err
		}
	}

	return true, err
}
<commit_msg>fix wallet journal with nil tax information.<commit_after>package eveConsumer

import (
	"errors"
	"fmt"
	"log"
	"strconv"
	"strings"

	"github.com/antihax/evedata/models"
	"github.com/garyburd/redigo/redis"
)

func init() {
	addConsumer("wallets", walletsConsumer, "EVEDATA_walletQueue")
	addTrigger("wallets", walletsTrigger)
}

// Perform contact sync for wardecs
func walletsTrigger(c *EVEConsumer) (bool, error) {

	// Gather characters for update. Group for optimized updating.
	rows, err := c.ctx.Db.Query(
		`SELECT characterID, tokenCharacterID FROM evedata.crestTokens WHERE
		walletCacheUntil < UTC_TIMESTAMP() AND lastStatus NOT LIKE "%400 Bad Request%" AND
		scopes LIKE "%characterWalletRead%";`)
	if err != nil {
		log.Printf("Wallets: Failed query: %v", err)
		return false, err
	}
	defer rows.Close()

	r := c.ctx.Cache.Get()
	defer r.Close()
	// Loop updatable characters
	for rows.Next() {
		var (
			char      int64 // Source char
			tokenChar int64 // Token Char
		)

		err = rows.Scan(&char, &tokenChar)
		if err != nil {
			log.Printf("Wallets: Failed scan: %v", err)
			continue
		}
		_, err = r.Do("SADD", "EVEDATA_walletQueue", fmt.Sprintf("%d:%d", char, tokenChar))
		if err != nil {
			log.Printf("Wallets: Failed scan: %v", err)
			continue
		}
	}

	return true, err
}

func walletsConsumer(c *EVEConsumer, redisPtr *redis.Conn) (bool, error) {
	r := *redisPtr
	ret, err := r.Do("SPOP", "EVEDATA_walletQueue")
	if err != nil {
		return false, err
	} else if ret == nil {
		return false, nil
	}

	v, err := redis.String(ret, err)
	if err != nil {
		return false, errors.New(fmt.Sprintf("error collecting redis string %s string: %s", err, v))
	}

	dest := strings.Split(v, ":")

	if len(dest) != 2 {
		return false, errors.New("Invalid wallet string")
	}

	char, err := strconv.ParseInt(dest[0], 10, 64)
	if err != nil {
		return false, errors.New(fmt.Sprintf("%s string: %s", err, v))
	}
	tokenChar, err := strconv.ParseInt(dest[1], 10, 64)
	if err != nil {
		return false, errors.New(fmt.Sprintf("%s string: %s", err, v))
	}

	token, err := c.getToken(char, tokenChar)
	if err != nil {
		return false, errors.New(fmt.Sprintf("%s string: %s", err, v))
	}

	var fromID int64 = 0
	for {
		wallets, err := c.ctx.ESI.EVEAPI.CharacterWalletJournalXML(token, tokenChar, fromID)
		if err != nil {
			tokenError(char, tokenChar, nil, err)
			return false, errors.New(fmt.Sprintf("%s %d %d", err, tokenChar, fromID))
		} else {
			tokenSuccess(char, tokenChar, 200, "OK")
		}
		// there are no entries in this journal page.
		if len(wallets.Entries) == 0 {
			break
		}

		tx, err := models.Begin()
		if err != nil {
			return false, err
		}

		var values []string

		for _, wallet := range wallets.Entries {
			if wallet.RefID < fromID || fromID == 0 {
				fromID = wallet.RefID
			}

			values = append(values, fmt.Sprintf("(%d,%d,%d,%d,%d,%d,%q,%f,%f,%q,%d,%f,%q)",
				tokenChar, wallet.RefID, wallet.RefTypeID, wallet.OwnerID1, wallet.OwnerID2,
				wallet.ArgID1, wallet.ArgName1, wallet.Amount, wallet.Balance,
				wallet.Reason, wallet.TaxReceiverID.Int64, wallet.TaxAmount.Float64, wallet.Date.UTC().Format(models.SQLTimeFormat)))
			if err != nil {
				log.Printf("Wallets: %v %d\n", err, wallet.ArgID1)
				break
			}
		}

		stmt := fmt.Sprintf(`INSERT INTO evedata.walletJournal
								(characterID, refID, refTypeID, ownerID1, ownerID2,
								argID1, argName1, amount, balance,
								reason, taxReceiverID, taxAmount, date)
								VALUES %s ON DUPLICATE KEY UPDATE characterID=characterID;`, strings.Join(values, ",\n"))

		_, err = tx.Exec(stmt)
		if err != nil {
			return false, err
		}

		_, err = tx.Exec(`UPDATE evedata.crestTokens SET walletCacheUntil = ?
							WHERE characterID = ? AND tokenCharacterID = ?`,
			wallets.CachedUntil.UTC(), char, tokenChar)
		if err != nil {
			log.Printf("Wallets: %v\n", err)
			break
		}

		err = models.RetryTransaction(tx)
		if err != nil {
			log.Printf("%s", err)
			return false, err
		}
	}

	fromID = 0
	for {
		transactions, err := c.ctx.ESI.EVEAPI.CharacterWalletTransactionXML(token, (int64)(tokenChar), fromID)
		if err != nil || transactions == nil {
			tokenError(char, tokenChar, nil, err)
			return false, err
		} else {
			tokenSuccess(char, tokenChar, 200, "OK")
		}
		// there are no entries in this journal page.
		if len(transactions.Entries) == 0 {
			break
		}

		tx, err := models.Begin()
		if err != nil {
			return false, err
		}

		var values []string

		for _, transaction := range transactions.Entries {
			if transaction.TransactionID < fromID || fromID == 0 {
				fromID = transaction.TransactionID
			}

			values = append(values, fmt.Sprintf("(%d,%d,%d,%d,%f,%d,%d,%q,%q,%d,%q,%d)",
				tokenChar, transaction.TransactionID, transaction.Quantity, transaction.TypeID, transaction.Price,
				transaction.ClientID, transaction.StationID, transaction.TransactionType,
				transaction.TransactionFor, transaction.JournalTransactionID, transaction.TransactionDateTime.UTC().Format(models.SQLTimeFormat), transaction.ClientTypeID))
		}

		stmt := fmt.Sprintf(`INSERT INTO evedata.walletTransactions
								(characterID, transactionID, quantity, typeID, price,
								clientID,  stationID, transactionType,
								transactionFor, journalTransactionID, transactionDateTime, clientTypeID)
								VALUES %s ON DUPLICATE KEY UPDATE characterID=characterID;`, strings.Join(values, ",\n"))

		_, err = tx.Exec(stmt)
		if err != nil {
			return false, err
		}

		_, err = tx.Exec(`UPDATE evedata.crestTokens SET walletCacheUntil = ?
							WHERE characterID = ? AND tokenCharacterID = ?`,
			transactions.CachedUntil.UTC(), char, tokenChar)
		if err != nil {
			log.Printf("Wallets: %v\n", err)
			break
		}

		err = models.RetryTransaction(tx)
		if err != nil {
			log.Printf("%s", err)
			return false, err
		}
	}

	return true, err
}
<|endoftext|>


<commit_before>/*
 * A name server which sends back the IP address of its client, the
 * recursive resolver. When queried for type TXT, it sends back the text
 * form of the address.  When queried for type A (resp. AAAA), it sends
 * back the IPv4 (resp. v6) address.
 *
 * Similar services: whoami.ultradns.net, whoami.akamai.net. Also (but it
 * is not their normal goal): rs.dns-oarc.net, porttest.dns-oarc.net,
 * amiopen.openresolvers.org.
 *
 * Original version from:
 * Stephane Bortzmeyer <stephane+grong@bortzmeyer.org>
 *
 * Adapted to Go DNS (i.e. completely rewritten)
 * Miek Gieben <miek@miek.nl>
 */

package main

import (
	"flag"
	"fmt"
	"github.com/miekg/dns"
	"log"
	"net"
	"os"
	"os/signal"
	"runtime/pprof"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var (
	printf   *bool
	compress *bool
	tsig     *string
)

const dom = "whoami.miek.nl."

func handleReflect(w dns.ResponseWriter, r *dns.Msg) {
	var (
		v4  bool
		rr  dns.RR
		str string
		a   net.IP
	)
	// TC must be done here
	m := new(dns.Msg)
	m.SetReply(r)
	m.Compress = *compress
	if ip, ok := w.RemoteAddr().(*net.UDPAddr); ok {
		str = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
		a = ip.IP
		v4 = a.To4() != nil
	}
	if ip, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		str = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
		a = ip.IP
		v4 = a.To4() != nil
	}

	if v4 {
		rr = new(dns.RR_A)
		rr.(*dns.RR_A).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
		rr.(*dns.RR_A).A = a.To4()
	} else {
		rr = new(dns.RR_AAAA)
		rr.(*dns.RR_AAAA).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 0}
		rr.(*dns.RR_AAAA).AAAA = a
	}

	t := new(dns.RR_TXT)
	t.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
	t.Txt = []string{str}

	switch r.Question[0].Qtype {
	case dns.TypeAXFR:
		c := make(chan *dns.XfrToken)
		var e *error
		if err := dns.XfrSend(w, r, c, e); err != nil {
			close(c)
			return
		}
		soa, _ := dns.NewRR(`whoami.miek.nl. IN SOA elektron.atoom.net. miekg.atoom.net. (
			2009032802
			21600
			7200
			604800
			3600)`)
		c <- &dns.XfrToken{RR: []dns.RR{soa, t, rr, soa}}
		close(c)
		w.Hijack()
		// w.Close() // Client closes
		return
	case dns.TypeTXT:
		m.Answer = append(m.Answer, t)
		m.Extra = append(m.Extra, rr)
	default:
		fallthrough
	case dns.TypeAAAA, dns.TypeA:
		m.Answer = append(m.Answer, rr)
		m.Extra = append(m.Extra, t)
	}

	if r.IsTsig() != nil {
		if w.TsigStatus() == nil {
			m.SetTsig(r.Extra[len(r.Extra)-1].(*dns.RR_TSIG).Hdr.Name, dns.HmacMD5, 300, time.Now().Unix())
		} else {
			println("Status", w.TsigStatus().Error())
		}
	}
	if *printf {
		fmt.Printf("%v\n", m.String())
	}
	w.Write(m)
}

func serve(net, name, secret string) {
	switch name {
	case "":
		err := dns.ListenAndServe(":8053", net, nil)
		if err != nil {
			fmt.Printf("Failed to setup the "+net+" server: %s\n", err.Error())
		}
	default:
		server := &dns.Server{Addr: ":8053", Net: "net", TsigSecret: map[string]string{name: secret}}
		err := server.ListenAndServe()
		if err != nil {
			fmt.Printf("Failed to setup the "+net+" server: %s\n", err.Error())
		}
	}
}

func main() {
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
	printf = flag.Bool("print", false, "print replies")
	compress = flag.Bool("compress", false, "compress replies")
	tsig = flag.String("tsig", "", "use MD5 hmac tsig: keyname:base64")
	var name, secret string
	flag.Usage = func() {
		flag.PrintDefaults()
	}
	flag.Parse()
	if *tsig != "" {
		a := strings.SplitN(*tsig, ":", 2)
		name, secret = a[0], a[1]
	}
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	dns.HandleFunc("miek.nl.", handleReflect)
	dns.HandleFunc("authors.bind.", dns.HandleAuthors)
	dns.HandleFunc("authors.server.", dns.HandleAuthors)
	dns.HandleFunc("version.bind.", dns.HandleVersion)
	dns.HandleFunc("version.server.", dns.HandleVersion)
	go serve("tcp", name, secret)
	go serve("udp", name, secret)
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
forever:
	for {
		select {
		case s:=<-sig:
			fmt.Printf("Signal (%d) received, stopping\n", s)
			break forever
		}
	}
}
<commit_msg>fix typo to use tsig in reflect demo server<commit_after>/*
 * A name server which sends back the IP address of its client, the
 * recursive resolver. When queried for type TXT, it sends back the text
 * form of the address.  When queried for type A (resp. AAAA), it sends
 * back the IPv4 (resp. v6) address.
 *
 * Similar services: whoami.ultradns.net, whoami.akamai.net. Also (but it
 * is not their normal goal): rs.dns-oarc.net, porttest.dns-oarc.net,
 * amiopen.openresolvers.org.
 *
 * Original version from:
 * Stephane Bortzmeyer <stephane+grong@bortzmeyer.org>
 *
 * Adapted to Go DNS (i.e. completely rewritten)
 * Miek Gieben <miek@miek.nl>
 */

package main

import (
	"flag"
	"fmt"
	"github.com/miekg/dns"
	"log"
	"net"
	"os"
	"os/signal"
	"runtime/pprof"
	"strconv"
	"strings"
	"syscall"
	"time"
)

var (
	printf   *bool
	compress *bool
	tsig     *string
)

const dom = "whoami.miek.nl."

func handleReflect(w dns.ResponseWriter, r *dns.Msg) {
	var (
		v4  bool
		rr  dns.RR
		str string
		a   net.IP
	)
	// TC must be done here
	m := new(dns.Msg)
	m.SetReply(r)
	m.Compress = *compress
	if ip, ok := w.RemoteAddr().(*net.UDPAddr); ok {
		str = "Port: " + strconv.Itoa(ip.Port) + " (udp)"
		a = ip.IP
		v4 = a.To4() != nil
	}
	if ip, ok := w.RemoteAddr().(*net.TCPAddr); ok {
		str = "Port: " + strconv.Itoa(ip.Port) + " (tcp)"
		a = ip.IP
		v4 = a.To4() != nil
	}

	if v4 {
		rr = new(dns.RR_A)
		rr.(*dns.RR_A).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
		rr.(*dns.RR_A).A = a.To4()
	} else {
		rr = new(dns.RR_AAAA)
		rr.(*dns.RR_AAAA).Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: 0}
		rr.(*dns.RR_AAAA).AAAA = a
	}

	t := new(dns.RR_TXT)
	t.Hdr = dns.RR_Header{Name: dom, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
	t.Txt = []string{str}

	switch r.Question[0].Qtype {
	case dns.TypeAXFR:
		c := make(chan *dns.XfrToken)
		var e *error
		if err := dns.XfrSend(w, r, c, e); err != nil {
			close(c)
			return
		}
		soa, _ := dns.NewRR(`whoami.miek.nl. IN SOA elektron.atoom.net. miekg.atoom.net. (
			2009032802
			21600
			7200
			604800
			3600)`)
		c <- &dns.XfrToken{RR: []dns.RR{soa, t, rr, soa}}
		close(c)
		w.Hijack()
		// w.Close() // Client closes
		return
	case dns.TypeTXT:
		m.Answer = append(m.Answer, t)
		m.Extra = append(m.Extra, rr)
	default:
		fallthrough
	case dns.TypeAAAA, dns.TypeA:
		m.Answer = append(m.Answer, rr)
		m.Extra = append(m.Extra, t)
	}

	if r.IsTsig() != nil {
		if w.TsigStatus() == nil {
			m.SetTsig(r.Extra[len(r.Extra)-1].(*dns.RR_TSIG).Hdr.Name, dns.HmacMD5, 300, time.Now().Unix())
		} else {
			println("Status", w.TsigStatus().Error())
		}
	}
	if *printf {
		fmt.Printf("%v\n", m.String())
	}
	w.Write(m)
}

func serve(net, name, secret string) {
	switch name {
	case "":
		err := dns.ListenAndServe(":8053", net, nil)
		if err != nil {
			fmt.Printf("Failed to setup the "+net+" server: %s\n", err.Error())
		}
	default:
		server := &dns.Server{Addr: ":8053", Net: net, TsigSecret: map[string]string{name: secret}}
		err := server.ListenAndServe()
		if err != nil {
			fmt.Printf("Failed to setup the "+net+" server: %s\n", err.Error())
		}
	}
}

func main() {
	cpuprofile := flag.String("cpuprofile", "", "write cpu profile to file")
	printf = flag.Bool("print", false, "print replies")
	compress = flag.Bool("compress", false, "compress replies")
	tsig = flag.String("tsig", "", "use MD5 hmac tsig: keyname:base64")
	var name, secret string
	flag.Usage = func() {
		flag.PrintDefaults()
	}
	flag.Parse()
	if *tsig != "" {
		a := strings.SplitN(*tsig, ":", 2)
		name, secret = a[0], a[1]
	}
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	dns.HandleFunc("miek.nl.", handleReflect)
	dns.HandleFunc("authors.bind.", dns.HandleAuthors)
	dns.HandleFunc("authors.server.", dns.HandleAuthors)
	dns.HandleFunc("version.bind.", dns.HandleVersion)
	dns.HandleFunc("version.server.", dns.HandleVersion)
	go serve("tcp", name, secret)
	go serve("udp", name, secret)
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
forever:
	for {
		select {
		case s:=<-sig:
			fmt.Printf("Signal (%d) received, stopping\n", s)
			break forever
		}
	}
}
<|endoftext|>


<commit_before>package spot

import "testing"

func TestBuildHardUrl(t *testing.T) {

	var params = map[string]string{
		"artist": "Mariah Carey",
		"track":  "always be my baby",
	}

	expected := "https://api.spotify.com/v1/search?q=artist:mariah+carey+track:always+be+my+baby+&type=track"
	url, _ := BuildHardUrl(params, []string{"track"})
	if url != expected {
		t.Errorf("Expected: %q, Got %q", expected, url)
	}

}
<commit_msg>adds fail function for easy debugging<commit_after>package spot

import "testing"

func TestBuildHardUrl(t *testing.T) {

	var params = map[string]string{
		"artist": "Mariah Carey",
		"track":  "always be my baby",
	}

	expected := "https://api.spotify.com/v1/search?q=artist:mariah+carey+track:always+be+my+baby+&type=track"
	url, _ := BuildHardUrl(params, []string{"track"})
	if url != expected {
		fail(t, expected, url)
	}

}

func fail(t *testing.T, expected, got string) {
	t.Errorf("Expected: %q, Got %q", expected, got)
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package syncutil_test

import (
	"errors"
	"testing"

	"github.com/jacobsa/gcloud/syncutil"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"golang.org/x/net/context"
)

func TestOgletest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type BundleTest struct {
	bundle       *syncutil.Bundle
	cancelParent context.CancelFunc
}

func init() { RegisterTestSuite(&BundleTest{}) }

func (t *BundleTest) SetUp(ti *TestInfo) {
	// Set up the parent context.
	parentCtx, cancelParent := context.WithCancel(context.Background())
	t.cancelParent = cancelParent

	// Set up the bundle.
	t.bundle = syncutil.NewBundle(parentCtx)
}

////////////////////////////////////////////////////////////////////////
// Test functions
////////////////////////////////////////////////////////////////////////

func (t *BundleTest) NoOperations() {
	ExpectEq(nil, t.bundle.Join())
}

func (t *BundleTest) SingleOp_Success() {
	t.bundle.Add(func(c context.Context) error {
		return nil
	})

	ExpectEq(nil, t.bundle.Join())
}

func (t *BundleTest) SingleOp_Error() {
	expected := errors.New("taco")
	t.bundle.Add(func(c context.Context) error {
		return expected
	})

	ExpectEq(expected, t.bundle.Join())
}

func (t *BundleTest) SingleOp_ParentCancelled() {
	// Start an op that waits for the context to be cancelled before returning an
	// expected value.
	expected := errors.New("taco")
	t.bundle.Add(func(c context.Context) error {
		<-c.Done()
		return expected
	})

	// Cancel the parent context, then join the bundle. The op should see the
	// cancellation, so we shouldn't deadlock and we should get the expected
	// value.
	t.cancelParent()
	ExpectEq(expected, t.bundle.Join())
}

func (t *BundleTest) MultipleOps_Success() {
	for i := 0; i < 4; i++ {
		t.bundle.Add(func(c context.Context) error {
			return nil
		})
	}

	ExpectEq(nil, t.bundle.Join())
}

func (t *BundleTest) MultipleOps_UnorderedErrors() {
	// Start multiple ops, each returning a different error.
	errs := []error{
		errors.New("taco"),
		errors.New("burrito"),
		errors.New("enchilada"),
	}

	for i := 0; i < len(errs); i++ {
		iCopy := i
		t.bundle.Add(func(c context.Context) error {
			return errs[iCopy]
		})
	}

	// Joining the bundle should result in some error from the list.
	ExpectThat(errs, Contains(t.bundle.Join()))
}

func (t *BundleTest) MultipleOps_OneError_OthersDontWait() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) MultipleOps_OneError_OthersWaitForCancellation() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) MultipleOps_ParentCancelled() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) MultipleOps_PreviousError_NewOpsObserve() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) MultipleOps_PreviousParentCancel_NewOpsObserve() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) JoinWaitsForAllOps() {
	AssertFalse(true, "TODO")
}
<commit_msg>BundleTest.MultipleOps_OneError_OthersDontWait<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package syncutil_test

import (
	"errors"
	"testing"

	"github.com/jacobsa/gcloud/syncutil"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"golang.org/x/net/context"
)

func TestOgletest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type BundleTest struct {
	bundle       *syncutil.Bundle
	cancelParent context.CancelFunc
}

func init() { RegisterTestSuite(&BundleTest{}) }

func (t *BundleTest) SetUp(ti *TestInfo) {
	// Set up the parent context.
	parentCtx, cancelParent := context.WithCancel(context.Background())
	t.cancelParent = cancelParent

	// Set up the bundle.
	t.bundle = syncutil.NewBundle(parentCtx)
}

////////////////////////////////////////////////////////////////////////
// Test functions
////////////////////////////////////////////////////////////////////////

func (t *BundleTest) NoOperations() {
	ExpectEq(nil, t.bundle.Join())
}

func (t *BundleTest) SingleOp_Success() {
	t.bundle.Add(func(c context.Context) error {
		return nil
	})

	ExpectEq(nil, t.bundle.Join())
}

func (t *BundleTest) SingleOp_Error() {
	expected := errors.New("taco")
	t.bundle.Add(func(c context.Context) error {
		return expected
	})

	ExpectEq(expected, t.bundle.Join())
}

func (t *BundleTest) SingleOp_ParentCancelled() {
	// Start an op that waits for the context to be cancelled before returning an
	// expected value.
	expected := errors.New("taco")
	t.bundle.Add(func(c context.Context) error {
		<-c.Done()
		return expected
	})

	// Cancel the parent context, then join the bundle. The op should see the
	// cancellation, so we shouldn't deadlock and we should get the expected
	// value.
	t.cancelParent()
	ExpectEq(expected, t.bundle.Join())
}

func (t *BundleTest) MultipleOps_Success() {
	for i := 0; i < 4; i++ {
		t.bundle.Add(func(c context.Context) error {
			return nil
		})
	}

	ExpectEq(nil, t.bundle.Join())
}

func (t *BundleTest) MultipleOps_UnorderedErrors() {
	// Start multiple ops, each returning a different error.
	errs := []error{
		errors.New("taco"),
		errors.New("burrito"),
		errors.New("enchilada"),
	}

	for i := 0; i < len(errs); i++ {
		iCopy := i
		t.bundle.Add(func(c context.Context) error {
			return errs[iCopy]
		})
	}

	// Joining the bundle should result in some error from the list.
	ExpectThat(errs, Contains(t.bundle.Join()))
}

func (t *BundleTest) MultipleOps_OneError_OthersDontWait() {
	expected := errors.New("taco")

	// Add two operations that succeed and one that fails.
	t.bundle.Add(func(c context.Context) error { return nil })
	t.bundle.Add(func(c context.Context) error { return expected })
	t.bundle.Add(func(c context.Context) error { return nil })

	// We should see the failure.
	ExpectEq(expected, t.bundle.Join())
}

func (t *BundleTest) MultipleOps_OneError_OthersWaitForCancellation() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) MultipleOps_ParentCancelled() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) MultipleOps_PreviousError_NewOpsObserve() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) MultipleOps_PreviousParentCancel_NewOpsObserve() {
	AssertFalse(true, "TODO")
}

func (t *BundleTest) JoinWaitsForAllOps() {
	AssertFalse(true, "TODO")
}
<|endoftext|>


<commit_before>package main

import (
    "net/http"
    "github.com/gorilla/mux"
)

func main() {
    r := mux.NewRouter()
    r.PathPrefix("/").Handler(http.FileServer(http.Dir("../app/")))
    http.Handle("/", r)
    http.ListenAndServe(":8000", nil)
}
<commit_msg>Add HTTPS redirect<commit_after>package main

import (
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

const (
	WEBSITE_URL = "localhost"
	HTTP_PORT   = ":8000"
	HTTPS_PORT  = ":8080"
)

func redirectHandler(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "https://"+WEBSITE_URL+HTTPS_PORT+r.RequestURI, http.StatusMovedPermanently)
}

func main() {
	r := mux.NewRouter()
	r.PathPrefix("/").Handler(http.FileServer(http.Dir("../app/")))
	http.Handle("/", r)
	go func() {
		err := http.ListenAndServe(HTTP_PORT, http.HandlerFunc(redirectHandler))
		if err != nil {
			log.Fatal(err)
		}
	}()
	err := http.ListenAndServeTLS(HTTPS_PORT, "cert.pem", "key.pem", nil)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>