<commit_before>package goBoom

import (
	"code.google.com/p/go.crypto/pbkdf2"
	"crypto/sha1"
	"fmt"
	"net/url"
	"strings"
)

type UserService struct {
	c *Client

	session string
}

func newUserService(c *Client) *UserService {
	u := &UserService{}
	if c == nil {
		u.c = NewClient(nil)
	} else {
		u.c = c
	}

	return u
}

type loginResponse struct {
	Cookie  string `json:"cookie"`
	Session string `json:"session"`
	User    struct {
		ApiKey      string      `json:"api_key"`
		Balance     interface{} `json:"balance"`
		Email       string      `json:"email"`
		ExternalID  string      `json:"external_id"`
		FtpUsername string      `json:"ftp_username"`
		ID          string      `json:"id"`
		Name        string      `json:"name"`
		Partner     string      `json:"partner"`
		PartnerLast interface{} `json:"partner_last"`
		Pro         string      `json:"pro"`
		Settings    struct {
			Ddl              float64 `json:"ddl"`
			RewriteBehaviour float64 `json:"rewrite_behaviour"`
		} `json:"settings"`
		Traffic struct {
			Current  float64 `json:"current"`
			Increase float64 `json:"increase"`
			Last     float64 `json:"last"`
			Max      float64 `json:"max"`
		} `json:"traffic"`
		Webspace float64 `json:"webspace"`
	} `json:"user"`
}

func (u *UserService) Login(name, passw string) (int, *loginResponse, error) {

	derived := pbkdf2.Key([]byte(passw), []byte(reverse(passw)), 1000, 16, sha1.New)

	reqParams := url.Values{
		"auth": []string{name},
		"pass": []string{fmt.Sprintf("%x", derived)},
	}

	req, err := u.c.NewReaderRequest("POST", "https://www.oboom.com/1.0/login", strings.NewReader(reqParams.Encode()), "")
	if err != nil {
		return 0, nil, err
	}

	var liResp loginResponse
	liStatus, resp, err := u.c.DoJson(req, &liResp)
	if err != nil {
		return 0, nil, err
	}

	if resp.StatusCode != liStatus {
		return liStatus, nil, fmt.Errorf("resp.StatusCode[%d] != liStatus[%d]", resp.StatusCode, liStatus)
	}
	fmt.Printf("Status Code[%d]\n", liStatus)

	u.session = liResp.Session

	return resp.StatusCode, &liResp, nil
}
<commit_msg>fixed login test<commit_after>package goBoom

import (
	"code.google.com/p/go.crypto/pbkdf2"
	"crypto/sha1"
	"fmt"
	"net/url"
	"strings"
)

type UserService struct {
	c *Client

	session string
}

func newUserService(c *Client) *UserService {
	u := &UserService{}
	if c == nil {
		u.c = NewClient(nil)
	} else {
		u.c = c
	}

	return u
}

type loginResponse struct {
	Cookie  string `json:"cookie"`
	Session string `json:"session"`
	User    struct {
		ApiKey      string      `json:"api_key"`
		Balance     interface{} `json:"balance"`
		Email       string      `json:"email"`
		ExternalID  string      `json:"external_id"`
		FtpUsername string      `json:"ftp_username"`
		ID          string      `json:"id"`
		Name        string      `json:"name"`
		Partner     string      `json:"partner"`
		PartnerLast interface{} `json:"partner_last"`
		Pro         string      `json:"pro"`
		Settings    struct {
			Ddl              float64 `json:"ddl"`
			RewriteBehaviour float64 `json:"rewrite_behaviour"`
		} `json:"settings"`
		Traffic struct {
			Current  float64 `json:"current"`
			Increase float64 `json:"increase"`
			Last     float64 `json:"last"`
			Max      float64 `json:"max"`
		} `json:"traffic"`
		Webspace float64 `json:"webspace"`
	} `json:"user"`
}

func (u *UserService) Login(name, passw string) (int, *loginResponse, error) {

	derived := pbkdf2.Key([]byte(passw), []byte(reverse(passw)), 1000, 16, sha1.New)

	reqParams := url.Values{
		"auth": []string{name},
		"pass": []string{fmt.Sprintf("%x", derived)},
	}

	oldHost := u.c.baseURL.Host
	u.c.baseURL.Host = strings.Replace(u.c.baseURL.Host, "api.oboom.com", "www.oboom.com", 1)

	req, err := u.c.NewReaderRequest("POST", "login", strings.NewReader(reqParams.Encode()), "")
	if err != nil {
		return 0, nil, err
	}

	u.c.baseURL.Host = oldHost

	var liResp loginResponse
	liStatus, resp, err := u.c.DoJson(req, &liResp)
	if err != nil {
		return 0, nil, err
	}

	if resp.StatusCode != liStatus {
		return liStatus, nil, fmt.Errorf("resp.StatusCode[%d] != liStatus[%d]", resp.StatusCode, liStatus)
	}
	fmt.Printf("Status Code[%d]\n", liStatus)

	u.session = liResp.Session

	return resp.StatusCode, &liResp, nil
}
<|endoftext|>


<commit_before>package soyjs

import (
	"github.com/robfig/soy/ast"
)

// JSWriter is provided to functions to write to the generated javascript.
type JSWriter interface {
	// Write writes the given arguments into the generated javascript.  It is
	// recommended to only pass strings and ast.Nodes to Write. Other types
	// are printed using their default string representation (fmt.Sprintf("%v")).
	Write(...interface{})
}

func (s *state) Write(args ...interface{}) {
	s.js(args...)
}

// Func represents a soy function that may invoked within a template.
type Func struct {
	Name            string
	Apply           func(js JSWriter, args []ast.Node)
	ValidArgLengths []int
}

// Funcs contains the available soy functions.
// Callers may add custom functions to this map.
var Funcs = map[string]Func{
	"isNonnull":     {"isNonnull", funcIsNonnull, []int{1}},
	"length":        {"length", funcLength, []int{1}},
	"keys":          {"keys", builtinFunc("getMapKeys"), []int{1}},
	"augmentMap":    {"augmentMap", builtinFunc("augmentMap"), []int{2}},
	"round":         {"round", funcRound, []int{1, 2}},
	"floor":         {"floor", funcFloor, []int{1}},
	"ceiling":       {"ceiling", funcCeiling, []int{1}},
	"min":           {"min", funcMin, []int{2}},
	"max":           {"max", funcMax, []int{2}},
	"randomInt":     {"randomInt", funcRandomInt, []int{1}},
	"strContains":   {"strContains", funcStrContains, []int{2}},
	"hasData":       {"hasData", funcHasData, []int{0}},
	"bidiGlobalDir": {"bidiGlobalDir", funcBidiGlobalDir, []int{0}},
	"bidiDirAttr":   {"bidiDirAttr", funcBidiDirAttr, []int{0}},
	"bidiStartEdge": {"bidiStartEdge", funcBidiStartEdge, []int{0}},
	"bidiEndEdge":   {"bidiEndEdge", funcBidiEndEdge, []int{0}},
}

// builtinFunc returns a function that writes a call to a soy.$$ builtin func.
func builtinFunc(name string) func(js JSWriter, args []ast.Node) {
	var funcStart = "soy.$$" + name + "("
	return func(js JSWriter, args []ast.Node) {
		js.Write(funcStart)
		for i, arg := range args {
			if i != 0 {
				js.Write(",")
			}
			js.Write(arg)
		}
		js.Write(")")
	}
}

func funcIsNonnull(js JSWriter, args []ast.Node) {
	js.Write(args[0], "!= null")
}

func funcLength(js JSWriter, args []ast.Node) {
	js.Write(args[0], ".length")
}

func funcRound(js JSWriter, args []ast.Node) {
	switch len(args) {
	case 1:
		js.Write("Math.round(", args[0], ")")
	default:
		js.Write(
			"Math.round(", args[0], "* Math.pow(10, ", args[1], ")) / Math.pow(10, ", args[1], ")")
	}
}

func funcFloor(js JSWriter, args []ast.Node) {
	js.Write("Math.floor(", args[0], ")")
}

func funcCeiling(js JSWriter, args []ast.Node) {
	js.Write("Math.ceil(", args[0], ")")
}

func funcMin(js JSWriter, args []ast.Node) {
	js.Write("Math.min(", args[0], ",", args[1], ")")
}

func funcMax(js JSWriter, args []ast.Node) {
	js.Write("Math.max(", args[0], ",", args[1], ")")
}

func funcRandomInt(js JSWriter, args []ast.Node) {
	js.Write("Math.floor(Math.random() * ", args[0], ")")
}

func funcStrContains(js JSWriter, args []ast.Node) {
	js.Write(args[0], ".indexOf(", args[1], ") != -1")
}

func funcHasData(js JSWriter, args []ast.Node) {
	js.Write("true")
}

func funcBidiGlobalDir(js JSWriter, args []ast.Node) {
	js.Write("1")
}

func funcBidiDirAttr(js JSWriter, args []ast.Node) {
	js.Write("soy.$$bidiDirAttr(0, ", args[0], ")")
}

func funcBidiStartEdge(js JSWriter, args []ast.Node) {
	js.Write("'left'")
}

func funcBidiEndEdge(js JSWriter, args []ast.Node) {
	js.Write("'right'")
}
<commit_msg>PC-24819: remove duplication from funcs.go<commit_after>package soyjs

import (
	"github.com/robfig/soy/ast"
)

// JSWriter is provided to functions to write to the generated javascript.
type JSWriter interface {
	// Write writes the given arguments into the generated javascript.  It is
	// recommended to only pass strings and ast.Nodes to Write. Other types
	// are printed using their default string representation (fmt.Sprintf("%v")).
	Write(...interface{})
}

func (s *state) Write(args ...interface{}) {
	s.js(args...)
}

// Func represents a soy function that may invoked within a template.
type Func struct {
	Name            string
	Apply           func(js JSWriter, args []ast.Node)
	ValidArgLengths []int
}

var funcs = []Func{
	{"isNonnull", funcIsNonnull, []int{1}},
	{"length", funcLength, []int{1}},
	{"keys", builtinFunc("getMapKeys"), []int{1}},
	{"augmentMap", builtinFunc("augmentMap"), []int{2}},
	{"round", funcRound, []int{1, 2}},
	{"floor", funcFloor, []int{1}},
	{"ceiling", funcCeiling, []int{1}},
	{"min", funcMin, []int{2}},
	{"max", funcMax, []int{2}},
	{"randomInt", funcRandomInt, []int{1}},
	{"strContains", funcStrContains, []int{2}},
	{"hasData", funcHasData, []int{0}},
	{"bidiGlobalDir", funcBidiGlobalDir, []int{0}},
	{"bidiDirAttr", funcBidiDirAttr, []int{0}},
	{"bidiStartEdge", funcBidiStartEdge, []int{0}},
	{"bidiEndEdge", funcBidiEndEdge, []int{0}},
}

// Funcs contains the available soy functions.
// Callers may add custom functions to this map.
var Funcs = make(map[string]Func, len(funcs))

func init() {
	for _, f := range funcs {
		Funcs[f.Name] = f
	}
}

// builtinFunc returns a function that writes a call to a soy.$$ builtin func.
func builtinFunc(name string) func(js JSWriter, args []ast.Node) {
	var funcStart = "soy.$$" + name + "("
	return func(js JSWriter, args []ast.Node) {
		js.Write(funcStart)
		for i, arg := range args {
			if i != 0 {
				js.Write(",")
			}
			js.Write(arg)
		}
		js.Write(")")
	}
}

func funcIsNonnull(js JSWriter, args []ast.Node) {
	js.Write(args[0], "!= null")
}

func funcLength(js JSWriter, args []ast.Node) {
	js.Write(args[0], ".length")
}

func funcRound(js JSWriter, args []ast.Node) {
	switch len(args) {
	case 1:
		js.Write("Math.round(", args[0], ")")
	default:
		js.Write(
			"Math.round(", args[0], "* Math.pow(10, ", args[1], ")) / Math.pow(10, ", args[1], ")")
	}
}

func funcFloor(js JSWriter, args []ast.Node) {
	js.Write("Math.floor(", args[0], ")")
}

func funcCeiling(js JSWriter, args []ast.Node) {
	js.Write("Math.ceil(", args[0], ")")
}

func funcMin(js JSWriter, args []ast.Node) {
	js.Write("Math.min(", args[0], ",", args[1], ")")
}

func funcMax(js JSWriter, args []ast.Node) {
	js.Write("Math.max(", args[0], ",", args[1], ")")
}

func funcRandomInt(js JSWriter, args []ast.Node) {
	js.Write("Math.floor(Math.random() * ", args[0], ")")
}

