<commit_before>package graphql

import (
	"context"
	"errors"
	"reflect"
	"strings"
	"testing"

	"github.com/davecgh/go-spew/spew"
	"github.com/samsarahq/thunder/internal"
)

func makeQuery() *Object {
	noArguments := func(json interface{}) (interface{}, error) {
		return nil, nil
	}

	query := &Object{
		Name:   "Query",
		Fields: make(map[string]*Field),
	}

	a := &Object{
		Name: "A",
		Key: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return source, nil
		},
		Fields: make(map[string]*Field),
	}

	query.Fields["a"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return 0, nil
		},
		Type:           a,
		ParseArguments: noArguments,
	}

	query.Fields["as"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return []int{0, 1, 2, 3}, nil
		},
		Type:           &List{Type: a},
		ParseArguments: noArguments,
	}

	query.Fields["static"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return "static", nil
		},
		Type:           &Scalar{Type: "string"},
		ParseArguments: noArguments,
	}

	query.Fields["error"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return nil, errors.New("test error")
		},
		Type:           &Scalar{Type: "string"},
		ParseArguments: noArguments,
	}

	query.Fields["panic"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			panic("test panic")
		},
		Type:           &Scalar{Type: "string"},
		ParseArguments: noArguments,
	}

	a.Fields["value"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return source.(int), nil
		},
		Type:           &Scalar{Type: "int"},
		ParseArguments: noArguments,
	}

	a.Fields["nested"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return source.(int) + 1, nil
		},
		Type:           a,
		ParseArguments: noArguments,
	}

	return query
}

func TestBasic(t *testing.T) {
	query := makeQuery()

	q := MustParse(`{
		static
		a { value nested { value } }
		as { value }
	}`, nil)

	if err := PrepareQuery(query, q.SelectionSet); err != nil {
		t.Error(err)
	}
	e := Executor{}
	result, err := e.Execute(context.Background(), query, nil, q)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(internal.AsJSON(result), internal.ParseJSON(`
		{
			"static": "static",
			"a": {
				"value": 0,
				"__key": 0,
				"nested": {
					"value": 1,
					"__key": 1
				}
			},
			"as": [
				{"value": 0, "__key": 0},
				{"value": 1, "__key": 1},
				{"value": 2, "__key": 2},
				{"value": 3, "__key": 3}
			]
		}`)) {
		t.Error("bad value", spew.Sdump(internal.AsJSON(result)))
	}
}

/*
func TestMissingField(t *testing.T) {
	q := MustParse(`
		{
			unknown
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q); err == nil {
		t.Error("expected error")
	}
}

func TestMissingSelectors(t *testing.T) {
	q := MustParse(`
		{
			nested
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q); err == nil {
		t.Error("expected error")
	}
}

func TestUnwantedSelectors(t *testing.T) {
	q := MustParse(`
		{
			bar { bar }
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q); err == nil {
		t.Error("expected error")
	}
}

func TestBadArgs(t *testing.T) {
	q := MustParse(`
		{
			sum(a: "123", b: 4)
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q); err == nil {
		t.Error("expected error")
	}
}
*/

