<commit_before>package todolist

import (
	"fmt"
	"regexp"
	"time"

	"github.com/jinzhu/now"
)

type DateFilter struct {
	Todos []*Todo
}

func NewDateFilter(todos []*Todo) *DateFilter {
	return &DateFilter{Todos: todos}
}

func (f *DateFilter) FilterDate(input string) []*Todo {
	if input == "agenda" {
		fmt.Println("input IS agenda")
		return f.filterAgenda(now.BeginningOfDay())
	}
	r, _ := regexp.Compile(`due .*$`)

	match := r.FindString(input)
	switch {
	case match == "due tod" || match == "due today":
		return f.filterToday(now.BeginningOfDay())
	case match == "due tom" || match == "due tomorrow":
		return f.filterTomorrow(now.BeginningOfDay())
	case match == "due sun" || match == "due sunday":
		return f.filterDay(now.BeginningOfDay(), time.Sunday)
	case match == "due mon" || match == "due monday":
		return f.filterDay(now.BeginningOfDay(), time.Monday)
	case match == "due tue" || match == "due tuesday":
		return f.filterDay(now.BeginningOfDay(), time.Tuesday)
	case match == "due wed" || match == "due wednesday":
		return f.filterDay(now.BeginningOfDay(), time.Wednesday)
	case match == "due thu" || match == "due thursday":
		return f.filterDay(now.BeginningOfDay(), time.Thursday)
	case match == "due fri" || match == "due friday":
		return f.filterDay(now.BeginningOfDay(), time.Friday)
	case match == "due sat" || match == "due saturday":
		return f.filterDay(now.BeginningOfDay(), time.Saturday)
	case match == "due this week":
		return f.filterThisWeek(now.BeginningOfDay())
	case match == "due next week":
		return f.filterNextWeek(now.BeginningOfDay())
	case match == "overdue":
		return f.filterOverdue(now.BeginningOfDay())
	}
	return f.Todos
}