func funcStrContains(js JSWriter, args []ast.Node) {
	js.Write(args[0], ".indexOf(", args[1], ") != -1")
}

func funcHasData(js JSWriter, args []ast.Node) {
	js.Write("true")
}

func funcBidiGlobalDir(js JSWriter, args []ast.Node) {
	js.Write("1")
}

func funcBidiDirAttr(js JSWriter, args []ast.Node) {
	js.Write("soy.$$bidiDirAttr(0, ", args[0], ")")
}

func funcBidiStartEdge(js JSWriter, args []ast.Node) {
	js.Write("'left'")
}

func funcBidiEndEdge(js JSWriter, args []ast.Node) {
	js.Write("'right'")
}
<|endoftext|>


<commit_before>package test

import (
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"strings"
	"sync/atomic"
	"text/template"
	"time"
)

const (
	// define min and max port range
	maxPort = 65535
	minPort = 10000
)

var (
	curPort = int32(maxPort + 1)
)

// BookPorts books free portsx
func BookPorts(num int) ([]int, error) {
	result := make([]int, 0, num)
	for len(result) < num {
		newPort := atomic.AddInt32(&curPort, -1)
		if newPort < minPort {
			return nil, errors.New("running out of available ports")
		}
		if portAvailable(newPort) {
			result = append(result, int(newPort))
		}
	}
	return result, nil
}

// CheckExecutable checks if given names are executables
func CheckExecutable(names ...string) error {
	for _, name := range names {
		if _, err := exec.LookPath(name); err != nil {
			return err
		}
	}
	return nil
}

// ApplyTemplate applies given variables to the "tplStr" and stores to "filePath"
func ApplyTemplate(filePath string, tplStr string, vars map[string]interface{}) error {
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	tpl, err := template.New("tpl").Parse(tplStr)
	if err != nil {
		return err
	}
	return tpl.Execute(file, vars)
}

// CheckListening checks if localhost is listening given ports
func CheckListening(ports ...int) bool {
	for _, p := range ports {
		conn, err := net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", p), 500*time.Millisecond)
		if err != nil {
			return false
		}
		conn.Close()
	}
	return true
}

// Exec runs "name" and "arg" in directory "workdir" with environements "envs" and wait util
// process finined. It returns error if fail to execute or exit code is not zero.
func Exec(workdir string, envs []string, stdin io.Reader, name string, arg ...interface{}) error {
	argStr := make([]string, 0, len(arg))
	for _, a := range arg {
		argStr = append(argStr, fmt.Sprintf("%v", a))
	}
	cmd := exec.Command(name, argStr...)
	cmd.Env = append(os.Environ(), envs...)
	cmd.Dir = workdir
	if stdin != nil {
		cmd.Stdin = stdin
	}
	bs, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("fail to start process, output:%s, err:%v", string(bs), err)
	}
	if !cmd.ProcessState.Success() {
		return fmt.Errorf("fail to start process, output:%s", string(bs))
	}
	return nil
}

// CombineError given errors into one err, note that nil error will be ignored
func CombineError(errs ...error) error {
	result := []string{}
	for _, err := range errs {
		if err != nil {
			result = append(result, err.Error())
		}
	}
	if len(result) != 0 {
		return errors.New(strings.Join(result, ", "))
	}
	return nil
}

func portAvailable(port int32) bool {
	// Listen to tcp4 only instead of tcp which may return an ipv6 address port.
	l, err := net.Listen("tcp4", fmt.Sprintf(":%d", port))
	if err != nil {
		return false
	}
	l.Close()
	return true
}

// WaitPortAvail waits until the port becomes dialable. It returns error if it's not
// available after timeout.
func WaitPortAvail(port int, timeout time.Duration) error {
	addr := fmt.Sprintf("localhost:%d", port)
	timer := time.NewTimer(timeout)
	wait := 1 * time.Second
	for {
		c, err := net.Dial("tcp", addr)
		if err == nil {
			c.Close()
			timer.Stop()
			return nil
		}
		fmt.Printf("Attempt to dial %v failed, err %v", addr, err)
		select {
		case <-timer.C:
			return fmt.Errorf("attempt to dial %v timeout after %v", port, timeout)
		case <-time.After(wait):
			fmt.Printf("Do another try after waiting for %v\n", wait)
			wait *= 2
		}
	}
}
<commit_msg>Support custom hostname<commit_after>package test

import (
	"errors"
	"fmt"
	"io"
	"net"
	"os"
	"os/exec"
	"strings"
	"sync/atomic"
	"text/template"
	"time"
)

const (
	// define min and max port range
	maxPort = 65535
	minPort = 10000
)

var (
	curPort = int32(maxPort + 1)
)

// BookPorts books free portsx
func BookPorts(num int, host ...string) ([]int, error) {
	result := make([]int, 0, num)
	for len(result) < num {
		newPort := atomic.AddInt32(&curPort, -1)
		if newPort < minPort {
			return nil, errors.New("running out of available ports")
		}
		if portAvailable(newPort, host...) {
			result = append(result, int(newPort))
		}
	}
	return result, nil
}

// CheckExecutable checks if given names are executables
func CheckExecutable(names ...string) error {
	for _, name := range names {
		if _, err := exec.LookPath(name); err != nil {
			return err
		}
	}
	return nil
}

// ApplyTemplate applies given variables to the "tplStr" and stores to "filePath"
func ApplyTemplate(filePath string, tplStr string, vars map[string]interface{}) error {
	file, err := os.Create(filePath)
	if err != nil {
		return err
	}
	defer file.Close()

	tpl, err := template.New("tpl").Parse(tplStr)
	if err != nil {
		return err
	}
	return tpl.Execute(file, vars)
}

// CheckListening checks if localhost is listening given ports
func CheckListening(ports ...int) bool {
	for _, p := range ports {
		conn, err := net.DialTimeout("tcp4", fmt.Sprintf("localhost:%d", p), 500*time.Millisecond)
		if err != nil {
			return false
		}
		conn.Close()
	}
	return true
}

// Exec runs "name" and "arg" in directory "workdir" with environements "envs" and wait util
// process finined. It returns error if fail to execute or exit code is not zero.
func Exec(workdir string, envs []string, stdin io.Reader, name string, arg ...interface{}) error {
	argStr := make([]string, 0, len(arg))
	for _, a := range arg {
		argStr = append(argStr, fmt.Sprintf("%v", a))
	}
	cmd := exec.Command(name, argStr...)
	cmd.Env = append(os.Environ(), envs...)
	cmd.Dir = workdir
	if stdin != nil {
		cmd.Stdin = stdin
	}
	bs, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("fail to start process, output:%s, err:%v", string(bs), err)
	}
	if !cmd.ProcessState.Success() {
		return fmt.Errorf("fail to start process, output:%s", string(bs))
	}
	return nil
}

// CombineError given errors into one err, note that nil error will be ignored
func CombineError(errs ...error) error {
	result := []string{}
	for _, err := range errs {
		if err != nil {
			result = append(result, err.Error())
		}
	}
	if len(result) != 0 {
		return errors.New(strings.Join(result, ", "))
	}
	return nil
}

func portAvailable(port int32, host ...string) bool {
	// Listen to tcp4 only instead of tcp which may return an ipv6 address port.
	h := ""
	if len(h) != 0 {
		h = host[0]
	}
	l, err := net.Listen("tcp4", fmt.Sprintf("%s:%d", h, port))
	if err != nil {
		return false
	}
	l.Close()
	return true
}

// WaitPortAvail waits until the port becomes dialable. It returns error if it's not
// available after timeout.
func WaitPortAvail(port int, timeout time.Duration, host ...string) error {
	h := "localhost"
	if len(host) != 0 {
		h = host[0]
	}
	addr := fmt.Sprintf("%s:%d", h, port)
	timer := time.NewTimer(timeout)
	wait := 1 * time.Second
	for {
		c, err := net.Dial("tcp", addr)
		if err == nil {
			c.Close()
			timer.Stop()
			return nil
		}
		fmt.Printf("Attempt to dial %v failed, err %v\n", addr, err)
		select {
		case <-timer.C:
			return fmt.Errorf("attempt to dial %v timeout after %v", port, timeout)
		case <-time.After(wait):
			fmt.Printf("Do another try after waiting for %v\n", wait)
			wait *= 2
		}
	}
}
<|endoftext|>


<commit_before>package ssh

import (
	"crypto/rand"
	"crypto/rsa"
	"encoding/binary"

	"golang.org/x/crypto/ssh"
)

func generateSigner() (ssh.Signer, error) {
	key, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	return ssh.NewSignerFromKey(key)
}

func parsePtyRequest(s []byte) (pty Pty, ok bool) {
	term, s, ok := parseString(s)
	if !ok {
		return
	}
	width32, s, ok := parseUint32(s)
	if width32 < 1 {
		ok = false
	}
	if !ok {
		return
	}
	height32, _, ok := parseUint32(s)
	if height32 < 1 {
		ok = false
	}
	if !ok {
		return
	}
	pty = Pty{
		Term: term,
		Window: Window{
			Width:  int(width32),
			Height: int(height32),
		},
	}
	return
}

func parseWinchRequest(s []byte) (win Window, ok bool) {
	width32, s, ok := parseUint32(s)
	if width32 < 1 {
		ok = false
	}
	if !ok {
		return
	}
	height32, _, ok := parseUint32(s)
	if height32 < 1 {
		ok = false
	}
	if !ok {
		return
	}
	win = Window{
		Width:  int(width32),
		Height: int(height32),
	}
	return
}

func parseString(in []byte) (out string, rest []byte, ok bool) {
	if len(in) < 4 {
		return
	}
	length := binary.BigEndian.Uint32(in)
	if uint32(len(in)) < 4+length {
		return
	}
	out = string(in[4 : 4+length])
	rest = in[4+length:]
	ok = true
	return
}

func parseUint32(in []byte) (uint32, []byte, bool) {
	if len(in) < 4 {
		return 0, nil, false
	}
	return binary.BigEndian.Uint32(in), in[4:], true
}
<commit_msg>Remove Pty minimum size requirement<commit_after>package ssh

import (
	"crypto/rand"
	"crypto/rsa"
	"encoding/binary"

	"golang.org/x/crypto/ssh"
)

func generateSigner() (ssh.Signer, error) {
	key, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, err
	}
	return ssh.NewSignerFromKey(key)
}

func parsePtyRequest(s []byte) (pty Pty, ok bool) {
	term, s, ok := parseString(s)
	if !ok {
		return
	}
	width32, s, ok := parseUint32(s)
	if !ok {
		return
	}
	height32, _, ok := parseUint32(s)
	if !ok {
		return
	}
	pty = Pty{
		Term: term,
		Window: Window{
			Width:  int(width32),
			Height: int(height32),
		},
	}
	return
}

func parseWinchRequest(s []byte) (win Window, ok bool) {
	width32, s, ok := parseUint32(s)
	if width32 < 1 {
		ok = false
	}
	if !ok {
		return
	}
	height32, _, ok := parseUint32(s)
	if height32 < 1 {
		ok = false
	}
	if !ok {
		return
	}
	win = Window{
		Width:  int(width32),
		Height: int(height32),
	}
	return
}

func parseString(in []byte) (out string, rest []byte, ok bool) {
	if len(in) < 4 {
		return
	}
	length := binary.BigEndian.Uint32(in)
	if uint32(len(in)) < 4+length {
		return
	}
	out = string(in[4 : 4+length])
	rest = in[4+length:]
	ok = true
	return
}

func parseUint32(in []byte) (uint32, []byte, bool) {
	if len(in) < 4 {
		return 0, nil, false
	}
	return binary.BigEndian.Uint32(in), in[4:], true
}
<|endoftext|>


<commit_before>package vitali

import (
    "fmt"
    "strings"
    "runtime"
    "hash/crc32"
)

func errorCode(msg string) uint32 {
    return crc32.ChecksumIEEE([]byte(msg))
}

func lineInfo(skip int) (where string) {
    _, fn, ln, ok := runtime.Caller(skip)
    if ok {
        where = fmt.Sprintf("%s:%d", strings.SplitN(fn, "/src/", 2)[1], ln)
    }
    return
}

func fullTrace(skip int, sep string) (trace string) {
    for {
        where := lineInfo(skip)
        skip++
        if where == "" {
            return
        } else if strings.HasSuffix(where, ":0") {
            continue
        }
        trace = trace + sep + where
    }
    return
}
<commit_msg>remove inaccurate file path stripping which causes bug<commit_after>package vitali