func TestError(t *testing.T) {
	query := makeQuery()

	q := MustParse(`
		query foo {
			error
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q.SelectionSet); err != nil {
		t.Error(err)
	}

	e := Executor{}
	_, err := e.Execute(context.Background(), query, nil, q)
	if err == nil || err.Error() != "foo.error: test error" {
		t.Error("expected test error")
	}
}

// TestPanic tests that a panicing resolver will report an error to a
// context implementing PanicReporter instead of crashing the server.
func TestPanic(t *testing.T) {
	query := makeQuery()

	q := MustParse(`
		{
			panic
		}
	`, nil)

	if err := PrepareQuery(query, q.SelectionSet); err != nil {
		t.Error(err)
	}

	e := Executor{}

	_, err := e.Execute(context.Background(), query, nil, q)
	if err == nil || !strings.Contains(err.Error(), "test panic") {
		t.Error("expected test panic")
	}
	if !strings.Contains(err.Error(), "executor_test.go") {
		t.Error("expected stacktrace")
	}
}

// TODO: Verify caching and concurrency
<commit_msg>graphql/executor_test: add test for repeat arg parsing<commit_after>package graphql

import (
	"context"
	"errors"
	"reflect"
	"strings"
	"testing"

	"github.com/davecgh/go-spew/spew"
	"github.com/samsarahq/thunder/internal"
)

func makeQuery(onArgParse *func()) *Object {
	noArguments := func(json interface{}) (interface{}, error) {
		return nil, nil
	}

	query := &Object{
		Name:   "Query",
		Fields: make(map[string]*Field),
	}

	a := &Object{
		Name: "A",
		Key: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return source, nil
		},
		Fields: make(map[string]*Field),
	}

	query.Fields["a"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return 0, nil
		},
		Type:           a,
		ParseArguments: noArguments,
	}

	query.Fields["as"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return []int{0, 1, 2, 3}, nil
		},
		Type:           &List{Type: a},
		ParseArguments: noArguments,
	}

	query.Fields["static"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return "static", nil
		},
		Type:           &Scalar{Type: "string"},
		ParseArguments: noArguments,
	}

	query.Fields["error"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return nil, errors.New("test error")
		},
		Type:           &Scalar{Type: "string"},
		ParseArguments: noArguments,
	}

	query.Fields["panic"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			panic("test panic")
		},
		Type:           &Scalar{Type: "string"},
		ParseArguments: noArguments,
	}

	a.Fields["value"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return source.(int), nil
		},
		Type:           &Scalar{Type: "int"},
		ParseArguments: noArguments,
	}

	a.Fields["nested"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return source.(int) + 1, nil
		},
		Type:           a,
		ParseArguments: noArguments,
	}

	a.Fields["fieldWithArgs"] = &Field{
		Resolve: func(ctx context.Context, source, args interface{}, selectionSet *SelectionSet) (interface{}, error) {
			return 1, nil
		},
		Type: &Scalar{Type: "int"},
		ParseArguments: func(json interface{}) (interface{}, error) {
			if onArgParse != nil {
				(*onArgParse)()
			}
			return nil, nil
		},
	}

	return query
}

func TestBasic(t *testing.T) {
	query := makeQuery(nil)

	q := MustParse(`{
		static
		a { value nested { value } }
		as { value }
	}`, nil)

	if err := PrepareQuery(query, q.SelectionSet); err != nil {
		t.Error(err)
	}
	e := Executor{}
	result, err := e.Execute(context.Background(), query, nil, q)
	if err != nil {
		t.Error(err)
	}

	if !reflect.DeepEqual(internal.AsJSON(result), internal.ParseJSON(`
		{
			"static": "static",
			"a": {
				"value": 0,
				"__key": 0,
				"nested": {
					"value": 1,
					"__key": 1
				}
			},
			"as": [
				{"value": 0, "__key": 0},
				{"value": 1, "__key": 1},
				{"value": 2, "__key": 2},
				{"value": 3, "__key": 3}
			]
		}`)) {
		t.Error("bad value", spew.Sdump(internal.AsJSON(result)))
	}
}

func TestRepeatedFragment(t *testing.T) {
	ctr := 0
	countArgParse := func() {
		ctr++
	}
	query := makeQuery(&countArgParse)

	q := MustParse(`{
		static
		a { value nested { value ...frag } ...frag }
		as { value }
	}
	fragment frag on A {
		fieldWithArgs(arg1: 1)
	}
	`, nil)

	if err := PrepareQuery(query, q.SelectionSet); err != nil {
		t.Error(err)
	}
	e := Executor{}
	_, err := e.Execute(context.Background(), query, nil, q)
	if err != nil {
		t.Error(err)
	}

	if ctr != 1 {
		t.Errorf("Expected args for fragment to be parsed once, but they were parsed %d times.", ctr)
	}
}

/*
func TestMissingField(t *testing.T) {
	q := MustParse(`
		{
			unknown
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q); err == nil {
		t.Error("expected error")
	}
}

func TestMissingSelectors(t *testing.T) {
	q := MustParse(`
		{
			nested
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q); err == nil {
		t.Error("expected error")
	}
}

func TestUnwantedSelectors(t *testing.T) {
	q := MustParse(`
		{
			bar { bar }
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q); err == nil {
		t.Error("expected error")
	}
}

func TestBadArgs(t *testing.T) {
	q := MustParse(`
		{
			sum(a: "123", b: 4)
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q); err == nil {
		t.Error("expected error")
	}
}
*/

func TestError(t *testing.T) {
	query := makeQuery(nil)

	q := MustParse(`
		query foo {
			error
		}
	`, map[string]interface{}{})

	if err := PrepareQuery(query, q.SelectionSet); err != nil {
		t.Error(err)
	}

	e := Executor{}
	_, err := e.Execute(context.Background(), query, nil, q)
	if err == nil || err.Error() != "foo.error: test error" {
		t.Error("expected test error")
	}
}

// TestPanic tests that a panicing resolver will report an error to a
// context implementing PanicReporter instead of crashing the server.
func TestPanic(t *testing.T) {
	query := makeQuery(nil)

	q := MustParse(`
		{
			panic
		}
	`, nil)

	if err := PrepareQuery(query, q.SelectionSet); err != nil {
		t.Error(err)
	}

	e := Executor{}

	_, err := e.Execute(context.Background(), query, nil, q)
	if err == nil || !strings.Contains(err.Error(), "test panic") {
		t.Error("expected test panic")
	}
	if !strings.Contains(err.Error(), "executor_test.go") {
		t.Error("expected stacktrace")
	}
}

// TODO: Verify caching and concurrency
<|endoftext|>


<commit_before>package interfaces

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"github.com/Tinker-Ware/gh-service/domain"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"golang.org/x/oauth2"
)

const htmlIndex = `
Logged in with GitHub
`

const htmlCloseWindow = `
Logged in with GitHub
`

type repoRequest struct {
	Owner   string `json:"owner"`
	Name    string `json:"name"`
	Private bool   `json:"private"`
	Org     string `json:"org"`
}

type fileRequest struct {
	domain.Author
	domain.File
}

type multipleFilesRequest struct {
	Author domain.Author `json:"author"`
	Files  []domain.File `json:"files"`
}

type GHInteractor interface {
	GHCallback(code, state, incomingState string) (*domain.User, error)
	GHLogin() (string, string)
	ShowUser(username string) (*domain.User, error)
	ShowRepos(username string) ([]domain.Repository, error)
	CreateRepo(username, reponame, org string, private bool) (*domain.Repository, error)
	ShowRepo(username, repo string) (*domain.Repository, error)
	ShowKeys(username string) ([]domain.Key, error)
	CreateKey(username string, key *domain.Key) error
	ShowKey(username string, id int) (*domain.Key, error)
	CreateFile(file domain.File, author domain.Author, username, repo string) error
	AddFiles(files []domain.File, author domain.Author, username, repo string) error
}

type WebServiceHandler struct {
	GHInteractor GHInteractor
	Sessions     *sessions.CookieStore
}

func (handler WebServiceHandler) Login(res http.ResponseWriter, req *http.Request) {

	url, state := handler.GHInteractor.GHLogin()

	fmt.Println("State login " + state)

	http.Redirect(res, req, url, http.StatusTemporaryRedirect)

}

func (handler WebServiceHandler) Callback(res http.ResponseWriter, req *http.Request) {

	incomingState := req.FormValue("state")
	code := req.FormValue("code")

	state := ""
	user, err := handler.GHInteractor.GHCallback(code, state, incomingState)
	if err != nil {
		return
	}

	usrB, _ := json.Marshal(user)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(usrB)

}

func (handler WebServiceHandler) Root(res http.ResponseWriter, req *http.Request) {
	res.Header().Set("Content-Type", "text/html; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(htmlIndex))
}

func (handler WebServiceHandler) GetCurrentUser(res http.ResponseWriter, req *http.Request) {
	session, err := handler.Sessions.Get(req, "user")
	if err != nil {
		http.Error(res, err.Error(), 500)
		return
	}

	usr := session.Values["user"]

	userS := usr.(string)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(userS))

}

func (handler WebServiceHandler) ShowUser(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	user, err := handler.GHInteractor.ShowUser(username)

	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusNotFound)
		return
	}

	userB, _ := json.Marshal(user)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(userB))
}

func (handler WebServiceHandler) ShowRepos(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	repos, err := handler.GHInteractor.ShowRepos(username)

	if err != nil {
		res.WriteHeader(http.StatusNotFound)
		return
	}

	reposB, _ := json.Marshal(repos)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(reposB))
}

func (handler WebServiceHandler) CreateRepo(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	decoder := json.NewDecoder(req.Body)
	repo := repoRequest{}
	err := decoder.Decode(&repo)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	r, err := handler.GHInteractor.CreateRepo(repo.Owner, repo.Name, repo.Org, repo.Private)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	repoB, _ := json.Marshal(r)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(repoB))

}

func (handler WebServiceHandler) ShowRepo(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	repo, err := handler.GHInteractor.ShowRepo(username, repoName)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return

	}

	repoB, _ := json.Marshal(repo)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(repoB))

}

func (handler WebServiceHandler) ShowKeys(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	keys, err := handler.GHInteractor.ShowKeys(username)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return

	}

	keysB, _ := json.Marshal(keys)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keysB))

}

func (handler WebServiceHandler) CreateKey(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	decoder := json.NewDecoder(req.Body)
	key := domain.Key{}
	err := decoder.Decode(&key)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	vars := mux.Vars(req)
	username := vars["username"]

	err = handler.GHInteractor.CreateKey(username, &key)

	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keyB))
}

func (handler WebServiceHandler) ShowKey(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	idStr := vars["id"]

	id, err := strconv.Atoi(idStr)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	key, err := handler.GHInteractor.ShowKey(username, id)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keyB))

}

func (handler WebServiceHandler) AddFileToRepository(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	decoder := json.NewDecoder(req.Body)
	file := fileRequest{}
	err := decoder.Decode(&file)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	err = handler.GHInteractor.CreateFile(file.File, file.Author, username, repoName)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.WriteHeader(http.StatusCreated)

}

func (handler WebServiceHandler) AddMultipleFilesToRepository(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	decoder := json.NewDecoder(req.Body)

	request := multipleFilesRequest{}

	err := decoder.Decode(&request)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}
	err = handler.GHInteractor.AddFiles(request.Files, request.Author, username, repoName)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.WriteHeader(http.StatusCreated)

}

func tokenToJSON(token *oauth2.Token) (string, error) {
	d, err := json.Marshal(token)
	if err != nil {
		return "", err
	}
	return string(d), nil

}

func tokenFromJSON(jsonStr string) (*oauth2.Token, error) {
	var token oauth2.Token
	if err := json.Unmarshal([]byte(jsonStr), &token); err != nil {
		return nil, err
	}
	return &token, nil
}
<commit_msg>Add a new struct to render the JSON inside a named object<commit_after>package interfaces

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"

	"github.com/Tinker-Ware/gh-service/domain"
	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"golang.org/x/oauth2"
)

const htmlIndex = `
Logged in with GitHub
`

const htmlCloseWindow = `
Logged in with GitHub
`

type repoRequest struct {
	Owner   string `json:"owner"`
	Name    string `json:"name"`
	Private bool   `json:"private"`
	Org     string `json:"org"`
}

type fileRequest struct {
	domain.Author
	domain.File
}

type multipleFilesRequest struct {
	Author domain.Author `json:"author"`
	Files  []domain.File `json:"files"`
}

type repoResponse struct {
	Repository *domain.Repository `json:"repository"`
}

type GHInteractor interface {
	GHCallback(code, state, incomingState string) (*domain.User, error)
	GHLogin() (string, string)
	ShowUser(username string) (*domain.User, error)
	ShowRepos(username string) ([]domain.Repository, error)
	CreateRepo(username, reponame, org string, private bool) (*domain.Repository, error)
	ShowRepo(username, repo string) (*domain.Repository, error)
	ShowKeys(username string) ([]domain.Key, error)
	CreateKey(username string, key *domain.Key) error
	ShowKey(username string, id int) (*domain.Key, error)
	CreateFile(file domain.File, author domain.Author, username, repo string) error
	AddFiles(files []domain.File, author domain.Author, username, repo string) error
}

type WebServiceHandler struct {
	GHInteractor GHInteractor
	Sessions     *sessions.CookieStore
}

func (handler WebServiceHandler) Login(res http.ResponseWriter, req *http.Request) {

	url, state := handler.GHInteractor.GHLogin()

	fmt.Println("State login " + state)

	http.Redirect(res, req, url, http.StatusTemporaryRedirect)

}

func (handler WebServiceHandler) Callback(res http.ResponseWriter, req *http.Request) {

	incomingState := req.FormValue("state")
	code := req.FormValue("code")

	state := ""
	user, err := handler.GHInteractor.GHCallback(code, state, incomingState)
	if err != nil {
		return
	}

	usrB, _ := json.Marshal(user)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusCreated)
	res.Write(usrB)

}

func (handler WebServiceHandler) Root(res http.ResponseWriter, req *http.Request) {
	res.Header().Set("Content-Type", "text/html; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(htmlIndex))
}

func (handler WebServiceHandler) GetCurrentUser(res http.ResponseWriter, req *http.Request) {
	session, err := handler.Sessions.Get(req, "user")
	if err != nil {
		http.Error(res, err.Error(), 500)
		return
	}

	usr := session.Values["user"]

	userS := usr.(string)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(userS))

}

func (handler WebServiceHandler) ShowUser(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	user, err := handler.GHInteractor.ShowUser(username)

	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusNotFound)
		return
	}

	userB, _ := json.Marshal(user)

	res.Header().Set("Content-Type", "application/json")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(userB))
}

func (handler WebServiceHandler) ShowRepos(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	repos, err := handler.GHInteractor.ShowRepos(username)

	if err != nil {
		res.WriteHeader(http.StatusNotFound)
		return
	}

	reposB, _ := json.Marshal(repos)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(reposB))
}

func (handler WebServiceHandler) CreateRepo(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	decoder := json.NewDecoder(req.Body)
	repo := repoRequest{}
	err := decoder.Decode(&repo)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	r, err := handler.GHInteractor.CreateRepo(repo.Owner, repo.Name, repo.Org, repo.Private)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	repoB, _ := json.Marshal(r)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(repoB))

}

func (handler WebServiceHandler) ShowRepo(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	repo, err := handler.GHInteractor.ShowRepo(username, repoName)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return

	}

	repoR := repoResponse{
		Repository: repo,
	}

	repoB, _ := json.Marshal(repoR)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(repoB))

}

func (handler WebServiceHandler) ShowKeys(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]

	keys, err := handler.GHInteractor.ShowKeys(username)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return

	}

	keysB, _ := json.Marshal(keys)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keysB))

}

func (handler WebServiceHandler) CreateKey(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	decoder := json.NewDecoder(req.Body)
	key := domain.Key{}
	err := decoder.Decode(&key)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	vars := mux.Vars(req)
	username := vars["username"]

	err = handler.GHInteractor.CreateKey(username, &key)

	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keyB))
}

func (handler WebServiceHandler) ShowKey(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	idStr := vars["id"]

	id, err := strconv.Atoi(idStr)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	key, err := handler.GHInteractor.ShowKey(username, id)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	keyB, _ := json.Marshal(key)

	res.Header().Set("Content-Type", "application/json; charset=utf-8")
	res.WriteHeader(http.StatusOK)
	res.Write([]byte(keyB))

}

func (handler WebServiceHandler) AddFileToRepository(res http.ResponseWriter, req *http.Request) {
	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	decoder := json.NewDecoder(req.Body)
	file := fileRequest{}
	err := decoder.Decode(&file)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	err = handler.GHInteractor.CreateFile(file.File, file.Author, username, repoName)
	if err != nil {
		fmt.Println(err.Error())
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.WriteHeader(http.StatusCreated)

}

func (handler WebServiceHandler) AddMultipleFilesToRepository(res http.ResponseWriter, req *http.Request) {
	defer req.Body.Close()

	vars := mux.Vars(req)
	username := vars["username"]
	repoName := vars["repo"]

	decoder := json.NewDecoder(req.Body)

	request := multipleFilesRequest{}

	err := decoder.Decode(&request)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}
	err = handler.GHInteractor.AddFiles(request.Files, request.Author, username, repoName)
	if err != nil {
		res.WriteHeader(http.StatusInternalServerError)
		return
	}

	res.WriteHeader(http.StatusCreated)

}

func tokenToJSON(token *oauth2.Token) (string, error) {
	d, err := json.Marshal(token)
	if err != nil {
		return "", err
	}
	return string(d), nil

}

func tokenFromJSON(jsonStr string) (*oauth2.Token, error) {
	var token oauth2.Token
	if err := json.Unmarshal([]byte(jsonStr), &token); err != nil {
		return nil, err
	}
	return &token, nil
}
<|endoftext|>


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

package go_download_sdk_test

import (
	"bytes"
	"io/ioutil"
	"testing"

	"github.com/bazelbuild/rules_go/go/tools/bazel_testing"
)

func TestMain(m *testing.M) {
	bazel_testing.TestMain(m, bazel_testing.Args{
		Main: `
-- BUILD.bazel --
load("@io_bazel_rules_go//go:def.bzl", "go_test")

go_test(
    name = "version_test",
    srcs = ["version_test.go"],
)

-- version_test.go --
package version_test

import (
	"flag"
	"runtime"
	"testing"
)

var want = flag.String("version", "", "")

func Test(t *testing.T) {
	if v := runtime.Version(); v != *want {
		t.Errorf("got version %q; want %q", v, *want)
	}
}
`,
	})
}

func Test(t *testing.T) {
	for _, test := range []struct {
		desc, rule, wantVersion string
	}{
		{
			desc: "version",
			rule: `
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk")

go_download_sdk(
    name = "go_sdk",
    version = "1.13",
)

`,
			wantVersion: "go1.13",
		}, {
			desc: "custom_archives",
			rule: `
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk")

go_download_sdk(
    name = "go_sdk",
    sdks = {
        "darwin_amd64": ("go1.13.darwin-amd64.tar.gz", "234ebbba1fbed8474340f79059cfb3af2a0f8b531c4ff0785346e0710e4003dd"),
        "linux_amd64": ("go1.13.linux-amd64.tar.gz", "68a2297eb099d1a76097905a2ce334e3155004ec08cdea85f24527be3c48e856"),
        "windows_amd64": ("go1.13.windows-amd64.zip", "7d162b83157d3171961f8e05a55b7da8476244df3fac28a5da1c9e215acfea89"),
    },
)
`,
			wantVersion: "go1.13",
		},
	} {
		t.Run(test.desc, func(t *testing.T) {
			origWorkspaceData, err := ioutil.ReadFile("WORKSPACE")
			if err != nil {
				t.Fatal(err)
			}

			i := bytes.Index(origWorkspaceData, []byte("go_rules_dependencies()"))
			if i < 0 {
				t.Fatalf("%s: could not find call to go_rules_dependencies()")
			}

			buf := &bytes.Buffer{}
			buf.Write(origWorkspaceData[:i])
			buf.WriteString(test.rule)
			buf.WriteString(`
go_rules_dependencies()

go_register_toolchains()
`)
			if err := ioutil.WriteFile("WORKSPACE", buf.Bytes(), 0666); err != nil {
				t.Fatal(err)
			}
			defer func() {
				if err := ioutil.WriteFile("WORKSPACE", origWorkspaceData, 0666); err != nil {
					t.Errorf("error restoring WORKSPACE: %v", err)
				}
			}()

			if err := bazel_testing.RunBazel("test", "//:version_test", "--test_arg=-version="+test.wantVersion); err != nil {
				t.Fatal(err)
			}
		})
	}
}
<commit_msg>Add ARM-64 version to go_download_sdk test. (#2832)<commit_after>// Copyright 2019 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package go_download_sdk_test

import (
	"bytes"
	"io/ioutil"
	"testing"

	"github.com/bazelbuild/rules_go/go/tools/bazel_testing"
)

func TestMain(m *testing.M) {
	bazel_testing.TestMain(m, bazel_testing.Args{
		Main: `
-- BUILD.bazel --
load("@io_bazel_rules_go//go:def.bzl", "go_test")

go_test(
    name = "version_test",
    srcs = ["version_test.go"],
)

-- version_test.go --
package version_test

import (
	"flag"
	"runtime"
	"testing"
)

var want = flag.String("version", "", "")

func Test(t *testing.T) {
	if v := runtime.Version(); v != *want {
		t.Errorf("got version %q; want %q", v, *want)
	}
}
`,
	})
}

func Test(t *testing.T) {
	for _, test := range []struct {
		desc, rule, wantVersion string
	}{
		{
			desc: "version",
			rule: `
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk")

go_download_sdk(
    name = "go_sdk",
    version = "1.16",
)

`,
			wantVersion: "go1.16",
		}, {
			desc: "custom_archives",
			rule: `
load("@io_bazel_rules_go//go:deps.bzl", "go_download_sdk")

go_download_sdk(
    name = "go_sdk",
    sdks = {
        "darwin_amd64": ("go1.16.darwin-amd64.tar.gz", "6000a9522975d116bf76044967d7e69e04e982e9625330d9a539a8b45395f9a8"),
        "darwin_arm64": ("go1.16.darwin-arm64.tar.gz", "4dac57c00168d30bbd02d95131d5de9ca88e04f2c5a29a404576f30ae9b54810"),
        "linux_amd64": ("go1.16.linux-amd64.tar.gz", "013a489ebb3e24ef3d915abe5b94c3286c070dfe0818d5bca8108f1d6e8440d2"),
        "windows_amd64": ("go1.16.windows-amd64.zip", "5cc88fa506b3d5c453c54c3ea218fc8dd05d7362ae1de15bb67986b72089ce93"),
    },
)
`,
			wantVersion: "go1.16",
		},
	} {
		t.Run(test.desc, func(t *testing.T) {
			origWorkspaceData, err := ioutil.ReadFile("WORKSPACE")
			if err != nil {
				t.Fatal(err)
			}

			i := bytes.Index(origWorkspaceData, []byte("go_rules_dependencies()"))
			if i < 0 {
				t.Fatalf("%s: could not find call to go_rules_dependencies()")
			}

			buf := &bytes.Buffer{}
			buf.Write(origWorkspaceData[:i])
			buf.WriteString(test.rule)
			buf.WriteString(`
go_rules_dependencies()

go_register_toolchains()
`)
			if err := ioutil.WriteFile("WORKSPACE", buf.Bytes(), 0666); err != nil {
				t.Fatal(err)
			}
			defer func() {
				if err := ioutil.WriteFile("WORKSPACE", origWorkspaceData, 0666); err != nil {
					t.Errorf("error restoring WORKSPACE: %v", err)
				}
			}()

			if err := bazel_testing.RunBazel("test", "//:version_test", "--test_arg=-version="+test.wantVersion); err != nil {
				t.Fatal(err)
			}
		})
	}
}
<|endoftext|>


<commit_before>package tail

import (
	"bufio"
	"context"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"

	fsnotify "github.com/fsnotify/fsnotify"
)

const (
	openRetryInterval = time.Second
	tailOldFileDelay  = 15 * time.Second
)

// Line is a line of the target file.
type Line struct {
	Text string
	Time time.Time
}

// Tail tails a file.
type Tail struct {
	Lines  <-chan *Line
	Errors <-chan error

	lines    chan<- *Line
	errors   chan<- error
	filename string
	wg       sync.WaitGroup
	ctx      context.Context
	cancel   context.CancelFunc
}

type tail struct {
	parent *Tail

	file    *os.File
	reader  *bufio.Reader
	watcher *fsnotify.Watcher
	buf     string
	ctx     context.Context
	cancel  context.CancelFunc
}

// NewTailFile starts tailing a file
func NewTailFile(filename string) (*Tail, error) {
	filename, err := filepath.Abs(filename)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithCancel(context.Background())
	lines := make(chan *Line, 16)
	errs := make(chan error, 1)
	parent := &Tail{
		Lines:    lines,
		Errors:   errs,
		lines:    lines,
		errors:   errs,
		filename: filename,
		ctx:      ctx,
		cancel:   cancel,
	}
	parent.wg.Add(1)
	go parent.runFile(os.SEEK_END)
	go parent.wait()
	return parent, nil
}

// NewTailReader starts tailing io.Reader
func NewTailReader(reader io.Reader) (*Tail, error) {
	ctx, cancel := context.WithCancel(context.Background())
	lines := make(chan *Line, 16)
	errs := make(chan error, 1)
	parent := &Tail{
		Lines:  lines,
		Errors: errs,
		lines:  lines,
		errors: errs,
		ctx:    ctx,
		cancel: cancel,
	}
	t := &tail{
		parent: parent,
		reader: bufio.NewReader(reader),
		ctx:    ctx,
		cancel: cancel,
	}
	parent.wg.Add(1)
	go t.runReader()
	go parent.wait()
	return parent, nil
}

// Close stops tailing the file.
func (t *Tail) Close() error {
	t.cancel()
	t.wg.Wait()
	return nil
}

func (t *Tail) wait() {
	t.wg.Wait()
	close(t.errors)
	close(t.lines)
}

// open opens the target file.
// If it does not exist, wait for creating new file.
func (t *Tail) open(seek int) (*tail, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, err
	}
	for {
		file, err := os.Open(t.filename)
		if err == nil {
			// success, seek and watch the file.
			if _, err := file.Seek(0, seek); err != nil {
				file.Close()
				watcher.Close()
				return nil, err
			}
			if err := watcher.Add(t.filename); err != nil {
				file.Close()
				watcher.Close()
				return nil, err
			}
			ctx, cancel := context.WithCancel(t.ctx)
			return &tail{
				parent:  t,
				file:    file,
				reader:  bufio.NewReader(file),
				watcher: watcher,
				ctx:     ctx,
				cancel:  cancel,
			}, nil
		}

		// fail. retry...
		seek = os.SEEK_SET
		select {
		case <-t.ctx.Done():
			return nil, t.ctx.Err()
		case <-time.After(openRetryInterval):
		}
	}
}

// runFile tails target files
func (t *Tail) runFile(seek int) {
	defer t.wg.Done()
	child, err := t.open(seek)
	if err != nil {
		if t.ctx.Err() != nil {
			// stopping tailing now. suppress the error.
			return
		}
		t.errors <- err
		return
	}
	t.wg.Add(1)
	go child.runFile()
}

// runFile tails a file
func (t *tail) runFile() {
	defer t.parent.wg.Done()
	defer t.watcher.Close()
	defer t.cancel()

	cherr := make(chan error)
	ch := make(chan struct{}, 1)
	defer close(ch)

	t.parent.wg.Add(1)
	go func() {
		defer t.parent.wg.Done()
		for {
			if err := t.restrict(); err != nil {
				select {
				case cherr <- err:
				case <-t.ctx.Done():
				}
				return
			}
			err := t.tail()
			if err == nil {
				continue
			}

			// wait for writing new lines.
			select {
			case cherr <- err:
			case <-t.ctx.Done():
				return
			}
			select {
			case _, ok := <-ch:
				if !ok {
					return
				}
			case <-t.ctx.Done():
				return
			}
		}
	}()

	var renamed bool
	var waiting bool // waiting for writing new lines?
	for {
		select {
		case event := <-t.watcher.Events:
			if (event.Op & fsnotify.Remove) != 0 {
				// the target file is removed, stop tailing.
				return
			}
			if (event.Op & fsnotify.Rename) != 0 {
				// log rotation is detected.
				if !renamed {
					// start to watch creating new file.
					t.parent.wg.Add(1)
					go t.parent.runFile(os.SEEK_SET)

					// wait a little, and stop tailing old file.
					go func() {
						timer := time.NewTimer(tailOldFileDelay)
						defer timer.Stop()
						select {
						case <-timer.C:
							t.cancel()
						case <-t.ctx.Done():
						}
					}()
				}
				name, err := getFileName(t.file)
				if err != nil {
					t.parent.errors <- err
					return
				}
				t.watcher.Add(name)
				renamed = true
			}

			// notify new lines are wrote.
			if waiting {
				ch <- struct{}{}
			}
		case err := <-cherr:
			if err == io.EOF {
				waiting = true
			} else {
				t.parent.errors <- err
				return
			}
		case err := <-t.watcher.Errors:
			t.parent.errors <- err
			return
		case <-t.ctx.Done():
			return
		}
	}
}

// runReader tails io.Reader
func (t *tail) runReader() {
	defer t.parent.wg.Done()
	defer t.cancel()
	err := t.tail()
	if err == io.EOF || err == io.ErrClosedPipe {
		return
	}
	if err != nil {
		t.parent.errors <- err
		return
	}
}

// restrict detects a file that is truncated
func (t *tail) restrict() error {
	stat, err := t.file.Stat()
	if err != nil {
		return err
	}
	pos, err := t.file.Seek(0, os.SEEK_CUR)
	if err != nil {
		return err
	}
	if stat.Size() < pos {
		// file is truncated. seek to head of file.
		_, err := t.file.Seek(0, os.SEEK_SET)
		if err != nil {
			return err
		}
	}
	return nil
}

// tail reads lines until EOF
func (t *tail) tail() error {
	for {
		line, err := t.reader.ReadString('\n')
		if err != nil {
			t.buf += line
			return err
		}
		t.parent.lines <- &Line{t.buf + line, time.Now()}
		t.buf = ""
	}
}
<commit_msg>update channel capacity<commit_after>package tail

import (
	"bufio"
	"context"
	"io"
	"os"
	"path/filepath"
	"sync"
	"time"

	fsnotify "github.com/fsnotify/fsnotify"
)

const (
	openRetryInterval = time.Second
	tailOldFileDelay  = 15 * time.Second
	linesCapacity     = 1024
	errorsCapacity    = 16
)

// Line is a line of the target file.
type Line struct {
	Text string
	Time time.Time
}

// Tail tails a file.
type Tail struct {
	Lines  <-chan *Line
	Errors <-chan error

	lines    chan<- *Line
	errors   chan<- error
	filename string
	wg       sync.WaitGroup
	ctx      context.Context
	cancel   context.CancelFunc
}

type tail struct {
	parent *Tail

	file    *os.File
	reader  *bufio.Reader
	watcher *fsnotify.Watcher
	buf     string
	ctx     context.Context
	cancel  context.CancelFunc
}

// NewTailFile starts tailing a file
func NewTailFile(filename string) (*Tail, error) {
	filename, err := filepath.Abs(filename)
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithCancel(context.Background())
	lines := make(chan *Line, linesCapacity)
	errs := make(chan error, errorsCapacity)
	parent := &Tail{
		Lines:    lines,
		Errors:   errs,
		lines:    lines,
		errors:   errs,
		filename: filename,
		ctx:      ctx,
		cancel:   cancel,
	}
	parent.wg.Add(1)
	go parent.runFile(os.SEEK_END)
	go parent.wait()
	return parent, nil
}

// NewTailReader starts tailing io.Reader
func NewTailReader(reader io.Reader) (*Tail, error) {
	ctx, cancel := context.WithCancel(context.Background())
	lines := make(chan *Line, linesCapacity)
	errs := make(chan error, errorsCapacity)
	parent := &Tail{
		Lines:  lines,
		Errors: errs,
		lines:  lines,
		errors: errs,
		ctx:    ctx,
		cancel: cancel,
	}
	t := &tail{
		parent: parent,
		reader: bufio.NewReader(reader),
		ctx:    ctx,
		cancel: cancel,
	}
	parent.wg.Add(1)
	go t.runReader()
	go parent.wait()
	return parent, nil
}

// Close stops tailing the file.
func (t *Tail) Close() error {
	t.cancel()
	t.wg.Wait()
	return nil
}

func (t *Tail) wait() {
	t.wg.Wait()
	close(t.errors)
	close(t.lines)
}

// open opens the target file.
// If it does not exist, wait for creating new file.
func (t *Tail) open(seek int) (*tail, error) {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, err
	}
	for {
		file, err := os.Open(t.filename)
		if err == nil {
			// success, seek and watch the file.
			if _, err := file.Seek(0, seek); err != nil {
				file.Close()
				watcher.Close()
				return nil, err
			}
			if err := watcher.Add(t.filename); err != nil {
				file.Close()
				watcher.Close()
				return nil, err
			}
			ctx, cancel := context.WithCancel(t.ctx)
			return &tail{
				parent:  t,
				file:    file,
				reader:  bufio.NewReader(file),
				watcher: watcher,
				ctx:     ctx,
				cancel:  cancel,
			}, nil
		}

		// fail. retry...
		seek = os.SEEK_SET
		select {
		case <-t.ctx.Done():
			return nil, t.ctx.Err()
		case <-time.After(openRetryInterval):
		}
	}
}

// runFile tails target files
func (t *Tail) runFile(seek int) {
	defer t.wg.Done()
	child, err := t.open(seek)
	if err != nil {
		if t.ctx.Err() != nil {
			// stopping tailing now. suppress the error.
			return
		}
		t.errors <- err
		return
	}
	t.wg.Add(1)
	go child.runFile()
}

// runFile tails a file
func (t *tail) runFile() {
	defer t.parent.wg.Done()
	defer t.watcher.Close()
	defer t.cancel()

	cherr := make(chan error)
	ch := make(chan struct{}, 1)
	defer close(ch)

	t.parent.wg.Add(1)
	go func() {
		defer t.parent.wg.Done()
		for {
			if err := t.restrict(); err != nil {
				select {
				case cherr <- err:
				case <-t.ctx.Done():
				}
				return
			}
			err := t.tail()
			if err == nil {
				continue
			}

			// wait for writing new lines.
			select {
			case cherr <- err:
			case <-t.ctx.Done():
				return
			}
			select {
			case _, ok := <-ch:
				if !ok {
					return
				}
			case <-t.ctx.Done():
				return
			}
		}
	}()

	var renamed bool
	var waiting bool // waiting for writing new lines?
	for {
		select {
		case event := <-t.watcher.Events:
			if (event.Op & fsnotify.Remove) != 0 {
				// the target file is removed, stop tailing.
				return
			}
			if (event.Op & fsnotify.Rename) != 0 {
				// log rotation is detected.
				if !renamed {
					// start to watch creating new file.
					t.parent.wg.Add(1)
					go t.parent.runFile(os.SEEK_SET)

					// wait a little, and stop tailing old file.
					go func() {
						timer := time.NewTimer(tailOldFileDelay)
						defer timer.Stop()
						select {
						case <-timer.C:
							t.cancel()
						case <-t.ctx.Done():
						}
					}()
				}
				name, err := getFileName(t.file)
				if err != nil {
					t.parent.errors <- err
					return
				}
				t.watcher.Add(name)
				renamed = true
			}

			// notify new lines are wrote.
			if waiting {
				ch <- struct{}{}
			}
		case err := <-cherr:
			if err == io.EOF {
				waiting = true
			} else {
				t.parent.errors <- err
				return
			}
		case err := <-t.watcher.Errors:
			t.parent.errors <- err
			return
		case <-t.ctx.Done():
			return
		}
	}
}

// runReader tails io.Reader
func (t *tail) runReader() {
	defer t.parent.wg.Done()
	defer t.cancel()
	err := t.tail()
	if err == io.EOF || err == io.ErrClosedPipe {
		return
	}
	if err != nil {
		t.parent.errors <- err
		return
	}
}

// restrict detects a file that is truncated
func (t *tail) restrict() error {
	stat, err := t.file.Stat()
	if err != nil {
		return err
	}
	pos, err := t.file.Seek(0, os.SEEK_CUR)
	if err != nil {
		return err
	}
	if stat.Size() < pos {
		// file is truncated. seek to head of file.
		_, err := t.file.Seek(0, os.SEEK_SET)
		if err != nil {
			return err
		}
	}
	return nil
}

// tail reads lines until EOF
func (t *tail) tail() error {
	for {
		line, err := t.reader.ReadString('\n')
		if err != nil {
			t.buf += line
			return err
		}
		t.parent.lines <- &Line{t.buf + line, time.Now()}
		t.buf = ""
	}
}
<|endoftext|>


<commit_before>package toodledo

import "time"

type TaskResponse struct {
	Meta  TaskResponseMeta
	Tasks []Task
}

type TaskResponseMeta struct {
	Num   int64 `json:"num"`
	Total int64 `json:"total"`
}

type ToodleTime int64

type Task struct {
	Completed int64  `json:"completed"`
	Folder    int64  `json:"folder"`
	ID        int64  `json:"id"`
	Modified  int64  `json:"modified"`
	Priority  int    `json:"priority"`
	Star      int    `json:"star"`
	Title     string `json:"title"`

	// Optional fields

	// Date and time are ToodleTimes and should not be used directly
	DueDate   ToodleTime `json:"duedate"`
	DueTime   ToodleTime `json:"duetime"`
	StartDate ToodleTime `json:"startdate"`
	StartTime ToodleTime `json:"starttime"`

	Length     int64  `json:"length"`
	TagsString string `json:"tag"`
	Parent     int64  `json:"parent"`
}

func (t Task) Due() *time.Time {
	return parseToodleDateTime(t.DueDate, t.DueTime)
}

func (t Task) Start() *time.Time {
	return parseToodleDateTime(t.StartDate, t.StartTime)
}

func (t Task) ImplicitStart() *time.Time {
	// Default to using the time implied by the due time and length
	if t.Length != 0 && t.Due() != nil {
		result := t.Due().Add(-1 * time.Duration(t.Length) * time.Minute)
		return &result
	}
	return t.Start()
}

func parseToodleDateTime(tdate, ttime ToodleTime) *time.Time {
	if tdate == 0 && ttime == 0 {
		return nil
	}
	//The day and clock time (hour/min/sec) are correct when read in GMT and interpreted as local time
	year, month, day := time.Unix(int64(tdate), 0).UTC().Date()
	hour, min, sec := time.Unix(int64(ttime), 0).UTC().Clock()

	//For some reason it gives the year as 1974 sometimes
	if year < 2010 {
		year, _, _ = time.Now().Date()
	}

	due := time.Date(year, month, day, hour, min, sec, 0, time.Local)
	return &due
}
<commit_msg>Add IsChild convenience function<commit_after>package toodledo

import "time"

type TaskResponse struct {
	Meta  TaskResponseMeta
	Tasks []Task
}

type TaskResponseMeta struct {
	Num   int64 `json:"num"`
	Total int64 `json:"total"`
}

type ToodleTime int64

type Task struct {
	Completed int64  `json:"completed"`
	Folder    int64  `json:"folder"`
	ID        int64  `json:"id"`
	Modified  int64  `json:"modified"`
	Priority  int    `json:"priority"`
	Star      int    `json:"star"`
	Title     string `json:"title"`

	// Optional fields

	// Date and time are ToodleTimes and should not be used directly
	DueDate   ToodleTime `json:"duedate"`
	DueTime   ToodleTime `json:"duetime"`
	StartDate ToodleTime `json:"startdate"`
	StartTime ToodleTime `json:"starttime"`

	Length     int64  `json:"length"`
	TagsString string `json:"tag"`
	Parent     int64  `json:"parent"`
}

func (t Task) Due() *time.Time {
	return parseToodleDateTime(t.DueDate, t.DueTime)
}

func (t Task) Start() *time.Time {
	return parseToodleDateTime(t.StartDate, t.StartTime)
}

func (t Task) ImplicitStart() *time.Time {
	// Default to using the time implied by the due time and length
	if t.Length != 0 && t.Due() != nil {
		result := t.Due().Add(-1 * time.Duration(t.Length) * time.Minute)
		return &result
	}
	return t.Start()
}

func (t Task) IsChild() bool{
    return t.Parent == 0
}

func parseToodleDateTime(tdate, ttime ToodleTime) *time.Time {
	if tdate == 0 && ttime == 0 {
		return nil
	}
	//The day and clock time (hour/min/sec) are correct when read in GMT and interpreted as local time
	year, month, day := time.Unix(int64(tdate), 0).UTC().Date()
	hour, min, sec := time.Unix(int64(ttime), 0).UTC().Clock()

	//For some reason it gives the year as 1974 sometimes
	if year < 2010 {
		year, _, _ = time.Now().Date()
	}

	due := time.Date(year, month, day, hour, min, sec, 0, time.Local)
	return &due
}
<|endoftext|>


<commit_before>// Copyright (c) 2014, Suryandaru Triandana <syndtr@gmail.com>
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package leveldb

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/syndtr/goleveldb/leveldb/opt"
	"github.com/syndtr/goleveldb/leveldb/testutil"
)

var _ = testutil.Defer(func() {
	Describe("Leveldb external", func() {
		o := &opt.Options{
			BlockCache:           opt.NoCache,
			BlockRestartInterval: 5,
			BlockSize:            50,
			Compression:          opt.NoCompression,
			MaxOpenFiles:         0,
			Strict:               opt.StrictAll,
			WriteBuffer:          1000,
		}

		Describe("write test", func() {
			It("should do write correctly", func(done Done) {
				db := newTestingDB(o, nil, nil)
				t := testutil.DBTesting{
					DB:      db,
					Deleted: testutil.KeyValue_Generate(nil, 1000, 1, 30, 5, 5).Clone(),
				}
				testutil.DoDBTesting(&t)
				db.TestClose()
				done <- true
			}, 9.0)
		})

		Describe("read test", func() {
			testutil.AllKeyValueTesting(nil, func(kv testutil.KeyValue) testutil.DB {
				// Building the DB.
				db := newTestingDB(o, nil, nil)
				kv.IterateShuffled(nil, func(i int, key, value []byte) {
					err := db.TestPut(key, value)
					Expect(err).NotTo(HaveOccurred())
				})
				testutil.Defer("teardown", func() {
					db.TestClose()
				})

				return db
			})
		})
	})
})
<commit_msg>leveldb: Decrease 'Leveldb external write test' test data<commit_after>// Copyright (c) 2014, Suryandaru Triandana <syndtr@gmail.com>
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package leveldb

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"github.com/syndtr/goleveldb/leveldb/opt"
	"github.com/syndtr/goleveldb/leveldb/testutil"
)

var _ = testutil.Defer(func() {
	Describe("Leveldb external", func() {
		o := &opt.Options{
			BlockCache:           opt.NoCache,
			BlockRestartInterval: 5,
			BlockSize:            50,
			Compression:          opt.NoCompression,
			MaxOpenFiles:         0,
			Strict:               opt.StrictAll,
			WriteBuffer:          1000,
		}

		Describe("write test", func() {
			It("should do write correctly", func(done Done) {
				db := newTestingDB(o, nil, nil)
				t := testutil.DBTesting{
					DB:      db,
					Deleted: testutil.KeyValue_Generate(nil, 500, 1, 30, 5, 5).Clone(),
				}
				testutil.DoDBTesting(&t)
				db.TestClose()
				done <- true
			}, 9.0)
		})

		Describe("read test", func() {
			testutil.AllKeyValueTesting(nil, func(kv testutil.KeyValue) testutil.DB {
				// Building the DB.
				db := newTestingDB(o, nil, nil)
				kv.IterateShuffled(nil, func(i int, key, value []byte) {
					err := db.TestPut(key, value)
					Expect(err).NotTo(HaveOccurred())
				})
				testutil.Defer("teardown", func() {
					db.TestClose()
				})

				return db
			})
		})
	})
})
<|endoftext|>


<commit_before>package main

import (
	"runtime"
	"fmt"
	"github.com/robert-butts/quadtree"
	"math/rand"
	"strconv"
	"time"
)

func init() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	rand.Seed(time.Now().UnixNano())
}

func main() {
	nodeCapacity := 4
	qt := quadtree.New(&quadtree.BoundingBox{
		Center:        quadtree.Point{100.0, 100.0},
		HalfDimension: quadtree.Point{50.0, 50.0},
	}, nodeCapacity)

	pointsToInsert := 10000000
	queries := 100
	threads := runtime.NumCPU()

	tpoints := pointsToInsert / threads
	done := make(chan bool)

	insertPoint := func() {
		for i := 0; i != tpoints; i++ {
			p := &quadtree.Point{rand.Float64()*100.0 + 50.0, rand.Float64()*100.0 + 50.0}
			qt.Insert(p)
		}
		done <- true
	}
	start := time.Now()
	for i := 0; i != threads; i++ {
		go insertPoint()
	}

	for i := 0; i != threads; i++ {
		<- done
	}
	end := time.Now()
	elapsed := end.Sub(start)
	fmt.Println("inserted " + strconv.Itoa(tpoints * threads) + " points in " + elapsed.String() + ".")

	found := 0
	start = time.Now()
	box := &quadtree.BoundingBox {
		Center: quadtree.Point { 100.0, 100.0 },
		HalfDimension: quadtree.Point { 5.0, 5.0,},
	}
	for i := 0; i != queries; i++ {
		box.Center = quadtree.Point{rand.Float64()*100.0 + 50.0, rand.Float64()*100.0 + 50.0}
		points := qt.Query(box)
		found += len(points)
	}
//	fmt.Println("found " + strconv.Itoa(len(points)) + " points")
	end = time.Now()
	elapsed = end.Sub(start)
	fmt.Println("queried " + strconv.Itoa(found) + " points via " + strconv.Itoa(queries) + " queries in " + elapsed.String() + ".")
	//	for _, point := range points {
	//		fmt.Println(point.String())
	//	}
}
<commit_msg>renamed test.go to conform to go test<commit_after><|endoftext|>


<commit_before>// Package timeutils provides some convenience functions around time.
package timeutils

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"time"
)

var (
	StdLayout     = "2006-01-02 15:04" // a simple time layout
	EmptyTimeZone = TimeZone("")       // the empty timezone
)

// TimeZone is a string that can be given to time.LoadLocation.
type TimeZone string

// MustLoadLoc loads the time.Location specified by the string, or panics.
func MustLoadLoc(tz TimeZone) *time.Location {
	loc, err := time.LoadLocation(string(tz))
	if err != nil {
		log.Fatal("bad location: %v\n", err)
	}
	return loc
}

// Must panics if error is non-nil.
//
// Intended use is to wrap function calls that must succeed, e.g:
//   t := Must(ParseStd("2013-07-31"))
func Must(t time.Time, err error) time.Time {
	if err != nil {
		log.Fatalf("got err: %v\n", err)
	}
	return t
}

// ParseStd parses the value using a standard layout, with time.UTC timezone.
func ParseStd(value string) (time.Time, error) {
	return time.Parse(StdLayout, value)
}

// daysIn returns the number of days in a month for a given year.
func daysIn(m time.Month, year int) int {
	// This is equivalent to the unexported time.daysIn(m, year).
	return time.Date(year, m+1, 0, 0, 0, 0, 0, time.UTC).Day()
}

// Weekday gets the Monday-indexed number for the time.Weekday.
func Weekday(d time.Weekday) int {
	day := (d - 1) % 7
	if day < 0 {
		day += 7
	}
	return int(day)
}

// StartOfWeek returns the start of the current week for the time.
func StartOfWeek(t time.Time) time.Time {
	// Figure out number of days to back up until Mon:
	// Sun is 0 -> 6, Sat is 6 -> 5, etc.
	toMon := Weekday(t.Weekday())
	y, m, d := t.AddDate(0, 0, -int(toMon)).Date()
	// Result is 00:00:00 on that year, month, day.
	return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
}

// Parse extracts time from string-based info, with some constraints.
//
// The described time cannot be in the future, or more than 1000 years in the past.
//
// Note that month is 0-indexed, unlike time.Month.
func Parse(year, month, day, hourMinute string, loc *time.Location) (time.Time, error) {
	now := time.Now().In(loc)

	y64, err := strconv.ParseInt(year, 10, 0)
	y := int(y64)
	if err != nil {
		return time.Time{}, err
	}
	if y < now.Year()-1000 {
		return time.Time{}, fmt.Errorf("bad year; %d is too far in the past", y)
	}
	m, err := strconv.ParseInt(month, 10, 0)
	if err != nil {
		return time.Time{}, err
	}
	if m < 0 || m > 11 {
		return time.Time{}, fmt.Errorf("bad month: %d is not within [0, 11]", m)
	}
	// Month +1 since time.Month is [1, 12].
	m = m + 1
	d64, err := strconv.ParseInt(day, 10, 0)
	d := int(d64)
	if err != nil {
		return time.Time{}, err
	}
	if d < 1 {
		return time.Time{}, fmt.Errorf("bad day: %d; can't be negative", d)
	} else if d > daysIn(time.Month(m), y) {
		return time.Time{}, fmt.Errorf("bad day: %d; only %d days in %v, %d", d, daysIn(time.Month(m), y), time.Month(m), y)
	}
	parts := strings.Split(hourMinute, ":")
	if len(parts) != 2 {
		return time.Time{}, fmt.Errorf("bad hour/minute: %s", hourMinute)
	}
	h, err := strconv.ParseInt(parts[0], 10, 0)
	if err != nil {
		return time.Time{}, err
	}
	if h < 0 || h > 60 {
		return time.Time{}, fmt.Errorf("bad hour: %d", h)
	}
	min, err := strconv.ParseInt(parts[1], 10, 0)
	if err != nil {
		return time.Time{}, err
	}
	if min < 0 || min > 60 {
		return time.Time{}, fmt.Errorf("bad minute: %d", min)
	}

	t := time.Time(time.Date(int(y), time.Month(m), int(d), int(h), int(min), 0, 0, loc))
	if t.After(now) {
		return time.Time{}, fmt.Errorf("bad time; %v is in the future", time.Time(t))
	}
	return t, nil
}

// Selector holds info useful to make time selections.
type Selector struct {
	SelectedDay   int
	SelectedMonth time.Month
	SelectedYear  int
	SelectedTime  string
	Months        []time.Month
	Years         []int
	DaysInMonth   []int
}

// Create populates a Selector from given starting point.
func (s *Selector) Create(from time.Time) {
	days := make([]int, 31)
	for d := 0; d < 31; d++ { // TODO: Actual number of days / month (change dynamically on selection?).
		days[d] = d + 1
	}
	numYears := 5
	years := make([]int, numYears)
	for i := 0; i < numYears; i++ {
		years[i] = from.Year() - i
	}
	*s = Selector{
		SelectedYear:  from.Year(),
		SelectedMonth: from.Month() - 1, // -1 to give [0, 11]
		SelectedDay:   from.Day(),
		SelectedTime:  from.Format("15:04"),
		DaysInMonth:   days,
		Months:        make([]time.Month, 12),
		Years:         years,
	}
	for i := 1; i <= 12; i++ {
		s.Months[i-1] = time.Month(i)
	}
}
<commit_msg>adds Day type<commit_after>// Package timeutils provides some convenience functions around time.
package timeutils

import (
	"fmt"
	"log"
	"strconv"
	"strings"
	"time"
)

var (
	StdLayout     = "2006-01-02 15:04" // a simple time layout
	EmptyTimeZone = TimeZone("")       // the empty timezone
)

// TimeZone is a string that can be given to time.LoadLocation.
type TimeZone string

// Day describes a specific day and can be used as map keys.
type Day struct {
	Year, Day int
	Month     time.Month
}

// FromTime parses a day object from a time.
func (d *Day) FromTime(t time.Time) {
	year, month, day := t.Date()
	*d = Day{year, day, month}
}

// ToTime returns the time object representing the start of the day.
func (d Day) ToTime() time.Time {
	return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, time.UTC)
}

// MustLoadLoc loads the time.Location specified by the string, or panics.
func MustLoadLoc(tz TimeZone) *time.Location {
	loc, err := time.LoadLocation(string(tz))
	if err != nil {
		log.Fatalf("bad location %v: %v\n", tz, err)
	}
	return loc
}

// Must panics if error is non-nil.
//
// Intended use is to wrap function calls that must succeed, e.g:
//   t := Must(ParseStd("2013-07-31"))
func Must(t time.Time, err error) time.Time {
	if err != nil {
		log.Fatalf("got err: %v\n", err)
	}
	return t
}

// ParseStd parses the value using a standard layout, with time.UTC timezone.
func ParseStd(value string) (time.Time, error) {
	return time.Parse(StdLayout, value)
}

// daysIn returns the number of days in a month for a given year.
func daysIn(m time.Month, year int) int {
	// This is equivalent to the unexported time.daysIn(m, year).
	return time.Date(year, m+1, 0, 0, 0, 0, 0, time.UTC).Day()
}

// Weekday gets the Monday-indexed number for the time.Weekday.
func Weekday(d time.Weekday) int {
	day := (d - 1) % 7
	if day < 0 {
		day += 7
	}
	return int(day)
}

// StartOfWeek returns the start of the current week for the time.
func StartOfWeek(t time.Time) time.Time {
	// Figure out number of days to back up until Mon:
	// Sun is 0 -> 6, Sat is 6 -> 5, etc.
	toMon := Weekday(t.Weekday())
	y, m, d := t.AddDate(0, 0, -int(toMon)).Date()
	// Result is 00:00:00 on that year, month, day.
	return time.Date(y, m, d, 0, 0, 0, 0, t.Location())
}

// Parse extracts time from string-based info, with some constraints.
//
// The described time cannot be in the future, or more than 1000 years in the past.
//
// Note that month is 0-indexed, unlike time.Month.
func Parse(year, month, day, hourMinute string, loc *time.Location) (time.Time, error) {
	now := time.Now().In(loc)

	y64, err := strconv.ParseInt(year, 10, 0)
	y := int(y64)
	if err != nil {
		return time.Time{}, err
	}
	if y < now.Year()-1000 {
		return time.Time{}, fmt.Errorf("bad year; %d is too far in the past", y)
	}
	m, err := strconv.ParseInt(month, 10, 0)
	if err != nil {
		return time.Time{}, err
	}
	if m < 0 || m > 11 {
		return time.Time{}, fmt.Errorf("bad month: %d is not within [0, 11]", m)
	}
	// Month +1 since time.Month is [1, 12].
	m = m + 1
	d64, err := strconv.ParseInt(day, 10, 0)
	d := int(d64)
	if err != nil {
		return time.Time{}, err
	}
	if d < 1 {
		return time.Time{}, fmt.Errorf("bad day: %d; can't be negative", d)
	} else if d > daysIn(time.Month(m), y) {
		return time.Time{}, fmt.Errorf("bad day: %d; only %d days in %v, %d", d, daysIn(time.Month(m), y), time.Month(m), y)
	}
	parts := strings.Split(hourMinute, ":")
	if len(parts) != 2 {
		return time.Time{}, fmt.Errorf("bad hour/minute: %s", hourMinute)
	}
	h, err := strconv.ParseInt(parts[0], 10, 0)
	if err != nil {
		return time.Time{}, err
	}
	if h < 0 || h > 60 {
		return time.Time{}, fmt.Errorf("bad hour: %d", h)
	}
	min, err := strconv.ParseInt(parts[1], 10, 0)
	if err != nil {
		return time.Time{}, err
	}
	if min < 0 || min > 60 {
		return time.Time{}, fmt.Errorf("bad minute: %d", min)
	}

	t := time.Time(time.Date(int(y), time.Month(m), int(d), int(h), int(min), 0, 0, loc))
	if t.After(now) {
		return time.Time{}, fmt.Errorf("bad time; %v is in the future", time.Time(t))
	}
	return t, nil
}

// Selector holds info useful to make time selections.
type Selector struct {
	SelectedDay   int
	SelectedMonth time.Month
	SelectedYear  int
	SelectedTime  string
	Months        []time.Month
	Years         []int
	DaysInMonth   []int
}

// Create populates a Selector from given starting point.
func (s *Selector) Create(from time.Time) {
	days := make([]int, 31)
	for d := 0; d < 31; d++ { // TODO: Actual number of days / month (change dynamically on selection?).
		days[d] = d + 1
	}
	numYears := 5
	years := make([]int, numYears)
	for i := 0; i < numYears; i++ {
		years[i] = from.Year() - i
	}
	*s = Selector{
		SelectedYear:  from.Year(),
		SelectedMonth: from.Month() - 1, // -1 to give [0, 11]
		SelectedDay:   from.Day(),
		SelectedTime:  from.Format("15:04"),
		DaysInMonth:   days,
		Months:        make([]time.Month, 12),
		Years:         years,
	}
	for i := 1; i <= 12; i++ {
		s.Months[i-1] = time.Month(i)
	}
}
<|endoftext|>


<commit_before>package tlsh

import (
	"bufio"
	"bytes"
	"encoding/hex"
	"io"
	"math"
	"os"
)

const (
	log1_5       = 0.4054651
	log1_3       = 0.26236426
	log1_1       = 0.095310180
	codeSize     = 32
	windowLength = 5
	effBuckets   = 128
	numBuckets   = 256
)

// Tlsh holds hash components
type Tlsh struct {
	checksum byte
	lValue   byte
	q1Ratio  byte
	q2Ratio  byte
	qRatio   byte
	code     [codeSize]byte
}

// New represents type factory for Tlsh
func New(checksum, lValue, q1Ratio, q2Ratio, qRatio byte, code [codeSize]byte) *Tlsh {
	return &Tlsh{
		checksum: checksum,
		lValue:   lValue,
		q1Ratio:  q1Ratio,
		q2Ratio:  q2Ratio,
		qRatio:   qRatio,
		code:     code,
	}
}

// Binary returns the binary representation of the hash
func (t *Tlsh) Binary() []byte {
	return append([]byte{swapByte(t.checksum), swapByte(t.lValue), t.qRatio}, t.code[:]...)
}

// String returns the string representation of the hash`
func (t *Tlsh) String() string {
	return hex.EncodeToString(t.Binary())
}

func quartilePoints(buckets [numBuckets]uint) (q1, q2, q3 uint) {
	var spl, spr uint
	p1 := uint(effBuckets/4 - 1)
	p2 := uint(effBuckets/2 - 1)
	p3 := uint(effBuckets - effBuckets/4 - 1)
	end := uint(effBuckets - 1)

	bucketCopy := make([]uint, effBuckets)
	copy(bucketCopy, buckets[:effBuckets])

	shortCutLeft := make([]uint, effBuckets)
	shortCutRight := make([]uint, effBuckets)

	for l, r := uint(0), end; ; {
		ret := partition(&bucketCopy, l, r)
		if ret > p2 {
			r = ret - 1
			shortCutRight[spr] = ret
			spr++
		} else if ret < p2 {
			l = ret + 1
			shortCutLeft[spl] = ret
			spl++
		} else {
			q2 = bucketCopy[p2]
			break
		}
	}

	shortCutLeft[spl] = p2 - 1
	shortCutRight[spr] = p2 + 1

	for i, l := uint(0), uint(0); i <= spl; i++ {
		r := shortCutLeft[i]
		if r > p1 {
			for {
				ret := partition(&bucketCopy, l, r)
				if ret > p1 {
					r = ret - 1
				} else if ret < p1 {
					l = ret + 1
				} else {
					q1 = bucketCopy[p1]
					break
				}
			}
			break
		} else if r < p1 {
			l = r
		} else {
			q1 = bucketCopy[p1]
			break
		}
	}

	for i, r := uint(0), end; i <= spr; i++ {
		l := shortCutRight[i]
		if l < p3 {
			for {
				ret := partition(&bucketCopy, l, r)
				if ret > p3 {
					r = ret - 1
				} else if ret < p3 {
					l = ret + 1
				} else {
					q3 = bucketCopy[p3]
					break
				}
			}
			break
		} else if l > p3 {
			r = l
		} else {
			q3 = bucketCopy[p3]
			break
		}
	}

	return q1, q2, q3
}

func partition(pbuf *[]uint, left, right uint) uint {
	if left == right {
		return left
	}

	rbuf := (*pbuf)

	if left+1 == right {
		if rbuf[left] > rbuf[right] {
			rbuf[right], rbuf[left] = rbuf[left], rbuf[right]
		}
		return left
	}

	ret := left
	pivot := (left + right) >> 1
	val := rbuf[pivot]

	rbuf[pivot] = rbuf[right]
	rbuf[right] = val

	for i := left; i < right; i++ {
		if rbuf[i] < val {
			rbuf[i], rbuf[ret] = rbuf[ret], rbuf[i]
			ret++
		}
	}

	rbuf[right] = rbuf[ret]
	rbuf[ret] = val

	return ret
}

func lValue(length int) byte {
	var l byte

	if length <= 656 {
		l = byte(math.Floor(math.Log(float64(length)) / log1_5))
	} else if length <= 3199 {
		l = byte(math.Floor(math.Log(float64(length))/log1_3 - 8.72777))
	} else {
		l = byte(math.Floor(math.Log(float64(length))/log1_1 - 62.5472))
	}

	return l % 255
}

func swapByte(in byte) byte {
	var out byte

	out = ((in & 0xF0) >> 4) & 0x0F
	out |= ((in & 0x0F) << 4) & 0xF0

	return out
}

func bucketsBinaryRepresentation(buckets [numBuckets]uint, q1, q2, q3 uint) [codeSize]byte {
	var biHash [codeSize]byte

	for i := 0; i < codeSize; i++ {
		var h byte
		for j := 0; j < 4; j++ {
			k := buckets[4*i+j]
			if q3 < k {
				h += 3 << (byte(j) * 2)
			} else if q2 < k {
				h += 2 << (byte(j) * 2)
			} else if q1 < k {
				h += 1 << (byte(j) * 2)
			}
		}
		// Prepend the new h to the hash
		biHash[(codeSize-1)-i] = h
	}
	return biHash
}

func hashTLSH(length int, buckets [numBuckets]uint, checksum byte, q1, q2, q3 uint) []byte {

	// binary representation of buckets
	biHash := bucketsBinaryRepresentation(buckets, q1, q2, q3)

	q1Ratio := byte(float32(q1)*100/float32(q3)) % 16
	q2Ratio := byte(float32(q2)*100/float32(q3)) % 16

	qRatio := ((q1Ratio & 0xF) << 4) | (q2Ratio & 0xF)

	// prepend header
	return append([]byte{swapByte(checksum), swapByte(lValue(length)), qRatio}, biHash[:]...)
}

func reverse(s [5]byte) [5]byte {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
	return s
}

func fillBuckets(r FuzzyReader) ([numBuckets]uint, byte, int, error) {
	buckets := [numBuckets]uint{}
	chunkSlice := make([]byte, windowLength)
	chunk := [windowLength]byte{}
	salt := [6]byte{2, 3, 5, 7, 11, 13}
	fileSize := 0
	checksum := byte(0)

	n, err := r.Read(chunkSlice)
	if err != nil {
		return [numBuckets]uint{}, 0, 0, err
	}
	copy(chunk[:], chunkSlice[0:5])
	chunk = reverse(chunk)
	fileSize += n

	chunk3 := &[3]byte{}

	for {
		chunk3[0] = chunk[0]
		chunk3[1] = chunk[1]
		chunk3[2] = checksum
		checksum = pearsonHash(0, chunk3)

		chunk3[2] = chunk[2]
		buckets[pearsonHash(salt[0], chunk3)]++

		chunk3[2] = chunk[3]
		buckets[pearsonHash(salt[1], chunk3)]++

		chunk3[1] = chunk[2]
		buckets[pearsonHash(salt[2], chunk3)]++

		chunk3[2] = chunk[4]
		buckets[pearsonHash(salt[3], chunk3)]++

		chunk3[1] = chunk[1]
		buckets[pearsonHash(salt[4], chunk3)]++

		chunk3[1] = chunk[3]
		buckets[pearsonHash(salt[5], chunk3)]++

		copy(chunk[1:], chunk[0:4])
		chunk[0], err = r.ReadByte()
		if err != nil {
			if err != io.EOF {
				return [numBuckets]uint{}, 0, 0, err
			}
			break
		}
		fileSize++
	}
	return buckets, checksum, fileSize, nil
}

// hashCalculate calculate TLSH
func hashCalculate(r FuzzyReader) (*Tlsh, error) {
	buckets, checksum, fileSize, err := fillBuckets(r)
	if err != nil {
		return &Tlsh{}, err
	}

	q1, q2, q3 := quartilePoints(buckets)
	q1Ratio := byte(float32(q1)*100/float32(q3)) % 16
	q2Ratio := byte(float32(q2)*100/float32(q3)) % 16
	qRatio := ((q1Ratio & 0xF) << 4) | (q2Ratio & 0xF)

	biHash := bucketsBinaryRepresentation(buckets, q1, q2, q3)

	return New(checksum, lValue(fileSize), q1Ratio, q2Ratio, qRatio, biHash), nil
}

// FuzzyReader interface
type FuzzyReader interface {
	Read([]byte) (int, error)
	ReadByte() (byte, error)
}

//HashReader calculates the TLSH for the input reader
func HashReader(r FuzzyReader) (string, error) {
	tlsh, err := hashCalculate(r)
	if err != nil {
		return "", err
	}

	return tlsh.String(), err
}

//HashBytes calculates the TLSH for the input byte slice
func HashBytes(blob []byte) (hash string, err error) {
	r := bytes.NewReader(blob)
	return HashReader(r)
}

//HashFilename calculates the TLSH for the input file
func HashFilename(filename string) (tlsh *Tlsh, err error) {
	f, err := os.Open(filename)
	defer f.Close()
	if err != nil {
		return &Tlsh{}, err
	}

	r := bufio.NewReader(f)
	tlsh, err = hashCalculate(r)
	if err != nil {
		return &Tlsh{}, err
	}
	return tlsh, nil
}

// Diff current hash with other hash
func (t *Tlsh) Diff(t2 *Tlsh) int {
	return diffTotal(t, t2, true)
}

// DiffFilenames calculate distance between two files
func DiffFilenames(filenameA, filenameB string) (int, error) {
	f, err := os.Open(filenameA)
	defer f.Close()
	if err != nil {
		return -1, err
	}
	r := bufio.NewReader(f)
	tlshA, err := hashCalculate(r)

	f, err = os.Open(filenameB)
	defer f.Close()
	if err != nil {
		return -1, err
	}
	r = bufio.NewReader(f)
	tlshB, err := hashCalculate(r)
	if err != nil {
		return -1, err
	}

	return tlshA.Diff(tlshB), nil
}
<commit_msg>Cleanup<commit_after>package tlsh

import (
	"bufio"
	"bytes"
	"encoding/hex"
	"io"
	"math"
	"os"
)

const (
	log1_5       = 0.4054651
	log1_3       = 0.26236426
	log1_1       = 0.095310180
	codeSize     = 32
	windowLength = 5
	effBuckets   = 128
	numBuckets   = 256
)

// Tlsh holds hash components
type Tlsh struct {
	checksum byte
	lValue   byte
	q1Ratio  byte
	q2Ratio  byte
	qRatio   byte
	code     [codeSize]byte
}

// New represents type factory for Tlsh
func New(checksum, lValue, q1Ratio, q2Ratio, qRatio byte, code [codeSize]byte) *Tlsh {
	return &Tlsh{
		checksum: checksum,
		lValue:   lValue,
		q1Ratio:  q1Ratio,
		q2Ratio:  q2Ratio,
		qRatio:   qRatio,
		code:     code,
	}
}

// Binary returns the binary representation of the hash
func (t *Tlsh) Binary() []byte {
	return append([]byte{swapByte(t.checksum), swapByte(t.lValue), t.qRatio}, t.code[:]...)
}

// String returns the string representation of the hash`
func (t *Tlsh) String() string {
	return hex.EncodeToString(t.Binary())
}

func quartilePoints(buckets [numBuckets]uint) (q1, q2, q3 uint) {
	var spl, spr uint
	p1 := uint(effBuckets/4 - 1)
	p2 := uint(effBuckets/2 - 1)
	p3 := uint(effBuckets - effBuckets/4 - 1)
	end := uint(effBuckets - 1)

	bucketCopy := make([]uint, effBuckets)
	copy(bucketCopy, buckets[:effBuckets])

	shortCutLeft := make([]uint, effBuckets)
	shortCutRight := make([]uint, effBuckets)

	for l, r := uint(0), end; ; {
		ret := partition(&bucketCopy, l, r)
		if ret > p2 {
			r = ret - 1
			shortCutRight[spr] = ret
			spr++
		} else if ret < p2 {
			l = ret + 1
			shortCutLeft[spl] = ret
			spl++
		} else {
			q2 = bucketCopy[p2]
			break
		}
	}

	shortCutLeft[spl] = p2 - 1
	shortCutRight[spr] = p2 + 1

	for i, l := uint(0), uint(0); i <= spl; i++ {
		r := shortCutLeft[i]
		if r > p1 {
			for {
				ret := partition(&bucketCopy, l, r)
				if ret > p1 {
					r = ret - 1
				} else if ret < p1 {
					l = ret + 1
				} else {
					q1 = bucketCopy[p1]
					break
				}
			}
			break
		} else if r < p1 {
			l = r
		} else {
			q1 = bucketCopy[p1]
			break
		}
	}

	for i, r := uint(0), end; i <= spr; i++ {
		l := shortCutRight[i]
		if l < p3 {
			for {
				ret := partition(&bucketCopy, l, r)
				if ret > p3 {
					r = ret - 1
				} else if ret < p3 {
					l = ret + 1
				} else {
					q3 = bucketCopy[p3]
					break
				}
			}
			break
		} else if l > p3 {
			r = l
		} else {
			q3 = bucketCopy[p3]
			break
		}
	}

	return q1, q2, q3
}

func partition(pbuf *[]uint, left, right uint) uint {
	if left == right {
		return left
	}

	rbuf := (*pbuf)

	if left+1 == right {
		if rbuf[left] > rbuf[right] {
			rbuf[right], rbuf[left] = rbuf[left], rbuf[right]
		}
		return left
	}

	ret := left
	pivot := (left + right) >> 1
	val := rbuf[pivot]

	rbuf[pivot] = rbuf[right]
	rbuf[right] = val

	for i := left; i < right; i++ {
		if rbuf[i] < val {
			rbuf[i], rbuf[ret] = rbuf[ret], rbuf[i]
			ret++
		}
	}

	rbuf[right] = rbuf[ret]
	rbuf[ret] = val

	return ret
}

func lValue(length int) byte {
	var l byte

	if length <= 656 {
		l = byte(math.Floor(math.Log(float64(length)) / log1_5))
	} else if length <= 3199 {
		l = byte(math.Floor(math.Log(float64(length))/log1_3 - 8.72777))
	} else {
		l = byte(math.Floor(math.Log(float64(length))/log1_1 - 62.5472))
	}

	return l % 255
}

func swapByte(in byte) byte {
	var out byte

	out = ((in & 0xF0) >> 4) & 0x0F
	out |= ((in & 0x0F) << 4) & 0xF0

	return out
}

func bucketsBinaryRepresentation(buckets [numBuckets]uint, q1, q2, q3 uint) [codeSize]byte {
	var biHash [codeSize]byte

	for i := 0; i < codeSize; i++ {
		var h byte
		for j := 0; j < 4; j++ {
			k := buckets[4*i+j]
			if q3 < k {
				h += 3 << (byte(j) * 2)
			} else if q2 < k {
				h += 2 << (byte(j) * 2)
			} else if q1 < k {
				h += 1 << (byte(j) * 2)
			}
		}
		// Prepend the new h to the hash
		biHash[(codeSize-1)-i] = h
	}
	return biHash
}

func reverse(s [5]byte) [5]byte {
	for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
		s[i], s[j] = s[j], s[i]
	}
	return s
}

func fillBuckets(r FuzzyReader) ([numBuckets]uint, byte, int, error) {
	buckets := [numBuckets]uint{}
	chunkSlice := make([]byte, windowLength)
	chunk := [windowLength]byte{}
	salt := [6]byte{2, 3, 5, 7, 11, 13}
	fileSize := 0
	checksum := byte(0)

	n, err := r.Read(chunkSlice)
	if err != nil {
		return [numBuckets]uint{}, 0, 0, err
	}
	copy(chunk[:], chunkSlice[0:5])
	chunk = reverse(chunk)
	fileSize += n

	chunk3 := &[3]byte{}

	for {
		chunk3[0] = chunk[0]
		chunk3[1] = chunk[1]
		chunk3[2] = checksum
		checksum = pearsonHash(0, chunk3)

		chunk3[2] = chunk[2]
		buckets[pearsonHash(salt[0], chunk3)]++

		chunk3[2] = chunk[3]
		buckets[pearsonHash(salt[1], chunk3)]++

		chunk3[1] = chunk[2]
		buckets[pearsonHash(salt[2], chunk3)]++

		chunk3[2] = chunk[4]
		buckets[pearsonHash(salt[3], chunk3)]++

		chunk3[1] = chunk[1]
		buckets[pearsonHash(salt[4], chunk3)]++

		chunk3[1] = chunk[3]
		buckets[pearsonHash(salt[5], chunk3)]++

		copy(chunk[1:], chunk[0:4])
		chunk[0], err = r.ReadByte()
		if err != nil {
			if err != io.EOF {
				return [numBuckets]uint{}, 0, 0, err
			}
			break
		}
		fileSize++
	}
	return buckets, checksum, fileSize, nil
}

// hashCalculate calculate TLSH
func hashCalculate(r FuzzyReader) (*Tlsh, error) {
	buckets, checksum, fileSize, err := fillBuckets(r)
	if err != nil {
		return &Tlsh{}, err
	}

	q1, q2, q3 := quartilePoints(buckets)
	q1Ratio := byte(float32(q1)*100/float32(q3)) % 16
	q2Ratio := byte(float32(q2)*100/float32(q3)) % 16
	qRatio := ((q1Ratio & 0xF) << 4) | (q2Ratio & 0xF)

	biHash := bucketsBinaryRepresentation(buckets, q1, q2, q3)

	return New(checksum, lValue(fileSize), q1Ratio, q2Ratio, qRatio, biHash), nil
}

// FuzzyReader interface
type FuzzyReader interface {
	Read([]byte) (int, error)
	ReadByte() (byte, error)
}

//HashReader calculates the TLSH for the input reader
func HashReader(r FuzzyReader) (string, error) {
	tlsh, err := hashCalculate(r)
	if err != nil {
		return "", err
	}

	return tlsh.String(), err
}

//HashBytes calculates the TLSH for the input byte slice
func HashBytes(blob []byte) (hash string, err error) {
	r := bytes.NewReader(blob)
	return HashReader(r)
}

//HashFilename calculates the TLSH for the input file
func HashFilename(filename string) (tlsh *Tlsh, err error) {
	f, err := os.Open(filename)
	defer f.Close()
	if err != nil {
		return &Tlsh{}, err
	}

	r := bufio.NewReader(f)
	tlsh, err = hashCalculate(r)
	if err != nil {
		return &Tlsh{}, err
	}
	return tlsh, nil
}

// Diff current hash with other hash
func (t *Tlsh) Diff(t2 *Tlsh) int {
	return diffTotal(t, t2, true)
}

// DiffFilenames calculate distance between two files
func DiffFilenames(filenameA, filenameB string) (int, error) {
	f, err := os.Open(filenameA)
	defer f.Close()
	if err != nil {
		return -1, err
	}
	r := bufio.NewReader(f)
	tlshA, err := hashCalculate(r)

	f, err = os.Open(filenameB)
	defer f.Close()
	if err != nil {
		return -1, err
	}
	r = bufio.NewReader(f)
	tlshB, err := hashCalculate(r)
	if err != nil {
		return -1, err
	}

	return tlshA.Diff(tlshB), nil
}
<|endoftext|>


<commit_before>package gweb

import (
	"html/template"
	"io"
)

type Tmpl struct {
	Templates *template.Template
}

func html(v string) template.HTML { return template.HTML(v) }

func (p *Tmpl) Load() {
	p.Templates = template.Must(template.New("").Funcs(template.FuncMap{
		"html": html,
	}).Delims("[[", "]]").ParseGlob("views/*.*"))
}

func (p *Tmpl) Execute(wr io.Writer, name string, data interface{}) error {
	return p.Templates.ExecuteTemplate(wr, name+".tpl", data)
}

func (p *Tmpl) Execute2(wr io.Writer, name string, data interface{}) error {
	return p.Templates.ExecuteTemplate(wr, name, data)
}
<commit_msg>add tmpl layout<commit_after>package gweb

import (
	"html/template"
	"io"
)

type Tmpl struct {
	Templates *template.Template
}

func html(v string) template.HTML { return template.HTML(v) }

func (p *Tmpl) Load() {
	p.Templates = template.Must(template.New("").Funcs(template.FuncMap{
		"html": html,
	}).Delims("[[", "]]").ParseGlob("views/layout/*.*"))

	p.Templates = template.Must(p.Templates.ParseGlob("views/*.*"))
}

func (p *Tmpl) Execute(wr io.Writer, name string, data interface{}) error {
	return p.Templates.ExecuteTemplate(wr, name+".tpl", data)
}

func (p *Tmpl) Execute2(wr io.Writer, name string, data interface{}) error {
	return p.Templates.ExecuteTemplate(wr, name, data)
}
<|endoftext|>


<commit_before>package toml

import (
	"errors"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"
)

type tomlValue struct {
	value    interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
	position Position
}

// TomlTree is the result of the parsing of a TOML file.
type TomlTree struct {
	values   map[string]interface{} // string -> *tomlValue, *TomlTree, []*TomlTree
	position Position
}

func newTomlTree() *TomlTree {
	return &TomlTree{
		values:   make(map[string]interface{}),
		position: Position{},
	}
}

// TreeFromMap initializes a new TomlTree object using the given map.
func TreeFromMap(m map[string]interface{}) (*TomlTree, error) {
	result, err := toTree(m)
	if err != nil {
		return nil, err
	}
	return result.(*TomlTree), nil
}

// Has returns a boolean indicating if the given key exists.
func (t *TomlTree) Has(key string) bool {
	if key == "" {
		return false
	}
	return t.HasPath(strings.Split(key, "."))
}

// HasPath returns true if the given path of keys exists, false otherwise.
func (t *TomlTree) HasPath(keys []string) bool {
	return t.GetPath(keys) != nil
}

// Keys returns the keys of the toplevel tree.
// Warning: this is a costly operation.
func (t *TomlTree) Keys() []string {
	var keys []string
	for k := range t.values {
		keys = append(keys, k)
	}
	return keys
}

// Get the value at key in the TomlTree.
// Key is a dot-separated path (e.g. a.b.c).
// Returns nil if the path does not exist in the tree.
// If keys is of length zero, the current tree is returned.
func (t *TomlTree) Get(key string) interface{} {
	if key == "" {
		return t
	}
	comps, err := parseKey(key)
	if err != nil {
		return nil
	}
	return t.GetPath(comps)
}

// GetPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned.
func (t *TomlTree) GetPath(keys []string) interface{} {
	if len(keys) == 0 {
		return t
	}
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		value, exists := subtree.values[intermediateKey]
		if !exists {
			return nil
		}
		switch node := value.(type) {
		case *TomlTree:
			subtree = node
		case []*TomlTree:
			// go to most recent element
			if len(node) == 0 {
				return nil
			}
			subtree = node[len(node)-1]
		default:
			return nil // cannot navigate through other node types
		}
	}
	// branch based on final node type
	switch node := subtree.values[keys[len(keys)-1]].(type) {
	case *tomlValue:
		return node.value
	default:
		return node
	}
}

// GetPosition returns the position of the given key.
func (t *TomlTree) GetPosition(key string) Position {
	if key == "" {
		return t.position
	}
	return t.GetPositionPath(strings.Split(key, "."))
}

// GetPositionPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned.
func (t *TomlTree) GetPositionPath(keys []string) Position {
	if len(keys) == 0 {
		return t.position
	}
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		value, exists := subtree.values[intermediateKey]
		if !exists {
			return Position{0, 0}
		}
		switch node := value.(type) {
		case *TomlTree:
			subtree = node
		case []*TomlTree:
			// go to most recent element
			if len(node) == 0 {
				return Position{0, 0}
			}
			subtree = node[len(node)-1]
		default:
			return Position{0, 0}
		}
	}
	// branch based on final node type
	switch node := subtree.values[keys[len(keys)-1]].(type) {
	case *tomlValue:
		return node.position
	case *TomlTree:
		return node.position
	case []*TomlTree:
		// go to most recent element
		if len(node) == 0 {
			return Position{0, 0}
		}
		return node[len(node)-1].position
	default:
		return Position{0, 0}
	}
}

// GetDefault works like Get but with a default value
func (t *TomlTree) GetDefault(key string, def interface{}) interface{} {
	val := t.Get(key)
	if val == nil {
		return def
	}
	return val
}

// Set an element in the tree.
// Key is a dot-separated path (e.g. a.b.c).
// Creates all necessary intermediates trees, if needed.
func (t *TomlTree) Set(key string, value interface{}) {
	t.SetPath(strings.Split(key, "."), value)
}

// SetPath sets an element in the tree.
// Keys is an array of path elements (e.g. {"a","b","c"}).
// Creates all necessary intermediates trees, if needed.
func (t *TomlTree) SetPath(keys []string, value interface{}) {
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		nextTree, exists := subtree.values[intermediateKey]
		if !exists {
			nextTree = newTomlTree()
			subtree.values[intermediateKey] = nextTree // add new element here
		}
		switch node := nextTree.(type) {
		case *TomlTree:
			subtree = node
		case []*TomlTree:
			// go to most recent element
			if len(node) == 0 {
				// create element if it does not exist
				subtree.values[intermediateKey] = append(node, newTomlTree())
			}
			subtree = node[len(node)-1]
		}
	}

	var toInsert interface{}

	switch value.(type) {
	case *TomlTree:
		toInsert = value
	case []*TomlTree:
		toInsert = value
	case *tomlValue:
		toInsert = value
	default:
		toInsert = &tomlValue{value: value}
	}

	subtree.values[keys[len(keys)-1]] = toInsert
}