func (f *DateFilter) filterAgenda(pivot time.Time) []*Todo {
	var ret []*Todo

	for _, todo := range f.Todos {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if dueTime.Before(pivot) || todo.Due == pivot.Format("2006-01-02") {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterToday(pivot time.Time) []*Todo {
	var ret []*Todo
	for _, todo := range f.Todos {
		if todo.Due == pivot.Format("2006-01-02") {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterDay(pivot time.Time, day time.Weekday) []*Todo {
	var ret []*Todo
	filtered := f.filterThisWeek(pivot)
	for _, todo := range filtered {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if dueTime.Weekday() == day {
			ret = append(ret, todo)
		}

	}
	return ret
}

func (f *DateFilter) filterTomorrow(pivot time.Time) []*Todo {
	var ret []*Todo
	pivot = pivot.AddDate(0, 0, 1)
	for _, todo := range f.Todos {
		if todo.Due == pivot.Format("2006-01-02") {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterThisWeek(pivot time.Time) []*Todo {
	var ret []*Todo

	begin := f.findSunday(pivot)
	end := begin.AddDate(0, 0, 7)

	for _, todo := range f.Todos {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if begin.Before(dueTime) && end.After(dueTime) {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterNextWeek(pivot time.Time) []*Todo {
	var ret []*Todo

	begin := f.findSunday(pivot).AddDate(0, 0, 7)
	end := begin.AddDate(0, 0, 7)

	for _, todo := range f.Todos {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if begin.Before(dueTime) && end.After(dueTime) {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterOverdue(pivot time.Time) []*Todo {
	var ret []*Todo

	pivotDate := pivot.Format("2006-01-02")

	for _, todo := range f.Todos {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if dueTime.Before(pivot) && pivotDate != todo.Due {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) findSunday(pivot time.Time) time.Time {
	switch now.New(pivot).Weekday() {
	case time.Sunday:
		return pivot
	case time.Monday:
		return pivot.AddDate(0, 0, -1)
	case time.Tuesday:
		return pivot.AddDate(0, 0, -2)
	case time.Wednesday:
		return pivot.AddDate(0, 0, -3)
	case time.Thursday:
		return pivot.AddDate(0, 0, -4)
	case time.Friday:
		return pivot.AddDate(0, 0, -5)
	case time.Saturday:
		return pivot.AddDate(0, 0, -6)
	}
	return pivot
}
<commit_msg>Ensure agenda works with other input<commit_after>package todolist

import (
	"regexp"
	"time"

	"github.com/jinzhu/now"
)

type DateFilter struct {
	Todos []*Todo
}

func NewDateFilter(todos []*Todo) *DateFilter {
	return &DateFilter{Todos: todos}
}

func (f *DateFilter) FilterDate(input string) []*Todo {
	agendaRegex, _ := regexp.Compile(`agenda .*$`)
	if agendaRegex.MatchString(input) {
		return f.filterAgenda(now.BeginningOfDay())
	}

	r, _ := regexp.Compile(`due .*$`)
	match := r.FindString(input)
	switch {
	case match == "due tod" || match == "due today":
		return f.filterToday(now.BeginningOfDay())
	case match == "due tom" || match == "due tomorrow":
		return f.filterTomorrow(now.BeginningOfDay())
	case match == "due sun" || match == "due sunday":
		return f.filterDay(now.BeginningOfDay(), time.Sunday)
	case match == "due mon" || match == "due monday":
		return f.filterDay(now.BeginningOfDay(), time.Monday)
	case match == "due tue" || match == "due tuesday":
		return f.filterDay(now.BeginningOfDay(), time.Tuesday)
	case match == "due wed" || match == "due wednesday":
		return f.filterDay(now.BeginningOfDay(), time.Wednesday)
	case match == "due thu" || match == "due thursday":
		return f.filterDay(now.BeginningOfDay(), time.Thursday)
	case match == "due fri" || match == "due friday":
		return f.filterDay(now.BeginningOfDay(), time.Friday)
	case match == "due sat" || match == "due saturday":
		return f.filterDay(now.BeginningOfDay(), time.Saturday)
	case match == "due this week":
		return f.filterThisWeek(now.BeginningOfDay())
	case match == "due next week":
		return f.filterNextWeek(now.BeginningOfDay())
	case match == "overdue":
		return f.filterOverdue(now.BeginningOfDay())
	}
	return f.Todos
}

func (f *DateFilter) filterAgenda(pivot time.Time) []*Todo {
	var ret []*Todo

	for _, todo := range f.Todos {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if dueTime.Before(pivot) || todo.Due == pivot.Format("2006-01-02") {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterToday(pivot time.Time) []*Todo {
	var ret []*Todo
	for _, todo := range f.Todos {
		if todo.Due == pivot.Format("2006-01-02") {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterDay(pivot time.Time, day time.Weekday) []*Todo {
	var ret []*Todo
	filtered := f.filterThisWeek(pivot)
	for _, todo := range filtered {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if dueTime.Weekday() == day {
			ret = append(ret, todo)
		}

	}
	return ret
}

func (f *DateFilter) filterTomorrow(pivot time.Time) []*Todo {
	var ret []*Todo
	pivot = pivot.AddDate(0, 0, 1)
	for _, todo := range f.Todos {
		if todo.Due == pivot.Format("2006-01-02") {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterThisWeek(pivot time.Time) []*Todo {
	var ret []*Todo

	begin := f.findSunday(pivot)
	end := begin.AddDate(0, 0, 7)

	for _, todo := range f.Todos {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if begin.Before(dueTime) && end.After(dueTime) {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterNextWeek(pivot time.Time) []*Todo {
	var ret []*Todo

	begin := f.findSunday(pivot).AddDate(0, 0, 7)
	end := begin.AddDate(0, 0, 7)

	for _, todo := range f.Todos {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if begin.Before(dueTime) && end.After(dueTime) {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) filterOverdue(pivot time.Time) []*Todo {
	var ret []*Todo

	pivotDate := pivot.Format("2006-01-02")

	for _, todo := range f.Todos {
		dueTime, _ := time.Parse("2006-01-02", todo.Due)
		if dueTime.Before(pivot) && pivotDate != todo.Due {
			ret = append(ret, todo)
		}
	}
	return ret
}

func (f *DateFilter) findSunday(pivot time.Time) time.Time {
	switch now.New(pivot).Weekday() {
	case time.Sunday:
		return pivot
	case time.Monday:
		return pivot.AddDate(0, 0, -1)
	case time.Tuesday:
		return pivot.AddDate(0, 0, -2)
	case time.Wednesday:
		return pivot.AddDate(0, 0, -3)
	case time.Thursday:
		return pivot.AddDate(0, 0, -4)
	case time.Friday:
		return pivot.AddDate(0, 0, -5)
	case time.Saturday:
		return pivot.AddDate(0, 0, -6)
	}
	return pivot
}
<|endoftext|>


<commit_before>package ray

import (
	"context"
	"io"
	"sync"
	"time"

	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/platform"
)

// NewRay creates a new Ray for direct traffic transport.
func NewRay(ctx context.Context) Ray {
	return &directRay{
		Input:  NewStream(ctx),
		Output: NewStream(ctx),
	}
}

type directRay struct {
	Input  *Stream
	Output *Stream
}

func (v *directRay) OutboundInput() InputStream {
	return v.Input
}

func (v *directRay) OutboundOutput() OutputStream {
	return v.Output
}

func (v *directRay) InboundInput() OutputStream {
	return v.Input
}

func (v *directRay) InboundOutput() InputStream {
	return v.Output
}

var streamSizeLimit uint64 = 10 * 1024 * 1024

func init() {
	const raySizeEnvKey = "v2ray.ray.buffer.size"
	size := platform.EnvFlag{
		Name:    raySizeEnvKey,
		AltName: platform.NormalizeEnvName(raySizeEnvKey),
	}.GetValueAsInt(10)
	streamSizeLimit = uint64(size) * 1024 * 1024
}

type Stream struct {
	access      sync.RWMutex
	data        buf.MultiBuffer
	size        uint64
	ctx         context.Context
	readSignal  chan bool
	writeSignal chan bool
	close       bool
	err         bool
}

func NewStream(ctx context.Context) *Stream {
	return &Stream{
		ctx:         ctx,
		readSignal:  make(chan bool, 1),
		writeSignal: make(chan bool, 1),
		size:        0,
	}
}

func (s *Stream) getData() (buf.MultiBuffer, error) {
	s.access.Lock()
	defer s.access.Unlock()

	if s.data != nil {
		mb := s.data
		s.data = nil
		s.size = 0
		return mb, nil
	}

	if s.close {
		return nil, io.EOF
	}

	if s.err {
		return nil, io.ErrClosedPipe
	}

	return nil, nil
}

func (s *Stream) Peek(b *buf.Buffer) {
	s.access.RLock()
	defer s.access.RUnlock()

	b.Reset(func(data []byte) (int, error) {
		return s.data.Copy(data), nil
	})
}

func (s *Stream) Read() (buf.MultiBuffer, error) {
	for {
		mb, err := s.getData()
		if err != nil {
			return nil, err
		}

		if mb != nil {
			s.notifyRead()
			return mb, nil
		}

		select {
		case <-s.ctx.Done():
			return nil, io.EOF
		case <-s.writeSignal:
		}
	}
}

func (s *Stream) ReadTimeout(timeout time.Duration) (buf.MultiBuffer, error) {
	for {
		mb, err := s.getData()
		if err != nil {
			return nil, err
		}

		if mb != nil {
			s.notifyRead()
			return mb, nil
		}

		select {
		case <-s.ctx.Done():
			return nil, io.EOF
		case <-time.After(timeout):
			return nil, buf.ErrReadTimeout
		case <-s.writeSignal:
		}
	}
}

// Size returns the number of bytes hold in the Stream.
func (s *Stream) Size() uint64 {
	s.access.RLock()
	defer s.access.RUnlock()

	return s.size
}

func (s *Stream) waitForStreamSize() error {
	if streamSizeLimit == 0 {
		return nil
	}

	for s.Size() >= streamSizeLimit {
		select {
		case <-s.ctx.Done():
			return io.ErrClosedPipe
		case <-s.readSignal:
			if s.err || s.close {
				return io.ErrClosedPipe
			}
		}
	}

	return nil
}

func (s *Stream) Write(data buf.MultiBuffer) error {
	if data.IsEmpty() {
		return nil
	}

	if err := s.waitForStreamSize(); err != nil {
		data.Release()
		return err
	}

	s.access.Lock()
	defer s.access.Unlock()

	if s.err || s.close {
		data.Release()
		return io.ErrClosedPipe
	}

	if s.data == nil {
		s.data = data
	} else {
		s.data.AppendMulti(data)
	}
	s.size += uint64(data.Len())
	s.notifyWrite()

	return nil
}

func (s *Stream) notifyRead() {
	select {
	case s.readSignal <- true:
	default:
	}
}

func (s *Stream) notifyWrite() {
	select {
	case s.writeSignal <- true:
	default:
	}
}

func (s *Stream) Close() {
	s.access.Lock()
	s.close = true
	s.notifyRead()
	s.notifyWrite()
	s.access.Unlock()
}

func (s *Stream) CloseError() {
	s.access.Lock()
	s.err = true
	if s.data != nil {
		s.data.Release()
		s.data = nil
		s.size = 0
	}
	s.notifyRead()
	s.notifyWrite()
	s.access.Unlock()
}
<commit_msg>fix lint warnings<commit_after>package ray

import (
	"context"
	"io"
	"sync"
	"time"

	"v2ray.com/core/common"
	"v2ray.com/core/common/buf"
	"v2ray.com/core/common/platform"
)

// NewRay creates a new Ray for direct traffic transport.
func NewRay(ctx context.Context) Ray {
	return &directRay{
		Input:  NewStream(ctx),
		Output: NewStream(ctx),
	}
}

type directRay struct {
	Input  *Stream
	Output *Stream
}

func (v *directRay) OutboundInput() InputStream {
	return v.Input
}

func (v *directRay) OutboundOutput() OutputStream {
	return v.Output
}

func (v *directRay) InboundInput() OutputStream {
	return v.Input
}

func (v *directRay) InboundOutput() InputStream {
	return v.Output
}

var streamSizeLimit uint64 = 10 * 1024 * 1024

func init() {
	const raySizeEnvKey = "v2ray.ray.buffer.size"
	size := platform.EnvFlag{
		Name:    raySizeEnvKey,
		AltName: platform.NormalizeEnvName(raySizeEnvKey),
	}.GetValueAsInt(10)
	streamSizeLimit = uint64(size) * 1024 * 1024
}

// Stream is a sequential container for data in bytes.
type Stream struct {
	access      sync.RWMutex
	data        buf.MultiBuffer
	size        uint64
	ctx         context.Context
	readSignal  chan bool
	writeSignal chan bool
	close       bool
	err         bool
}

// NewStream creates a new Stream.
func NewStream(ctx context.Context) *Stream {
	return &Stream{
		ctx:         ctx,
		readSignal:  make(chan bool, 1),
		writeSignal: make(chan bool, 1),
		size:        0,
	}
}

func (s *Stream) getData() (buf.MultiBuffer, error) {
	s.access.Lock()
	defer s.access.Unlock()

	if s.data != nil {
		mb := s.data
		s.data = nil
		s.size = 0
		return mb, nil
	}

	if s.close {
		return nil, io.EOF
	}

	if s.err {
		return nil, io.ErrClosedPipe
	}

	return nil, nil
}

// Peek fills in the given buffer with data from head of the Stream.
func (s *Stream) Peek(b *buf.Buffer) {
	s.access.RLock()
	defer s.access.RUnlock()

	common.Must(b.Reset(func(data []byte) (int, error) {
		return s.data.Copy(data), nil
	}))
}

// Read reads data from the Stream.
func (s *Stream) Read() (buf.MultiBuffer, error) {
	for {
		mb, err := s.getData()
		if err != nil {
			return nil, err
		}

		if mb != nil {
			s.notifyRead()
			return mb, nil
		}

		select {
		case <-s.ctx.Done():
			return nil, io.EOF
		case <-s.writeSignal:
		}
	}
}

// ReadTimeout reads from the Stream with a specified timeout.
func (s *Stream) ReadTimeout(timeout time.Duration) (buf.MultiBuffer, error) {
	for {
		mb, err := s.getData()
		if err != nil {
			return nil, err
		}

		if mb != nil {
			s.notifyRead()
			return mb, nil
		}

		select {
		case <-s.ctx.Done():
			return nil, io.EOF
		case <-time.After(timeout):
			return nil, buf.ErrReadTimeout
		case <-s.writeSignal:
		}
	}
}

// Size returns the number of bytes hold in the Stream.
func (s *Stream) Size() uint64 {
	s.access.RLock()
	defer s.access.RUnlock()

	return s.size
}

// waitForStreamSize waits until the Stream has room for more data, or any error happens.
func (s *Stream) waitForStreamSize() error {
	if streamSizeLimit == 0 {
		return nil
	}

	for s.Size() >= streamSizeLimit {
		select {
		case <-s.ctx.Done():
			return io.ErrClosedPipe
		case <-s.readSignal:
			if s.err || s.close {
				return io.ErrClosedPipe
			}
		}
	}

	return nil
}

// Write writes more data into the Stream.
func (s *Stream) Write(data buf.MultiBuffer) error {
	if data.IsEmpty() {
		return nil
	}

	if err := s.waitForStreamSize(); err != nil {
		data.Release()
		return err
	}

	s.access.Lock()
	defer s.access.Unlock()

	if s.err || s.close {
		data.Release()
		return io.ErrClosedPipe
	}

	if s.data == nil {
		s.data = data
	} else {
		s.data.AppendMulti(data)
	}
	s.size += uint64(data.Len())
	s.notifyWrite()

	return nil
}

func (s *Stream) notifyRead() {
	select {
	case s.readSignal <- true:
	default:
	}
}

func (s *Stream) notifyWrite() {
	select {
	case s.writeSignal <- true:
	default:
	}
}

// Close closes the stream for writing. Read() still works until EOF.
func (s *Stream) Close() {
	s.access.Lock()
	s.close = true
	s.notifyRead()
	s.notifyWrite()
	s.access.Unlock()
}

// CloseError closes the Stream with error. Read() will return an error afterwards.
func (s *Stream) CloseError() {
	s.access.Lock()
	s.err = true
	if s.data != nil {
		s.data.Release()
		s.data = nil
		s.size = 0
	}
	s.notifyRead()
	s.notifyWrite()
	s.access.Unlock()
}
<|endoftext|>


<commit_before>package rapi

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
	"text/template"

	"github.com/gorilla/mux"
)

type TransformCb func() (err error)

type Endpoint struct {
	config       *Config
	path         string
	reqExtStruct interface{}
	reqIntStruct interface{}
	resExtStruct interface{}
	resIntStruct interface{}
	transformer  Transformable
}

func NewEndpoint(a *Api, method, path string) *Endpoint {
	ep := &Endpoint{
		config:      a.config,
		path:        path,
		transformer: a.transformer,
	}

	a.Route(method, ep.config.Listener.Prefix+path, ep)

	return ep
}

func (ep *Endpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tr := http.DefaultTransport

	ep.CopyUrlVars(r)

	r.URL.Host = ep.config.Backend.Address
	r.URL.Scheme = "http"
	r.URL.Path = ep.config.Backend.Prefix + ep.path

	if ep.reqIntStruct != nil && ep.reqExtStruct != nil {
		ep.transformer.TransformRequest(r, &ep.reqExtStruct, &ep.reqIntStruct)
	}

	res, resErr := tr.RoundTrip(r)
	if resErr != nil {
		panic(fmt.Sprintf("Response error: %s", resErr))
	} else {
		defer res.Body.Close()
	}

	if ep.resIntStruct != nil && ep.resExtStruct != nil {
		ep.transformer.TransformResponse(res, &ep.resIntStruct, &ep.resExtStruct)
	}

	w.WriteHeader(res.StatusCode)
	_, ioErr := io.Copy(w, res.Body)

	if ioErr != nil {
		log.Printf("Error writting response: %s", ioErr)
	}
}

func (ep *Endpoint) CopyUrlVars(r *http.Request) {
	var path bytes.Buffer

	vars := mux.Vars(r)
	if len(vars) == 0 {
		return
	}

	t, err := template.New("path").Parse(ep.path)
	if err != nil {
		return
	}

	t.Execute(&path, vars)
	ep.path = path.String()
}

func (ep *Endpoint) InternalPath(path string) *Endpoint {
	ep.path = path
	return ep
}

func (ep *Endpoint) TransformRequest(ex, in interface{}) *Endpoint {
	ep.reqExtStruct = ex
	ep.reqIntStruct = in
	return ep
}

func (ep *Endpoint) TransformResponse(in, ex interface{}) *Endpoint {
	ep.resIntStruct = in
	ep.resExtStruct = ex
	return ep
}

// To be done
func (ep *Endpoint) TransformRequestCb(cb TransformCb) *Endpoint {
	err := cb()
	if err != nil {
		log.Print("Something went wrong")
	}
	return ep
}

// To be done
func (ep *Endpoint) TransformResponseCb(cb TransformCb) *Endpoint {
	err := cb()
	if err != nil {
		log.Print("Something went wrong")
	}
	return ep
}
<commit_msg>Add downstream https request support<commit_after>package rapi

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io"
	"log"
	"net/http"
	"text/template"

	"github.com/gorilla/mux"
)

type TransformCb func() (err error)

type Endpoint struct {
	config       *Config
	path         string
	reqExtStruct interface{}
	reqIntStruct interface{}
	resExtStruct interface{}
	resIntStruct interface{}
	transformer  Transformable
}

func NewEndpoint(a *Api, method, path string) *Endpoint {
	ep := &Endpoint{
		config:      a.config,
		path:        path,
		transformer: a.transformer,
	}

	a.Route(method, ep.config.Listener.Prefix+path, ep)

	return ep
}

func (ep *Endpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	tr := http.DefaultTransport

	ep.CopyUrlVars(r)

	r.URL.Host = ep.config.Backend.Address
	r.URL.Path = ep.config.Backend.Prefix + ep.path

	if ep.config.Backend.Tls.Enable {
		r.URL.Scheme = "https"
		if ep.config.Backend.Tls.InsecureSkipVerify {
			tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
		}
	} else {
		r.URL.Scheme = "http"
	}

	if ep.reqIntStruct != nil && ep.reqExtStruct != nil {
		ep.transformer.TransformRequest(r, &ep.reqExtStruct, &ep.reqIntStruct)
	}

	res, resErr := tr.RoundTrip(r)
	if resErr != nil {
		panic(fmt.Sprintf("Response error: %s", resErr))
	} else {
		defer res.Body.Close()
	}

	if ep.resIntStruct != nil && ep.resExtStruct != nil {
		ep.transformer.TransformResponse(res, &ep.resIntStruct, &ep.resExtStruct)
	}

	w.WriteHeader(res.StatusCode)
	_, ioErr := io.Copy(w, res.Body)

	if ioErr != nil {
		log.Printf("Error writting response: %s", ioErr)
	}
}

func (ep *Endpoint) CopyUrlVars(r *http.Request) {
	var path bytes.Buffer

	vars := mux.Vars(r)
	if len(vars) == 0 {
		return
	}

	t, err := template.New("path").Parse(ep.path)
	if err != nil {
		return
	}

	t.Execute(&path, vars)
	ep.path = path.String()
}

func (ep *Endpoint) InternalPath(path string) *Endpoint {
	ep.path = path
	return ep
}

func (ep *Endpoint) TransformRequest(ex, in interface{}) *Endpoint {
	ep.reqExtStruct = ex
	ep.reqIntStruct = in
	return ep
}

func (ep *Endpoint) TransformResponse(in, ex interface{}) *Endpoint {
	ep.resIntStruct = in
	ep.resExtStruct = ex
	return ep
}

// To be done
func (ep *Endpoint) TransformRequestCb(cb TransformCb) *Endpoint {
	err := cb()
	if err != nil {
		log.Print("Something went wrong")
	}
	return ep
}

// To be done
func (ep *Endpoint) TransformResponseCb(cb TransformCb) *Endpoint {
	err := cb()
	if err != nil {
		log.Print("Something went wrong")
	}
	return ep
}
<|endoftext|>


<commit_before>package libkbfs

import (
	"log"
	"sync"
	"time"

	"golang.org/x/net/context"
)

// KBFSOpsStandard implements the KBFSOps interface, and is go-routine
// safe by forwarding requests to individual per-folder-branch
// handlers that are go-routine-safe.
type KBFSOpsStandard struct {
	config  Config
	ops     map[FolderBranch]*FolderBranchOps
	opsLock sync.RWMutex
}

var _ KBFSOps = (*KBFSOpsStandard)(nil)

// NewKBFSOpsStandard constructs a new KBFSOpsStandard object.
func NewKBFSOpsStandard(config Config) *KBFSOpsStandard {
	return &KBFSOpsStandard{
		config: config,
		ops:    make(map[FolderBranch]*FolderBranchOps),
	}
}

// Shutdown safely shuts down any background goroutines that may have
// been launched by KBFSOpsStandard.
func (fs *KBFSOpsStandard) Shutdown() {
	for _, ops := range fs.ops {
		ops.Shutdown()
	}
}

// GetFavorites implements the KBFSOps interface for
// KBFSOpsStandard.
//
// Notes:
//
// Now that this uses keybased to get the list of
// favorites, it gets the folder name as a string.  In order to
// return TlfHandles, it has to call ParseTlfHandle(), which is
// expensive in that it calls resolveUser on each user in each
// favorite, which calls Identify.
//
// So, for example, doing an `ls /keybase/private` when you have
// lots of favorites is going to result in a lot of identify
// calls.
//
// It would be nice to have `ls /keybase/private` not result in
// identify calls and just display the list of favorite names,
// then when you `cd /keybase/private/alice,bob` or `cp x.tar.gz
// /keybase/private/alice,bob,charlie` any necessary identify
// calls will be made.
//
// Will explore how best to do that in a separate branch.
//
func (fs *KBFSOpsStandard) GetFavorites(ctx context.Context) ([]*TlfHandle, error) {
	kbd := fs.config.KBPKI()
	folders, err := kbd.FavoriteList(ctx)
	if err != nil {
		return nil, err
	}

	var handles []*TlfHandle
	for _, f := range folders {
		handle, err := ParseTlfHandle(ctx, fs.config, f.Name)
		if err != nil {
			// not a fatal error.
			log.Printf("ParseTlfHandler error: %s", err)
			continue
		}
		handles = append(handles, handle)
	}
	return handles, nil
}

func (fs *KBFSOpsStandard) getOps(fb FolderBranch) *FolderBranchOps {
	fs.opsLock.RLock()
	if ops, ok := fs.ops[fb]; ok {
		fs.opsLock.RUnlock()
		return ops
	}

	fs.opsLock.RUnlock()
	fs.opsLock.Lock()
	defer fs.opsLock.Unlock()
	// look it up again in case someone else got the lock
	ops, ok := fs.ops[fb]
	if !ok {
		// TODO: add some interface for specifying the type of the
		// branch; for now assume online and read-write.
		ops = NewFolderBranchOps(fs.config, fb, standard)
		fs.ops[fb] = ops
	}
	return ops
}

func (fs *KBFSOpsStandard) getOpsByNode(node Node) *FolderBranchOps {
	return fs.getOps(node.GetFolderBranch())
}

// GetOrCreateRootNodeForHandle implements the KBFSOps interface for
// KBFSOpsStandard
func (fs *KBFSOpsStandard) GetOrCreateRootNodeForHandle(
	ctx context.Context, handle *TlfHandle, branch BranchName) (
	node Node, de DirEntry, err error) {
	// Do GetForHandle() unlocked -- no cache lookups, should be fine
	mdops := fs.config.MDOps()
	// TODO: only do this the first time, cache the folder ID after that
	md, err := mdops.GetForHandle(ctx, handle)
	if err != nil {
		return
	}

	// TODO: in andy_md2 branch, if GetForHandle returns (id, nil, nil) then
	// the folder was just created.  For now, we don't know, so we'll
	// just assume it was created.
	created := true
	if created && branch == MasterBranch {
		// add folder to favorites
		err = fs.config.KBPKI().FavoriteAdd(ctx, handle.ToKBFolder(ctx, fs.config))
		if err != nil {
			return
		}
	}

	fb := FolderBranch{Tlf: md.ID, Branch: branch}
	ops := fs.getOps(fb)
	if branch == MasterBranch {
		// For now, only the master branch can be initialized with a
		// branch new MD object.
		err = ops.CheckForNewMDAndInit(ctx, md)
		if err != nil {
			return
		}
	}

	node, de, _, err = ops.GetRootNode(ctx, fb)
	return
}

// GetRootNode implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) GetRootNode(ctx context.Context,
	folderBranch FolderBranch) (Node, DirEntry, *TlfHandle, error) {
	ops := fs.getOps(folderBranch)
	return ops.GetRootNode(ctx, folderBranch)
}

// GetDirChildren implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) GetDirChildren(ctx context.Context, dir Node) (
	map[string]EntryType, error) {
	ops := fs.getOpsByNode(dir)
	return ops.GetDirChildren(ctx, dir)
}

// Lookup implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Lookup(ctx context.Context, dir Node, name string) (
	Node, DirEntry, error) {
	ops := fs.getOpsByNode(dir)
	return ops.Lookup(ctx, dir, name)
}

// Stat implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Stat(ctx context.Context, node Node) (
	DirEntry, error) {
	ops := fs.getOpsByNode(node)
	return ops.Stat(ctx, node)
}

// CreateDir implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) CreateDir(
	ctx context.Context, dir Node, name string) (Node, DirEntry, error) {
	ops := fs.getOpsByNode(dir)
	return ops.CreateDir(ctx, dir, name)
}

// CreateFile implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) CreateFile(
	ctx context.Context, dir Node, name string, isExec bool) (
	Node, DirEntry, error) {
	ops := fs.getOpsByNode(dir)
	return ops.CreateFile(ctx, dir, name, isExec)
}

// CreateLink implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) CreateLink(
	ctx context.Context, dir Node, fromName string, toPath string) (
	DirEntry, error) {
	ops := fs.getOpsByNode(dir)
	return ops.CreateLink(ctx, dir, fromName, toPath)
}

// RemoveDir implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) RemoveDir(
	ctx context.Context, dir Node, name string) error {
	ops := fs.getOpsByNode(dir)
	return ops.RemoveDir(ctx, dir, name)
}

// RemoveEntry implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) RemoveEntry(
	ctx context.Context, dir Node, name string) error {
	ops := fs.getOpsByNode(dir)
	return ops.RemoveEntry(ctx, dir, name)
}

// Rename implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Rename(
	ctx context.Context, oldParent Node, oldName string, newParent Node,
	newName string) error {
	oldFB := oldParent.GetFolderBranch()
	newFB := newParent.GetFolderBranch()

	// only works for nodes within the same topdir
	if oldFB != newFB {
		return RenameAcrossDirsError{}
	}

	ops := fs.getOpsByNode(oldParent)
	return ops.Rename(ctx, oldParent, oldName, newParent, newName)
}

// Read implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Read(
	ctx context.Context, file Node, dest []byte, off int64) (
	numRead int64, err error) {
	ops := fs.getOpsByNode(file)
	return ops.Read(ctx, file, dest, off)
}

// Write implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Write(
	ctx context.Context, file Node, data []byte, off int64) error {
	ops := fs.getOpsByNode(file)
	return ops.Write(ctx, file, data, off)
}

// Truncate implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Truncate(
	ctx context.Context, file Node, size uint64) error {
	ops := fs.getOpsByNode(file)
	return ops.Truncate(ctx, file, size)
}

// SetEx implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) SetEx(
	ctx context.Context, file Node, ex bool) error {
	ops := fs.getOpsByNode(file)
	return ops.SetEx(ctx, file, ex)
}

// SetMtime implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) SetMtime(
	ctx context.Context, file Node, mtime *time.Time) error {
	ops := fs.getOpsByNode(file)
	return ops.SetMtime(ctx, file, mtime)
}

// Sync implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Sync(ctx context.Context, file Node) error {
	ops := fs.getOpsByNode(file)
	return ops.Sync(ctx, file)
}

// Notifier:
var _ Notifier = (*KBFSOpsStandard)(nil)

// RegisterForChanges implements the Notifer interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) RegisterForChanges(
	folderBranches []FolderBranch, obs Observer) error {
	for _, fb := range folderBranches {
		// TODO: add branch parameter to notifier interface
		ops := fs.getOps(fb)
		return ops.RegisterForChanges(obs)
	}
	return nil
}

// UnregisterFromChanges implements the Notifer interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) UnregisterFromChanges(
	folderBranches []FolderBranch, obs Observer) error {
	for _, fb := range folderBranches {
		// TODO: add branch parameter to notifier interface
		ops := fs.getOps(fb)
		return ops.UnregisterFromChanges(obs)
	}
	return nil
}
<commit_msg>added getOpsByHandle, FavoriteAdd called in it if FolderBranch not in ops.<commit_after>package libkbfs

import (
	"log"
	"sync"
	"time"

	"golang.org/x/net/context"
)

// KBFSOpsStandard implements the KBFSOps interface, and is go-routine
// safe by forwarding requests to individual per-folder-branch
// handlers that are go-routine-safe.
type KBFSOpsStandard struct {
	config  Config
	ops     map[FolderBranch]*FolderBranchOps
	opsLock sync.RWMutex
}

var _ KBFSOps = (*KBFSOpsStandard)(nil)

// NewKBFSOpsStandard constructs a new KBFSOpsStandard object.
func NewKBFSOpsStandard(config Config) *KBFSOpsStandard {
	return &KBFSOpsStandard{
		config: config,
		ops:    make(map[FolderBranch]*FolderBranchOps),
	}
}

// Shutdown safely shuts down any background goroutines that may have
// been launched by KBFSOpsStandard.
func (fs *KBFSOpsStandard) Shutdown() {
	for _, ops := range fs.ops {
		ops.Shutdown()
	}
}

// GetFavorites implements the KBFSOps interface for
// KBFSOpsStandard.
//
// Notes:
//
// Now that this uses keybased to get the list of
// favorites, it gets the folder name as a string.  In order to
// return TlfHandles, it has to call ParseTlfHandle(), which is
// expensive in that it calls resolveUser on each user in each
// favorite, which calls Identify.
//
// So, for example, doing an `ls /keybase/private` when you have
// lots of favorites is going to result in a lot of identify
// calls.
//
// It would be nice to have `ls /keybase/private` not result in
// identify calls and just display the list of favorite names,
// then when you `cd /keybase/private/alice,bob` or `cp x.tar.gz
// /keybase/private/alice,bob,charlie` any necessary identify
// calls will be made.
//
// Will explore how best to do that in a separate branch.
//
func (fs *KBFSOpsStandard) GetFavorites(ctx context.Context) ([]*TlfHandle, error) {
	kbd := fs.config.KBPKI()
	folders, err := kbd.FavoriteList(ctx)
	if err != nil {
		return nil, err
	}

	var handles []*TlfHandle
	for _, f := range folders {
		handle, err := ParseTlfHandle(ctx, fs.config, f.Name)
		if err != nil {
			// not a fatal error.
			log.Printf("ParseTlfHandler error: %s", err)
			continue
		}
		handles = append(handles, handle)
	}
	return handles, nil
}

func (fs *KBFSOpsStandard) getOps(fb FolderBranch) *FolderBranchOps {
	fs.opsLock.RLock()
	if ops, ok := fs.ops[fb]; ok {
		fs.opsLock.RUnlock()
		return ops
	}

	fs.opsLock.RUnlock()
	fs.opsLock.Lock()
	defer fs.opsLock.Unlock()
	// look it up again in case someone else got the lock
	ops, ok := fs.ops[fb]
	if !ok {
		// TODO: add some interface for specifying the type of the
		// branch; for now assume online and read-write.
		ops = NewFolderBranchOps(fs.config, fb, standard)
		fs.ops[fb] = ops
	}
	return ops
}

func (fs *KBFSOpsStandard) getOpsByNode(node Node) *FolderBranchOps {
	return fs.getOps(node.GetFolderBranch())
}

func (fs *KBFSOpsStandard) getOpsByHandle(ctx context.Context, handle *TlfHandle, fb FolderBranch) (*FolderBranchOps, error) {
	fs.opsLock.RLock()
	_, exists := fs.ops[fb]
	fs.opsLock.RUnlock()

	if !exists && fb.Branch == MasterBranch {
		err := fs.config.KBPKI().FavoriteAdd(ctx, handle.ToKBFolder(ctx, fs.config))
		if err != nil {
			return nil, err
		}
	}

	return fs.getOps(fb), nil
}

// GetOrCreateRootNodeForHandle implements the KBFSOps interface for
// KBFSOpsStandard
func (fs *KBFSOpsStandard) GetOrCreateRootNodeForHandle(
	ctx context.Context, handle *TlfHandle, branch BranchName) (
	node Node, de DirEntry, err error) {

	// Do GetForHandle() unlocked -- no cache lookups, should be fine
	mdops := fs.config.MDOps()
	// TODO: only do this the first time, cache the folder ID after that
	md, err := mdops.GetForHandle(ctx, handle)
	if err != nil {
		return
	}

	fb := FolderBranch{Tlf: md.ID, Branch: branch}
	ops, err := fs.getOpsByHandle(ctx, handle, fb)
	if err != nil {
		return
	}
	if branch == MasterBranch {
		// For now, only the master branch can be initialized with a
		// branch new MD object.
		err = ops.CheckForNewMDAndInit(ctx, md)
		if err != nil {
			return
		}
	}

	node, de, _, err = ops.GetRootNode(ctx, fb)
	return
}

// GetRootNode implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) GetRootNode(ctx context.Context,
	folderBranch FolderBranch) (Node, DirEntry, *TlfHandle, error) {
	ops := fs.getOps(folderBranch)
	return ops.GetRootNode(ctx, folderBranch)
}

// GetDirChildren implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) GetDirChildren(ctx context.Context, dir Node) (
	map[string]EntryType, error) {
	ops := fs.getOpsByNode(dir)
	return ops.GetDirChildren(ctx, dir)
}

// Lookup implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Lookup(ctx context.Context, dir Node, name string) (
	Node, DirEntry, error) {
	ops := fs.getOpsByNode(dir)
	return ops.Lookup(ctx, dir, name)
}

// Stat implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Stat(ctx context.Context, node Node) (
	DirEntry, error) {
	ops := fs.getOpsByNode(node)
	return ops.Stat(ctx, node)
}

// CreateDir implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) CreateDir(
	ctx context.Context, dir Node, name string) (Node, DirEntry, error) {
	ops := fs.getOpsByNode(dir)
	return ops.CreateDir(ctx, dir, name)
}

// CreateFile implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) CreateFile(
	ctx context.Context, dir Node, name string, isExec bool) (
	Node, DirEntry, error) {
	ops := fs.getOpsByNode(dir)
	return ops.CreateFile(ctx, dir, name, isExec)
}

// CreateLink implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) CreateLink(
	ctx context.Context, dir Node, fromName string, toPath string) (
	DirEntry, error) {
	ops := fs.getOpsByNode(dir)
	return ops.CreateLink(ctx, dir, fromName, toPath)
}

// RemoveDir implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) RemoveDir(
	ctx context.Context, dir Node, name string) error {
	ops := fs.getOpsByNode(dir)
	return ops.RemoveDir(ctx, dir, name)
}

// RemoveEntry implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) RemoveEntry(
	ctx context.Context, dir Node, name string) error {
	ops := fs.getOpsByNode(dir)
	return ops.RemoveEntry(ctx, dir, name)
}

// Rename implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Rename(
	ctx context.Context, oldParent Node, oldName string, newParent Node,
	newName string) error {
	oldFB := oldParent.GetFolderBranch()
	newFB := newParent.GetFolderBranch()

	// only works for nodes within the same topdir
	if oldFB != newFB {
		return RenameAcrossDirsError{}
	}

	ops := fs.getOpsByNode(oldParent)
	return ops.Rename(ctx, oldParent, oldName, newParent, newName)
}

// Read implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Read(
	ctx context.Context, file Node, dest []byte, off int64) (
	numRead int64, err error) {
	ops := fs.getOpsByNode(file)
	return ops.Read(ctx, file, dest, off)
}