import (
    "fmt"
    "strings"
    "runtime"
    "hash/crc32"
)

func errorCode(msg string) uint32 {
    return crc32.ChecksumIEEE([]byte(msg))
}

func lineInfo(skip int) (where string) {
    _, fn, ln, ok := runtime.Caller(skip)
    if ok {
        where = fmt.Sprintf("%s:%d", fn, ln)
    }
    return
}

func fullTrace(skip int, sep string) (trace string) {
    for {
        where := lineInfo(skip)
        skip++
        if where == "" {
            return
        } else if strings.HasSuffix(where, ":0") {
            continue
        }
        trace = trace + sep + where
    }
    return
}
<|endoftext|>


<commit_before>package memberlist

import (
	"bytes"
	"compress/lzw"
	"encoding/binary"
	"fmt"
	"github.com/ugorji/go/codec"
	"io"
	"math"
	"math/rand"
	"net"
	"time"
)

// pushPullScale is the minimum number of nodes
// before we start scaling the push/pull timing. The scale
// effect is the log2(Nodes) - log2(pushPullScale). This means
// that the 33rd node will cause us to double the interval,
// while the 65th will triple it.
const pushPullScaleThreshold = 32

/*
 * Contains an entry for each private block:
 * 10.0.0.0/8
 * 172.16.0.0/12
 * 192.168/16
 */
var privateBlocks []*net.IPNet

var loopbackBlock *net.IPNet

const (
	// Constant litWidth 2-8
	lzwLitWidth = 8
)

func init() {
	// Seed the random number generator
	rand.Seed(time.Now().UnixNano())

	// Add each private block
	privateBlocks = make([]*net.IPNet, 3)
	_, block, err := net.ParseCIDR("10.0.0.0/8")
	if err != nil {
		panic(fmt.Sprintf("Bad cidr. Got %v", err))
	}
	privateBlocks[0] = block

	_, block, err = net.ParseCIDR("172.16.0.0/12")
	if err != nil {
		panic(fmt.Sprintf("Bad cidr. Got %v", err))
	}
	privateBlocks[1] = block

	_, block, err = net.ParseCIDR("192.168.0.0/16")
	if err != nil {
		panic(fmt.Sprintf("Bad cidr. Got %v", err))
	}
	privateBlocks[2] = block

	_, block, err = net.ParseCIDR("127.0.0.0/8")
	if err != nil {
		panic(fmt.Sprintf("Bad cidr. Got %v", err))
	}
	loopbackBlock = block
}

// Decode reverses the encode operation on a byte slice input
func decode(buf []byte, out interface{}) error {
	r := bytes.NewBuffer(buf)
	hd := codec.MsgpackHandle{}
	dec := codec.NewDecoder(r, &hd)
	return dec.Decode(out)
}

// Encode writes an encoded object to a new bytes buffer
func encode(msgType messageType, in interface{}) (*bytes.Buffer, error) {
	buf := bytes.NewBuffer(nil)
	buf.WriteByte(uint8(msgType))
	hd := codec.MsgpackHandle{}
	enc := codec.NewEncoder(buf, &hd)
	err := enc.Encode(in)
	return buf, err
}

// Returns a random offset between 0 and n
func randomOffset(n int) int {
	if n == 0 {
		return 0
	}
	return int(rand.Uint32() % uint32(n))
}

// suspicionTimeout computes the timeout that should be used when
// a node is suspected
func suspicionTimeout(suspicionMult, n int, interval time.Duration) time.Duration {
	nodeScale := math.Ceil(math.Log10(float64(n + 1)))
	timeout := time.Duration(suspicionMult) * time.Duration(nodeScale) * interval
	return timeout
}

// retransmitLimit computes the limit of retransmissions
func retransmitLimit(retransmitMult, n int) int {
	nodeScale := math.Ceil(math.Log10(float64(n + 1)))
	limit := retransmitMult * int(nodeScale)
	return limit
}

// shuffleNodes randomly shuffles the input nodes
func shuffleNodes(nodes []*nodeState) {
	for i := range nodes {
		j := rand.Intn(i + 1)
		nodes[i], nodes[j] = nodes[j], nodes[i]
	}
}

// pushPushScale is used to scale the time interval at which push/pull
// syncs take place. It is used to prevent network saturation as the
// cluster size grows
func pushPullScale(interval time.Duration, n int) time.Duration {
	// Don't scale until we cross the threshold
	if n <= pushPullScaleThreshold {
		return interval
	}

	multiplier := math.Ceil(math.Log2(float64(n))-math.Log2(pushPullScaleThreshold)) + 1.0
	return time.Duration(multiplier) * interval
}

// moveDeadNodes moves all the nodes in the dead state
// to the end of the slice and returns the index of the first dead node.
func moveDeadNodes(nodes []*nodeState) int {
	numDead := 0
	n := len(nodes)
	for i := 0; i < n-numDead; i++ {
		if nodes[i].State != stateDead {
			continue
		}

		// Move this node to the end
		nodes[i], nodes[n-numDead-1] = nodes[n-numDead-1], nodes[i]
		numDead++
		i--
	}
	return n - numDead
}

// kRandomNodes is used to select up to k random nodes, excluding a given
// node and any non-alive nodes. It is possible that less than k nodes are returned.
func kRandomNodes(k int, excludes []string, nodes []*nodeState) []*nodeState {
	n := len(nodes)
	kNodes := make([]*nodeState, 0, k)
OUTER:
	// Probe up to 3*n times, with large n this is not necessary
	// since k << n, but with small n we want search to be
	// exhaustive
	for i := 0; i < 3*n && len(kNodes) < k; i++ {
		// Get random node
		idx := randomOffset(n)
		node := nodes[idx]

		// Exclude node if match
		for _, exclude := range excludes {
			if node.Name == exclude {
				continue OUTER
			}
		}

		// Exclude if not alive
		if node.State != stateAlive {
			continue
		}

		// Check if we have this node already
		for j := 0; j < len(kNodes); j++ {
			if node == kNodes[j] {
				continue OUTER
			}
		}

		// Append the node
		kNodes = append(kNodes, node)
	}
	return kNodes
}

// makeCompoundMessage takes a list of messages and generates
// a single compound message containing all of them
func makeCompoundMessage(msgs [][]byte) *bytes.Buffer {
	// Create a local buffer
	buf := bytes.NewBuffer(nil)

	// Write out the type
	buf.WriteByte(uint8(compoundMsg))

	// Write out the number of message
	buf.WriteByte(uint8(len(msgs)))

	// Add the message lengths
	for _, m := range msgs {
		binary.Write(buf, binary.BigEndian, uint16(len(m)))
	}

	// Append the messages
	for _, m := range msgs {
		buf.Write(m)
	}

	return buf
}

// decodeCompoundMessage splits a compound message and returns
// the slices of individual messages. Also returns the number
// of truncated messages and any potential error
func decodeCompoundMessage(buf []byte) (trunc int, parts [][]byte, err error) {
	if len(buf) < 1 {
		err = fmt.Errorf("missing compound length byte")
		return
	}
	numParts := uint8(buf[0])
	buf = buf[1:]

	// Check we have enough bytes
	if len(buf) < int(numParts*2) {
		err = fmt.Errorf("truncated len slice")
		return
	}

	// Decode the lengths
	lengths := make([]uint16, numParts)
	for i := 0; i < int(numParts); i++ {
		lengths[i] = binary.BigEndian.Uint16(buf[i*2 : i*2+2])
	}
	buf = buf[numParts*2:]

	// Split each message
	for idx, msgLen := range lengths {
		if len(buf) < int(msgLen) {
			trunc = int(numParts) - idx
			return
		}

		// Extract the slice, seek past on the buffer
		slice := buf[:msgLen]
		buf = buf[msgLen:]
		parts = append(parts, slice)
	}
	return
}

// Returns if the given IP is in a private block
func isPrivateIP(ip_str string) bool {
	ip := net.ParseIP(ip_str)
	for _, priv := range privateBlocks {
		if priv.Contains(ip) {
			return true
		}
	}
	return false
}

// Returns if the given IP is in a loopback block
func isLoopbackIP(ip_str string) bool {
	ip := net.ParseIP(ip_str)
	return loopbackBlock.Contains(ip)
}

// compressPayload takes an opaque input buffer, compresses it
// and wraps it in a compress{} message that is encoded.
func compressPayload(inp []byte) (*bytes.Buffer, error) {
	var buf bytes.Buffer
	compressor := lzw.NewWriter(&buf, lzw.LSB, lzwLitWidth)

	_, err := compressor.Write(inp)
	if err != nil {
		return nil, err
	}

	// Ensure we flush everything out
	if err := compressor.Close(); err != nil {
		return nil, err
	}

	// Create a compressed message
	c := compress{
		Algo: lzwAlgo,
		Buf:  buf.Bytes(),
	}
	return encode(compressMsg, &c)
}

// decompressPayload is used to unpack an encoded compress{}
// message and return its payload uncompressed
func decompressPayload(msg []byte) ([]byte, error) {
	// Decode the message
	var c compress
	if err := decode(msg, &c); err != nil {
		return nil, err
	}
	return decompressBuffer(&c)
}

// decompressBuffer is used to decompress the buffer of
// a single compress message, handling multiple algorithms
func decompressBuffer(c *compress) ([]byte, error) {
	// Verify the algorithm
	if c.Algo != lzwAlgo {
		return nil, fmt.Errorf("Cannot decompress unknown algorithm %d", c.Algo)
	}

	// Create a uncompressor
	uncomp := lzw.NewReader(bytes.NewReader(c.Buf), lzw.LSB, lzwLitWidth)
	defer uncomp.Close()

	// Read all the data
	var b bytes.Buffer
	_, err := io.Copy(&b, uncomp)
	if err != nil {
		return nil, err
	}

	// Return the uncompressed bytes
	return b.Bytes(), nil
}
<commit_msg>Use a ByteReader instead of Buffer for decode<commit_after>package memberlist

import (
	"bytes"
	"compress/lzw"
	"encoding/binary"
	"fmt"
	"github.com/ugorji/go/codec"
	"io"
	"math"
	"math/rand"
	"net"
	"time"
)

// pushPullScale is the minimum number of nodes
// before we start scaling the push/pull timing. The scale
// effect is the log2(Nodes) - log2(pushPullScale). This means
// that the 33rd node will cause us to double the interval,
// while the 65th will triple it.
const pushPullScaleThreshold = 32

/*
 * Contains an entry for each private block:
 * 10.0.0.0/8
 * 172.16.0.0/12
 * 192.168/16
 */
var privateBlocks []*net.IPNet

var loopbackBlock *net.IPNet

const (
	// Constant litWidth 2-8
	lzwLitWidth = 8
)

func init() {
	// Seed the random number generator
	rand.Seed(time.Now().UnixNano())

	// Add each private block
	privateBlocks = make([]*net.IPNet, 3)
	_, block, err := net.ParseCIDR("10.0.0.0/8")
	if err != nil {
		panic(fmt.Sprintf("Bad cidr. Got %v", err))
	}
	privateBlocks[0] = block

	_, block, err = net.ParseCIDR("172.16.0.0/12")
	if err != nil {
		panic(fmt.Sprintf("Bad cidr. Got %v", err))
	}
	privateBlocks[1] = block

	_, block, err = net.ParseCIDR("192.168.0.0/16")
	if err != nil {
		panic(fmt.Sprintf("Bad cidr. Got %v", err))
	}
	privateBlocks[2] = block

	_, block, err = net.ParseCIDR("127.0.0.0/8")
	if err != nil {
		panic(fmt.Sprintf("Bad cidr. Got %v", err))
	}
	loopbackBlock = block
}

// Decode reverses the encode operation on a byte slice input
func decode(buf []byte, out interface{}) error {
	r := bytes.NewReader(buf)
	hd := codec.MsgpackHandle{}
	dec := codec.NewDecoder(r, &hd)
	return dec.Decode(out)
}

// Encode writes an encoded object to a new bytes buffer
func encode(msgType messageType, in interface{}) (*bytes.Buffer, error) {
	buf := bytes.NewBuffer(nil)
	buf.WriteByte(uint8(msgType))
	hd := codec.MsgpackHandle{}
	enc := codec.NewEncoder(buf, &hd)
	err := enc.Encode(in)
	return buf, err
}

// Returns a random offset between 0 and n
func randomOffset(n int) int {
	if n == 0 {
		return 0
	}
	return int(rand.Uint32() % uint32(n))
}