// createSubTree takes a tree and a key and create the necessary intermediate
// subtrees to create a subtree at that point. In-place.
//
// e.g. passing a.b.c will create (assuming tree is empty) tree[a], tree[a][b]
// and tree[a][b][c]
//
// Returns nil on success, error object on failure
func (t *TomlTree) createSubTree(keys []string, pos Position) error {
	subtree := t
	for _, intermediateKey := range keys {
		nextTree, exists := subtree.values[intermediateKey]
		if !exists {
			tree := newTomlTree()
			tree.position = pos
			subtree.values[intermediateKey] = tree
			nextTree = tree
		}

		switch node := nextTree.(type) {
		case []*TomlTree:
			subtree = node[len(node)-1]
		case *TomlTree:
			subtree = node
		default:
			return fmt.Errorf("unknown type for path %s (%s): %T (%#v)",
				strings.Join(keys, "."), intermediateKey, nextTree, nextTree)
		}
	}
	return nil
}

// Query compiles and executes a query on a tree and returns the query result.
func (t *TomlTree) Query(query string) (*QueryResult, error) {
	q, err := CompileQuery(query)
	if err != nil {
		return nil, err
	}
	return q.Execute(t), nil
}

// LoadReader creates a TomlTree from any io.Reader.
func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(runtime.Error); ok {
				panic(r)
			}
			err = errors.New(r.(string))
		}
	}()
	tree = parseToml(lexToml(reader))
	return
}