// Write implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Write(
	ctx context.Context, file Node, data []byte, off int64) error {
	ops := fs.getOpsByNode(file)
	return ops.Write(ctx, file, data, off)
}

// Truncate implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Truncate(
	ctx context.Context, file Node, size uint64) error {
	ops := fs.getOpsByNode(file)
	return ops.Truncate(ctx, file, size)
}

// SetEx implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) SetEx(
	ctx context.Context, file Node, ex bool) error {
	ops := fs.getOpsByNode(file)
	return ops.SetEx(ctx, file, ex)
}

// SetMtime implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) SetMtime(
	ctx context.Context, file Node, mtime *time.Time) error {
	ops := fs.getOpsByNode(file)
	return ops.SetMtime(ctx, file, mtime)
}

// Sync implements the KBFSOps interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) Sync(ctx context.Context, file Node) error {
	ops := fs.getOpsByNode(file)
	return ops.Sync(ctx, file)
}

// Notifier:
var _ Notifier = (*KBFSOpsStandard)(nil)

// RegisterForChanges implements the Notifer interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) RegisterForChanges(
	folderBranches []FolderBranch, obs Observer) error {
	for _, fb := range folderBranches {
		// TODO: add branch parameter to notifier interface
		ops := fs.getOps(fb)
		return ops.RegisterForChanges(obs)
	}
	return nil
}