// suspicionTimeout computes the timeout that should be used when
// a node is suspected
func suspicionTimeout(suspicionMult, n int, interval time.Duration) time.Duration {
	nodeScale := math.Ceil(math.Log10(float64(n + 1)))
	timeout := time.Duration(suspicionMult) * time.Duration(nodeScale) * interval
	return timeout
}

// retransmitLimit computes the limit of retransmissions
func retransmitLimit(retransmitMult, n int) int {
	nodeScale := math.Ceil(math.Log10(float64(n + 1)))
	limit := retransmitMult * int(nodeScale)
	return limit
}

// shuffleNodes randomly shuffles the input nodes
func shuffleNodes(nodes []*nodeState) {
	for i := range nodes {
		j := rand.Intn(i + 1)
		nodes[i], nodes[j] = nodes[j], nodes[i]
	}
}

// pushPushScale is used to scale the time interval at which push/pull
// syncs take place. It is used to prevent network saturation as the
// cluster size grows
func pushPullScale(interval time.Duration, n int) time.Duration {
	// Don't scale until we cross the threshold
	if n <= pushPullScaleThreshold {
		return interval
	}

	multiplier := math.Ceil(math.Log2(float64(n))-math.Log2(pushPullScaleThreshold)) + 1.0
	return time.Duration(multiplier) * interval
}

// moveDeadNodes moves all the nodes in the dead state
// to the end of the slice and returns the index of the first dead node.
func moveDeadNodes(nodes []*nodeState) int {
	numDead := 0
	n := len(nodes)
	for i := 0; i < n-numDead; i++ {
		if nodes[i].State != stateDead {
			continue
		}

		// Move this node to the end
		nodes[i], nodes[n-numDead-1] = nodes[n-numDead-1], nodes[i]
		numDead++
		i--
	}
	return n - numDead
}

// kRandomNodes is used to select up to k random nodes, excluding a given
// node and any non-alive nodes. It is possible that less than k nodes are returned.
func kRandomNodes(k int, excludes []string, nodes []*nodeState) []*nodeState {
	n := len(nodes)
	kNodes := make([]*nodeState, 0, k)
OUTER:
	// Probe up to 3*n times, with large n this is not necessary
	// since k << n, but with small n we want search to be
	// exhaustive
	for i := 0; i < 3*n && len(kNodes) < k; i++ {
		// Get random node
		idx := randomOffset(n)
		node := nodes[idx]

		// Exclude node if match
		for _, exclude := range excludes {
			if node.Name == exclude {
				continue OUTER
			}
		}

		// Exclude if not alive
		if node.State != stateAlive {
			continue
		}

		// Check if we have this node already
		for j := 0; j < len(kNodes); j++ {
			if node == kNodes[j] {
				continue OUTER
			}
		}

		// Append the node
		kNodes = append(kNodes, node)
	}
	return kNodes
}

// makeCompoundMessage takes a list of messages and generates
// a single compound message containing all of them
func makeCompoundMessage(msgs [][]byte) *bytes.Buffer {
	// Create a local buffer
	buf := bytes.NewBuffer(nil)

	// Write out the type
	buf.WriteByte(uint8(compoundMsg))

	// Write out the number of message
	buf.WriteByte(uint8(len(msgs)))

	// Add the message lengths
	for _, m := range msgs {
		binary.Write(buf, binary.BigEndian, uint16(len(m)))
	}

	// Append the messages
	for _, m := range msgs {
		buf.Write(m)
	}

	return buf
}

// decodeCompoundMessage splits a compound message and returns
// the slices of individual messages. Also returns the number
// of truncated messages and any potential error
func decodeCompoundMessage(buf []byte) (trunc int, parts [][]byte, err error) {
	if len(buf) < 1 {
		err = fmt.Errorf("missing compound length byte")
		return
	}
	numParts := uint8(buf[0])
	buf = buf[1:]

	// Check we have enough bytes
	if len(buf) < int(numParts*2) {
		err = fmt.Errorf("truncated len slice")
		return
	}

	// Decode the lengths
	lengths := make([]uint16, numParts)
	for i := 0; i < int(numParts); i++ {
		lengths[i] = binary.BigEndian.Uint16(buf[i*2 : i*2+2])
	}
	buf = buf[numParts*2:]

	// Split each message
	for idx, msgLen := range lengths {
		if len(buf) < int(msgLen) {
			trunc = int(numParts) - idx
			return
		}

		// Extract the slice, seek past on the buffer
		slice := buf[:msgLen]
		buf = buf[msgLen:]
		parts = append(parts, slice)
	}
	return
}

// Returns if the given IP is in a private block
func isPrivateIP(ip_str string) bool {
	ip := net.ParseIP(ip_str)
	for _, priv := range privateBlocks {
		if priv.Contains(ip) {
			return true
		}
	}
	return false
}

// Returns if the given IP is in a loopback block
func isLoopbackIP(ip_str string) bool {
	ip := net.ParseIP(ip_str)
	return loopbackBlock.Contains(ip)
}

// compressPayload takes an opaque input buffer, compresses it
// and wraps it in a compress{} message that is encoded.
func compressPayload(inp []byte) (*bytes.Buffer, error) {
	var buf bytes.Buffer
	compressor := lzw.NewWriter(&buf, lzw.LSB, lzwLitWidth)

	_, err := compressor.Write(inp)
	if err != nil {
		return nil, err
	}

	// Ensure we flush everything out
	if err := compressor.Close(); err != nil {
		return nil, err
	}

	// Create a compressed message
	c := compress{
		Algo: lzwAlgo,
		Buf:  buf.Bytes(),
	}
	return encode(compressMsg, &c)
}

// decompressPayload is used to unpack an encoded compress{}
// message and return its payload uncompressed
func decompressPayload(msg []byte) ([]byte, error) {
	// Decode the message
	var c compress
	if err := decode(msg, &c); err != nil {
		return nil, err
	}
	return decompressBuffer(&c)
}

// decompressBuffer is used to decompress the buffer of
// a single compress message, handling multiple algorithms
func decompressBuffer(c *compress) ([]byte, error) {
	// Verify the algorithm
	if c.Algo != lzwAlgo {
		return nil, fmt.Errorf("Cannot decompress unknown algorithm %d", c.Algo)
	}

	// Create a uncompressor
	uncomp := lzw.NewReader(bytes.NewReader(c.Buf), lzw.LSB, lzwLitWidth)
	defer uncomp.Close()

	// Read all the data
	var b bytes.Buffer
	_, err := io.Copy(&b, uncomp)
	if err != nil {
		return nil, err
	}

	// Return the uncompressed bytes
	return b.Bytes(), nil
}
<|endoftext|>


<commit_before>// Diff Match and Patch – utility functions
// 	Original work: Copyright 2006 Google Inc.
// 	Go port:	Copyright 2012 M. Teichgräber
//
// Use of this source code is governed by the Apache License,
// Version 2.0, that can be found in the LICENSE file.

package dmp

import (
	"strings"
	"unicode/utf8"
)

// Determine the common prefix of two strings.
// Returns the number of bytes common to the
// start of each string.
func commonPrefix(text1, text2 string) string {
	n := min(len(text1), len(text2))
	for i := 0; i < n; i++ {
		if text1[i] != text2[i] {
			n = i
			for n > 0 && !utf8.RuneStart(text1[n]) {
				n--
			}
			break
		}
	}
	return text1[:n]
}

// Determine the common suffix of two strings.
// Returns the number of bytes common to the end of
// each string.
func commonSuffix(text1, text2 string) string {
	n1 := len(text1)
	n2 := len(text2)
	n := min(n1, n2)

	for i := 1; i <= n; i++ {
		if text1[n1-i] != text2[n2-i] {
			n = i - 1
			for n > 0 && !utf8.RuneStart(text1[n1-n]) {
				n--
			}
			break
		}
	}
	return text1[n1-n:]
}

// Determine if the suffix of the first string is the prefix of the second.
// Returns the number of bytes common to the end of the first
// string and the start of the second string.
func commonOverlap(text1, text2 string) (best string) {
	// Cache the text lengths to prevent multiple calls.
	n1 := len(text1)
	n2 := len(text2)

	switch {
	// Eliminate the null case
	case n1 == 0 || n2 == 0:
		return

	// Truncate the longer string
	case n1 > n2:
		text1 = utf8SliceRightX(text1, n1-n2)
		n1 = len(text1)
	case n2 < n1:
		text2 = text2[:n1]
	}

	// Quick check for the worst case.
	if text1 == text2 {
		return text1
	}

	// Start by looking for a single character match
	// and increase length until no match is found.
	length := len(utf8SliceRight(text1, n1-1))
	for length <= n1 {
		pattern := text1[n1-length:]
		found := strings.Index(text2, pattern)
		if found == -1 {
			return
		}
		length += found
		if found == 0 {
			best = text2[:length]
			if length == n1 {
				return
			}
			length = len(utf8SliceRight(text1, n1-length-1))
		}
	}
	return
}

func min(n1, n2 int) int {
	if n1 < n2 {
		return n1
	}
	return n2
}

func max(n1, n2 int) int {
	if n1 > n2 {
		return n1
	}
	return n2
}

func isOdd(v int) bool {
	return v&1 != 0
}

// Create a slice s[i0:], taking care that i0
// points to the start of a character. Decrease
// i0 until this condition is met.
func utf8SliceRight(s string, i0 int) string {
	for i0 >= 0 && !utf8.RuneStart(s[i0]) {
		i0--
	}
	return s[i0:]
}

// Create a slice s[i0:], taking care that i0
// points to the start of a character. Increase
// i0 until this condition is met.
func utf8SliceRightX(s string, i0 int) string {
	n := len(s)
	for i0 != n && !utf8.RuneStart(s[i0]) {
		i0++
	}
	return s[i0:]
}

func firstRune(s string) (r rune) {
	r, _ = utf8.DecodeRuneInString(s)
	return
}

func lastRune(s string) (r rune) {
	r, _ = utf8.DecodeLastRuneInString(s)
	return
}

func firstUTF8(s string) string {
	_, n := utf8.DecodeRuneInString(s)
	return s[:n]
}

func lastUTF8(s string) string {
	_, n := utf8.DecodeLastRuneInString(s)
	return s[len(s)-n:]
}

func exceedsRuneCount(s string, count int) (exceeds bool) {
	for _ = range s {
		if count == 0 {
			exceeds = true
			break
		}
		count--
	}
	return
}

func runeCount(s string) int {
	return utf8.RuneCountInString(s)
}

type strbuf []string

func (p *strbuf) join() (s string) {
	buf := *p
	s = strings.Join(buf, "")
	*p = buf[:0]
	return
}
<commit_msg>util.go: go fmt<commit_after>// Diff Match and Patch – utility functions
// 	Original work: Copyright 2006 Google Inc.
// 	Go port:	Copyright 2012 M. Teichgräber
//
// Use of this source code is governed by the Apache License,
// Version 2.0, that can be found in the LICENSE file.

package dmp

import (
	"strings"
	"unicode/utf8"
)

// Determine the common prefix of two strings.
// Returns the number of bytes common to the
// start of each string.
func commonPrefix(text1, text2 string) string {
	n := min(len(text1), len(text2))
	for i := 0; i < n; i++ {
		if text1[i] != text2[i] {
			n = i
			for n > 0 && !utf8.RuneStart(text1[n]) {
				n--
			}
			break
		}
	}
	return text1[:n]
}

// Determine the common suffix of two strings.
// Returns the number of bytes common to the end of
// each string.
func commonSuffix(text1, text2 string) string {
	n1 := len(text1)
	n2 := len(text2)
	n := min(n1, n2)

	for i := 1; i <= n; i++ {
		if text1[n1-i] != text2[n2-i] {
			n = i - 1
			for n > 0 && !utf8.RuneStart(text1[n1-n]) {
				n--
			}
			break
		}
	}
	return text1[n1-n:]
}

// Determine if the suffix of the first string is the prefix of the second.
// Returns the number of bytes common to the end of the first
// string and the start of the second string.
func commonOverlap(text1, text2 string) (best string) {
	// Cache the text lengths to prevent multiple calls.
	n1 := len(text1)
	n2 := len(text2)

	switch {
	// Eliminate the null case
	case n1 == 0 || n2 == 0:
		return

	// Truncate the longer string
	case n1 > n2:
		text1 = utf8SliceRightX(text1, n1-n2)
		n1 = len(text1)
	case n2 < n1:
		text2 = text2[:n1]
	}

	// Quick check for the worst case.
	if text1 == text2 {
		return text1
	}

	// Start by looking for a single character match
	// and increase length until no match is found.
	length := len(utf8SliceRight(text1, n1-1))
	for length <= n1 {
		pattern := text1[n1-length:]
		found := strings.Index(text2, pattern)
		if found == -1 {
			return
		}
		length += found
		if found == 0 {
			best = text2[:length]
			if length == n1 {
				return
			}
			length = len(utf8SliceRight(text1, n1-length-1))
		}
	}
	return
}