// Load creates a TomlTree from a string.
func Load(content string) (tree *TomlTree, err error) {
	return LoadReader(strings.NewReader(content))
}

// LoadFile creates a TomlTree from a file.
func LoadFile(path string) (tree *TomlTree, err error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return LoadReader(file)
}
<commit_msg>Initialize keys array to final length (#155)<commit_after>package toml

import (
	"errors"
	"fmt"
	"io"
	"os"
	"runtime"
	"strings"
)

type tomlValue struct {
	value    interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
	position Position
}

// TomlTree is the result of the parsing of a TOML file.
type TomlTree struct {
	values   map[string]interface{} // string -> *tomlValue, *TomlTree, []*TomlTree
	position Position
}

func newTomlTree() *TomlTree {
	return &TomlTree{
		values:   make(map[string]interface{}),
		position: Position{},
	}
}

// TreeFromMap initializes a new TomlTree object using the given map.
func TreeFromMap(m map[string]interface{}) (*TomlTree, error) {
	result, err := toTree(m)
	if err != nil {
		return nil, err
	}
	return result.(*TomlTree), nil
}

// Has returns a boolean indicating if the given key exists.
func (t *TomlTree) Has(key string) bool {
	if key == "" {
		return false
	}
	return t.HasPath(strings.Split(key, "."))
}

// HasPath returns true if the given path of keys exists, false otherwise.
func (t *TomlTree) HasPath(keys []string) bool {
	return t.GetPath(keys) != nil
}

// Keys returns the keys of the toplevel tree.
// Warning: this is a costly operation.
func (t *TomlTree) Keys() []string {
	keys := make([]string, len(t.values))
	i := 0
	for k := range t.values {
		keys[i] = k
		i++
	}
	return keys
}

// Get the value at key in the TomlTree.
// Key is a dot-separated path (e.g. a.b.c).
// Returns nil if the path does not exist in the tree.
// If keys is of length zero, the current tree is returned.
func (t *TomlTree) Get(key string) interface{} {
	if key == "" {
		return t
	}
	comps, err := parseKey(key)
	if err != nil {
		return nil
	}
	return t.GetPath(comps)
}

// GetPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned.
func (t *TomlTree) GetPath(keys []string) interface{} {
	if len(keys) == 0 {
		return t
	}
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		value, exists := subtree.values[intermediateKey]
		if !exists {
			return nil
		}
		switch node := value.(type) {
		case *TomlTree:
			subtree = node
		case []*TomlTree:
			// go to most recent element
			if len(node) == 0 {
				return nil
			}
			subtree = node[len(node)-1]
		default:
			return nil // cannot navigate through other node types
		}
	}
	// branch based on final node type
	switch node := subtree.values[keys[len(keys)-1]].(type) {
	case *tomlValue:
		return node.value
	default:
		return node
	}
}