// UnregisterFromChanges implements the Notifer interface for KBFSOpsStandard
func (fs *KBFSOpsStandard) UnregisterFromChanges(
	folderBranches []FolderBranch, obs Observer) error {
	for _, fb := range folderBranches {
		// TODO: add branch parameter to notifier interface
		ops := fs.getOps(fb)
		return ops.UnregisterFromChanges(obs)
	}
	return nil
}
<|endoftext|>


<commit_before>// Database stuff.
package storage

import (
	"database/sql"
	_ "github.com/mattn/go-sqlite3"
	"github.com/semanticize/dumpparser/hash/countmin"
	"log"
	"os"
	"strconv"
)

const create = (`
	pragma foreign_keys = on;
	pragma journal_mode = off;
	pragma synchronous = off;

	drop table if exists linkstats;
	drop table if exists ngramfreq;

	create table parameters (
		key   text primary key not NULL,
		value text default NULL
	);

	create table ngramfreq (
		row   integer not NULL,
		col   integer not NULL,
		count integer not NULL
	);

	-- XXX I tried to put the link targets in a separate table with a foreign
	-- key in this one, but inserting into that table would sometimes fail.
	create table linkstats (
		ngramhash integer not NULL,
		target    string  not NULL,		-- actually UTF-8
		count     float   not NULL
	);

	create index target on linkstats(target);
	create unique index hash_target on linkstats(ngramhash, target);
`)

func MakeDB(path string, overwrite bool, maxNGram uint) (db *sql.DB, err error) {
	if overwrite {
		os.Remove(path)
	}
	db, err = sql.Open("sqlite3", path)
	defer func() {
		if err != nil && db != nil {
			db.Close()
			db = nil
		}
	}()

	if err == nil {
		err = db.Ping()
	}
	if err == nil {
		_, err = db.Exec(create)
	}
	if err == nil {
		_, err = db.Exec(`insert into parameters values ("maxngram", ?)`,
			strconv.FormatUint(uint64(maxNGram), 10))
	}
	return
}

// XXX move this elsewhere
const DefaultMaxNGram = 7

// XXX Load and return the n-gram count-min sketch as well?
func LoadModel(path string) (db *sql.DB, maxNGram int, err error) {
	db, err = sql.Open("sqlite3", path)
	defer func() {
		if err != nil && db != nil {
			db.Close()
			db = nil
		}
	}()

	if err == nil {
		db.Ping()
	}
	if err == nil {
		maxNGram, err = loadModel(db)
	}
	return
}

func loadModel(db *sql.DB) (maxNGram int, err error) {
	var maxNGramStr string
	rows := db.QueryRow(`select value from parameters where key = "maxngram"`)
	err = rows.Scan(&maxNGramStr)
	if err == sql.ErrNoRows {
		log.Printf("no maxngram setting in database, using default=%d",
			DefaultMaxNGram)
		maxNGram = DefaultMaxNGram
	} else if maxNGramStr == "" {
		// go-sqlite3 seems to return this if the parameter is not set...
		maxNGram = DefaultMaxNGram
	} else {
		var max64 int64
		max64, err = strconv.ParseInt(maxNGramStr, 10, 0)
		maxNGram = int(max64)
	}
	return
}

func Finalize(db *sql.DB) (err error) {
	_, err = db.Exec("drop index target;")
	if err != nil {
		return
	}
	_, err = db.Exec("vacuum;")
	return
}

// Prepares statement; panics on error.
func MustPrepare(db *sql.DB, statement string) *sql.Stmt {
	stmt, err := db.Prepare(statement)
	if err != nil {
		panic(err)
	}
	return stmt
}

type linkCount struct {
	hash  int64
	count float64
}