func min(n1, n2 int) int {
	if n1 < n2 {
		return n1
	}
	return n2
}

func max(n1, n2 int) int {
	if n1 > n2 {
		return n1
	}
	return n2
}

func isOdd(v int) bool {
	return v&1 != 0
}

// Create a slice s[i0:], taking care that i0
// points to the start of a character. Decrease
// i0 until this condition is met.
func utf8SliceRight(s string, i0 int) string {
	for i0 >= 0 && !utf8.RuneStart(s[i0]) {
		i0--
	}
	return s[i0:]
}

// Create a slice s[i0:], taking care that i0
// points to the start of a character. Increase
// i0 until this condition is met.
func utf8SliceRightX(s string, i0 int) string {
	n := len(s)
	for i0 != n && !utf8.RuneStart(s[i0]) {
		i0++
	}
	return s[i0:]
}

func firstRune(s string) (r rune) {
	r, _ = utf8.DecodeRuneInString(s)
	return
}

func lastRune(s string) (r rune) {
	r, _ = utf8.DecodeLastRuneInString(s)
	return
}

func firstUTF8(s string) string {
	_, n := utf8.DecodeRuneInString(s)
	return s[:n]
}

func lastUTF8(s string) string {
	_, n := utf8.DecodeLastRuneInString(s)
	return s[len(s)-n:]
}

func exceedsRuneCount(s string, count int) (exceeds bool) {
	for _ = range s {
		if count == 0 {
			exceeds = true
			break
		}
		count--
	}
	return
}

func runeCount(s string) int {
	return utf8.RuneCountInString(s)
}

type strbuf []string

func (p *strbuf) join() (s string) {
	buf := *p
	s = strings.Join(buf, "")
	*p = buf[:0]
	return
}
<|endoftext|>


<commit_before>// Copyright (C) 2013 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// Package uuid provides implementation of Universally Unique Identifier (UUID).
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
// version 2 (as specified in DCE 1.1).
package uuid

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"hash"
	"net"
	"os"
	"strings"
	"time"
)

// UUID layout variants.
const (
	VariantNCS = iota
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// UUID DCE domains.
const (
	DomainPerson = iota
	DomainGroup
	DomainOrg
)

// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000

// UUID v1/v2 storage.
var (
	clockSequence uint16
	lastTime      uint64
	hardwareAddr  [6]byte
	posixUID      = uint32(os.Getuid())
	posixGID      = uint32(os.Getgid())
)

// Epoch calculation function
var epochFunc func() uint64

// Initialize storage
func init() {
	buf := make([]byte, 2)
	rand.Read(buf)
	clockSequence = binary.BigEndian.Uint16(buf)

	// Initialize hardwareAddr randomly in case
	// of real network interfaces absence
	rand.Read(hardwareAddr[:])

	interfaces, err := net.Interfaces()
	if err == nil {
		for _, iface := range interfaces {
			if len(iface.HardwareAddr) >= 6 {
				copy(hardwareAddr[:], iface.HardwareAddr)
				break
			}
		}
	}
	epochFunc = unixTimeFunc
}

// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
	return epochStart + uint64(time.Now().UnixNano()/100)
}

// UUID representation compliant with specification
// described in RFC 4122.
type UUID [16]byte

// Predefined namespace UUIDs.
var (
	NamespaceDNS, _  = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
	NamespaceURL, _  = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
	NamespaceOID, _  = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
	NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
)

// And returns result of binary AND of two UUIDs.
func And(u1 UUID, u2 UUID) UUID {
	u := UUID{}
	for i := 0; i < 16; i++ {
		u[i] = u1[i] & u2[i]
	}
	return u
}

// Or returns result of binary OR of two UUIDs.
func Or(u1 UUID, u2 UUID) UUID {
	u := UUID{}
	for i := 0; i < 16; i++ {
		u[i] = u1[i] | u2[i]
	}
	return u
}

// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
	return bytes.Equal(u1[:], u2[:])
}

// Version returns algorithm version used to generate UUID.
func (u UUID) Version() uint {
	return uint(u[6] >> 4)
}

// Variant returns UUID layout variant.
func (u UUID) Variant() uint {
	switch {
	case (u[8] & 0x80) == 0x00:
		return VariantNCS
	case (u[8]&0xc0)|0x80 == 0x80:
		return VariantRFC4122
	case (u[8]&0xe0)|0xc0 == 0xc0:
		return VariantMicrosoft
	}
	return VariantFuture
}

// Bytes returns bytes slice representation of UUID.
func (u UUID) Bytes() []byte {
	return u[:]
}

// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u UUID) String() string {
	return fmt.Sprintf("%x-%x-%x-%x-%x",
		u[:4], u[4:6], u[6:8], u[8:10], u[10:])
}

// SetVersion sets version bits.
func (u *UUID) SetVersion(v byte) {
	u[6] = (u[6] & 0x0f) | (v << 4)
}

// SetVariant sets variant bits as described in RFC 4122.
func (u *UUID) SetVariant() {
	u[8] = (u[8] & 0xbf) | 0x80
}

// Returns UUID epoch timestamp
func getTimestamp() uint64 {
	timeNow := epochFunc()
	// Clock changed backwards since last UUID generation.
	// Should increase clock sequence.
	if timeNow <= lastTime {
		clockSequence++
	}
	lastTime = timeNow
	return timeNow
}

// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
	if len(input) != 16 {
		err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(input))
		return
	}

	copy(u[:], input)

	return
}

// FromString returns UUID parsed from string input.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
func FromString(input string) (u UUID, err error) {
	s := strings.Replace(input, "-", "", -1)

	if len(s) == 41 && s[:9] == "urn:uuid:" {
		s = s[9:]
	} else if len(s) == 34 && s[0] == '{' && s[33] == '}' {
		s = s[1:33]
	}

	if len(s) != 32 {
		err = fmt.Errorf("uuid: invalid UUID string: %s", input)
		return
	}

	b := []byte(s)
	_, err = hex.Decode(u[:], b)

	return
}

// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
	u := UUID{}

	timeNow := getTimestamp()

	binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSequence)

	copy(u[10:], hardwareAddr[:])

	u.SetVersion(1)
	u.SetVariant()

	return u
}

// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
	u := UUID{}

	switch domain {
	case DomainPerson:
		binary.BigEndian.PutUint32(u[0:], posixUID)
	case DomainGroup:
		binary.BigEndian.PutUint32(u[0:], posixGID)
	}

	timeNow := getTimestamp()

	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSequence)
	u[9] = domain

	copy(u[10:], hardwareAddr[:])

	u.SetVersion(2)
	u.SetVariant()

	return u
}

// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
	u := newFromHash(md5.New(), ns, name)
	u.SetVersion(3)
	u.SetVariant()

	return u
}

// NewV4 returns random generated UUID.
func NewV4() UUID {
	u := UUID{}
	rand.Read(u[:])
	u.SetVersion(4)
	u.SetVariant()

	return u
}

// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
	u := newFromHash(sha1.New(), ns, name)
	u.SetVersion(5)
	u.SetVariant()

	return u
}

// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
	u := UUID{}
	h.Write(ns[:])
	h.Write([]byte(name))
	copy(u[:], h.Sum(nil))

	return u
}
<commit_msg>Set multicast bit for random generated MAC<commit_after>// Copyright (C) 2013 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

// Package uuid provides implementation of Universally Unique Identifier (UUID).
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
// version 2 (as specified in DCE 1.1).
package uuid

import (
	"bytes"
	"crypto/md5"
	"crypto/rand"
	"crypto/sha1"
	"encoding/binary"
	"encoding/hex"
	"fmt"
	"hash"
	"net"
	"os"
	"strings"
	"time"
)

// UUID layout variants.
const (
	VariantNCS = iota
	VariantRFC4122
	VariantMicrosoft
	VariantFuture
)

// UUID DCE domains.
const (
	DomainPerson = iota
	DomainGroup
	DomainOrg
)

// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000

// UUID v1/v2 storage.
var (
	clockSequence uint16
	lastTime      uint64
	hardwareAddr  [6]byte
	posixUID      = uint32(os.Getuid())
	posixGID      = uint32(os.Getgid())
)

// Epoch calculation function
var epochFunc func() uint64

// Initialize storage
func init() {
	buf := make([]byte, 2)
	rand.Read(buf)
	clockSequence = binary.BigEndian.Uint16(buf)

	// Initialize hardwareAddr randomly in case
	// of real network interfaces absence
	rand.Read(hardwareAddr[:])

	// Set multicast bit as recommended in RFC 4122
	hardwareAddr[0] |= 0x01

	interfaces, err := net.Interfaces()
	if err == nil {
		for _, iface := range interfaces {
			if len(iface.HardwareAddr) >= 6 {
				copy(hardwareAddr[:], iface.HardwareAddr)
				break
			}
		}
	}
	epochFunc = unixTimeFunc
}

// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
	return epochStart + uint64(time.Now().UnixNano()/100)
}

// UUID representation compliant with specification
// described in RFC 4122.
type UUID [16]byte

// Predefined namespace UUIDs.
var (
	NamespaceDNS, _  = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
	NamespaceURL, _  = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
	NamespaceOID, _  = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
	NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
)

// And returns result of binary AND of two UUIDs.
func And(u1 UUID, u2 UUID) UUID {
	u := UUID{}
	for i := 0; i < 16; i++ {
		u[i] = u1[i] & u2[i]
	}
	return u
}

// Or returns result of binary OR of two UUIDs.
func Or(u1 UUID, u2 UUID) UUID {
	u := UUID{}
	for i := 0; i < 16; i++ {
		u[i] = u1[i] | u2[i]
	}
	return u
}

// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
	return bytes.Equal(u1[:], u2[:])
}

// Version returns algorithm version used to generate UUID.
func (u UUID) Version() uint {
	return uint(u[6] >> 4)
}

// Variant returns UUID layout variant.
func (u UUID) Variant() uint {
	switch {
	case (u[8] & 0x80) == 0x00:
		return VariantNCS
	case (u[8]&0xc0)|0x80 == 0x80:
		return VariantRFC4122
	case (u[8]&0xe0)|0xc0 == 0xc0:
		return VariantMicrosoft
	}
	return VariantFuture
}

// Bytes returns bytes slice representation of UUID.
func (u UUID) Bytes() []byte {
	return u[:]
}

// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u UUID) String() string {
	return fmt.Sprintf("%x-%x-%x-%x-%x",
		u[:4], u[4:6], u[6:8], u[8:10], u[10:])
}

// SetVersion sets version bits.
func (u *UUID) SetVersion(v byte) {
	u[6] = (u[6] & 0x0f) | (v << 4)
}

// SetVariant sets variant bits as described in RFC 4122.
func (u *UUID) SetVariant() {
	u[8] = (u[8] & 0xbf) | 0x80
}

// Returns UUID epoch timestamp
func getTimestamp() uint64 {
	timeNow := epochFunc()
	// Clock changed backwards since last UUID generation.
	// Should increase clock sequence.
	if timeNow <= lastTime {
		clockSequence++
	}
	lastTime = timeNow
	return timeNow
}

// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
	if len(input) != 16 {
		err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(input))
		return
	}

	copy(u[:], input)

	return
}

// FromString returns UUID parsed from string input.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
func FromString(input string) (u UUID, err error) {
	s := strings.Replace(input, "-", "", -1)

	if len(s) == 41 && s[:9] == "urn:uuid:" {
		s = s[9:]
	} else if len(s) == 34 && s[0] == '{' && s[33] == '}' {
		s = s[1:33]
	}

	if len(s) != 32 {
		err = fmt.Errorf("uuid: invalid UUID string: %s", input)
		return
	}

	b := []byte(s)
	_, err = hex.Decode(u[:], b)

	return
}

// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
	u := UUID{}

	timeNow := getTimestamp()

	binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSequence)

	copy(u[10:], hardwareAddr[:])

	u.SetVersion(1)
	u.SetVariant()

	return u
}

// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
	u := UUID{}

	switch domain {
	case DomainPerson:
		binary.BigEndian.PutUint32(u[0:], posixUID)
	case DomainGroup:
		binary.BigEndian.PutUint32(u[0:], posixGID)
	}

	timeNow := getTimestamp()

	binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
	binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
	binary.BigEndian.PutUint16(u[8:], clockSequence)
	u[9] = domain

	copy(u[10:], hardwareAddr[:])

	u.SetVersion(2)
	u.SetVariant()

	return u
}

// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
	u := newFromHash(md5.New(), ns, name)
	u.SetVersion(3)
	u.SetVariant()

	return u
}

// NewV4 returns random generated UUID.
func NewV4() UUID {
	u := UUID{}
	rand.Read(u[:])
	u.SetVersion(4)
	u.SetVariant()

	return u
}

// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
	u := newFromHash(sha1.New(), ns, name)
	u.SetVersion(5)
	u.SetVariant()

	return u
}

// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
	u := UUID{}
	h.Write(ns[:])
	h.Write([]byte(name))
	copy(u[:], h.Sum(nil))

	return u
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/gob"
	"encoding/json"
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"
)

var qa_urls = []string{
	"http://is.qa.ec2.srcclr.com:3000/services",
	"http://10.0.3.103:3000/services",
	"http://10.0.3.126:3000/services",
}

var prod_urls = []string{
	"http://is.ec2.srcclr.com:3000/services",
	"http://10.0.5.8:3000/services",
	"http://10.0.5.201:3000/services",
}

// A map for Puppet Versions JSON
type PuppetVersions interface{}

// The final map to be passed to template
type Compared map[string]map[string]map[string]string

// Our bare page
type Page struct {
	Title   string
	Body    []byte
	Compare Compared
	Time    string
}

// What do *you* think this does?
func colorize(versions []string) (color string, err error) {
	match_fail, _ := regexp.Compile(`Failed`)
	if len(versions) > 1 {
		for i := 0; i < len(versions); i++ {
			if match_fail.MatchString(versions[i]) {
				return "orange", nil
			}
		}
		for i := 0; i < len(versions); i++ {
			if versions[i] == versions[i+1] {
				color = "green"
				return color, nil
			} else {
				color = "red"
				return color, nil
			}
		}
	} else {
		return "green", nil
	}
	return "versions not an array?", err
}

func compare(puppet_v map[string]interface{}, qa_v map[string]map[string]string, prod_v map[string]map[string]string) (Compared, error) {
	c := make(map[string]map[string]map[string]string)
	// Setup regex for QA match
	match_qa, err := regexp.Compile(`_qa`)
	if err != nil {
		log.Println("Couldn't compile regex")
		return nil, err
	}
	match_prod, err := regexp.Compile(`_production`)
	if err != nil {
		log.Println("Couldn't compile regex")
		return nil, err
	}
	// Get environments from PuppetVersions, populate top level map
	c["qa"] = make(map[string]map[string]string)
	c["production"] = make(map[string]map[string]string)

	for p_name, pv := range puppet_v {
		// Create regex match for service name
		p_name_arry := strings.Split(p_name, "_")
		match_name := p_name_arry[0]
		match_svc, _ := regexp.Compile(match_name)
		pv_string := pv.(string)
		// Match QA map
		if match_qa.MatchString(p_name) {
			// Add the name and puppet version to QA map
			c["qa"][match_name] = make(map[string]string)
			c["qa"][match_name]["pv"] = pv_string

			// Init new array, add versions for this service
			colorize_arry := []string{}
			colorize_arry = append(colorize_arry, pv_string)
			for svc_name, endpoints := range qa_v {
				if match_svc.MatchString(svc_name) {
					for ep, version := range endpoints {
						c["qa"][match_name][ep] = version
						colorize_arry = append(colorize_arry, version)
						color, _ := colorize(colorize_arry)
						c["qa"][match_name]["color"] = color
					}
				}
			}
		}
		// Do it again for production env
		if match_prod.MatchString(p_name) {
			log.Println("Production MATCH: ", p_name, " ", pv)
			c["production"][match_name] = make(map[string]string)
			c["production"][match_name]["pv"] = pv_string

			// Init new array, add versions for this service
			colorize_arry := []string{}
			colorize_arry = append(colorize_arry, pv_string)
			for svc_name, endpoints := range prod_v {
				if match_svc.MatchString(svc_name) {
					for ep, version := range endpoints {
						c["production"][match_name][ep] = version
						colorize_arry = append(colorize_arry, version)
						color, _ := colorize(colorize_arry)
						c["production"][match_name]["color"] = color
					}
				}
			}
		}
	}

	return c, nil
}

func puppetversions(url string) (PuppetVersions, error) {
	// Get response and handle any errors on return
	resp, err := http.Get(url)
	defer resp.Body.Close()
	if err != nil {
		log.Println(err)
		return nil, err
	}

	// Read JSON from request
	jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// Unmarshel the JSON to our struct
	var v PuppetVersions
	err = json.Unmarshal(jsonDataFromHttp, &v)
	if err != nil {
		return nil, err
	}

	return v, nil
}

func getServices(urls []string) (map[string][]string, error) {
	available_services := make(map[string][]string)

	for _, url := range urls {
		resp, err := http.Get(url)
		if err != nil {
			log.Println(err)
			return nil, err
		}
		defer resp.Body.Close()
		jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}

		var services map[string]map[string][]string //interface{}

		err = json.Unmarshal(jsonDataFromHttp, &services)
		if err != nil {
			return nil, err
		}

		for _, v := range services {
			log.Println("Values: ", v)
			for name, endpoints := range v {
				log.Println("Name: ", name, " ", endpoints)
				available_services[name] = []string{}
				for _, ep := range endpoints {
					available_services[name] = append(available_services[name], ep)
				}
			}
		}
	}

	return available_services, nil
}

func queryServiceVersion(endpoint string) (version string, err error) {
	log.Println("Querying SERVICE address: ", endpoint)
	query_arry := []string{"http://", endpoint, "/info"}
	query := strings.Join(query_arry, "")
	// Query the URI
	timeout := time.Duration(1 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(query)
	if err != nil {
		log.Println("ERROR querying ", query, " ", err)
		return fmt.Sprintf("Failed: %s", err), err
	}
	defer resp.Body.Close()

	// Get data and unmarshel the JSON to our map
	jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println("ERROR unmarsheling data for ", jsonDataFromHttp)
		return fmt.Sprintf("Failed: %s", err), err
	}
	var info_response interface{}
	err = json.Unmarshal(jsonDataFromHttp, &info_response)
	if err != nil {
		return fmt.Sprintf("Failed: %s", err), err
	}
	// Parse out the version from the response
	info_map := info_response.(map[string]interface{})
	log.Println("Response: ", info_response)
	for _, values := range info_map {
		sub_info_map := values.(map[string]interface{})
		for key, info := range sub_info_map {
			string_info := info.(string)
			if key == "version" {
				log.Println("Version: ", string_info)
				return string_info, nil
			}
		}
	}
	return version, nil
}

func getVersions(services map[string][]string) (runningversions map[string]map[string]string, err error) {

	rv := make(map[string]map[string]string)

	for name, endpoints := range services {
		rv[name] = make(map[string]string)
		for _, endpoint := range endpoints {
			query_arry := strings.Fields(endpoint)
			if len(query_arry) == 2 {
				info_ep := query_arry[1]
				version, _ := queryServiceVersion(info_ep)
				rv[name][endpoint] = version
			} else {
				info_ep := query_arry[0]
				version, _ := queryServiceVersion(info_ep)
				rv[name][endpoint] = version
			}
		}
	}
	runningversions = rv
	return runningversions, nil
}

func refreshState() {
	for {
		// Get the versions from the puppet master
		log.Println("Getting Puppet Versions - Make sure VPN is on!")
		pv, err := puppetversions("http://puppet.ec2.srcclr.com:1015/versions")
		if err != nil {
			log.Println("Failed to get Puppet Versions from http://puppet.ec2.srcclr.com:1015/versions\n")
			log.Println(err)
		}
		log.Println("Puppet Versions: ", pv)

		// QA
		log.Println("Getting available services...")
		qa_rs, err := getServices(qa_urls)
		if err != nil {
			log.Println("Failed getting qa versions")
		}

		log.Println("RUNNING SERVICES QA: ", qa_rs)

		qa_v, err := getVersions(qa_rs)
		if err != nil {
			log.Println("Failed getting versions for ", qa_rs)
		}

		log.Println("Running Versions QA: ", qa_v)

		// PRODUCTION
		log.Println("Getting available services...")
		prod_rs, err := getServices(prod_urls)
		if err != nil {
			log.Println("Failed getting production versions")
		}

		log.Println("RUNNING SERVICES QA: ", prod_rs)

		prod_v, err := getVersions(prod_rs)
		if err != nil {
			log.Println("Failed getting versions for ", prod_rs)
		}

		log.Println("Running Versions PRODUCTION: ", prod_v)

		// Build the compared map of maps of strings of other types ... blah blah blah
		pv_map := pv.(map[string]interface{})
		compared, _ := compare(pv_map, qa_v, prod_v)

		for k, v := range compared {
			log.Println(k, " ", v, "\n")
		}
		datafile, err := os.Create("compared.gob")
		if err != nil {
			log.Println(err)
			os.Exit(1)
		}

		dataEncoder := gob.NewEncoder(datafile)
		dataEncoder.Encode(compared)
		datafile.Close()

		log.Println("Sleeping...")
		time.Sleep(time.Second * 10)
	}
}

func loadPage(title string) (*Page, error) {

	t := time.Now().String()
	log.Println(t)
	// Hit and quit it
	go refreshState()

	//read state file to compared
	var compared Compared
	datafile, err := os.Open("compared.gob")
	if err != nil {
		log.Println(err)
	}

	dataDecoder := gob.NewDecoder(datafile)
	err = dataDecoder.Decode(&compared)
	if err != nil {
		log.Println(err)
	}

	datafile.Close()

	filename := title + ".html"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Println(err)
		return nil, err
	}

	return &Page{
			Title:   title,
			Body:    body,
			Compare: compared,
			Time:    t,
		},
		nil
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	log.Println("Loading page view...")
	title := "versionctl"
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}

	// Parse the template, execute and write it to stdout for good measure
	log.Println("Parsing go template...")
	t, _ := template.ParseFiles("versionctl.html")
	t.Execute(w, p)
	//log.Println("Serving:\n", string(p.Title), string(p.Body))
}

func main() {
	fmt.Println(`____   ____                  .__              ____________________.____      `)
	fmt.Println(`\   \ /   /___________  _____|__| ____   ____ \_   ___ \__    ___/|    |     `)
	fmt.Println(` \   Y   // __ \_  __ \/  ___/  |/  _ \ /    \/    \  \/ |    |   |    |     `)
	fmt.Println(`  \     /\  ___/|  | \/\___ \|  (  <_> )   |  \     \____|    |   |    |___  `)
	fmt.Println(`   \___/  \___  >__|  /____  >__|\____/|___|  /\______  /|____|   |_______ \ `)
	fmt.Println(`              \/           \/               \/        \/                  \/ `)

	log.Println("Starting vctl...")
	http.HandleFunc("/", viewHandler)
	http.ListenAndServe(":9000", nil)
}
<commit_msg>fixed logging<commit_after>package main

import (
	"encoding/gob"
	"encoding/json"
	"flag"
	"fmt"
	log "github.com/Sirupsen/logrus"
	"html/template"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strings"
	"time"
)

// Verbose mode?
var verbose = flag.Bool("v", false, "Verbose mode.")

var qa_urls = []string{
	"http://is.qa.ec2.srcclr.com:3000/services",
	"http://10.0.3.103:3000/services",
	"http://10.0.3.126:3000/services",
}

var prod_urls = []string{
	"http://is.ec2.srcclr.com:3000/services",
	"http://10.0.5.8:3000/services",
	"http://10.0.5.201:3000/services",
}

// A map for Puppet Versions JSON
type PuppetVersions interface{}

// The final map to be passed to template
type Compared map[string]map[string]map[string]string

// Our bare page
type Page struct {
	Title   string
	Body    []byte
	Compare Compared
	Time    string
}

// What do *you* think this does?
func colorize(versions []string) (color string, err error) {
	match_fail, _ := regexp.Compile(`Failed`)
	if len(versions) > 1 {
		for i := 0; i < len(versions); i++ {
			if match_fail.MatchString(versions[i]) {
				return "orange", nil
			}
		}
		for i := 0; i < len(versions); i++ {
			if versions[i] == versions[i+1] {
				color = "green"
				return color, nil
			} else {
				color = "red"
				return color, nil
			}
		}
	} else {
		return "green", nil
	}
	return "versions not an array?", err
}