// GetPosition returns the position of the given key.
func (t *TomlTree) GetPosition(key string) Position {
	if key == "" {
		return t.position
	}
	return t.GetPositionPath(strings.Split(key, "."))
}

// GetPositionPath returns the element in the tree indicated by 'keys'.
// If keys is of length zero, the current tree is returned.
func (t *TomlTree) GetPositionPath(keys []string) Position {
	if len(keys) == 0 {
		return t.position
	}
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		value, exists := subtree.values[intermediateKey]
		if !exists {
			return Position{0, 0}
		}
		switch node := value.(type) {
		case *TomlTree:
			subtree = node
		case []*TomlTree:
			// go to most recent element
			if len(node) == 0 {
				return Position{0, 0}
			}
			subtree = node[len(node)-1]
		default:
			return Position{0, 0}
		}
	}
	// branch based on final node type
	switch node := subtree.values[keys[len(keys)-1]].(type) {
	case *tomlValue:
		return node.position
	case *TomlTree:
		return node.position
	case []*TomlTree:
		// go to most recent element
		if len(node) == 0 {
			return Position{0, 0}
		}
		return node[len(node)-1].position
	default:
		return Position{0, 0}
	}
}

// GetDefault works like Get but with a default value
func (t *TomlTree) GetDefault(key string, def interface{}) interface{} {
	val := t.Get(key)
	if val == nil {
		return def
	}
	return val
}