func ProcessRedirects(db *sql.DB, redirs map[string]string) error {
	counts := make([]linkCount, 0)

	old := MustPrepare(db,
		`select ngramhash, count from linkstats where target = ?`)
	del := MustPrepare(db, `delete from linkstats where target = ?`)
	ins := MustPrepare(db, `insert or ignore into linkstats values (?, ?, 0)`)
	update := MustPrepare(db,
		`update linkstats set count = count + ? where target = ? and ngramhash = ?`)

	for from, to := range redirs {
		rows, err := old.Query(from)
		if err != nil {
			return err
		}

		// SQLite won't let us INSERT or UPDATE while doing a SELECT.
		for counts = counts[:0]; rows.Next(); {
			var count float64
			var hash int64
			rows.Scan(&hash, &count)
			counts = append(counts, linkCount{hash, count})
		}
		rows.Close()
		err = rows.Err()
		if err != nil {
			return err
		}

		_, err = del.Exec(from)
		if err != nil {
			return err
		}

		for _, c := range counts {
			_, err = ins.Exec(c.hash, to)
			if err != nil {
				return err
			}

			_, err = update.Exec(c.count, to, c.hash)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// Load count-min sketch from table ngramfreq.
func LoadCM(db *sql.DB) (sketch *countmin.Sketch, err error) {
	var nrows, ncols int
	shapequery := "select max(row) + 1, max(col) + 1 from ngramfreq"
	err = db.QueryRow(shapequery).Scan(&nrows, &ncols)
	if err != nil {
		return
	}

	cmrows := make([][]uint32, nrows)
	for i := 0; i < nrows; i++ {
		cmrows[i] = make([]uint32, ncols)
	}
	dbrows, err := db.Query("select row, col, count from ngramfreq")
	if err != nil {
		return
	}
	for dbrows.Next() {
		var i, j, count uint32
		if err = dbrows.Scan(&i, &j, &count); err != nil {
			return
		}
		cmrows[i][j] = count
	}
	sketch, err = countmin.NewFromCounts(cmrows)
	return
}

// Store count-min sketch into table ngramfreq.
func StoreCM(db *sql.DB, sketch *countmin.Sketch) (err error) {
	insCM, err := db.Prepare(`insert into ngramfreq values (?, ?, ?)`)
	if err != nil {
		return
	}

	for i, row := range sketch.Counts() {
		for j, v := range row {
			_, err = insCM.Exec(i, j, int(v))
			if err != nil {
				return
			}
		}
	}
	return
}
<commit_msg>make maxNGram a uint in storage<commit_after>// Database stuff.
package storage

import (
	"database/sql"
	"fmt"
	_ "github.com/mattn/go-sqlite3"
	"github.com/semanticize/dumpparser/hash/countmin"
	"log"
	"os"
	"strconv"
)

const create = (`
	pragma foreign_keys = on;
	pragma journal_mode = off;
	pragma synchronous = off;

	drop table if exists linkstats;
	drop table if exists ngramfreq;

	create table parameters (
		key   text primary key not NULL,
		value text default NULL
	);

	create table ngramfreq (
		row   integer not NULL,
		col   integer not NULL,
		count integer not NULL
	);

	-- XXX I tried to put the link targets in a separate table with a foreign
	-- key in this one, but inserting into that table would sometimes fail.
	create table linkstats (
		ngramhash integer not NULL,
		target    string  not NULL,		-- actually UTF-8
		count     float   not NULL
	);

	create index target on linkstats(target);
	create unique index hash_target on linkstats(ngramhash, target);
`)

func MakeDB(path string, overwrite bool, maxNGram uint) (db *sql.DB, err error) {
	if overwrite {
		os.Remove(path)
	}
	db, err = sql.Open("sqlite3", path)
	defer func() {
		if err != nil && db != nil {
			db.Close()
			db = nil
		}
	}()

	if err == nil {
		err = db.Ping()
	}
	if err == nil {
		_, err = db.Exec(create)
	}
	if err == nil {
		_, err = db.Exec(`insert into parameters values ("maxngram", ?)`,
			strconv.FormatUint(uint64(maxNGram), 10))
	}
	return
}

// XXX move this elsewhere
const DefaultMaxNGram = 7

// XXX Load and return the n-gram count-min sketch as well?
func LoadModel(path string) (db *sql.DB, maxNGram uint, err error) {
	db, err = sql.Open("sqlite3", path)
	defer func() {
		if err != nil && db != nil {
			db.Close()
			db = nil
		}
	}()

	if err == nil {
		db.Ping()
	}
	if err == nil {
		maxNGram, err = loadModel(db)
	}
	return
}

func loadModel(db *sql.DB) (maxNGram uint, err error) {
	var maxNGramStr string
	rows := db.QueryRow(`select value from parameters where key = "maxngram"`)
	err = rows.Scan(&maxNGramStr)
	if err == sql.ErrNoRows {
		log.Printf("no maxngram setting in database, using default=%d",
			DefaultMaxNGram)
		maxNGram = DefaultMaxNGram
	} else if maxNGramStr == "" {
		// go-sqlite3 seems to return this if the parameter is not set...
		maxNGram = DefaultMaxNGram
	} else {
		var max64 int64
		max64, err = strconv.ParseInt(maxNGramStr, 10, 0)
		if max64 <= 0 {
			err = fmt.Errorf("invalid value maxngram=%d, must be >0")
		} else {
			maxNGram = uint(max64)
		}
	}
	return
}

func Finalize(db *sql.DB) (err error) {
	_, err = db.Exec("drop index target;")
	if err != nil {
		return
	}
	_, err = db.Exec("vacuum;")
	return
}

// Prepares statement; panics on error.
func MustPrepare(db *sql.DB, statement string) *sql.Stmt {
	stmt, err := db.Prepare(statement)
	if err != nil {
		panic(err)
	}
	return stmt
}

type linkCount struct {
	hash  int64
	count float64
}

func ProcessRedirects(db *sql.DB, redirs map[string]string) error {
	counts := make([]linkCount, 0)

	old := MustPrepare(db,
		`select ngramhash, count from linkstats where target = ?`)
	del := MustPrepare(db, `delete from linkstats where target = ?`)
	ins := MustPrepare(db, `insert or ignore into linkstats values (?, ?, 0)`)
	update := MustPrepare(db,
		`update linkstats set count = count + ? where target = ? and ngramhash = ?`)

	for from, to := range redirs {
		rows, err := old.Query(from)
		if err != nil {
			return err
		}

		// SQLite won't let us INSERT or UPDATE while doing a SELECT.
		for counts = counts[:0]; rows.Next(); {
			var count float64
			var hash int64
			rows.Scan(&hash, &count)
			counts = append(counts, linkCount{hash, count})
		}
		rows.Close()
		err = rows.Err()
		if err != nil {
			return err
		}

		_, err = del.Exec(from)
		if err != nil {
			return err
		}

		for _, c := range counts {
			_, err = ins.Exec(c.hash, to)
			if err != nil {
				return err
			}

			_, err = update.Exec(c.count, to, c.hash)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// Load count-min sketch from table ngramfreq.
func LoadCM(db *sql.DB) (sketch *countmin.Sketch, err error) {
	var nrows, ncols int
	shapequery := "select max(row) + 1, max(col) + 1 from ngramfreq"
	err = db.QueryRow(shapequery).Scan(&nrows, &ncols)
	if err != nil {
		return
	}

	cmrows := make([][]uint32, nrows)
	for i := 0; i < nrows; i++ {
		cmrows[i] = make([]uint32, ncols)
	}
	dbrows, err := db.Query("select row, col, count from ngramfreq")
	if err != nil {
		return
	}
	for dbrows.Next() {
		var i, j, count uint32
		if err = dbrows.Scan(&i, &j, &count); err != nil {
			return
		}
		cmrows[i][j] = count
	}
	sketch, err = countmin.NewFromCounts(cmrows)
	return
}

// Store count-min sketch into table ngramfreq.
func StoreCM(db *sql.DB, sketch *countmin.Sketch) (err error) {
	insCM, err := db.Prepare(`insert into ngramfreq values (?, ?, ?)`)
	if err != nil {
		return
	}

	for i, row := range sketch.Counts() {
		for j, v := range row {
			_, err = insCM.Exec(i, j, int(v))
			if err != nil {
				return
			}
		}
	}
	return
}
<|endoftext|>


<commit_before>package daemon

import (
	"log"
)

type LinuxRecord struct {
	name        string
	description string
}

func newDaemon(name, description string) (*LinuxRecord, error) {

	return &LinuxRecord{name, description}, nil
}

func (linux *LinuxRecord) Install() error {
	log.Println(linux.description, "has not been installed due to dummy mode")

	return nil
}

func (linux *LinuxRecord) Remove() error {
	log.Println(linux.description, "has not been removed due to dummy mode")

	return nil
}

func (linux *LinuxRecord) Start() error {
	log.Println(linux.description, "has not been started due to dummy mode")

	return nil
}

func (linux *LinuxRecord) Stop() error {
	log.Println(linux.description, "has not been stoped due to dummy mode")

	return nil
}

func (linux *LinuxRecord) Sratus() error {
	log.Println(linux.description, "has not benn used due to dummy mode")

	return "", nil
}
<commit_msg>fix status<commit_after>package daemon

import (
	"log"
)

type LinuxRecord struct {
	name        string
	description string
}

func newDaemon(name, description string) (*LinuxRecord, error) {

	return &LinuxRecord{name, description}, nil
}

func (linux *LinuxRecord) Install() error {
	log.Println(linux.description, "has not been installed due to dummy mode")

	return nil
}

func (linux *LinuxRecord) Remove() error {
	log.Println(linux.description, "has not been removed due to dummy mode")

	return nil
}

func (linux *LinuxRecord) Start() error {
	log.Println(linux.description, "has not been started due to dummy mode")

	return nil
}

func (linux *LinuxRecord) Stop() error {
	log.Println(linux.description, "has not been stoped due to dummy mode")

	return nil
}

func (linux *LinuxRecord) Sratus() (string, error) {
	log.Println(linux.description, "has not benn used due to dummy mode")

	return "", nil
}
<|endoftext|>


<commit_before>package root

import (
	"context"
	"sort"
	"strings"

	"github.com/fatih/color"
	"github.com/justwatchcom/gopass/config"
	"github.com/justwatchcom/gopass/store"
	"github.com/justwatchcom/gopass/store/sub"
	"github.com/justwatchcom/gopass/utils/fsutil"
	"github.com/justwatchcom/gopass/utils/out"
	"github.com/pkg/errors"
)

// AddMount adds a new mount
func (r *Store) AddMount(ctx context.Context, alias, path string, keys ...string) error {
	path = fsutil.CleanPath(path)
	if _, found := r.mounts[alias]; found {
		return errors.Errorf("%s is already mounted", alias)
	}
	if err := r.addMount(ctx, alias, path, keys...); err != nil {
		return errors.Wrapf(err, "failed to add mount")
	}

	// check for duplicate mounts
	return r.checkMounts()
}

func (r *Store) addMount(ctx context.Context, alias, path string, keys ...string) error {
	if alias == "" {
		return errors.Errorf("alias must not be empty")
	}
	if r.mounts == nil {
		r.mounts = make(map[string]*sub.Store, 1)
	}
	if _, found := r.mounts[alias]; found {
		return errors.Errorf("%s is already mounted", alias)
	}

	// propagate our config settings to the sub store
	s := sub.New(alias, path)

	if !s.Initialized() {
		if len(keys) < 1 {
			return errors.Errorf("password store %s is not initialized. Try gopass init --store %s --path %s", alias, alias, path)
		}
		if err := s.Init(ctx, path, keys...); err != nil {
			return errors.Wrapf(err, "failed to initialize store '%s' at '%s'", alias, path)
		}
		out.Green(ctx, "Password store %s initialized for:", path)
		for _, r := range s.Recipients(ctx) {
			color.Yellow(r)
		}
	}

	r.mounts[alias] = s
	if r.cfg.Mounts == nil {
		r.cfg.Mounts = make(map[string]*config.StoreConfig, 1)
	}
	// imporant: copy root config to avoid overwriting it with sub store
	// values
	sc := *r.cfg.Root
	sc.Path = path
	r.cfg.Mounts[alias] = &sc
	return nil
}

// RemoveMount removes and existing mount
func (r *Store) RemoveMount(ctx context.Context, alias string) error {
	if _, found := r.mounts[alias]; !found {
		return errors.Errorf("%s is not mounted", alias)
	}
	if _, found := r.mounts[alias]; !found {
		out.Yellow(ctx, "%s is not initialized", alias)
	}
	delete(r.mounts, alias)
	return nil
}

// Mounts returns a map of mounts with their paths
func (r *Store) Mounts() map[string]string {
	m := make(map[string]string, len(r.mounts))
	for alias, sub := range r.mounts {
		m[alias] = sub.Path()
	}
	return m
}

// MountPoints returns a sorted list of mount points. It encodes the logic that
// the longer a mount point the more specific it is. This allows to "shadow" a
// shorter mount point by a longer one.
func (r *Store) MountPoints() []string {
	mps := make([]string, 0, len(r.mounts))
	for k := range r.mounts {
		mps = append(mps, k)
	}
	sort.Sort(sort.Reverse(store.ByPathLen(mps)))
	return mps
}

// mountPoint returns the most-specific mount point for the given key
func (r *Store) mountPoint(name string) string {
	for _, mp := range r.MountPoints() {
		if strings.HasPrefix(name+"/", mp+"/") {
			return mp
		}
	}
	return ""
}

// getStore returns the Store object at the most-specific mount point for the
// given key
// context with sub store options set, sub store reference, truncated path to secret
func (r *Store) getStore(ctx context.Context, name string) (context.Context, *sub.Store, string) {
	name = strings.TrimSuffix(name, "/")
	mp := r.mountPoint(name)
	if sub, found := r.mounts[mp]; found {
		return r.cfg.Mounts[mp].WithContext(ctx), sub, strings.TrimPrefix(name, sub.Alias())
	}
	return ctx, r.store, name
}

// GetSubStore returns an exact match for a mount point or an error if this
// mount point does not exist
func (r *Store) GetSubStore(name string) (*sub.Store, error) {
	if name == "" {
		return r.store, nil
	}
	if sub, found := r.mounts[name]; found {
		return sub, nil
	}
	return nil, errors.Errorf("no such mount point '%s'", name)
}

// checkMounts performs some sanity checks on our mounts. At the moment it
// only checks if some path is mounted twice.
func (r *Store) checkMounts() error {
	paths := make(map[string]string, len(r.mounts))
	for k, v := range r.mounts {
		if _, found := paths[v.Path()]; found {
			return errors.Errorf("Doubly mounted path at %s: %s", v.Path(), k)
		}
		paths[v.Path()] = k
	}
	return nil
}
<commit_msg>Update config when removing mounts (#405)<commit_after>package root

import (
	"context"
	"sort"
	"strings"

	"github.com/fatih/color"
	"github.com/justwatchcom/gopass/config"
	"github.com/justwatchcom/gopass/store"
	"github.com/justwatchcom/gopass/store/sub"
	"github.com/justwatchcom/gopass/utils/fsutil"
	"github.com/justwatchcom/gopass/utils/out"
	"github.com/pkg/errors"
)

// AddMount adds a new mount
func (r *Store) AddMount(ctx context.Context, alias, path string, keys ...string) error {
	path = fsutil.CleanPath(path)
	if _, found := r.mounts[alias]; found {
		return errors.Errorf("%s is already mounted", alias)
	}
	if err := r.addMount(ctx, alias, path, keys...); err != nil {
		return errors.Wrapf(err, "failed to add mount")
	}

	// check for duplicate mounts
	return r.checkMounts()
}

func (r *Store) addMount(ctx context.Context, alias, path string, keys ...string) error {
	if alias == "" {
		return errors.Errorf("alias must not be empty")
	}
	if r.mounts == nil {
		r.mounts = make(map[string]*sub.Store, 1)
	}
	if _, found := r.mounts[alias]; found {
		return errors.Errorf("%s is already mounted", alias)
	}

	// propagate our config settings to the sub store
	s := sub.New(alias, path)

	if !s.Initialized() {
		if len(keys) < 1 {
			return errors.Errorf("password store %s is not initialized. Try gopass init --store %s --path %s", alias, alias, path)
		}
		if err := s.Init(ctx, path, keys...); err != nil {
			return errors.Wrapf(err, "failed to initialize store '%s' at '%s'", alias, path)
		}
		out.Green(ctx, "Password store %s initialized for:", path)
		for _, r := range s.Recipients(ctx) {
			color.Yellow(r)
		}
	}

	r.mounts[alias] = s
	if r.cfg.Mounts == nil {
		r.cfg.Mounts = make(map[string]*config.StoreConfig, 1)
	}
	// imporant: copy root config to avoid overwriting it with sub store
	// values
	sc := *r.cfg.Root
	sc.Path = path
	r.cfg.Mounts[alias] = &sc
	return nil
}

// RemoveMount removes and existing mount
func (r *Store) RemoveMount(ctx context.Context, alias string) error {
	if _, found := r.mounts[alias]; !found {
		return errors.Errorf("%s is not mounted", alias)
	}
	if _, found := r.mounts[alias]; !found {
		out.Yellow(ctx, "%s is not initialized", alias)
	}
	delete(r.mounts, alias)
	delete(r.cfg.Mounts, alias)
	return nil
}

// Mounts returns a map of mounts with their paths
func (r *Store) Mounts() map[string]string {
	m := make(map[string]string, len(r.mounts))
	for alias, sub := range r.mounts {
		m[alias] = sub.Path()
	}
	return m
}

// MountPoints returns a sorted list of mount points. It encodes the logic that
// the longer a mount point the more specific it is. This allows to "shadow" a
// shorter mount point by a longer one.
func (r *Store) MountPoints() []string {
	mps := make([]string, 0, len(r.mounts))
	for k := range r.mounts {
		mps = append(mps, k)
	}
	sort.Sort(sort.Reverse(store.ByPathLen(mps)))
	return mps
}

// mountPoint returns the most-specific mount point for the given key
func (r *Store) mountPoint(name string) string {
	for _, mp := range r.MountPoints() {
		if strings.HasPrefix(name+"/", mp+"/") {
			return mp
		}
	}
	return ""
}

// getStore returns the Store object at the most-specific mount point for the
// given key
// context with sub store options set, sub store reference, truncated path to secret
func (r *Store) getStore(ctx context.Context, name string) (context.Context, *sub.Store, string) {
	name = strings.TrimSuffix(name, "/")
	mp := r.mountPoint(name)
	if sub, found := r.mounts[mp]; found {
		return r.cfg.Mounts[mp].WithContext(ctx), sub, strings.TrimPrefix(name, sub.Alias())
	}
	return ctx, r.store, name
}

// GetSubStore returns an exact match for a mount point or an error if this
// mount point does not exist
func (r *Store) GetSubStore(name string) (*sub.Store, error) {
	if name == "" {
		return r.store, nil
	}
	if sub, found := r.mounts[name]; found {
		return sub, nil
	}
	return nil, errors.Errorf("no such mount point '%s'", name)
}

// checkMounts performs some sanity checks on our mounts. At the moment it
// only checks if some path is mounted twice.
func (r *Store) checkMounts() error {
	paths := make(map[string]string, len(r.mounts))
	for k, v := range r.mounts {
		if _, found := paths[v.Path()]; found {
			return errors.Errorf("Doubly mounted path at %s: %s", v.Path(), k)
		}
		paths[v.Path()] = k
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright © 2016 NAME HERE <EMAIL ADDRESS>
//
// 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 cmd

import (
	"archive/zip"
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"golang.org/x/crypto/openpgp"

	"github.com/google/go-github/github"
	"github.com/kardianos/osext"
	"github.com/spf13/cobra"
	"github.com/stratumn/go/generator/repo"
)

var (
	force      bool
	prerelease bool
	generators bool
)

// updateCmd represents the update command
var updateCmd = &cobra.Command{
	Use:   "update",
	Short: "Update Stratumn CLI or generators",
	Long: `Update Stratumn CLI or update generators to latest version.

It can download the latest version of the Stratumn CLI. It checks that the binary is cryptographically signed before installing.

It can also update generators using the --generators flag.
`,
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) > 0 {
			return errors.New("unexpected arguments")
		}

		if generators {
			return updateGenerators()
		}

		return updateCLI()
	},
}

func init() {
	RootCmd.AddCommand(updateCmd)

	updateCmd.PersistentFlags().BoolVarP(
		&force,
		"force",
		"f",
		false,
		"Download latest version even if not more recent",
	)

	updateCmd.PersistentFlags().BoolVarP(
		&prerelease,
		"prerelease",
		"P",
		false,
		"Download prerelease version",
	)

	updateCmd.PersistentFlags().BoolVarP(
		&generators,
		"generators",
		"g",
		false,
		"Update generators",
	)
}

func updateGenerators() error {
	fmt.Println("Updating generators...")

	// Find all installed repos.
	path := generatorsPath
	matches, err := filepath.Glob(filepath.Join(path, "*", "*", repo.StatesDir, "*"))
	if err != nil {
		return err
	}

	for _, match := range matches {
		var (
			parts = strings.Split(match, string(filepath.Separator))
			l     = len(parts)
			owner = parts[l-4]
			rep   = parts[l-3]
			ref   = parts[l-1]
			name  = fmt.Sprintf("%s/%s@%s", owner, rep, ref)
			p     = filepath.Join(path, owner, rep)
		)

		fmt.Printf("  * Updating %q...\n", name)

		r := repo.New(p, owner, rep, ghToken)
		if err != nil {
			return err
		}

		_, updated, err := r.Update(ref, force)
		if err != nil {
			return err
		}

		if updated {
			fmt.Printf("  * %q updated successfully.\n", name)
		} else {
			fmt.Printf("  * %q already up-to-date.\n", name)
		}
	}

	fmt.Println("Generators updated successfully.")

	return nil
}

func updateCLI() error {
	fmt.Println("Updating CLI...")
	client := github.NewClient(nil)

	// Find latest release.
	asset, tag, err := findRelease(client)
	if err != nil {
		return err
	}
	if asset == nil {
		fmt.Println("CLI already up-to-date.")
		return nil
	}

	fmt.Printf("  * Downloading %q@%q...\n", *asset.Name, *tag)

	// Create temporary directory.
	tempDir, err := ioutil.TempDir("", "")
	if err != nil {
		return err
	}
	defer os.RemoveAll(tempDir)

	// Download release.
	tempZipFile := filepath.Join(tempDir, "temp.zip")
	if err = dlRelease(client, tempZipFile, asset); err != nil {
		return err
	}

	fmt.Printf("  * Extracting %q...\n", *asset.Name)

	// Find binary and signature.
	zrc, binZF, sigZF, err := findReleaseFiles(tempZipFile)
	if err != nil {
		return err
	}
	defer zrc.Close()
	if binZF == nil {
		return fmt.Errorf("Could not find binary in %q.\n", *asset.Name)
	}
	if sigZF == nil {
		return fmt.Errorf("Could not find signature in %q.\n", *asset.Name)
	}

	// Get the current binary path.
	execPath, err := osext.Executable()
	if err != nil {
		return err
	}

	// Get the current binary file info.
	info, err := os.Stat(execPath)
	if err != nil {
		return err
	}

	// Copy the new binary to the temporary directory.
	binPath := filepath.Join(tempDir, filepath.Base(execPath))
	if err := copyZF(binPath, binZF, 0644); err != nil {
		return err
	}

	// Copy the signature the the temporary directory.
	sigPath := filepath.Join(tempDir, filepath.Base(execPath)+SigExt)
	if err := copyZF(sigPath, sigZF, 0644); err != nil {
		return err
	}

	// Check the signature.
	fmt.Println("  * Verifying cryptographic signature...")
	if err := checkSig(binPath, sigPath); err != nil {
		return fmt.Errorf("Failed to verify signature: %s.\n", err)
	}

	fmt.Println("  * Updating binary...")

	// Remove previous old binary if present.
	oldPath := filepath.Join(filepath.Dir(execPath), OldBinary)
	if err := os.Remove(oldPath); err != nil && !os.IsNotExist(err) {
		return err
	}

	// Rename current binary.
	if err := os.Rename(execPath, oldPath); err != nil {
		return err
	}

	// Copy new binary to final destination.
	if err := copyF(execPath, binPath, info.Mode()); err != nil {
		fmt.Println(err)
		// Try to recover old binary.
		if err := os.Remove(execPath); err != nil && !os.IsNotExist(err) {
			fmt.Println(err)
		}
		if err := os.Rename(oldPath, execPath); err != nil {
			fmt.Println(err)
		}
		return errors.New("failed to update binary")
	}

	fmt.Println("CLI updated successfully.")

	return nil
}

func findRelease(client *github.Client) (*github.ReleaseAsset, *string, error) {
	rels, res, err := client.Repositories.ListReleases(Owner, Repo, nil)
	if err != nil {
		return nil, nil, err
	}
	defer res.Body.Close()

	var (
		name  = fmt.Sprintf(AssetFormat, runtime.GOOS, runtime.GOARCH)
		asset *github.ReleaseAsset
		tag   *string
	)
	for _, r := range rels {
		if *r.Prerelease == prerelease {
			if force || *r.TagName != "v"+version {
				for _, a := range r.Assets {
					if *a.Name == name {
						asset = &a
						tag = r.TagName
						break
					}
				}
			}
			break
		}
	}

	return asset, tag, nil
}

func dlRelease(client *github.Client, dst string, asset *github.ReleaseAsset) error {
	rc, url, err := client.Repositories.DownloadReleaseAsset(Owner, Repo, *asset.ID)
	if err != nil {
		return err
	}

	var r io.ReadCloser

	if rc != nil {
		r = rc
	} else if url != "" {
		res, err2 := http.Get(url)
		if err2 != nil {
			return err2
		}
		r = res.Body
	}
	defer r.Close()

	f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = io.Copy(f, r)
	return err
}

func findReleaseFiles(src string) (*zip.ReadCloser, *zip.File, *zip.File, error) {
	rc, err := zip.OpenReader(src)
	if err != nil {
		return nil, nil, nil, err
	}

	wantBin := AssetBinary
	if runtime.GOOS == win {
		wantBin = AssetBinaryWin
	}
	wantSig := wantBin + SigExt

	var binZF, sigZF *zip.File
	for _, f := range rc.File {
		switch f.Name {
		case wantBin:
			binZF = f
		case wantSig:
			sigZF = f
		}
	}

	return rc, binZF, sigZF, nil
}

func copy(dst string, r io.Reader, mode os.FileMode) error {
	f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, mode)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, r)
	return err
}

func copyZF(dst string, zf *zip.File, mode os.FileMode) error {
	rc, err := zf.Open()
	if err != nil {
		return err
	}
	defer rc.Close()
	return copy(dst, rc, mode)
}

func copyF(dst, src string, mode os.FileMode) error {
	f, err := os.Open(src)
	if err != nil {
		return err
	}
	defer f.Close()
	return copy(dst, f, mode)
}

func checkSig(targetPath, sigPath string) error {
	target, err := os.Open(targetPath)
	if err != nil {
		return err
	}
	defer target.Close()
	sig, err := os.Open(sigPath)
	if err != nil {
		return err
	}
	defer sig.Close()
	r := bytes.NewReader([]byte(pubKey))
	keyring, err := openpgp.ReadArmoredKeyRing(r)
	if err != nil {
		return err
	}
	_, err = openpgp.CheckArmoredDetachedSignature(keyring, target, sig)
	return err
}
<commit_msg>Update update.go<commit_after>// Copyright 2016 Stratumn
//
// 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 cmd

import (
	"archive/zip"
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"

	"golang.org/x/crypto/openpgp"

	"github.com/google/go-github/github"
	"github.com/kardianos/osext"
	"github.com/spf13/cobra"
	"github.com/stratumn/go/generator/repo"
)

var (
	force      bool
	prerelease bool
	generators bool
)

// updateCmd represents the update command
var updateCmd = &cobra.Command{
	Use:   "update",
	Short: "Update Stratumn CLI or generators",
	Long: `Update Stratumn CLI or update generators to latest version.

It can download the latest version of the Stratumn CLI. It checks that the binary is cryptographically signed before installing.

It can also update generators using the --generators flag.
`,
	RunE: func(cmd *cobra.Command, args []string) error {
		if len(args) > 0 {
			return errors.New("unexpected arguments")
		}

		if generators {
			return updateGenerators()
		}

		return updateCLI()
	},
}

func init() {
	RootCmd.AddCommand(updateCmd)

	updateCmd.PersistentFlags().BoolVarP(
		&force,
		"force",
		"f",
		false,
		"Download latest version even if not more recent",
	)

	updateCmd.PersistentFlags().BoolVarP(
		&prerelease,
		"prerelease",
		"P",
		false,
		"Download prerelease version",
	)

	updateCmd.PersistentFlags().BoolVarP(
		&generators,
		"generators",
		"g",
		false,
		"Update generators",
	)
}

func updateGenerators() error {
	fmt.Println("Updating generators...")

	// Find all installed repos.
	path := generatorsPath
	matches, err := filepath.Glob(filepath.Join(path, "*", "*", repo.StatesDir, "*"))
	if err != nil {
		return err
	}

	for _, match := range matches {
		var (
			parts = strings.Split(match, string(filepath.Separator))
			l     = len(parts)
			owner = parts[l-4]
			rep   = parts[l-3]
			ref   = parts[l-1]
			name  = fmt.Sprintf("%s/%s@%s", owner, rep, ref)
			p     = filepath.Join(path, owner, rep)
		)

		fmt.Printf("  * Updating %q...\n", name)

		r := repo.New(p, owner, rep, ghToken)
		if err != nil {
			return err
		}

		_, updated, err := r.Update(ref, force)
		if err != nil {
			return err
		}

		if updated {
			fmt.Printf("  * %q updated successfully.\n", name)
		} else {
			fmt.Printf("  * %q already up-to-date.\n", name)
		}
	}

	fmt.Println("Generators updated successfully.")

	return nil
}

func updateCLI() error {
	fmt.Println("Updating CLI...")
	client := github.NewClient(nil)

	// Find latest release.
	asset, tag, err := findRelease(client)
	if err != nil {
		return err
	}
	if asset == nil {
		fmt.Println("CLI already up-to-date.")
		return nil
	}

	fmt.Printf("  * Downloading %q@%q...\n", *asset.Name, *tag)

	// Create temporary directory.
	tempDir, err := ioutil.TempDir("", "")
	if err != nil {
		return err
	}
	defer os.RemoveAll(tempDir)

	// Download release.
	tempZipFile := filepath.Join(tempDir, "temp.zip")
	if err = dlRelease(client, tempZipFile, asset); err != nil {
		return err
	}

	fmt.Printf("  * Extracting %q...\n", *asset.Name)

	// Find binary and signature.
	zrc, binZF, sigZF, err := findReleaseFiles(tempZipFile)
	if err != nil {
		return err
	}
	defer zrc.Close()
	if binZF == nil {
		return fmt.Errorf("Could not find binary in %q.\n", *asset.Name)
	}
	if sigZF == nil {
		return fmt.Errorf("Could not find signature in %q.\n", *asset.Name)
	}

	// Get the current binary path.
	execPath, err := osext.Executable()
	if err != nil {
		return err
	}

	// Get the current binary file info.
	info, err := os.Stat(execPath)
	if err != nil {
		return err
	}

	// Copy the new binary to the temporary directory.
	binPath := filepath.Join(tempDir, filepath.Base(execPath))
	if err := copyZF(binPath, binZF, 0644); err != nil {
		return err
	}

	// Copy the signature the the temporary directory.
	sigPath := filepath.Join(tempDir, filepath.Base(execPath)+SigExt)
	if err := copyZF(sigPath, sigZF, 0644); err != nil {
		return err
	}

	// Check the signature.
	fmt.Println("  * Verifying cryptographic signature...")
	if err := checkSig(binPath, sigPath); err != nil {
		return fmt.Errorf("Failed to verify signature: %s.\n", err)
	}

	fmt.Println("  * Updating binary...")

	// Remove previous old binary if present.
	oldPath := filepath.Join(filepath.Dir(execPath), OldBinary)
	if err := os.Remove(oldPath); err != nil && !os.IsNotExist(err) {
		return err
	}

	// Rename current binary.
	if err := os.Rename(execPath, oldPath); err != nil {
		return err
	}

	// Copy new binary to final destination.
	if err := copyF(execPath, binPath, info.Mode()); err != nil {
		fmt.Println(err)
		// Try to recover old binary.
		if err := os.Remove(execPath); err != nil && !os.IsNotExist(err) {
			fmt.Println(err)
		}
		if err := os.Rename(oldPath, execPath); err != nil {
			fmt.Println(err)
		}
		return errors.New("failed to update binary")
	}

	fmt.Println("CLI updated successfully.")

	return nil
}

func findRelease(client *github.Client) (*github.ReleaseAsset, *string, error) {
	rels, res, err := client.Repositories.ListReleases(Owner, Repo, nil)
	if err != nil {
		return nil, nil, err
	}
	defer res.Body.Close()

	var (
		name  = fmt.Sprintf(AssetFormat, runtime.GOOS, runtime.GOARCH)
		asset *github.ReleaseAsset
		tag   *string
	)
	for _, r := range rels {
		if *r.Prerelease == prerelease {
			if force || *r.TagName != "v"+version {
				for _, a := range r.Assets {
					if *a.Name == name {
						asset = &a
						tag = r.TagName
						break
					}
				}
			}
			break
		}
	}

	return asset, tag, nil
}

func dlRelease(client *github.Client, dst string, asset *github.ReleaseAsset) error {
	rc, url, err := client.Repositories.DownloadReleaseAsset(Owner, Repo, *asset.ID)
	if err != nil {
		return err
	}

	var r io.ReadCloser

	if rc != nil {
		r = rc
	} else if url != "" {
		res, err2 := http.Get(url)
		if err2 != nil {
			return err2
		}
		r = res.Body
	}
	defer r.Close()

	f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	_, err = io.Copy(f, r)
	return err
}

func findReleaseFiles(src string) (*zip.ReadCloser, *zip.File, *zip.File, error) {
	rc, err := zip.OpenReader(src)
	if err != nil {
		return nil, nil, nil, err
	}

	wantBin := AssetBinary
	if runtime.GOOS == win {
		wantBin = AssetBinaryWin
	}
	wantSig := wantBin + SigExt

	var binZF, sigZF *zip.File
	for _, f := range rc.File {
		switch f.Name {
		case wantBin:
			binZF = f
		case wantSig:
			sigZF = f
		}
	}

	return rc, binZF, sigZF, nil
}

func copy(dst string, r io.Reader, mode os.FileMode) error {
	f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, mode)
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = io.Copy(f, r)
	return err
}

func copyZF(dst string, zf *zip.File, mode os.FileMode) error {
	rc, err := zf.Open()
	if err != nil {
		return err
	}
	defer rc.Close()
	return copy(dst, rc, mode)
}

func copyF(dst, src string, mode os.FileMode) error {
	f, err := os.Open(src)
	if err != nil {
		return err
	}
	defer f.Close()
	return copy(dst, f, mode)
}

func checkSig(targetPath, sigPath string) error {
	target, err := os.Open(targetPath)
	if err != nil {
		return err
	}
	defer target.Close()
	sig, err := os.Open(sigPath)
	if err != nil {
		return err
	}
	defer sig.Close()
	r := bytes.NewReader([]byte(pubKey))
	keyring, err := openpgp.ReadArmoredKeyRing(r)
	if err != nil {
		return err
	}
	_, err = openpgp.CheckArmoredDetachedSignature(keyring, target, sig)
	return err
}
<|endoftext|>


<commit_before>package stringUtils

import "testing"

func TestIsEmpty(t *testing.T) {
	blank := ""
	actual := IsEmpty(blank)
	if actual == false {
		t.Fail()
	}
}
<commit_msg>add test code<commit_after>package stringUtils

import "testing"

func TestIsEmpty(t *testing.T) {
	blank := ""
	actual := IsEmpty(blank)
	if actual == false {
		t.Errorf("fail test, black should empty")
	}
	nilString := nil
	actual = IsEmpty(nilString)
	if actual == false {
		t.Error("fail test, nil should empty")
	}
}
<|endoftext|>


<commit_before>package tablestorageproxy

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httputil"
	"strings"
	"time"
)

type GoHaveStorage interface {
	GetKey() []byte
	GetAccount() string
}

type TableStorageProxy struct {
	goHaveStorage GoHaveStorage
	baseUrl string
}

func New(goHaveStorage GoHaveStorage) *TableStorageProxy {
	var tableStorageProxy TableStorageProxy

	tableStorageProxy.goHaveStorage = goHaveStorage
	tableStorageProxy.baseUrl = "https://"+goHaveStorage.GetAccount()+".table.core.windows.net/"

	return &tableStorageProxy
}

func (tableStorageProxy *TableStorageProxy) QueryTables() {
	tableStorageProxy.get("Tables")
}

func (tableStorageProxy *TableStorageProxy) QueryEntity(tableName string, partitionKey string, rowKey string, selects string) {
	client := &http.Client{}
	request, _ := http.NewRequest("GET", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29?$select="+selects, nil)
	request.Header.Set("Accept", "application/json;odata=nometadata")

	tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) DeleteEntity(tableName string, partitionKey string, rowKey string) {
	client := &http.Client{}
	request, _ := http.NewRequest("DELETE", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29", nil)
	request.Header.Set("If-Match", "*")

	tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) UpdateEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	client := &http.Client{}
	request, _ := http.NewRequest("PUT", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29",  bytes.NewBuffer(json))
	request.Header.Set("If-Match", "*")
	addPayloadHeaders(request, len(json))

	tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) MergeEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	client := &http.Client{}
		request, _ := http.NewRequest("MERGE", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29",  bytes.NewBuffer(json))
		request.Header.Set("If-Match", "*")
		addPayloadHeaders(request, len(json))

		tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) InsertOrMergeEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	client := &http.Client{}
	request, _ := http.NewRequest("MERGE", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29",  bytes.NewBuffer(json))
	addPayloadHeaders(request, len(json))

	tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) InsertOrReplaceEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	client := &http.Client{}
		request, _ := http.NewRequest("PUT", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29",  bytes.NewBuffer(json))
		addPayloadHeaders(request, len(json))

		tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
	}

func (tableStorageProxy *TableStorageProxy) QueryEntities(tableName string, selects string, filter string, top string) {
	client := &http.Client{}
	request, _ := http.NewRequest("GET", tableStorageProxy.baseUrl+tableName +"?$filter="+filter + "&$select=" + selects+"&$top="+top, nil)
	request.Header.Set("Accept", "application/json;odata=nometadata")

	tableStorageProxy.executeRequest(request, client, tableName)
}

func (tableStorageProxy *TableStorageProxy) DeleteTable(tableName string) {
	target := "Tables%28%27" + tableName + "%27%29"

	client := &http.Client{}
	request, _ := http.NewRequest("DELETE", tableStorageProxy.baseUrl+target, nil)
	request.Header.Set("Content-Type", "application/atom+xml")

	tableStorageProxy.executeRequest(request, client, target)
}

type CreateTableArgs struct {
	TableName string
}

func (tableStorageProxy *TableStorageProxy) CreateTable(tableName string) {
	var createTableArgs CreateTableArgs
	createTableArgs.TableName = tableName

	json, _ := json.Marshal(createTableArgs)
	tableStorageProxy.postJson("Tables", json)
}

func (tableStorageProxy *TableStorageProxy) InsertEntity(tableName string, json []byte) {
	tableStorageProxy.postJson(tableName, json)
}

func (tableStorageProxy *TableStorageProxy) get(target string) {
	client := &http.Client{}
	request, _ := http.NewRequest("GET", tableStorageProxy.baseUrl+target, nil)
	request.Header.Set("Accept", "application/json;odata=nometadata")

	tableStorageProxy.executeRequest(request, client, target)
}

func (tableStorageProxy *TableStorageProxy) postJson(target string, json []byte) {
	client := &http.Client{}
	request, _ := http.NewRequest("POST", tableStorageProxy.baseUrl+target, bytes.NewBuffer(json))
	addPayloadHeaders(request, len(json))

	tableStorageProxy.executeRequest(request, client, target)
}

func addPayloadHeaders(request *http.Request, bodyLength int) {
	request.Header.Set("Content-Type", "application/json")
	request.Header.Set("Content-Length", string(bodyLength))
}

func (tableStorageProxy *TableStorageProxy) executeRequest(request *http.Request, client *http.Client, target string) {
	xmsdate, Authentication := tableStorageProxy.calculateDateAndAuthentication(target)

	request.Header.Set("x-ms-date", xmsdate)
	request.Header.Set("x-ms-version", "2013-08-15")
	request.Header.Set("Authorization", Authentication)

	requestDump, _ := httputil.DumpRequest(request, true)

	fmt.Printf("Request: %s\n", requestDump)

	response, _ := client.Do(request)

	responseDump, _ := httputil.DumpResponse(response, true)
	fmt.Printf("Response: %s\n", responseDump)
}

func (tableStorageProxy *TableStorageProxy) calculateDateAndAuthentication(target string) (string, string) {
	xmsdate := strings.Replace(time.Now().UTC().Add(-time.Minute).Format(time.RFC1123), "UTC", "GMT", -1)
	SignatureString := xmsdate + "\n/" + tableStorageProxy.goHaveStorage.GetAccount() + "/" + target
	Authentication := "SharedKeyLite " + tableStorageProxy.goHaveStorage.GetAccount() + ":" + computeHmac256(SignatureString, tableStorageProxy.goHaveStorage.GetKey())
	return xmsdate, Authentication
}

func computeHmac256(message string, key []byte) string {
	h := hmac.New(sha256.New, key)
	h.Write([]byte(message))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
<commit_msg>Extracting<commit_after>package tablestorageproxy

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httputil"
	"strings"
	"time"
)

type GoHaveStorage interface {
	GetKey() []byte
	GetAccount() string
}

type TableStorageProxy struct {
	goHaveStorage GoHaveStorage
	baseUrl string
}

func New(goHaveStorage GoHaveStorage) *TableStorageProxy {
	var tableStorageProxy TableStorageProxy

	tableStorageProxy.goHaveStorage = goHaveStorage
	tableStorageProxy.baseUrl = "https://"+goHaveStorage.GetAccount()+".table.core.windows.net/"

	return &tableStorageProxy
}

func (tableStorageProxy *TableStorageProxy) QueryTables() {
	tableStorageProxy.get("Tables")
}

func (tableStorageProxy *TableStorageProxy) QueryEntity(tableName string, partitionKey string, rowKey string, selects string) {
	client := &http.Client{}
	request, _ := http.NewRequest("GET", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29?$select="+selects, nil)
	request.Header.Set("Accept", "application/json;odata=nometadata")

	tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) DeleteEntity(tableName string, partitionKey string, rowKey string) {
	client := &http.Client{}
	request, _ := http.NewRequest("DELETE", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29", nil)
	request.Header.Set("If-Match", "*")

	tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) UpdateEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	client := &http.Client{}
	request, _ := http.NewRequest("PUT", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29",  bytes.NewBuffer(json))
	request.Header.Set("If-Match", "*")
	addPayloadHeaders(request, len(json))

	tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) MergeEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	client := &http.Client{}
		request, _ := http.NewRequest("MERGE", tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29",  bytes.NewBuffer(json))
		request.Header.Set("If-Match", "*")
		addPayloadHeaders(request, len(json))

		tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) InsertOrMergeEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("MERGE",tableName, partitionKey, rowKey, json)
}

func (tableStorageProxy *TableStorageProxy) InsertOrReplaceEntity(tableName string, partitionKey string, rowKey string, json []byte) {
	tableStorageProxy.executeEntityRequest("PUT",tableName, partitionKey, rowKey, json)
}

func (tableStorageProxy *TableStorageProxy)  executeEntityRequest(httpVerb string, tableName string, partitionKey string, rowKey string, json []byte) {
	client := &http.Client{}
	request, _ := http.NewRequest(httpVerb, tableStorageProxy.baseUrl+tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29",  bytes.NewBuffer(json))
	addPayloadHeaders(request, len(json))

	tableStorageProxy.executeRequest(request, client, tableName + "%28PartitionKey=%27" + partitionKey + "%27,RowKey=%27" + rowKey + "%27%29")
}

func (tableStorageProxy *TableStorageProxy) QueryEntities(tableName string, selects string, filter string, top string) {
	client := &http.Client{}
	request, _ := http.NewRequest("GET", tableStorageProxy.baseUrl+tableName +"?$filter="+filter + "&$select=" + selects+"&$top="+top, nil)
	request.Header.Set("Accept", "application/json;odata=nometadata")

	tableStorageProxy.executeRequest(request, client, tableName)
}

func (tableStorageProxy *TableStorageProxy) DeleteTable(tableName string) {
	target := "Tables%28%27" + tableName + "%27%29"

	client := &http.Client{}
	request, _ := http.NewRequest("DELETE", tableStorageProxy.baseUrl+target, nil)
	request.Header.Set("Content-Type", "application/atom+xml")

	tableStorageProxy.executeRequest(request, client, target)
}

type CreateTableArgs struct {
	TableName string
}

func (tableStorageProxy *TableStorageProxy) CreateTable(tableName string) {
	var createTableArgs CreateTableArgs
	createTableArgs.TableName = tableName

	json, _ := json.Marshal(createTableArgs)
	tableStorageProxy.postJson("Tables", json)
}

func (tableStorageProxy *TableStorageProxy) InsertEntity(tableName string, json []byte) {
	tableStorageProxy.postJson(tableName, json)
}

func (tableStorageProxy *TableStorageProxy) get(target string) {
	client := &http.Client{}
	request, _ := http.NewRequest("GET", tableStorageProxy.baseUrl+target, nil)
	request.Header.Set("Accept", "application/json;odata=nometadata")

	tableStorageProxy.executeRequest(request, client, target)
}

func (tableStorageProxy *TableStorageProxy) postJson(target string, json []byte) {
	client := &http.Client{}
	request, _ := http.NewRequest("POST", tableStorageProxy.baseUrl+target, bytes.NewBuffer(json))
	addPayloadHeaders(request, len(json))

	tableStorageProxy.executeRequest(request, client, target)
}

func addPayloadHeaders(request *http.Request, bodyLength int) {
	request.Header.Set("Content-Type", "application/json")
	request.Header.Set("Content-Length", string(bodyLength))
}

func (tableStorageProxy *TableStorageProxy) executeRequest(request *http.Request, client *http.Client, target string) {
	xmsdate, Authentication := tableStorageProxy.calculateDateAndAuthentication(target)

	request.Header.Set("x-ms-date", xmsdate)
	request.Header.Set("x-ms-version", "2013-08-15")
	request.Header.Set("Authorization", Authentication)

	requestDump, _ := httputil.DumpRequest(request, true)

	fmt.Printf("Request: %s\n", requestDump)

	response, _ := client.Do(request)

	responseDump, _ := httputil.DumpResponse(response, true)
	fmt.Printf("Response: %s\n", responseDump)
}

func (tableStorageProxy *TableStorageProxy) calculateDateAndAuthentication(target string) (string, string) {
	xmsdate := strings.Replace(time.Now().UTC().Add(-time.Minute).Format(time.RFC1123), "UTC", "GMT", -1)
	SignatureString := xmsdate + "\n/" + tableStorageProxy.goHaveStorage.GetAccount() + "/" + target
	Authentication := "SharedKeyLite " + tableStorageProxy.goHaveStorage.GetAccount() + ":" + computeHmac256(SignatureString, tableStorageProxy.goHaveStorage.GetKey())
	return xmsdate, Authentication
}

func computeHmac256(message string, key []byte) string {
	h := hmac.New(sha256.New, key)
	h.Write([]byte(message))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
<|endoftext|>


<commit_before>package styled

import (
	"strings"
)

// Transform transforms a Text according to a transformer. It does nothing if
// the transformer is not valid.
func Transform(t Text, transformer string) Text {
	f := FindTransformer(transformer)
	if f == nil {
		return t
	}
	t = t.Clone()
	for _, seg := range t {
		f(seg)
	}
	return t
}

// FindTransformer looks up a transformer name and if successful returns a
// function that can be used to transform a styled Segment.
func FindTransformer(transformerName string) func(*Segment) {
	switch {
	// Catch special colors early
	case transformerName == "default":
		return func(s *Segment) { s.Foreground = "" }
	case transformerName == "bg-default":
		return func(s *Segment) { s.Background = "" }
	case strings.HasPrefix(transformerName, "bg-"):
		return buildColorTransformer(strings.TrimPrefix(transformerName, "bg-"), false)
	case strings.HasPrefix(transformerName, "no-"):
		return buildBoolTransformer(strings.TrimPrefix(transformerName, "no-"), false, false)
	case strings.HasPrefix(transformerName, "toggle-"):
		return buildBoolTransformer(strings.TrimPrefix(transformerName, "toggle-"), false, true)

	default:
		if f := buildColorTransformer(transformerName, true); f != nil {
			return f
		}
		return buildBoolTransformer(transformerName, true, false)
	}
}

func buildColorTransformer(transformerName string, setForeground bool) func(*Segment) {
	if isValidColorName(transformerName) {
		if setForeground {
			return func(s *Segment) { s.Foreground = transformerName }
		} else {
			return func(s *Segment) { s.Background = transformerName }
		}
	}

	return nil
}

func buildBoolTransformer(transformerName string, val, toggle bool) func(*Segment) {
	switch transformerName {
	case "bold":
		if toggle {
			return func(s *Segment) { s.Bold = !s.Bold }
		}
		return func(s *Segment) { s.Bold = val }
	case "dim":
		if toggle {
			return func(s *Segment) { s.Dim = !s.Dim }
		}
		return func(s *Segment) { s.Dim = val }
	case "italic":
		if toggle {
			return func(s *Segment) { s.Italic = !s.Italic }
		}
		return func(s *Segment) { s.Italic = val }
	case "underlined":
		if toggle {
			return func(s *Segment) { s.Underlined = !s.Underlined }
		}
		return func(s *Segment) { s.Underlined = val }
	case "blink":
		if toggle {
			return func(s *Segment) { s.Blink = !s.Blink }
		}
		return func(s *Segment) { s.Blink = val }
	case "inverse":
		if toggle {
			return func(s *Segment) { s.Inverse = !s.Inverse }
		}
		return func(s *Segment) { s.Inverse = val }
	}

	return nil
}
<commit_msg>styled: Simplify implementation of FindTransformer.<commit_after>package styled

import (
	"strings"
)

// Transform transforms a Text according to a transformer. It does nothing if
// the transformer is not valid.
func Transform(t Text, transformer string) Text {
	f := FindTransformer(transformer)
	if f == nil {
		return t
	}
	t = t.Clone()
	for _, seg := range t {
		f(seg)
	}
	return t
}

// FindTransformer finds the named transformer, a function that mutates a
// *Segment. If the name is not a valid transformer, it returns nil.
func FindTransformer(name string) func(*Segment) {
	switch {
	// Catch special colors early
	case name == "default":
		return func(s *Segment) { s.Foreground = "" }
	case name == "bg-default":
		return func(s *Segment) { s.Background = "" }
	case strings.HasPrefix(name, "bg-"):
		if color := name[len("bg-"):]; isValidColorName(color) {
			return func(s *Segment) { s.Background = color }
		}
	case strings.HasPrefix(name, "no-"):
		if f := boolFieldAccessor(name[len("no-"):]); f != nil {
			return func(s *Segment) { *f(s) = false }
		}
	case strings.HasPrefix(name, "toggle-"):
		if f := boolFieldAccessor(name[len("toggle-"):]); f != nil {
			return func(s *Segment) {
				p := f(s)
				*p = !*p
			}
		}
	default:
		if isValidColorName(name) {
			return func(s *Segment) { s.Foreground = name }
		}
		if f := boolFieldAccessor(name); f != nil {
			return func(s *Segment) { *f(s) = true }
		}
	}
	return nil
}

func boolFieldAccessor(name string) func(*Segment) *bool {
	switch name {
	case "bold":
		return func(s *Segment) *bool { return &s.Bold }
	case "dim":
		return func(s *Segment) *bool { return &s.Dim }
	case "italic":
		return func(s *Segment) *bool { return &s.Italic }
	case "underlined":
		return func(s *Segment) *bool { return &s.Underlined }
	case "blink":
		return func(s *Segment) *bool { return &s.Blink }
	case "inverse":
		return func(s *Segment) *bool { return &s.Inverse }
	default:
		return nil
	}
}
<|endoftext|>