func compare(puppet_v map[string]interface{}, qa_v map[string]map[string]string, prod_v map[string]map[string]string) (Compared, error) {
	c := make(map[string]map[string]map[string]string)
	// Setup regex for QA match
	match_qa, err := regexp.Compile(`_qa`)
	if err != nil {
		log.Error("Couldn't compile regex")
		return nil, err
	}
	match_prod, err := regexp.Compile(`_production`)
	if err != nil {
		log.Error("Couldn't compile regex")
		return nil, err
	}
	// Get environments from PuppetVersions, populate top level map
	c["qa"] = make(map[string]map[string]string)
	c["production"] = make(map[string]map[string]string)

	for p_name, pv := range puppet_v {
		// Create regex match for service name
		p_name_arry := strings.Split(p_name, "_")
		match_name := p_name_arry[0]
		match_svc, _ := regexp.Compile(match_name)
		pv_string := pv.(string)
		// Match QA map
		if match_qa.MatchString(p_name) {
			// Add the name and puppet version to QA map
			c["qa"][match_name] = make(map[string]string)
			c["qa"][match_name]["pv"] = pv_string

			// Init new array, add versions for this service
			colorize_arry := []string{}
			colorize_arry = append(colorize_arry, pv_string)
			for svc_name, endpoints := range qa_v {
				if match_svc.MatchString(svc_name) {
					for ep, version := range endpoints {
						c["qa"][match_name][ep] = version
						colorize_arry = append(colorize_arry, version)
						color, _ := colorize(colorize_arry)
						c["qa"][match_name]["color"] = color
					}
				}
			}
		}
		// Do it again for production env
		if match_prod.MatchString(p_name) {
			log.Debug("Production MATCH: ", p_name, " ", pv)
			c["production"][match_name] = make(map[string]string)
			c["production"][match_name]["pv"] = pv_string

			// Init new array, add versions for this service
			colorize_arry := []string{}
			colorize_arry = append(colorize_arry, pv_string)
			for svc_name, endpoints := range prod_v {
				if match_svc.MatchString(svc_name) {
					for ep, version := range endpoints {
						c["production"][match_name][ep] = version
						colorize_arry = append(colorize_arry, version)
						color, _ := colorize(colorize_arry)
						c["production"][match_name]["color"] = color
					}
				}
			}
		}
	}

	return c, nil
}

func puppetversions(url string) (PuppetVersions, error) {
	// Get response and handle any errors on return
	resp, err := http.Get(url)
	defer resp.Body.Close()
	if err != nil {
		log.Error(err)
		return nil, err
	}

	// Read JSON from request
	jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// Unmarshel the JSON to our struct
	var v PuppetVersions
	err = json.Unmarshal(jsonDataFromHttp, &v)
	if err != nil {
		return nil, err
	}

	return v, nil
}

func getServices(urls []string) (map[string][]string, error) {
	available_services := make(map[string][]string)

	for _, url := range urls {
		resp, err := http.Get(url)
		if err != nil {
			log.Error(err)
			return nil, err
		}
		defer resp.Body.Close()
		jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}

		var services map[string]map[string][]string //interface{}

		err = json.Unmarshal(jsonDataFromHttp, &services)
		if err != nil {
			return nil, err
		}

		for _, v := range services {
			log.Debug("Values: ", v)
			for name, endpoints := range v {
				log.Debug("Name: ", name, " ", endpoints)
				available_services[name] = []string{}
				for _, ep := range endpoints {
					available_services[name] = append(available_services[name], ep)
				}
			}
		}
	}

	return available_services, nil
}

func queryServiceVersion(endpoint string) (version string, err error) {
	log.Debug("Querying SERVICE address: ", endpoint)
	query_arry := []string{"http://", endpoint, "/info"}
	query := strings.Join(query_arry, "")
	// Query the URI
	timeout := time.Duration(1 * time.Second)
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(query)
	if err != nil {
		log.Debug("ERROR querying ", query, " ", err)
		return fmt.Sprintf("Failed: %s", err), err
	}
	defer resp.Body.Close()

	// Get data and unmarshel the JSON to our map
	jsonDataFromHttp, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Error("ERROR unmarsheling data for ", jsonDataFromHttp)
		return fmt.Sprintf("Failed: %s", err), err
	}
	var info_response interface{}
	err = json.Unmarshal(jsonDataFromHttp, &info_response)
	if err != nil {
		return fmt.Sprintf("Failed: %s", err), err
	}
	// Parse out the version from the response
	info_map := info_response.(map[string]interface{})
	log.Debug("Response: ", info_response)
	for _, values := range info_map {
		sub_info_map := values.(map[string]interface{})
		for key, info := range sub_info_map {
			string_info := info.(string)
			if key == "version" {
				log.Debug("Version: ", string_info)
				return string_info, nil
			}
		}
	}
	return version, nil
}

func getVersions(services map[string][]string) (runningversions map[string]map[string]string, err error) {

	rv := make(map[string]map[string]string)

	for name, endpoints := range services {
		rv[name] = make(map[string]string)
		for _, endpoint := range endpoints {
			query_arry := strings.Fields(endpoint)
			if len(query_arry) == 2 {
				info_ep := query_arry[1]
				version, _ := queryServiceVersion(info_ep)
				rv[name][endpoint] = version
			} else {
				info_ep := query_arry[0]
				version, _ := queryServiceVersion(info_ep)
				rv[name][endpoint] = version
			}
		}
	}
	runningversions = rv
	return runningversions, nil
}

func refreshState() {
	for {
		// Get the versions from the puppet master
		log.Debug("Getting Puppet Versions - Make sure VPN is on!")
		pv, err := puppetversions("http://puppet.ec2.srcclr.com:1015/versions")
		if err != nil {
			log.Debug("Failed to get Puppet Versions from http://puppet.ec2.srcclr.com:1015/versions\n")
			log.Error(err)
		}
		log.Debug("Puppet Versions: ", pv)

		// QA
		log.Debug("Getting available services...")
		qa_rs, err := getServices(qa_urls)
		if err != nil {
			log.Error("Failed getting qa versions")
		}

		log.Debug("RUNNING SERVICES QA: ", qa_rs)

		qa_v, err := getVersions(qa_rs)
		if err != nil {
			log.Error("Failed getting versions for ", qa_rs)
		}

		log.Debug("Running Versions QA: ", qa_v)

		// PRODUCTION
		log.Debug("Getting available services...")
		prod_rs, err := getServices(prod_urls)
		if err != nil {
			log.Error("Failed getting production versions")
		}

		log.Debug("RUNNING SERVICES QA: ", prod_rs)

		prod_v, err := getVersions(prod_rs)
		if err != nil {
			log.Error("Failed getting versions for ", prod_rs)
		}

		log.Debug("Running Versions PRODUCTION: ", prod_v)

		// Build the compared map of maps of strings of other types ... blah blah blah
		pv_map := pv.(map[string]interface{})
		compared, _ := compare(pv_map, qa_v, prod_v)

		datafile, err := os.Create("compared.gob")
		if err != nil {
			log.Error(err)
			os.Exit(1)
		}

		dataEncoder := gob.NewEncoder(datafile)
		dataEncoder.Encode(compared)
		datafile.Close()

		time.Sleep(time.Second * 10)
	}
}

func loadPage(title string) (*Page, error) {

	t := time.Now().String()
	// Hit and quit it
	go refreshState()

	//read state file to compared
	var compared Compared
	datafile, err := os.Open("compared.gob")
	if err != nil {
		log.Error(err)
	}

	dataDecoder := gob.NewDecoder(datafile)
	err = dataDecoder.Decode(&compared)
	if err != nil {
		log.Error(err)
	}

	datafile.Close()

	filename := title + ".html"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	return &Page{
			Title:   title,
			Body:    body,
			Compare: compared,
			Time:    t,
		},
		nil
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	title := "versionctl"
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}

	// Parse the template
	t, _ := template.ParseFiles("versionctl.html")
	t.Execute(w, p)
}

func main() {
	fmt.Println(`____   ____                  .__              ____________________.____      `)
	fmt.Println(`\   \ /   /___________  _____|__| ____   ____ \_   ___ \__    ___/|    |     `)
	fmt.Println(` \   Y   // __ \_  __ \/  ___/  |/  _ \ /    \/    \  \/ |    |   |    |     `)
	fmt.Println(`  \     /\  ___/|  | \/\___ \|  (  <_> )   |  \     \____|    |   |    |___  `)
	fmt.Println(`   \___/  \___  >__|  /____  >__|\____/|___|  /\______  /|____|   |_______ \ `)
	fmt.Println(`              \/           \/               \/        \/                  \/ `)
	// Set log level
	flag.Parse()
	if *verbose {
		log.SetLevel(log.DebugLevel)
	} else {
		log.SetLevel(log.InfoLevel)
	}
	// Pass view handler to HTTP func
	http.HandleFunc("/", viewHandler)
	// Deploy server
	http.ListenAndServe(":9000", nil)
}
<|endoftext|>


<commit_before>// Package vego is a pure-go implementation of Vega, a grammar of graphics.
//
// See:
//  https://github.com/trifacta/vega/wiki/Tutorial
//  https://github.com/wrobstory/vincent
//  http://bokeh.pydata.org/index.html
package vego
<commit_msg>vego: references are now in README<commit_after>// Package vego is a pure-go implementation of Vega, a grammar of graphics.
package vego
<|endoftext|>


<commit_before>package utron

import (
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

// View is an interface for rendering templates.
type View interface {
	Render(out io.Writer, name string, data interface{}) error
}

// SimpleView implements View interface, but based on golang templates.
type SimpleView struct {
	viewDir string
	tmpl    *template.Template
}

//NewSimpleView returns a SimpleView with templates loaded from viewDir
func NewSimpleView(viewDir string) (View, error) {
	info, err := os.Stat(viewDir)
	if err != nil {
		return nil, err
	}
	if !info.IsDir() {
		return nil, fmt.Errorf("utron: %s is not a directory", viewDir)
	}
	s := &SimpleView{
		viewDir: viewDir,
		tmpl:    template.New(filepath.Base(viewDir)),
	}
	return s.load(viewDir)
}

// load loads templates from dir. The templates should be valid golang templates
//
// Only files with extension .html, .tpl, .tmpl will be loaded. references to these templates
// should be relative to the dir. That is, if  dir is foo, you dont have to refer to
// foo/bar.tpl, instead just use bar.tpl
func (s *SimpleView) load(dir string) (View, error) {

	// supported is the list of file extensions that will be parsed as templates
	supported := []string{".tpl", ".html", ".tmpl"}

	werr := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}

		extension := filepath.Ext(path)
		found := false
		for _, ext := range supported {
			if ext == extension {
				found = true
				break
			}
		}
		if !found {
			return nil
		}

		data, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}

		// We remove the directory name from the path
		// this means if we have directory foo, with file bar.tpl
		// full path for bar file foo/bar.tpl
		// we trim the foo part and remain with /bar.tpl
		//
		// NOTE we don't account for the opening slash, when dir ends with /.
		name := strings.TrimPrefix(path, dir)

		name = strings.TrimPrefix(name, "/") // case  we missed the opening slash

		name = strings.TrimSuffix(name, extension) // remove extension

		t := s.tmpl.New(name)
		_, err = t.Parse(string(data))
		if err != nil {
			return err
		}
		return nil
	})

	if werr != nil {
		return nil, werr
	}

	return s, nil
}

// Render executes template named name, passing data as context, the output is written to out.
func (s *SimpleView) Render(out io.Writer, name string, data interface{}) error {
	return s.tmpl.ExecuteTemplate(out, name, data)
}
<commit_msg>slicing paths instead of using string.TrimSpace.<commit_after>package utron

import (
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

// View is an interface for rendering templates.
type View interface {
	Render(out io.Writer, name string, data interface{}) error
}

// SimpleView implements View interface, but based on golang templates.
type SimpleView struct {
	viewDir string
	tmpl    *template.Template
}

//NewSimpleView returns a SimpleView with templates loaded from viewDir
func NewSimpleView(viewDir string) (View, error) {
	info, err := os.Stat(viewDir)
	if err != nil {
		return nil, err
	}
	if !info.IsDir() {
		return nil, fmt.Errorf("utron: %s is not a directory", viewDir)
	}
	s := &SimpleView{
		viewDir: viewDir,
		tmpl:    template.New(filepath.Base(viewDir)),
	}
	return s.load(viewDir)
}

// load loads templates from dir. The templates should be valid golang templates
//
// Only files with extension .html, .tpl, .tmpl will be loaded. references to these templates
// should be relative to the dir. That is, if  dir is foo, you dont have to refer to
// foo/bar.tpl, instead just use bar.tpl
func (s *SimpleView) load(dir string) (View, error) {

	// supported is the list of file extensions that will be parsed as templates
	supported := []string{".tpl", ".html", ".tmpl"}

	werr := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.IsDir() {
			return nil
		}

		extension := filepath.Ext(path)
		found := false
		for _, ext := range supported {
			if ext == extension {
				found = true
				break
			}
		}
		if !found {
			return nil
		}

		data, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}

		// We remove the directory name from the path
		// this means if we have directory foo, with file bar.tpl
		// full path for bar file foo/bar.tpl
		// we trim the foo part and remain with /bar.tpl
		//
		// NOTE we don't account for the opening slash, when dir ends with /.
		name := path[len(dir):]

		name = filepath.ToSlash(name)

		name = strings.TrimPrefix(name, "/") // case  we missed the opening slash

		name = strings.TrimSuffix(name, extension) // remove extension

		t := s.tmpl.New(name)
		_, err = t.Parse(string(data))
		if err != nil {
			return err
		}
		return nil
	})

	if werr != nil {
		return nil, werr
	}

	return s, nil
}