// Set an element in the tree.
// Key is a dot-separated path (e.g. a.b.c).
// Creates all necessary intermediates trees, if needed.
func (t *TomlTree) Set(key string, value interface{}) {
	t.SetPath(strings.Split(key, "."), value)
}

// SetPath sets an element in the tree.
// Keys is an array of path elements (e.g. {"a","b","c"}).
// Creates all necessary intermediates trees, if needed.
func (t *TomlTree) SetPath(keys []string, value interface{}) {
	subtree := t
	for _, intermediateKey := range keys[:len(keys)-1] {
		nextTree, exists := subtree.values[intermediateKey]
		if !exists {
			nextTree = newTomlTree()
			subtree.values[intermediateKey] = nextTree // add new element here
		}
		switch node := nextTree.(type) {
		case *TomlTree:
			subtree = node
		case []*TomlTree:
			// go to most recent element
			if len(node) == 0 {
				// create element if it does not exist
				subtree.values[intermediateKey] = append(node, newTomlTree())
			}
			subtree = node[len(node)-1]
		}
	}

	var toInsert interface{}

	switch value.(type) {
	case *TomlTree:
		toInsert = value
	case []*TomlTree:
		toInsert = value
	case *tomlValue:
		toInsert = value
	default:
		toInsert = &tomlValue{value: value}
	}

	subtree.values[keys[len(keys)-1]] = toInsert
}

// createSubTree takes a tree and a key and create the necessary intermediate
// subtrees to create a subtree at that point. In-place.
//
// e.g. passing a.b.c will create (assuming tree is empty) tree[a], tree[a][b]
// and tree[a][b][c]
//
// Returns nil on success, error object on failure
func (t *TomlTree) createSubTree(keys []string, pos Position) error {
	subtree := t
	for _, intermediateKey := range keys {
		nextTree, exists := subtree.values[intermediateKey]
		if !exists {
			tree := newTomlTree()
			tree.position = pos
			subtree.values[intermediateKey] = tree
			nextTree = tree
		}

		switch node := nextTree.(type) {
		case []*TomlTree:
			subtree = node[len(node)-1]
		case *TomlTree:
			subtree = node
		default:
			return fmt.Errorf("unknown type for path %s (%s): %T (%#v)",
				strings.Join(keys, "."), intermediateKey, nextTree, nextTree)
		}
	}
	return nil
}

// Query compiles and executes a query on a tree and returns the query result.
func (t *TomlTree) Query(query string) (*QueryResult, error) {
	q, err := CompileQuery(query)
	if err != nil {
		return nil, err
	}
	return q.Execute(t), nil
}

// LoadReader creates a TomlTree from any io.Reader.
func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
	defer func() {
		if r := recover(); r != nil {
			if _, ok := r.(runtime.Error); ok {
				panic(r)
			}
			err = errors.New(r.(string))
		}
	}()
	tree = parseToml(lexToml(reader))
	return
}

// Load creates a TomlTree from a string.
func Load(content string) (tree *TomlTree, err error) {
	return LoadReader(strings.NewReader(content))
}

// LoadFile creates a TomlTree from a file.
func LoadFile(path string) (tree *TomlTree, err error) {
	file, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer file.Close()
	return LoadReader(file)
}
<|endoftext|>