// Render executes template named name, passing data as context, the output is written to out.
func (s *SimpleView) Render(out io.Writer, name string, data interface{}) error {
	return s.tmpl.ExecuteTemplate(out, name, data)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
)

var extensions = []string{".jpg", ".jpeg", ".JPG", ".JPEG"}
var metaDir = ".album"

var root = flag.String("root", "", "Album root")
var metaRoot string

func walker(path string, info os.FileInfo, err error) error {

	if info.IsDir() {

		if path == "." {
			return nil
		}

		if path == ".." {
			return nil
		}

		if strings.HasPrefix(info.Name(), ".") {
			return filepath.SkipDir
		}

		return nil
	}

	for _, ext := range extensions {
		if ext == filepath.Ext(info.Name()) {
			normalizedPath := strings.TrimPrefix(path, *root)
			normalizedPath = strings.TrimPrefix(normalizedPath, "/")

			metaDataPath := filepath.Join(metaRoot, "hash", normalizedPath) + ".sha1"

			hashFile, hashFileErr := os.Open(metaDataPath)

			if hashFileErr == nil {
				hashFile.Close()
				return nil
			}

			log.Println("Hashing", normalizedPath)

			file, fileErr := os.Open(path)

			if fileErr != nil {
				return fileErr
			}

			sha := sha1.New()
			io.Copy(sha, file)

			file.Close()

			os.MkdirAll(filepath.Dir(metaDataPath), 0755)
			hashFile, hashFileErr = os.Create(metaDataPath)

			if hashFileErr == nil {
				hashFile.Write(sha.Sum(nil))
				hashFile.Close()
			} else {
				log.Println("Could not write hash file: ", hashFileErr)
			}

			if fileErr != nil {
				return fileErr
			}

			break
		}
	}

	return nil
}

var Usage = func() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	flag.PrintDefaults()
}

func main() {
	flag.Parse()

	if *root == "" {
		Usage()
		return
	}

	*root = filepath.Clean(*root)
	metaRoot = filepath.Join(*root, metaDir)

	if _, rootErr := ioutil.ReadDir(*root); rootErr != nil {
		log.Fatal("Root directory could not be read")
	}

	log.Println("Meta dir: " + metaDir)
	log.Println("Root: " + *root)

	finish := make(chan int)
	go func() {
		walkErr := filepath.Walk(*root, walker)

		if walkErr != nil {
			log.Fatal(walkErr.Error())
		}
		close(finish)
	}()

	<-finish
}
<commit_msg>Concurrency, most likely not done right yet<commit_after>package main

import (
	"crypto/sha1"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
)

var extensions = []string{".jpg", ".jpeg", ".JPG", ".JPEG"}
var metaDir = ".album"

var root = flag.String("root", "", "Album root")
var metaRoot string

type HashingTask struct {
	MetaDataPath string
	FilePath     string
}

func walker(path string, info os.FileInfo, err error) error {

	if info.IsDir() {

		if path == "." {
			return nil
		}

		if path == ".." {
			return nil
		}

		if strings.HasPrefix(info.Name(), ".") {
			return filepath.SkipDir
		}

		return nil
	}

	for _, ext := range extensions {
		if ext == filepath.Ext(info.Name()) {
			normalizedPath := strings.TrimPrefix(path, *root)
			normalizedPath = strings.TrimPrefix(normalizedPath, "/")

			metaDataPath := filepath.Join(metaRoot, "hash", normalizedPath) + ".sha1"

			hashFile, hashFileErr := os.Open(metaDataPath)

			if hashFileErr == nil {
				hashFile.Close()
				return nil
			}

			hasher <- HashingTask{metaDataPath, path}
			// hasher

			break
		}
	}

	return nil
}

var Usage = func() {
	fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
	flag.PrintDefaults()
}

var hasher = make(chan HashingTask, runtime.NumCPU())

func main() {
	flag.Parse()

	if *root == "" {
		Usage()
		return
	}

	log.Printf("Setting up for %d CPUs", runtime.NumCPU())

	*root = filepath.Clean(*root)
	metaRoot = filepath.Join(*root, metaDir)

	if _, rootErr := ioutil.ReadDir(*root); rootErr != nil {
		log.Fatal("Root directory could not be read")
	}

	log.Println("Meta dir: " + metaDir)
	log.Println("Root: " + *root)

	go func() {

		for task := range hasher {

			go func(task HashingTask) {
				log.Println("Task starting for", task.FilePath)
				file, fileErr := os.Open(task.FilePath)

				if fileErr != nil {
					return
				}

				sha := sha1.New()
				io.Copy(sha, file)

				file.Close()

				// sum := sha.Sum(nil)

				/*os.MkdirAll(filepath.Dir(task.MetaDataPath), 0755)
				hashFile, hashFileErr := os.Create(task.MetaDataPath)

				if hashFileErr == nil {
					hashFile.Write(sum)
					hashFile.Close()
				} else {
					log.Println("Could not write hash file: ", hashFileErr)
				}*/

				log.Println("Task done for", task.FilePath)
			}(task)
		}

	}()

	walkErr := filepath.Walk(*root, walker)

	if walkErr != nil {
		log.Fatal(walkErr.Error())
	}
}
<|endoftext|>


<commit_before>package main

import (
	"html/template"
	"io/ioutil"
	"net/http"
)

type Page struct {
	Title string
	Body  []byte
}

var templates = template.Must(template.ParseFiles("edit.tpl.html", "view.tpl.html"))

func (p *Page) save() error {
	filename := p.Title + ".txt"
	return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
	filename := title + ".txt"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return &Page{Title: title, Body: body}, nil
}

func main() {
	http.HandleFunc("/view/", viewHandler)
	http.HandleFunc("/edit/", editHandler)
	http.HandleFunc("/save/", saveHandler)
	http.ListenAndServe(":8080", nil)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/view/"):]
	p, err := loadPage(title)
	if err != nil {
		http.Redirect(w, r, "/edit/"+title, http.StatusFound)
		return
	}
	renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/edit/"):]
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}
	renderTemplate(w, "edit", p)
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
	err := templates.ExecuteTemplate(w, tmpl+".tpl.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
	title := r.URL.Path[len("/save/"):]
	body := r.FormValue("body")
	p := &Page{Title: title, Body: []byte(body)}
	err := p.save()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	http.Redirect(w, r, "/view/"+title, http.StatusFound)
}
<commit_msg>Security improvement<commit_after>package main

import (
	"errors"
	"html/template"
	"io/ioutil"
	"net/http"
	"regexp"
)

type Page struct {
	Title string
	Body  []byte
}

var templates = template.Must(template.ParseFiles("edit.tpl.html", "view.tpl.html"))

var validPath = regexp.MustCompile("^/(edit|save|view)/([a-zA-Z0-9]+)$")

func (p *Page) save() error {
	filename := p.Title + ".txt"
	return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, error) {
	filename := title + ".txt"
	body, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil, err
	}
	return &Page{Title: title, Body: body}, nil
}

func main() {
	http.HandleFunc("/view/", viewHandler)
	http.HandleFunc("/edit/", editHandler)
	http.HandleFunc("/save/", saveHandler)
	http.ListenAndServe(":8080", nil)
}

func viewHandler(w http.ResponseWriter, r *http.Request) {
	title, err := getTitle(w, r)
	if err != nil {
		return
	}
	p, err := loadPage(title)
	if err != nil {
		http.Redirect(w, r, "/edit/"+title, http.StatusFound)
		return
	}
	renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request) {
	title, err := getTitle(w, r)
	if err != nil {
		return
	}
	p, err := loadPage(title)
	if err != nil {
		p = &Page{Title: title}
	}
	renderTemplate(w, "edit", p)
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
	err := templates.ExecuteTemplate(w, tmpl+".tpl.html", p)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func saveHandler(w http.ResponseWriter, r *http.Request) {
	title, err := getTitle(w, r)
	if err != nil {
		return
	}
	body := r.FormValue("body")
	p := &Page{Title: title, Body: []byte(body)}
	err = p.save()
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

func getTitle(w http.ResponseWriter, r *http.Request) (string, error) {
	m := validPath.FindStringSubmatch(r.URL.Path)
	if m == nil {
		http.NotFound(w, r)
		return "", errors.New("Invalid Page Title")
	}
	return m[2], nil // The title is the second subexpression.
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"fmt"
	"net/http"
)

func checkServerError(rw http.ResponseWriter, err error) bool {
	switch {
	case err == sql.ErrNoRows:
		serverResponse(rw, "url not found", 404)
		return true
	case err != nil:
		serverError(rw, err, 500)
		return true
	}

	return false
}

func createUrlHandler(rw http.ResponseWriter, req *http.Request) {
	err := req.ParseForm()
	if err != nil {
		serverError(rw, err, 500)
		return
	}

	url := req.Form.Get("url")

	if url == "" {
		serverResponse(rw, "url should be defined", 422)
		return
	}

	code, err := createUrl(url)
	if err != nil {
		serverError(rw, err, 500)
		return
	}

	shortUrl := fmt.Sprintf("http://%s/%s", config.Url.Domain, code)

	serverResponse(rw, shortUrl, 200)
}

func redirectHandler(rw http.ResponseWriter, req *http.Request) {
	code := requestVars(req)["code"]

	url, err := getUrl(code)

	err = hitRedirect(code)
	if err != nil {
		serverError(rw, err, 500)
		return
	}

	http.Redirect(rw, req, url, 302)
}

func expandHandler(rw http.ResponseWriter, req *http.Request) {
	code := requestVars(req)["code"]

	url, err := getUrl(code)

	if checkServerError(rw, err) {
		return
	}

	serverResponse(rw, url, 200)
}

func statisticsHandler(rw http.ResponseWriter, req *http.Request) {
	code := requestVars(req)["code"]

	count, err := getOpenCount(code)

	if checkServerError(rw, err) {
		return
	}

	serverResponse(rw, fmt.Sprintf("%d", count), 200)
}
<commit_msg>Fix redirect status<commit_after>package main

import (
	"database/sql"
	"fmt"
	"net/http"
)

func checkServerError(rw http.ResponseWriter, err error) bool {
	switch {
	case err == sql.ErrNoRows:
		serverResponse(rw, "url not found", 404)
		return true
	case err != nil:
		serverError(rw, err, 500)
		return true
	}

	return false
}

func createUrlHandler(rw http.ResponseWriter, req *http.Request) {
	err := req.ParseForm()
	if err != nil {
		serverError(rw, err, 500)
		return
	}

	url := req.Form.Get("url")

	if url == "" {
		serverResponse(rw, "url should be defined", 422)
		return
	}

	code, err := createUrl(url)
	if err != nil {
		serverError(rw, err, 500)
		return
	}

	shortUrl := fmt.Sprintf("http://%s/%s", config.Url.Domain, code)

	serverResponse(rw, shortUrl, 200)
}

func redirectHandler(rw http.ResponseWriter, req *http.Request) {
	code := requestVars(req)["code"]

	url, err := getUrl(code)

	err = hitRedirect(code)
	if err != nil {
		serverError(rw, err, 500)
		return
	}

	http.Redirect(rw, req, url, 301)
}

func expandHandler(rw http.ResponseWriter, req *http.Request) {
	code := requestVars(req)["code"]

	url, err := getUrl(code)

	if checkServerError(rw, err) {
		return
	}

	serverResponse(rw, url, 200)
}

func statisticsHandler(rw http.ResponseWriter, req *http.Request) {
	code := requestVars(req)["code"]

	count, err := getOpenCount(code)

	if checkServerError(rw, err) {
		return
	}

	serverResponse(rw, fmt.Sprintf("%d", count), 200)
}
<|endoftext|>