<commit_before>// Copyright 2016 Insionng
//
// 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.

// Usage
//
// template := "http://{{host}}/?q={{query}}&foo={{bar}}{{bar}}"
// t := femplate.New(template, "{{", "}}")
// s := t.ExecuteString(map[string]interface{}{
//        "host":  "google.com",
//        "query": url.QueryEscape("hello=world"),
//        "bar":   "foobar",
//    })
//    fmt.Printf("%s", s)
//
//    Output:
//    http://google.com/?q=hello%3Dworld&foo=foobarfoobar
//
//
// Advanced usage
//
// template := "Hello, [user]! You won [prize]!!! [foobar]"
// t, err := fasttemplate.NewTemplate(template, "[", "]")
// if err != nil {
// 	log.Fatalf("unexpected error when parsing template: %s", err)
// }
// s := t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) {
// 	switch tag {
// 	case "user":
// 		return w.Write([]byte("John"))
// 	case "prize":
// 		return w.Write([]byte("$100500"))
// 	default:
// 		return w.Write([]byte(fmt.Sprintf("[unknown tag %q]", tag)))
// 	}
// })
// fmt.Printf("%s", s)
//
// Output:
// Hello, John! You won $100500!!! [unknown tag "foobar"]
//

package fempla

import (
	"fmt"
	"io"
	"io/ioutil"
	"path/filepath"
	"sync"

	"github.com/insionng/macross"
	"github.com/insionng/macross/libraries/femplate"
)

type Option struct {
	// Directory to load templates. Default is "templates"
	Directory string
	// Reload to reload templates everytime.
	Reload bool
	// DelimLeft "{{"
	DelimLeft string
	// DelimRight "}}"
	DelimRight string
}

type Renderer struct {
	Option
	templates map[string]*femplate.Template
	lock      sync.RWMutex
}

func perparOption(options []Option) Option {
	var opt Option
	if len(options) > 0 {
		opt = options[0]
	}
	if len(opt.Directory) == 0 {
		opt.Directory = "templates"
	}
	if len(opt.DelimLeft) == 0 {
		opt.DelimLeft = "{{"
	}
	if len(opt.DelimRight) == 0 {
		opt.DelimRight = "}}"
	}
	return opt
}

func Renderor(opt ...Option) *Renderer {
	o := perparOption(opt)
	r := &Renderer{
		Option:    o,
		templates: make(map[string]*femplate.Template),
	}
	return r
}

func (r *Renderer) fromFile(path string) (t *femplate.Template, err error) {
	buf, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	t = femplate.New(string(buf), r.Option.DelimLeft, r.Option.DelimRight)
	return t, nil
}

func (r *Renderer) buildTemplatesCache(name string) (t *femplate.Template, err error) {
	r.lock.Lock()
	defer r.lock.Unlock()
	t, err = r.fromFile(filepath.Join(r.Directory, name))
	if err != nil {
		return
	}
	r.templates[name] = t
	return
}

func (r *Renderer) getTemplate(name string) (t *femplate.Template, err error) {
	name = name + ".html"
	if r.Reload {
		return r.fromFile(filepath.Join(r.Directory, name))
	}
	r.lock.RLock()
	var ok bool
	if t, ok = r.templates[name]; !ok {
		r.lock.RUnlock()
		t, err = r.buildTemplatesCache(name)
	} else {
		r.lock.RUnlock()
	}
	return
}

/*
func getContext(templateData interface{}) map[string]interface{} {
	if templateData == nil {
		return nil
	}
	contextData, isMap := templateData.(map[string]interface{})
	if isMap {
		return contextData
	}
	return nil
}
*/

func (r *Renderer) Render(w io.Writer, name string, ctx *macross.Context) error {
	template, err := r.getTemplate(name)
	if err != nil {
		return err
	}
	s := template.ExecuteString(ctx.GetStore())
	//_, err = io.Copy(w, bytes.NewReader([]byte(s)))
	_, err = fmt.Fprintf(w, "%s", s)
	return err
}
<commit_msg>add Delims for template engine<commit_after>// Copyright 2016 Insionng
//
// 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.

// Usage
//
// template := "http://{{host}}/?q={{query}}&foo={{bar}}{{bar}}"
// t := femplate.New(template, "{{", "}}")
// s := t.ExecuteString(map[string]interface{}{
//        "host":  "google.com",
//        "query": url.QueryEscape("hello=world"),
//        "bar":   "foobar",
//    })
//    fmt.Printf("%s", s)
//
//    Output:
//    http://google.com/?q=hello%3Dworld&foo=foobarfoobar
//
//
// Advanced usage
//
// template := "Hello, [user]! You won [prize]!!! [foobar]"
// t, err := fasttemplate.NewTemplate(template, "[", "]")
// if err != nil {
// 	log.Fatalf("unexpected error when parsing template: %s", err)
// }
// s := t.ExecuteFuncString(func(w io.Writer, tag string) (int, error) {
// 	switch tag {
// 	case "user":
// 		return w.Write([]byte("John"))
// 	case "prize":
// 		return w.Write([]byte("$100500"))
// 	default:
// 		return w.Write([]byte(fmt.Sprintf("[unknown tag %q]", tag)))
// 	}
// })
// fmt.Printf("%s", s)
//
// Output:
// Hello, John! You won $100500!!! [unknown tag "foobar"]
//

package fempla

import (
	"fmt"
	"io"
	"io/ioutil"
	"path/filepath"
	"sync"

	"github.com/insionng/macross"
	"github.com/insionng/macross/libraries/femplate"
)

type (
	Renderer struct {
		Option
		templates map[string]*femplate.Template
		lock      sync.RWMutex
	}

	Option struct {
		// Directory to load templates. Default is "templates"
		Directory string
		// Reload to reload templates everytime.
		Reload bool
		// DelimLeft "{{"
		DelimLeft string
		// DelimRight "}}"
		DelimRight string
	}
)

func perparOption(options []Option) Option {
	var opt Option
	if len(options) > 0 {
		opt = options[0]
	}
	if len(opt.Directory) == 0 {
		opt.Directory = "templates"
	}
	if len(opt.DelimLeft) == 0 {
		opt.DelimLeft = "{{"
	}
	if len(opt.DelimRight) == 0 {
		opt.DelimRight = "}}"
	}
	return opt
}

func Renderor(opt ...Option) *Renderer {
	o := perparOption(opt)
	r := &Renderer{
		Option:    o,
		templates: make(map[string]*femplate.Template),
	}
	return r
}

func (r *Renderer) fromFile(path string) (t *femplate.Template, err error) {
	buf, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	t = femplate.New(string(buf), r.Option.DelimLeft, r.Option.DelimRight)
	return t, nil
}

func (r *Renderer) buildTemplatesCache(name string) (t *femplate.Template, err error) {
	r.lock.Lock()
	defer r.lock.Unlock()
	t, err = r.fromFile(filepath.Join(r.Directory, name))
	if err != nil {
		return
	}
	r.templates[name] = t
	return
}

func (r *Renderer) getTemplate(name string) (t *femplate.Template, err error) {
	name = name + ".html"
	if r.Reload {
		return r.fromFile(filepath.Join(r.Directory, name))
	}
	r.lock.RLock()
	var ok bool
	if t, ok = r.templates[name]; !ok {
		r.lock.RUnlock()
		t, err = r.buildTemplatesCache(name)
	} else {
		r.lock.RUnlock()
	}
	return
}

/*
func getContext(templateData interface{}) map[string]interface{} {
	if templateData == nil {
		return nil
	}
	contextData, isMap := templateData.(map[string]interface{})
	if isMap {
		return contextData
	}
	return nil
}
*/

func (r *Renderer) Render(w io.Writer, name string, ctx *macross.Context) error {
	template, err := r.getTemplate(name)
	if err != nil {
		return err
	}
	s := template.ExecuteString(ctx.GetStore())
	//_, err = io.Copy(w, bytes.NewReader([]byte(s)))
	_, err = fmt.Fprintf(w, "%s", s)
	return err
}
<|endoftext|>


<commit_before>package gocb

import "fmt"

// MapGet retrieves a single item from a map document by its key.
func (b *Bucket) MapGet(key, path string, valuePtr interface{}) (Cas, error) {
	frag, err := b.LookupIn(key).Get(path).Execute()
	if err != nil {
		return 0, err
	}
	err = frag.ContentByIndex(0, valuePtr)
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// MapRemove removes a specified key from the specified map document.
func (b *Bucket) MapRemove(key, path string) (Cas, error) {
	frag, err := b.MutateIn(key, 0, 0).Remove(path).Execute()
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// MapSize returns the current number of items in a map document.
// PERFORMANCE NOTICE: This currently performs a full document fetch...
func (b *Bucket) MapSize(key string) (uint, Cas, error) {
	var mapContents map[string]interface{}
	cas, err := b.Get(key, &mapContents)
	if err != nil {
		return 0, 0, err
	}

	return uint(len(mapContents)), cas, nil
}

// MapAdd inserts an item to a map document.
func (b *Bucket) MapAdd(key, path string, value interface{}, createMap bool) (Cas, error) {
	for {
		frag, err := b.MutateIn(key, 0, 0).Insert(path, value, false).Execute()
		if err != nil {
			if IsKeyNotFoundError(err) && createMap {
				data := make(map[string]interface{})
				data[path] = value
				cas, err := b.Insert(key, data, 0)
				if err != nil {
					if IsKeyExistsError(err) {
						continue
					}

					return 0, err
				}
				return cas, nil
			}
			return 0, err
		}
		return frag.Cas(), nil
	}
}

// ListGet retrieves an item from a list document by index.
func (b *Bucket) ListGet(key string, index uint, valuePtr interface{}) (Cas, error) {
	frag, err := b.LookupIn(key).Get(fmt.Sprintf("[%d]", index)).Execute()
	if err != nil {
		return 0, err
	}
	err = frag.ContentByIndex(0, valuePtr)
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// ListAppend inserts an item to the end of a list document.
func (b *Bucket) ListAppend(key string, value interface{}, createList bool) (Cas, error) {
	for {
		frag, err := b.MutateIn(key, 0, 0).ArrayAppend("", value, false).Execute()
		if err != nil {
			if IsKeyNotFoundError(err) && createList {
				var data []interface{}
				data = append(data, value)
				cas, err := b.Insert(key, data, 0)
				if err != nil {
					if IsKeyExistsError(err) {
						continue
					}

					return 0, err
				}
				return cas, nil
			}
			return 0, err
		}
		return frag.Cas(), nil
	}
}

// ListPrepend inserts an item to the beginning of a list document.
func (b *Bucket) ListPrepend(key string, value interface{}, createList bool) (Cas, error) {
	for {
		frag, err := b.MutateIn(key, 0, 0).ArrayPrepend("", value, false).Execute()
		if err != nil {
			if IsKeyNotFoundError(err) && createList {
				var data []interface{}
				data = append(data, value)
				cas, err := b.Insert(key, data, 0)
				if err != nil {
					if IsKeyExistsError(err) {
						continue
					}

					return 0, err
				}
				return cas, nil
			}
			return 0, err
		}
		return frag.Cas(), nil
	}
}

// ListRemove removes an item from a list document by its index.
func (b *Bucket) ListRemove(key string, index uint) (Cas, error) {
	frag, err := b.MutateIn(key, 0, 0).Remove(fmt.Sprintf("[%d]", index)).Execute()
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// ListSet replaces the item at a particular index of a list document.
func (b *Bucket) ListSet(key string, index uint, value interface{}) (Cas, error) {
	frag, err := b.MutateIn(key, 0, 0).Replace(fmt.Sprintf("[%d]", index), value).Execute()
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// ListSize returns the current number of items in a list.
// PERFORMANCE NOTICE: This currently performs a full document fetch...
func (b *Bucket) ListSize(key string) (uint, Cas, error) {
	var listContents []interface{}
	cas, err := b.Get(key, &listContents)
	if err != nil {
		return 0, 0, err
	}

	return uint(len(listContents)), cas, nil
}

// SetAdd adds a new value to a set document.
func (b *Bucket) SetAdd(key string, value interface{}, createSet bool) (Cas, error) {
	for {
		frag, err := b.MutateIn(key, 0, 0).ArrayAddUnique("", value, false).Execute()
		if err != nil {
			if IsKeyNotFoundError(err) && createSet {
				var data []interface{}
				data = append(data, value)
				cas, err := b.Insert(key, data, 0)
				if err != nil {
					if IsKeyExistsError(err) {
						continue
					}

					return 0, err
				}
				return cas, nil
			}
			return 0, err
		}
		return frag.Cas(), nil
	}
}

// SetExists checks if a particular value exists within the specified set document.
// PERFORMANCE WARNING: This performs a full set fetch and compare.
func (b *Bucket) SetExists(key string, value interface{}) (bool, Cas, error) {
	var setContents []interface{}
	cas, err := b.Get(key, &setContents)
	if err != nil {
		return false, 0, err
	}

	for _, item := range setContents {
		if item == value {
			return true, cas, nil
		}
	}

	return false, 0, nil
}

// SetSize returns the current number of values in a set.
// PERFORMANCE NOTICE: This currently performs a full document fetch...
func (b *Bucket) SetSize(key string) (uint, Cas, error) {
	var setContents []interface{}
	cas, err := b.Get(key, &setContents)
	if err != nil {
		return 0, 0, err
	}

	return uint(len(setContents)), cas, nil
}

// SetRemove removes a single specified value from the specified set document.
// WARNING: This relies on Go's interface{} comparison behaviour!
// PERFORMANCE WARNING: This performs full set fetch, modify, store cycles.
func (b *Bucket) SetRemove(key string, value interface{}) (Cas, error) {
	for {
		var setContents []interface{}
		cas, err := b.Get(key, &setContents)
		if err != nil {
			return 0, err
		}

		foundItem := false
		var newSetContents []interface{}
		for _, item := range setContents {
			if item == value {
				foundItem = true
			} else {
				newSetContents = append(newSetContents, item)
			}
		}

		if !foundItem {
			return 0, ErrRangeError
		}

		cas, err = b.Replace(key, newSetContents, cas, 0)
		if err != nil {
			if IsKeyExistsError(err) {
				// If this is just a CAS error, try again!
				continue
			}

			return 0, err
		}

		return cas, nil
	}
}

// QueuePush adds a new item to the end of a queue.
func (b *Bucket) QueuePush(key string, value interface{}, createQueue bool) (Cas, error) {
	return b.ListPrepend(key, value, createQueue)
}

// QueuePop pops the oldest item from a queue and returns it.
func (b *Bucket) QueuePop(key string, valuePtr interface{}) (Cas, error) {
	for {
		getFrag, err := b.LookupIn(key).Get("[-1]").Execute()
		if err != nil {
			return 0, err
		}

		rmFrag, err := b.MutateIn(key, getFrag.Cas(), 0).Remove("[-1]").Execute()
		if err != nil {
			if IsKeyExistsError(err) {
				// If this is just a CAS error, try again!
				continue
			}

			return 0, err
		}

		err = getFrag.ContentByIndex(0, valuePtr)
		if err != nil {
			return 0, err
		}

		return rmFrag.Cas(), nil
	}
}

// QueueSize returns the current size of a queue.
func (b *Bucket) QueueSize(key string) (uint, Cas, error) {
	var queueContents []interface{}
	cas, err := b.Get(key, &queueContents)
	if err != nil {
		return 0, 0, err
	}

	return uint(len(queueContents)), cas, nil
}
<commit_msg>fix SetRemove when removing last item<commit_after>package gocb

import "fmt"

// MapGet retrieves a single item from a map document by its key.
func (b *Bucket) MapGet(key, path string, valuePtr interface{}) (Cas, error) {
	frag, err := b.LookupIn(key).Get(path).Execute()
	if err != nil {
		return 0, err
	}
	err = frag.ContentByIndex(0, valuePtr)
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// MapRemove removes a specified key from the specified map document.
func (b *Bucket) MapRemove(key, path string) (Cas, error) {
	frag, err := b.MutateIn(key, 0, 0).Remove(path).Execute()
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// MapSize returns the current number of items in a map document.
// PERFORMANCE NOTICE: This currently performs a full document fetch...
func (b *Bucket) MapSize(key string) (uint, Cas, error) {
	var mapContents map[string]interface{}
	cas, err := b.Get(key, &mapContents)
	if err != nil {
		return 0, 0, err
	}

	return uint(len(mapContents)), cas, nil
}

// MapAdd inserts an item to a map document.
func (b *Bucket) MapAdd(key, path string, value interface{}, createMap bool) (Cas, error) {
	for {
		frag, err := b.MutateIn(key, 0, 0).Insert(path, value, false).Execute()
		if err != nil {
			if IsKeyNotFoundError(err) && createMap {
				data := make(map[string]interface{})
				data[path] = value
				cas, err := b.Insert(key, data, 0)
				if err != nil {
					if IsKeyExistsError(err) {
						continue
					}

					return 0, err
				}
				return cas, nil
			}
			return 0, err
		}
		return frag.Cas(), nil
	}
}

// ListGet retrieves an item from a list document by index.
func (b *Bucket) ListGet(key string, index uint, valuePtr interface{}) (Cas, error) {
	frag, err := b.LookupIn(key).Get(fmt.Sprintf("[%d]", index)).Execute()
	if err != nil {
		return 0, err
	}
	err = frag.ContentByIndex(0, valuePtr)
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// ListAppend inserts an item to the end of a list document.
func (b *Bucket) ListAppend(key string, value interface{}, createList bool) (Cas, error) {
	for {
		frag, err := b.MutateIn(key, 0, 0).ArrayAppend("", value, false).Execute()
		if err != nil {
			if IsKeyNotFoundError(err) && createList {
				var data []interface{}
				data = append(data, value)
				cas, err := b.Insert(key, data, 0)
				if err != nil {
					if IsKeyExistsError(err) {
						continue
					}

					return 0, err
				}
				return cas, nil
			}
			return 0, err
		}
		return frag.Cas(), nil
	}
}

// ListPrepend inserts an item to the beginning of a list document.
func (b *Bucket) ListPrepend(key string, value interface{}, createList bool) (Cas, error) {
	for {
		frag, err := b.MutateIn(key, 0, 0).ArrayPrepend("", value, false).Execute()
		if err != nil {
			if IsKeyNotFoundError(err) && createList {
				var data []interface{}
				data = append(data, value)
				cas, err := b.Insert(key, data, 0)
				if err != nil {
					if IsKeyExistsError(err) {
						continue
					}

					return 0, err
				}
				return cas, nil
			}
			return 0, err
		}
		return frag.Cas(), nil
	}
}

// ListRemove removes an item from a list document by its index.
func (b *Bucket) ListRemove(key string, index uint) (Cas, error) {
	frag, err := b.MutateIn(key, 0, 0).Remove(fmt.Sprintf("[%d]", index)).Execute()
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// ListSet replaces the item at a particular index of a list document.
func (b *Bucket) ListSet(key string, index uint, value interface{}) (Cas, error) {
	frag, err := b.MutateIn(key, 0, 0).Replace(fmt.Sprintf("[%d]", index), value).Execute()
	if err != nil {
		return 0, err
	}
	return frag.Cas(), nil
}

// ListSize returns the current number of items in a list.
// PERFORMANCE NOTICE: This currently performs a full document fetch...
func (b *Bucket) ListSize(key string) (uint, Cas, error) {
	var listContents []interface{}
	cas, err := b.Get(key, &listContents)
	if err != nil {
		return 0, 0, err
	}

	return uint(len(listContents)), cas, nil
}

// SetAdd adds a new value to a set document.
func (b *Bucket) SetAdd(key string, value interface{}, createSet bool) (Cas, error) {
	for {
		frag, err := b.MutateIn(key, 0, 0).ArrayAddUnique("", value, false).Execute()
		if err != nil {
			if IsKeyNotFoundError(err) && createSet {
				var data []interface{}
				data = append(data, value)
				cas, err := b.Insert(key, data, 0)
				if err != nil {
					if IsKeyExistsError(err) {
						continue
					}

					return 0, err
				}
				return cas, nil
			}
			return 0, err
		}
		return frag.Cas(), nil
	}
}

// SetExists checks if a particular value exists within the specified set document.
// PERFORMANCE WARNING: This performs a full set fetch and compare.
func (b *Bucket) SetExists(key string, value interface{}) (bool, Cas, error) {
	var setContents []interface{}
	cas, err := b.Get(key, &setContents)
	if err != nil {
		return false, 0, err
	}

	for _, item := range setContents {
		if item == value {
			return true, cas, nil
		}
	}

	return false, 0, nil
}

// SetSize returns the current number of values in a set.
// PERFORMANCE NOTICE: This currently performs a full document fetch...
func (b *Bucket) SetSize(key string) (uint, Cas, error) {
	var setContents []interface{}
	cas, err := b.Get(key, &setContents)
	if err != nil {
		return 0, 0, err
	}

	return uint(len(setContents)), cas, nil
}

// SetRemove removes a single specified value from the specified set document.
// WARNING: This relies on Go's interface{} comparison behaviour!
// PERFORMANCE WARNING: This performs full set fetch, modify, store cycles.
func (b *Bucket) SetRemove(key string, value interface{}) (Cas, error) {
	for {
		var setContents []interface{}
		cas, err := b.Get(key, &setContents)
		if err != nil {
			return 0, err
		}

		foundItem := false
		newSetContents := make([]interface{}, 0)
		for _, item := range setContents {
			if item == value {
				foundItem = true
			} else {
				newSetContents = append(newSetContents, item)
			}
		}

		if !foundItem {
			return 0, ErrRangeError
		}

		cas, err = b.Replace(key, newSetContents, cas, 0)
		if err != nil {
			if IsKeyExistsError(err) {
				// If this is just a CAS error, try again!
				continue
			}

			return 0, err
		}

		return cas, nil
	}
}

// QueuePush adds a new item to the end of a queue.
func (b *Bucket) QueuePush(key string, value interface{}, createQueue bool) (Cas, error) {
	return b.ListPrepend(key, value, createQueue)
}

// QueuePop pops the oldest item from a queue and returns it.
func (b *Bucket) QueuePop(key string, valuePtr interface{}) (Cas, error) {
	for {
		getFrag, err := b.LookupIn(key).Get("[-1]").Execute()
		if err != nil {
			return 0, err
		}

		rmFrag, err := b.MutateIn(key, getFrag.Cas(), 0).Remove("[-1]").Execute()
		if err != nil {
			if IsKeyExistsError(err) {
				// If this is just a CAS error, try again!
				continue
			}

			return 0, err
		}

		err = getFrag.ContentByIndex(0, valuePtr)
		if err != nil {
			return 0, err
		}

		return rmFrag.Cas(), nil
	}
}

// QueueSize returns the current size of a queue.
func (b *Bucket) QueueSize(key string) (uint, Cas, error) {
	var queueContents []interface{}
	cas, err := b.Get(key, &queueContents)
	if err != nil {
		return 0, 0, err
	}

	return uint(len(queueContents)), cas, nil
}
<|endoftext|>


<commit_before>package channeldb

import (
	"encoding/binary"
	"fmt"
	"io"

	"github.com/lightningnetwork/lnd/keychain"
	"github.com/lightningnetwork/lnd/lnwire"
	"github.com/lightningnetwork/lnd/shachain"
	"github.com/roasbeef/btcd/btcec"
	"github.com/roasbeef/btcd/chaincfg/chainhash"
	"github.com/roasbeef/btcd/wire"
	"github.com/roasbeef/btcutil"
)

// outPointSize is the size of a serialized outpoint on disk.
const outPointSize = 36

// writeOutpoint writes an outpoint to the passed writer using the minimal
// amount of bytes possible.
func writeOutpoint(w io.Writer, o *wire.OutPoint) error {
	if _, err := w.Write(o.Hash[:]); err != nil {
		return err
	}
	if err := binary.Write(w, byteOrder, o.Index); err != nil {
		return err
	}

	return nil
}

// readOutpoint reads an outpoint from the passed reader that was previously
// written using the writeOutpoint struct.
func readOutpoint(r io.Reader, o *wire.OutPoint) error {
	if _, err := io.ReadFull(r, o.Hash[:]); err != nil {
		return err
	}
	if err := binary.Read(r, byteOrder, &o.Index); err != nil {
		return err
	}

	return nil
}

// UnknownElementType is an error returned when the codec is unable to encode or
// decode a particular type.
type UnknownElementType struct {
	method  string
	element interface{}
}

// Error returns the name of the method that encountered the error, as well as
// the type that was unsupported.
func (e UnknownElementType) Error() string {
	return fmt.Sprintf("Unknown type in %s: %T", e.method, e.element)
}

// WriteElement is a one-stop shop to write the big endian representation of
// any element which is to be serialized for storage on disk. The passed
// io.Writer should be backed by an appropriately sized byte slice, or be able
// to dynamically expand to accommodate additional data.
func WriteElement(w io.Writer, element interface{}) error {
	switch e := element.(type) {
	case keychain.KeyDescriptor:
		if err := binary.Write(w, byteOrder, e.Family); err != nil {
			return err
		}
		if err := binary.Write(w, byteOrder, e.Index); err != nil {
			return err
		}

		if e.PubKey != nil {
			if err := binary.Write(w, byteOrder, true); err != nil {
			}

			return WriteElement(w, e.PubKey)
		}

		return binary.Write(w, byteOrder, false)
	case ChannelType:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case chainhash.Hash:
		if _, err := w.Write(e[:]); err != nil {
			return err
		}

	case wire.OutPoint:
		return writeOutpoint(w, &e)

	case lnwire.ShortChannelID:
		if err := binary.Write(w, byteOrder, e.ToUint64()); err != nil {
			return err
		}

	case uint64:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case uint32:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case int32:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case uint16:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case bool:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case btcutil.Amount:
		if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
			return err
		}

	case lnwire.MilliSatoshi:
		if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
			return err
		}

	case *btcec.PublicKey:
		b := e.SerializeCompressed()
		if _, err := w.Write(b); err != nil {
			return err
		}

	case shachain.Producer:
		return e.Encode(w)

	case shachain.Store:
		return e.Encode(w)

	case *wire.MsgTx:
		return e.Serialize(w)

	case [32]byte:
		if _, err := w.Write(e[:]); err != nil {
			return err
		}

	case []byte:
		if err := wire.WriteVarBytes(w, 0, e); err != nil {
			return err
		}

	case lnwire.Message:
		if _, err := lnwire.WriteMessage(w, e, 0); err != nil {
			return err
		}

	case ChannelStatus:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case ClosureType:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case lnwire.FundingFlag:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	default:
		return UnknownElementType{"WriteElement", e}
	}

	return nil
}

// WriteElements is writes each element in the elements slice to the passed
// io.Writer using WriteElement.
func WriteElements(w io.Writer, elements ...interface{}) error {
	for _, element := range elements {
		err := WriteElement(w, element)
		if err != nil {
			return err
		}
	}
	return nil
}

// ReadElement is a one-stop utility function to deserialize any datastructure
// encoded using the serialization format of the database.
func ReadElement(r io.Reader, element interface{}) error {
	switch e := element.(type) {
	case *keychain.KeyDescriptor:
		if err := binary.Read(r, byteOrder, &e.Family); err != nil {
			return err
		}
		if err := binary.Read(r, byteOrder, &e.Index); err != nil {
			return err
		}

		var hasPubKey bool
		if err := binary.Read(r, byteOrder, &hasPubKey); err != nil {
			return err
		}

		if hasPubKey {
			return ReadElement(r, &e.PubKey)
		}

	case *ChannelType:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *chainhash.Hash:
		if _, err := io.ReadFull(r, e[:]); err != nil {
			return err
		}

	case *wire.OutPoint:
		return readOutpoint(r, e)

	case *lnwire.ShortChannelID:
		var a uint64
		if err := binary.Read(r, byteOrder, &a); err != nil {
			return err
		}
		*e = lnwire.NewShortChanIDFromInt(a)

	case *uint64:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *uint32:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *int32:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *uint16:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *bool:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *btcutil.Amount:
		var a uint64
		if err := binary.Read(r, byteOrder, &a); err != nil {
			return err
		}

		*e = btcutil.Amount(a)

	case *lnwire.MilliSatoshi:
		var a uint64
		if err := binary.Read(r, byteOrder, &a); err != nil {
			return err
		}

		*e = lnwire.MilliSatoshi(a)

	case **btcec.PublicKey:
		var b [btcec.PubKeyBytesLenCompressed]byte
		if _, err := io.ReadFull(r, b[:]); err != nil {
			return err
		}

		pubKey, err := btcec.ParsePubKey(b[:], btcec.S256())
		if err != nil {
			return err
		}
		*e = pubKey

	case *shachain.Producer:
		var root [32]byte
		if _, err := io.ReadFull(r, root[:]); err != nil {
			return err
		}

		// TODO(roasbeef): remove
		producer, err := shachain.NewRevocationProducerFromBytes(root[:])
		if err != nil {
			return err
		}

		*e = producer

	case *shachain.Store:
		store, err := shachain.NewRevocationStoreFromBytes(r)
		if err != nil {
			return err
		}

		*e = store

	case **wire.MsgTx:
		tx := wire.NewMsgTx(2)
		if err := tx.Deserialize(r); err != nil {
			return err
		}

		*e = tx

	case *[32]byte:
		if _, err := io.ReadFull(r, e[:]); err != nil {
			return err
		}

	case *[]byte:
		bytes, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
		if err != nil {
			return err
		}

		*e = bytes

	case *lnwire.Message:
		msg, err := lnwire.ReadMessage(r, 0)
		if err != nil {
			return err
		}

		*e = msg

	case *ChannelStatus:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *ClosureType:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *lnwire.FundingFlag:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	default:
		return UnknownElementType{"ReadElement", e}
	}

	return nil
}

// ReadElements deserializes a variable number of elements into the passed
// io.Reader, with each element being deserialized according to the ReadElement
// function.
func ReadElements(r io.Reader, elements ...interface{}) error {
	for _, element := range elements {
		err := ReadElement(r, element)
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>channledb/codec: add net.Addr and []net.Addr to codec<commit_after>package channeldb

import (
	"encoding/binary"
	"fmt"
	"io"
	"net"

	"github.com/lightningnetwork/lnd/keychain"
	"github.com/lightningnetwork/lnd/lnwire"
	"github.com/lightningnetwork/lnd/shachain"
	"github.com/roasbeef/btcd/btcec"
	"github.com/roasbeef/btcd/chaincfg/chainhash"
	"github.com/roasbeef/btcd/wire"
	"github.com/roasbeef/btcutil"
)

// outPointSize is the size of a serialized outpoint on disk.
const outPointSize = 36

// writeOutpoint writes an outpoint to the passed writer using the minimal
// amount of bytes possible.
func writeOutpoint(w io.Writer, o *wire.OutPoint) error {
	if _, err := w.Write(o.Hash[:]); err != nil {
		return err
	}
	if err := binary.Write(w, byteOrder, o.Index); err != nil {
		return err
	}

	return nil
}

// readOutpoint reads an outpoint from the passed reader that was previously
// written using the writeOutpoint struct.
func readOutpoint(r io.Reader, o *wire.OutPoint) error {
	if _, err := io.ReadFull(r, o.Hash[:]); err != nil {
		return err
	}
	if err := binary.Read(r, byteOrder, &o.Index); err != nil {
		return err
	}

	return nil
}

// UnknownElementType is an error returned when the codec is unable to encode or
// decode a particular type.
type UnknownElementType struct {
	method  string
	element interface{}
}

// Error returns the name of the method that encountered the error, as well as
// the type that was unsupported.
func (e UnknownElementType) Error() string {
	return fmt.Sprintf("Unknown type in %s: %T", e.method, e.element)
}

// WriteElement is a one-stop shop to write the big endian representation of
// any element which is to be serialized for storage on disk. The passed
// io.Writer should be backed by an appropriately sized byte slice, or be able
// to dynamically expand to accommodate additional data.
func WriteElement(w io.Writer, element interface{}) error {
	switch e := element.(type) {
	case keychain.KeyDescriptor:
		if err := binary.Write(w, byteOrder, e.Family); err != nil {
			return err
		}
		if err := binary.Write(w, byteOrder, e.Index); err != nil {
			return err
		}

		if e.PubKey != nil {
			if err := binary.Write(w, byteOrder, true); err != nil {
			}

			return WriteElement(w, e.PubKey)
		}

		return binary.Write(w, byteOrder, false)
	case ChannelType:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case chainhash.Hash:
		if _, err := w.Write(e[:]); err != nil {
			return err
		}

	case wire.OutPoint:
		return writeOutpoint(w, &e)

	case lnwire.ShortChannelID:
		if err := binary.Write(w, byteOrder, e.ToUint64()); err != nil {
			return err
		}

	case uint64:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case uint32:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case int32:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case uint16:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case bool:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case btcutil.Amount:
		if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
			return err
		}

	case lnwire.MilliSatoshi:
		if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
			return err
		}

	case *btcec.PublicKey:
		b := e.SerializeCompressed()
		if _, err := w.Write(b); err != nil {
			return err
		}

	case shachain.Producer:
		return e.Encode(w)

	case shachain.Store:
		return e.Encode(w)

	case *wire.MsgTx:
		return e.Serialize(w)

	case [32]byte:
		if _, err := w.Write(e[:]); err != nil {
			return err
		}

	case []byte:
		if err := wire.WriteVarBytes(w, 0, e); err != nil {
			return err
		}

	case lnwire.Message:
		if _, err := lnwire.WriteMessage(w, e, 0); err != nil {
			return err
		}

	case ChannelStatus:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case ClosureType:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case lnwire.FundingFlag:
		if err := binary.Write(w, byteOrder, e); err != nil {
			return err
		}

	case net.Addr:
		if err := serializeAddr(w, e); err != nil {
			return err
		}

	case []net.Addr:
		if err := WriteElement(w, uint32(len(e))); err != nil {
			return err
		}

		for _, addr := range e {
			if err := serializeAddr(w, addr); err != nil {
				return err
			}
		}

	default:
		return UnknownElementType{"WriteElement", e}
	}

	return nil
}

// WriteElements is writes each element in the elements slice to the passed
// io.Writer using WriteElement.
func WriteElements(w io.Writer, elements ...interface{}) error {
	for _, element := range elements {
		err := WriteElement(w, element)
		if err != nil {
			return err
		}
	}
	return nil
}

// ReadElement is a one-stop utility function to deserialize any datastructure
// encoded using the serialization format of the database.
func ReadElement(r io.Reader, element interface{}) error {
	switch e := element.(type) {
	case *keychain.KeyDescriptor:
		if err := binary.Read(r, byteOrder, &e.Family); err != nil {
			return err
		}
		if err := binary.Read(r, byteOrder, &e.Index); err != nil {
			return err
		}

		var hasPubKey bool
		if err := binary.Read(r, byteOrder, &hasPubKey); err != nil {
			return err
		}

		if hasPubKey {
			return ReadElement(r, &e.PubKey)
		}

	case *ChannelType:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *chainhash.Hash:
		if _, err := io.ReadFull(r, e[:]); err != nil {
			return err
		}

	case *wire.OutPoint:
		return readOutpoint(r, e)

	case *lnwire.ShortChannelID:
		var a uint64
		if err := binary.Read(r, byteOrder, &a); err != nil {
			return err
		}
		*e = lnwire.NewShortChanIDFromInt(a)

	case *uint64:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *uint32:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *int32:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *uint16:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *bool:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *btcutil.Amount:
		var a uint64
		if err := binary.Read(r, byteOrder, &a); err != nil {
			return err
		}

		*e = btcutil.Amount(a)

	case *lnwire.MilliSatoshi:
		var a uint64
		if err := binary.Read(r, byteOrder, &a); err != nil {
			return err
		}

		*e = lnwire.MilliSatoshi(a)

	case **btcec.PublicKey:
		var b [btcec.PubKeyBytesLenCompressed]byte
		if _, err := io.ReadFull(r, b[:]); err != nil {
			return err
		}

		pubKey, err := btcec.ParsePubKey(b[:], btcec.S256())
		if err != nil {
			return err
		}
		*e = pubKey

	case *shachain.Producer:
		var root [32]byte
		if _, err := io.ReadFull(r, root[:]); err != nil {
			return err
		}

		// TODO(roasbeef): remove
		producer, err := shachain.NewRevocationProducerFromBytes(root[:])
		if err != nil {
			return err
		}

		*e = producer

	case *shachain.Store:
		store, err := shachain.NewRevocationStoreFromBytes(r)
		if err != nil {
			return err
		}

		*e = store

	case **wire.MsgTx:
		tx := wire.NewMsgTx(2)
		if err := tx.Deserialize(r); err != nil {
			return err
		}

		*e = tx

	case *[32]byte:
		if _, err := io.ReadFull(r, e[:]); err != nil {
			return err
		}

	case *[]byte:
		bytes, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
		if err != nil {
			return err
		}

		*e = bytes

	case *lnwire.Message:
		msg, err := lnwire.ReadMessage(r, 0)
		if err != nil {
			return err
		}

		*e = msg

	case *ChannelStatus:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *ClosureType:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *lnwire.FundingFlag:
		if err := binary.Read(r, byteOrder, e); err != nil {
			return err
		}

	case *net.Addr:
		addr, err := deserializeAddr(r)
		if err != nil {
			return err
		}
		*e = addr

	case *[]net.Addr:
		var numAddrs uint32
		if err := ReadElement(r, &numAddrs); err != nil {
			return err
		}

		*e = make([]net.Addr, numAddrs)
		for i := uint32(0); i < numAddrs; i++ {
			addr, err := deserializeAddr(r)
			if err != nil {
				return err
			}
			(*e)[i] = addr
		}

	default:
		return UnknownElementType{"ReadElement", e}
	}

	return nil
}

// ReadElements deserializes a variable number of elements into the passed
// io.Reader, with each element being deserialized according to the ReadElement
// function.
func ReadElements(r io.Reader, elements ...interface{}) error {
	for _, element := range elements {
		err := ReadElement(r, element)
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package middleware

import (
	"fmt"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"

	"github.com/techjanitor/pram-get/config"
	e "github.com/techjanitor/pram-get/errors"
	u "github.com/techjanitor/pram-get/utils"
)

// checks for session cookie and handles permissions
func Auth(perms Permissions) gin.HandlerFunc {
	return func(c *gin.Context) {

		// set default anonymous user
		user := u.User{
			Id:    1,
			Group: 0,
		}

		// parse jwt token if its there
		token, err := jwt.ParseFromRequest(c.Request, func(token *jwt.Token) (interface{}, error) {

			// check alg
			_, ok := token.Method.(*jwt.SigningMethodHMAC)
			if !ok {
				return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
			}

			return []byte(config.Settings.Session.Secret), nil
		})
		// if theres no token set the anon user info
		if err == jwt.ErrNoTokenInRequest {
			err = user.Info()
			if err != nil {
				c.JSON(e.ErrorMessage(e.ErrInternalError))
				c.Error(err)
				return
			}
			// if theres some jwt error then return unauth
		} else if err != nil {
			c.JSON(e.ErrorMessage(e.ErrUnauthorized))
			c.Error(err)
			c.Abort()
			return
		}

		// process token
		if token != nil {
			// if the token is valid set the data
			if err == nil && token.Valid {

				uid, ok := token.Claims["user_id"].(float64)
				if !ok {
					c.JSON(e.ErrorMessage(e.ErrInternalError))
					c.Error(err)
					c.Abort()
					return
				}

				// set user id
				user.Id = uint(uid)

				// get the rest of the user info
				err = user.Info()
				if err == e.ErrNotFound {
					c.JSON(http.StatusBadRequest, gin.H{"error_message": e.ErrInvalidUser.Error()})
					c.Error(err)
					return
				} else if err != nil {
					c.JSON(e.ErrorMessage(e.ErrInternalError))
					c.Error(err)
					return
				}

			}

		}

		// check if user meets set permissions
		if user.Group < perms.Minimum {
			c.JSON(e.ErrorMessage(e.ErrUnauthorized))
			c.Error(e.ErrUnauthorized)
			c.Abort()
			return
		}

		// set user data
		c.Set("userdata", user)

		c.Next()

	}

}

// permissions data
type Permissions struct {
	Minimum uint
}

func SetAuthLevel() Permissions {
	return Permissions{}
}

// All users
func (p Permissions) All() Permissions {
	p.Minimum = 0
	return p
}

// registered users
func (p Permissions) Registered() Permissions {
	p.Minimum = 1
	return p
}

// moderators
func (p Permissions) Moderators() Permissions {
	p.Minimum = 2
	return p
}

// admins
func (p Permissions) Admins() Permissions {
	p.Minimum = 3
	return p
}
<commit_msg>get userdata from auth middleware<commit_after>package middleware

import (
	"fmt"
	jwt "github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"net/http"

	"github.com/techjanitor/pram-get/config"
	e "github.com/techjanitor/pram-get/errors"
	u "github.com/techjanitor/pram-get/utils"
)

// checks for session cookie and handles permissions
func Auth(perms Permissions) gin.HandlerFunc {
	return func(c *gin.Context) {

		// set default anonymous user
		user := u.User{
			Id:    1,
			Group: 0,
		}

		// parse jwt token if its there
		token, err := jwt.ParseFromRequest(c.Request, func(token *jwt.Token) (interface{}, error) {

			// check alg
			_, ok := token.Method.(*jwt.SigningMethodHMAC)
			if !ok {
				return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
			}

			return []byte(config.Settings.Session.Secret), nil
		})
		// if theres no token set the anon user info
		if err == jwt.ErrNoTokenInRequest {
			err = user.Info()
			if err != nil {
				c.JSON(e.ErrorMessage(e.ErrInternalError))
				c.Error(err)
				return
			}
			// if theres some jwt error then return unauth
		} else if err != nil {
			c.JSON(e.ErrorMessage(e.ErrUnauthorized))
			c.Error(err)
			c.Abort()
			return
		}

		// process token
		if token != nil {
			// if the token is valid set the data
			if err == nil && token.Valid {

				uid, ok := token.Claims["user_id"].(float64)
				if !ok {
					c.JSON(e.ErrorMessage(e.ErrInternalError))
					c.Error(err)
					c.Abort()
					return
				}

				// set user id
				user.Id = uint(uid)

				// get the rest of the user info
				err = user.Info()
				if err == e.ErrNotFound {
					c.JSON(http.StatusBadRequest, gin.H{"error_message": e.ErrInvalidUser.Error()})
					c.Error(err)
					return
				} else if err != nil {
					c.JSON(e.ErrorMessage(e.ErrInternalError))
					c.Error(err)
					return
				}

			} else {
				c.JSON(e.ErrorMessage(e.ErrInternalError))
				c.Error(err)
				return
			}

		}

		// check if user meets set permissions
		if user.Group < perms.Minimum {
			c.JSON(e.ErrorMessage(e.ErrUnauthorized))
			c.Error(e.ErrUnauthorized)
			c.Abort()
			return
		}

		// set user data
		c.Set("userdata", user)

		c.Next()

	}

}

// permissions data
type Permissions struct {
	Minimum uint
}

func SetAuthLevel() Permissions {
	return Permissions{}
}

// All users
func (p Permissions) All() Permissions {
	p.Minimum = 0
	return p
}

// registered users
func (p Permissions) Registered() Permissions {
	p.Minimum = 1
	return p
}

// moderators
func (p Permissions) Moderators() Permissions {
	p.Minimum = 2
	return p
}

// admins
func (p Permissions) Admins() Permissions {
	p.Minimum = 3
	return p
}
<|endoftext|>


<commit_before>package middleware

import (
	"bufio"
	"compress/gzip"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"sync"

	"github.com/go-playground/pure"
)

type gzipWriter struct {
	io.Writer
	http.ResponseWriter
	sniffComplete bool
}

func (w *gzipWriter) Write(b []byte) (int, error) {

	if !w.sniffComplete {
		if w.Header().Get(pure.ContentType) == "" {
			w.Header().Set(pure.ContentType, http.DetectContentType(b))
		}
		w.sniffComplete = true
	}

	return w.Writer.Write(b)
}

func (w *gzipWriter) Flush() error {
	return w.Writer.(*gzip.Writer).Flush()
}

func (w *gzipWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	return w.ResponseWriter.(http.Hijacker).Hijack()
}

func (w *gzipWriter) CloseNotify() <-chan bool {
	return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
}

var gzipPool = sync.Pool{
	New: func() interface{} {
		return &gzipWriter{Writer: gzip.NewWriter(ioutil.Discard)}
	},
}

// Gzip returns a middleware which compresses HTTP response using gzip compression
// scheme.
func Gzip(next http.HandlerFunc) http.HandlerFunc {

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

		var gz *gzipWriter
		var gzr *gzip.Writer

		w.Header().Add(pure.Vary, pure.AcceptEncoding)

		if strings.Contains(r.Header.Get(pure.AcceptEncoding), pure.Gzip) {

			gz = gzipPool.Get().(*gzipWriter)
			gz.sniffComplete = false
			gzr = gz.Writer.(*gzip.Writer)
			gzr.Reset(w)
			gz.ResponseWriter = w

			w.Header().Set(pure.ContentEncoding, pure.Gzip)

			w = gz
			defer func() {

				// fmt.Println(gz.sniffComplete)
				if !gz.sniffComplete {
					// We have to reset response to it's pristine state when
					// nothing is written to body.
					w.Header().Del(pure.ContentEncoding)
					gzr.Reset(ioutil.Discard)
				}

				gzr.Close()
				gzipPool.Put(gz)
			}()
		}

		next(w, r)
	}
}

// GzipLevel returns a middleware which compresses HTTP response using gzip compression
// scheme using the level specified
func GzipLevel(level int) pure.Middleware {

	// test gzip level, then don't have to each time one is created
	// in the pool

	if _, err := gzip.NewWriterLevel(ioutil.Discard, level); err != nil {
		panic(err)
	}

	var gzipPool = sync.Pool{
		New: func() interface{} {
			z, _ := gzip.NewWriterLevel(ioutil.Discard, level)

			return &gzipWriter{Writer: z}
		},
	}

	return func(next http.HandlerFunc) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {

			var gz *gzipWriter
			var gzr *gzip.Writer

			w.Header().Add(pure.Vary, pure.AcceptEncoding)

			if strings.Contains(r.Header.Get(pure.AcceptEncoding), pure.Gzip) {

				gz = gzipPool.Get().(*gzipWriter)
				gz.sniffComplete = false
				gzr = gz.Writer.(*gzip.Writer)
				gzr.Reset(w)
				gz.ResponseWriter = w

				w.Header().Set(pure.ContentEncoding, pure.Gzip)

				w = gz
				defer func() {

					// fmt.Println(gz.sniffComplete)
					if !gz.sniffComplete {
						// We have to reset response to it's pristine state when
						// nothing is written to body.
						w.Header().Del(pure.ContentEncoding)
						gzr.Reset(ioutil.Discard)
					}

					gzr.Close()
					gzipPool.Put(gz)
				}()
			}

			next(w, r)
		}
	}
}
<commit_msg>cleanup a couple gzip variables.<commit_after>package middleware

import (
	"bufio"
	"compress/gzip"
	"io"
	"io/ioutil"
	"net"
	"net/http"
	"strings"
	"sync"

	"github.com/go-playground/pure"
)

type gzipWriter struct {
	io.Writer
	http.ResponseWriter
	sniffComplete bool
}

func (w *gzipWriter) Write(b []byte) (int, error) {

	if !w.sniffComplete {
		if w.Header().Get(pure.ContentType) == "" {
			w.Header().Set(pure.ContentType, http.DetectContentType(b))
		}
		w.sniffComplete = true
	}

	return w.Writer.Write(b)
}

func (w *gzipWriter) Flush() error {
	return w.Writer.(*gzip.Writer).Flush()
}

func (w *gzipWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
	return w.ResponseWriter.(http.Hijacker).Hijack()
}

func (w *gzipWriter) CloseNotify() <-chan bool {
	return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
}

var gzipPool = sync.Pool{
	New: func() interface{} {
		return &gzipWriter{Writer: gzip.NewWriter(ioutil.Discard)}
	},
}

// Gzip returns a middleware which compresses HTTP response using gzip compression
// scheme.
func Gzip(next http.HandlerFunc) http.HandlerFunc {

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

		w.Header().Add(pure.Vary, pure.AcceptEncoding)

		if strings.Contains(r.Header.Get(pure.AcceptEncoding), pure.Gzip) {

			gz := gzipPool.Get().(*gzipWriter)
			gz.sniffComplete = false
			gzr := gz.Writer.(*gzip.Writer)
			gzr.Reset(w)
			gz.ResponseWriter = w

			w.Header().Set(pure.ContentEncoding, pure.Gzip)

			w = gz
			defer func() {

				// fmt.Println(gz.sniffComplete)
				if !gz.sniffComplete {
					// We have to reset response to it's pristine state when
					// nothing is written to body.
					w.Header().Del(pure.ContentEncoding)
					gzr.Reset(ioutil.Discard)
				}

				gzr.Close()
				gzipPool.Put(gz)
			}()
		}

		next(w, r)
	}
}

// GzipLevel returns a middleware which compresses HTTP response using gzip compression
// scheme using the level specified
func GzipLevel(level int) pure.Middleware {

	// test gzip level, then don't have to each time one is created
	// in the pool

	if _, err := gzip.NewWriterLevel(ioutil.Discard, level); err != nil {
		panic(err)
	}

	var gzipPool = sync.Pool{
		New: func() interface{} {
			z, _ := gzip.NewWriterLevel(ioutil.Discard, level)

			return &gzipWriter{Writer: z}
		},
	}

	return func(next http.HandlerFunc) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {

			w.Header().Add(pure.Vary, pure.AcceptEncoding)

			if strings.Contains(r.Header.Get(pure.AcceptEncoding), pure.Gzip) {

				gz := gzipPool.Get().(*gzipWriter)
				gz.sniffComplete = false
				gzr := gz.Writer.(*gzip.Writer)
				gzr.Reset(w)
				gz.ResponseWriter = w

				w.Header().Set(pure.ContentEncoding, pure.Gzip)

				w = gz
				defer func() {

					// fmt.Println(gz.sniffComplete)
					if !gz.sniffComplete {
						// We have to reset response to it's pristine state when
						// nothing is written to body.
						w.Header().Del(pure.ContentEncoding)
						gzr.Reset(ioutil.Discard)
					}

					gzr.Close()
					gzipPool.Put(gz)
				}()
			}

			next(w, r)
		}
	}
}
<|endoftext|>


<commit_before>package docker

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/dotcloud/docker/utils"
	"io"
	"io/ioutil"
	"os"
	"path"
	"reflect"
	"strings"
)

type BuildFile interface {
	Build(io.Reader, io.Reader) (string, error)
	CmdFrom(string) error
	CmdRun(string) error
}

type buildFile struct {
	runtime *Runtime
	builder *Builder
	srv     *Server

	image      string
	maintainer string
	config     *Config
	context    string

	tmpContainers map[string]struct{}
	tmpImages     map[string]struct{}

	out io.Writer
}

func (b *buildFile) clearTmp(containers, images map[string]struct{}) {
	for c := range containers {
		tmp := b.runtime.Get(c)
		b.runtime.Destroy(tmp)
		utils.Debugf("Removing container %s", c)
	}
	for i := range images {
		b.runtime.graph.Delete(i)
		utils.Debugf("Removing image %s", i)
	}
}

func (b *buildFile) CmdFrom(name string) error {
	image, err := b.runtime.repositories.LookupImage(name)
	if err != nil {
		if b.runtime.graph.IsNotExist(err) {

			var tag, remote string
			if strings.Contains(name, ":") {
				remoteParts := strings.Split(name, ":")
				tag = remoteParts[1]
				remote = remoteParts[0]
			} else {
				remote = name
			}

			if err := b.srv.ImagePull(remote, tag, "", b.out, false); err != nil {
				return err
			}

			image, err = b.runtime.repositories.LookupImage(name)
			if err != nil {
				return err
			}
		} else {
			return err
		}
	}
	b.image = image.Id
	b.config = &Config{}
	return nil
}

func (b *buildFile) CmdMaintainer(name string) error {
	b.maintainer = name
	return b.commit("", b.config.Cmd, fmt.Sprintf("MAINTAINER %s", name))
}

func (b *buildFile) CmdRun(args string) error {
	if b.image == "" {
		return fmt.Errorf("Please provide a source image with `from` prior to run")
	}
	config, _, err := ParseRun([]string{b.image, "/bin/sh", "-c", args}, nil)
	if err != nil {
		return err
	}

	cmd := b.config.Cmd
	b.config.Cmd = nil
	MergeConfig(b.config, config)

	utils.Debugf("Commang to be executed: %v", b.config.Cmd)

	if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil {
		return err
	} else if cache != nil {
		utils.Debugf("[BUILDER] Use cached version")
		b.image = cache.Id
		return nil
	} else {
		utils.Debugf("[BUILDER] Cache miss")
	}

	cid, err := b.run()
	if err != nil {
		return err
	}
	if err := b.commit(cid, cmd, "run"); err != nil {
		return err
	}
	b.config.Cmd = cmd
	return nil
}

func (b *buildFile) CmdEnv(args string) error {
	tmp := strings.SplitN(args, " ", 2)
	if len(tmp) != 2 {
		return fmt.Errorf("Invalid ENV format")
	}
	key := strings.Trim(tmp[0], " ")
	value := strings.Trim(tmp[1], " ")

	for i, elem := range b.config.Env {
		if strings.HasPrefix(elem, key+"=") {
			b.config.Env[i] = key + "=" + value
			return nil
		}
	}
	b.config.Env = append(b.config.Env, key+"="+value)
	return b.commit("", b.config.Cmd, fmt.Sprintf("ENV %s=%s", key, value))
}

func (b *buildFile) CmdCmd(args string) error {
	var cmd []string
	if err := json.Unmarshal([]byte(args), &cmd); err != nil {
		utils.Debugf("Error unmarshalling: %s, using /bin/sh -c", err)
		cmd = []string{"/bin/sh", "-c", args}
	}
	return b.commit("", cmd, fmt.Sprintf("CMD %v", cmd))
}

func (b *buildFile) CmdExpose(args string) error {
	ports := strings.Split(args, " ")
	b.config.PortSpecs = append(ports, b.config.PortSpecs...)
	return b.commit("", b.config.Cmd, fmt.Sprintf("EXPOSE %v", ports))
}

func (b *buildFile) CmdInsert(args string) error {
	if b.image == "" {
		return fmt.Errorf("Please provide a source image with `from` prior to insert")
	}
	tmp := strings.SplitN(args, " ", 2)
	if len(tmp) != 2 {
		return fmt.Errorf("Invalid INSERT format")
	}
	sourceUrl := strings.Trim(tmp[0], " ")
	destPath := strings.Trim(tmp[1], " ")

	file, err := utils.Download(sourceUrl, b.out)
	if err != nil {
		return err
	}
	defer file.Body.Close()

	cmd := b.config.Cmd
	b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) INSERT %s in %s", sourceUrl, destPath)}
	cid, err := b.run()
	if err != nil {
		return err
	}

	container := b.runtime.Get(cid)
	if container == nil {
		return fmt.Errorf("An error occured while creating the container")
	}

	if err := container.Inject(file.Body, destPath); err != nil {
		return err
	}
	if err := b.commit(cid, cmd, fmt.Sprintf("INSERT %s in %s", sourceUrl, destPath)); err != nil {
		return err
	}
	b.config.Cmd = cmd
	return nil
}

func (b *buildFile) CmdAdd(args string) error {
	if b.context == "" {
		return fmt.Errorf("No context given. Impossible to use ADD")
	}
	tmp := strings.SplitN(args, " ", 2)
	if len(tmp) != 2 {
		return fmt.Errorf("Invalid INSERT format")
	}
	orig := strings.Trim(tmp[0], " ")
	dest := strings.Trim(tmp[1], " ")

	cmd := b.config.Cmd
	b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) ADD %s in %s", orig, dest)}
	cid, err := b.run()
	if err != nil {
		return err
	}

	container := b.runtime.Get(cid)
	if container == nil {
		return fmt.Errorf("Error while creating the container (CmdAdd)")
	}

	if err := os.MkdirAll(path.Join(container.rwPath(), dest), 0700); err != nil {
		return err
	}

	origPath := path.Join(b.context, orig)
	destPath := path.Join(container.rwPath(), dest)

	fi, err := os.Stat(origPath)
	if err != nil {
		return err
	}
	if fi.IsDir() {
		files, err := ioutil.ReadDir(path.Join(b.context, orig))
		if err != nil {
			return err
		}
		for _, fi := range files {
			if err := utils.CopyDirectory(path.Join(origPath, fi.Name()), path.Join(destPath, fi.Name())); err != nil {
				return err
			}
		}
	} else {
		if err := utils.CopyDirectory(origPath, destPath); err != nil {
			return err
		}
	}
	return b.commit(cid, cmd, fmt.Sprintf("ADD %s in %s", orig, dest))
}

func (b *buildFile) run() (string, error) {
	if b.image == "" {
		return "", fmt.Errorf("Please provide a source image with `from` prior to run")
	}
	b.config.Image = b.image

	// Create the container and start it
	c, err := b.builder.Create(b.config)
	if err != nil {
		return "", err
	}
	b.tmpContainers[c.Id] = struct{}{}

	//start the container
	if err := c.Start(); err != nil {
		return "", err
	}

	// Wait for it to finish
	if ret := c.Wait(); ret != 0 {
		return "", fmt.Errorf("The command %v returned a non-zero code: %d", b.config.Cmd, ret)
	}

	return c.Id, nil
}

// Commit the container <id> with the autorun command <autoCmd>
func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
	if b.image == "" {
		return fmt.Errorf("Please provide a source image with `from` prior to commit")
	}
	b.config.Image = b.image
	if id == "" {
		b.config.Cmd = []string{"/bin/sh", "-c", "#(nop) " + comment}

		if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil {
			return err
		} else if cache != nil {
			utils.Debugf("[BUILDER] Use cached version")
			b.image = cache.Id
			return nil
		} else {
			utils.Debugf("[BUILDER] Cache miss")
		}

		if cid, err := b.run(); err != nil {
			return err
		} else {
			id = cid
		}
	}

	container := b.runtime.Get(id)
	if container == nil {
		return fmt.Errorf("An error occured while creating the container")
	}

	// Note: Actually copy the struct
	autoConfig := *b.config
	autoConfig.Cmd = autoCmd
	// Commit the container
	image, err := b.builder.Commit(container, "", "", "", b.maintainer, &autoConfig)
	if err != nil {
		return err
	}
	b.tmpImages[image.Id] = struct{}{}
	b.image = image.Id
	return nil
}

func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) {
	defer b.clearTmp(b.tmpContainers, b.tmpImages)

	if context != nil {
		name, err := ioutil.TempDir("/tmp", "docker-build")
		if err != nil {
			return "", err
		}
		if err := Untar(context, name); err != nil {
			return "", err
		}
		defer os.RemoveAll(name)
		b.context = name
	}
	file := bufio.NewReader(dockerfile)
	for {
		line, err := file.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			return "", err
		}
		line = strings.Replace(strings.TrimSpace(line), "	", " ", 1)
		// Skip comments and empty line
		if len(line) == 0 || line[0] == '#' {
			continue
		}
		tmp := strings.SplitN(line, " ", 2)
		if len(tmp) != 2 {
			return "", fmt.Errorf("Invalid Dockerfile format")
		}
		instruction := strings.ToLower(strings.Trim(tmp[0], " "))
		arguments := strings.Trim(tmp[1], " ")

		fmt.Fprintf(b.out, "%s %s (%s)\n", strings.ToUpper(instruction), arguments, b.image)

		method, exists := reflect.TypeOf(b).MethodByName("Cmd" + strings.ToUpper(instruction[:1]) + strings.ToLower(instruction[1:]))
		if !exists {
			fmt.Fprintf(b.out, "Skipping unknown instruction %s\n", strings.ToUpper(instruction))
			continue
		}
		ret := method.Func.Call([]reflect.Value{reflect.ValueOf(b), reflect.ValueOf(arguments)})[0].Interface()
		if ret != nil {
			return "", ret.(error)
		}

		fmt.Fprintf(b.out, "===> %v\n", b.image)
	}
	if b.image != "" {
		// The build is successful, keep the temporary containers and images
		for i := range b.tmpImages {
			delete(b.tmpImages, i)
		}
		fmt.Fprintf(b.out, "Build success.\n Image id:\n%s\n", b.image)
		return b.image, nil
	}
	for i := range b.tmpContainers {
		delete(b.tmpContainers, i)
	}
	return "", fmt.Errorf("An error occured during the build\n")
}

func NewBuildFile(srv *Server, out io.Writer) BuildFile {
	return &buildFile{
		builder:       NewBuilder(srv.runtime),
		runtime:       srv.runtime,
		srv:           srv,
		config:        &Config{},
		out:           out,
		tmpContainers: make(map[string]struct{}),
		tmpImages:     make(map[string]struct{}),
	}
}
<commit_msg>Fix ADD behavior on single files<commit_after>package docker

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/dotcloud/docker/utils"
	"io"
	"io/ioutil"
	"os"
	"path"
	"reflect"
	"strings"
)

type BuildFile interface {
	Build(io.Reader, io.Reader) (string, error)
	CmdFrom(string) error
	CmdRun(string) error
}

type buildFile struct {
	runtime *Runtime
	builder *Builder
	srv     *Server

	image      string
	maintainer string
	config     *Config
	context    string

	tmpContainers map[string]struct{}
	tmpImages     map[string]struct{}

	out io.Writer
}

func (b *buildFile) clearTmp(containers, images map[string]struct{}) {
	for c := range containers {
		tmp := b.runtime.Get(c)
		b.runtime.Destroy(tmp)
		utils.Debugf("Removing container %s", c)
	}
	for i := range images {
		b.runtime.graph.Delete(i)
		utils.Debugf("Removing image %s", i)
	}
}

func (b *buildFile) CmdFrom(name string) error {
	image, err := b.runtime.repositories.LookupImage(name)
	if err != nil {
		if b.runtime.graph.IsNotExist(err) {

			var tag, remote string
			if strings.Contains(name, ":") {
				remoteParts := strings.Split(name, ":")
				tag = remoteParts[1]
				remote = remoteParts[0]
			} else {
				remote = name
			}

			if err := b.srv.ImagePull(remote, tag, "", b.out, false); err != nil {
				return err
			}

			image, err = b.runtime.repositories.LookupImage(name)
			if err != nil {
				return err
			}
		} else {
			return err
		}
	}
	b.image = image.Id
	b.config = &Config{}
	return nil
}

func (b *buildFile) CmdMaintainer(name string) error {
	b.maintainer = name
	return b.commit("", b.config.Cmd, fmt.Sprintf("MAINTAINER %s", name))
}

func (b *buildFile) CmdRun(args string) error {
	if b.image == "" {
		return fmt.Errorf("Please provide a source image with `from` prior to run")
	}
	config, _, err := ParseRun([]string{b.image, "/bin/sh", "-c", args}, nil)
	if err != nil {
		return err
	}

	cmd := b.config.Cmd
	b.config.Cmd = nil
	MergeConfig(b.config, config)

	utils.Debugf("Commang to be executed: %v", b.config.Cmd)

	if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil {
		return err
	} else if cache != nil {
		utils.Debugf("[BUILDER] Use cached version")
		b.image = cache.Id
		return nil
	} else {
		utils.Debugf("[BUILDER] Cache miss")
	}

	cid, err := b.run()
	if err != nil {
		return err
	}
	if err := b.commit(cid, cmd, "run"); err != nil {
		return err
	}
	b.config.Cmd = cmd
	return nil
}

func (b *buildFile) CmdEnv(args string) error {
	tmp := strings.SplitN(args, " ", 2)
	if len(tmp) != 2 {
		return fmt.Errorf("Invalid ENV format")
	}
	key := strings.Trim(tmp[0], " ")
	value := strings.Trim(tmp[1], " ")

	for i, elem := range b.config.Env {
		if strings.HasPrefix(elem, key+"=") {
			b.config.Env[i] = key + "=" + value
			return nil
		}
	}
	b.config.Env = append(b.config.Env, key+"="+value)
	return b.commit("", b.config.Cmd, fmt.Sprintf("ENV %s=%s", key, value))
}

func (b *buildFile) CmdCmd(args string) error {
	var cmd []string
	if err := json.Unmarshal([]byte(args), &cmd); err != nil {
		utils.Debugf("Error unmarshalling: %s, using /bin/sh -c", err)
		cmd = []string{"/bin/sh", "-c", args}
	}
	return b.commit("", cmd, fmt.Sprintf("CMD %v", cmd))
}

func (b *buildFile) CmdExpose(args string) error {
	ports := strings.Split(args, " ")
	b.config.PortSpecs = append(ports, b.config.PortSpecs...)
	return b.commit("", b.config.Cmd, fmt.Sprintf("EXPOSE %v", ports))
}

func (b *buildFile) CmdInsert(args string) error {
	if b.image == "" {
		return fmt.Errorf("Please provide a source image with `from` prior to insert")
	}
	tmp := strings.SplitN(args, " ", 2)
	if len(tmp) != 2 {
		return fmt.Errorf("Invalid INSERT format")
	}
	sourceUrl := strings.Trim(tmp[0], " ")
	destPath := strings.Trim(tmp[1], " ")

	file, err := utils.Download(sourceUrl, b.out)
	if err != nil {
		return err
	}
	defer file.Body.Close()

	cmd := b.config.Cmd
	b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) INSERT %s in %s", sourceUrl, destPath)}
	cid, err := b.run()
	if err != nil {
		return err
	}

	container := b.runtime.Get(cid)
	if container == nil {
		return fmt.Errorf("An error occured while creating the container")
	}

	if err := container.Inject(file.Body, destPath); err != nil {
		return err
	}
	if err := b.commit(cid, cmd, fmt.Sprintf("INSERT %s in %s", sourceUrl, destPath)); err != nil {
		return err
	}
	b.config.Cmd = cmd
	return nil
}

func (b *buildFile) CmdAdd(args string) error {
	if b.context == "" {
		return fmt.Errorf("No context given. Impossible to use ADD")
	}
	tmp := strings.SplitN(args, " ", 2)
	if len(tmp) != 2 {
		return fmt.Errorf("Invalid INSERT format")
	}
	orig := strings.Trim(tmp[0], " ")
	dest := strings.Trim(tmp[1], " ")

	cmd := b.config.Cmd
	b.config.Cmd = []string{"/bin/sh", "-c", fmt.Sprintf("#(nop) ADD %s in %s", orig, dest)}
	cid, err := b.run()
	if err != nil {
		return err
	}

	container := b.runtime.Get(cid)
	if container == nil {
		return fmt.Errorf("Error while creating the container (CmdAdd)")
	}
	if err := container.EnsureMounted(); err != nil {
		return err
	}
	defer container.Unmount()

	origPath := path.Join(b.context, orig)
	destPath := path.Join(container.RootfsPath(), dest)

	if err := os.MkdirAll(path.Dir(destPath), 0700); err != nil {
		return err
	}

	fi, err := os.Stat(origPath)
	if err != nil {
		return err
	}
	if fi.IsDir() {
		files, err := ioutil.ReadDir(path.Join(b.context, orig))
		if err != nil {
			return err
		}
		for _, fi := range files {
			if err := utils.CopyDirectory(path.Join(origPath, fi.Name()), path.Join(destPath, fi.Name())); err != nil {
				return err
			}
		}
	} else {
		if err := utils.CopyDirectory(origPath, destPath); err != nil {
			return err
		}
	}
	return b.commit(cid, cmd, fmt.Sprintf("ADD %s in %s", orig, dest))
}

func (b *buildFile) run() (string, error) {
	if b.image == "" {
		return "", fmt.Errorf("Please provide a source image with `from` prior to run")
	}
	b.config.Image = b.image

	// Create the container and start it
	c, err := b.builder.Create(b.config)
	if err != nil {
		return "", err
	}
	b.tmpContainers[c.Id] = struct{}{}

	//start the container
	if err := c.Start(); err != nil {
		return "", err
	}

	// Wait for it to finish
	if ret := c.Wait(); ret != 0 {
		return "", fmt.Errorf("The command %v returned a non-zero code: %d", b.config.Cmd, ret)
	}

	return c.Id, nil
}

// Commit the container <id> with the autorun command <autoCmd>
func (b *buildFile) commit(id string, autoCmd []string, comment string) error {
	if b.image == "" {
		return fmt.Errorf("Please provide a source image with `from` prior to commit")
	}
	b.config.Image = b.image
	if id == "" {
		b.config.Cmd = []string{"/bin/sh", "-c", "#(nop) " + comment}

		if cache, err := b.srv.ImageGetCached(b.image, b.config); err != nil {
			return err
		} else if cache != nil {
			utils.Debugf("[BUILDER] Use cached version")
			b.image = cache.Id
			return nil
		} else {
			utils.Debugf("[BUILDER] Cache miss")
		}

		if cid, err := b.run(); err != nil {
			return err
		} else {
			id = cid
		}
	}

	container := b.runtime.Get(id)
	if container == nil {
		return fmt.Errorf("An error occured while creating the container")
	}

	// Note: Actually copy the struct
	autoConfig := *b.config
	autoConfig.Cmd = autoCmd
	// Commit the container
	image, err := b.builder.Commit(container, "", "", "", b.maintainer, &autoConfig)
	if err != nil {
		return err
	}
	b.tmpImages[image.Id] = struct{}{}
	b.image = image.Id
	return nil
}

func (b *buildFile) Build(dockerfile, context io.Reader) (string, error) {
	defer b.clearTmp(b.tmpContainers, b.tmpImages)

	if context != nil {
		name, err := ioutil.TempDir("/tmp", "docker-build")
		if err != nil {
			return "", err
		}
		if err := Untar(context, name); err != nil {
			return "", err
		}
		defer os.RemoveAll(name)
		b.context = name
	}
	file := bufio.NewReader(dockerfile)
	for {
		line, err := file.ReadString('\n')
		if err != nil {
			if err == io.EOF {
				break
			}
			return "", err
		}
		line = strings.Replace(strings.TrimSpace(line), "	", " ", 1)
		// Skip comments and empty line
		if len(line) == 0 || line[0] == '#' {
			continue
		}
		tmp := strings.SplitN(line, " ", 2)
		if len(tmp) != 2 {
			return "", fmt.Errorf("Invalid Dockerfile format")
		}
		instruction := strings.ToLower(strings.Trim(tmp[0], " "))
		arguments := strings.Trim(tmp[1], " ")

		fmt.Fprintf(b.out, "%s %s (%s)\n", strings.ToUpper(instruction), arguments, b.image)

		method, exists := reflect.TypeOf(b).MethodByName("Cmd" + strings.ToUpper(instruction[:1]) + strings.ToLower(instruction[1:]))
		if !exists {
			fmt.Fprintf(b.out, "Skipping unknown instruction %s\n", strings.ToUpper(instruction))
			continue
		}
		ret := method.Func.Call([]reflect.Value{reflect.ValueOf(b), reflect.ValueOf(arguments)})[0].Interface()
		if ret != nil {
			return "", ret.(error)
		}

		fmt.Fprintf(b.out, "===> %v\n", b.image)
	}
	if b.image != "" {
		// The build is successful, keep the temporary containers and images
		for i := range b.tmpImages {
			delete(b.tmpImages, i)
		}
		fmt.Fprintf(b.out, "Build success.\n Image id:\n%s\n", b.image)
		return b.image, nil
	}
	for i := range b.tmpContainers {
		delete(b.tmpContainers, i)
	}
	return "", fmt.Errorf("An error occured during the build\n")
}

func NewBuildFile(srv *Server, out io.Writer) BuildFile {
	return &buildFile{
		builder:       NewBuilder(srv.runtime),
		runtime:       srv.runtime,
		srv:           srv,
		config:        &Config{},
		out:           out,
		tmpContainers: make(map[string]struct{}),
		tmpImages:     make(map[string]struct{}),
	}
}
<|endoftext|>


<commit_before>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2018-12-10 04:34:53.457019 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "667e7c3b14534a4f8a066a62b76301b756222574"
<commit_msg>"Autogenerated build info"<commit_after>package sparta

// THIS FILE IS AUTOMATICALLY GENERATED
// DO NOT EDIT
// CREATED: 2018-12-10 04:36:17.137855 +0000 UTC

// SpartaGitHash is the commit hash of this Sparta library
const SpartaGitHash = "682281e6b663103e027901760acec7790ad33de3"
<|endoftext|>


<commit_before>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sensors

import "time"

type Location struct {
	Latitude   float64
	Longitude  float64
	Altitude   float64
	Accuracy   float64
	RecordedAt time.Time
}

type LocationNotifier struct {
	distance float64
	fn       func(*Location)
}

func NewLocationNotifier(distance float64) (*LocationNotifier, error) {
	panic("not yet")
}

func (l *LocationNotifier) Stop() error {
	panic("not yet")
}

func (l *LocationNotifier) HandleFunc(fn *Location) error {
	l.fn = fn
}

func (l *LocationNotifier) LastKnownLocation() (*Location, error) {
	panic("not yet")
}

type Accelerometer struct {
	fn func(deltaX, deltaY, deltaZ float64)
}

func NewAccelerometer() (*Accelerometer, error) {
	panic("not yet implemented")
}

func (a *Accelerometer) HandleFunc(fn func(deltaX, deltaY, deltaZ float64)) {
	a.fn = fn
}

func (a *Accelerometer) Stop() error {
	panic("not yet implemented")
}

type Gyroscope struct {
	// TODO(jbd): add criteria
	fn func(roll, pitch, yaw float64)
}

func NewGyroscope() (*Gyroscope, error) {
	panic("not yet implemented")
}

func (g *Gyroscope) HandleFunc(fn func(roll, pitch, yaw float64)) {
	g.fn = fn
}

func (g *Gyroscope) Stop() error {
	panic("not yet implemented")
}

type Magnetometer struct {
	fn func(azimut, pitch, roll float64)
}

func NewMagnetometer() (*Magnetometer, error) {
	panic("not yet implemented")
}

func (m *Magnetometer) HandleFunc(fn func(azimut, pitch, roll float64)) {
	m.fn = fn
}

func (m *Magnetometer) Stop() error {
	panic("not yet implemented")
}

// Type of the network that is currently in use.
const (
	TypeWiFi = iota
	TypeMobile
	TypeOther
)

// Connectivity status.
const (
	StatusUnknown = iota
	StatusConnecting
	StatusConnected
	StatusDisconnecting
)

// Connectivity returns the type and the status of the network that is
// currently in use.
func Connectivity() (networkType int, status int) {
	panic("not yet")
}
<commit_msg>fix the broken build.<commit_after>// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package sensors

import "time"

// TODO(jbd): Find a better name for HandleFunc.

type Location struct {
	Latitude  float64
	Longitude float64
	Altitude  float64
	Accuracy  float64
}

type LocationNotifier struct {
	distance float64
	fn       func(loc *Location, at time.Time)
}

func NewLocationNotifier(distance float64) (*LocationNotifier, error) {
	panic("not yet")
}

func (l *LocationNotifier) Stop() error {
	panic("not yet")
}

func (l *LocationNotifier) HandleFunc(fn func(loc *Location, at time.Time)) {
	l.fn = fn
}

func (l *LocationNotifier) LastKnownLocation() (*Location, error) {
	panic("not yet")
}

type Accelerometer struct {
	fn func(deltaX, deltaY, deltaZ float64)
}

func NewAccelerometer() (*Accelerometer, error) {
	panic("not yet implemented")
}

func (a *Accelerometer) HandleFunc(fn func(deltaX, deltaY, deltaZ float64)) {
	a.fn = fn
}

func (a *Accelerometer) Stop() error {
	panic("not yet implemented")
}

type Gyroscope struct {
	// TODO(jbd): add criteria
	fn func(roll, pitch, yaw float64)
}

func NewGyroscope() (*Gyroscope, error) {
	panic("not yet implemented")
}

func (g *Gyroscope) HandleFunc(fn func(roll, pitch, yaw float64)) {
	g.fn = fn
}

func (g *Gyroscope) Stop() error {
	panic("not yet implemented")
}

type Magnetometer struct {
	fn func(azimut, pitch, roll float64)
}

func NewMagnetometer() (*Magnetometer, error) {
	panic("not yet implemented")
}

func (m *Magnetometer) HandleFunc(fn func(azimut, pitch, roll float64)) {
	m.fn = fn
}

func (m *Magnetometer) Stop() error {
	panic("not yet implemented")
}

// Type of the network that is currently in use.
const (
	TypeWiFi = iota
	TypeMobile
	TypeOther
)

// Connectivity status.
const (
	StatusUnknown = iota
	StatusConnecting
	StatusConnected
	StatusDisconnecting
)

// Connectivity returns the type and the status of the network that is
// currently in use.
func Connectivity() (networkType int, status int) {
	panic("not yet")
}
<|endoftext|>


<commit_before>// Package charset provides functions to decode and encode charsets.
package charset

import (
	"fmt"
	"io"
	"strings"

	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/encoding/traditionalchinese"
)

var charsets = map[string]encoding.Encoding{
	"big5":         traditionalchinese.Big5,
	"euc-jp":       japanese.EUCJP,
	"gbk":          simplifiedchinese.GBK,
	"gb2312":       simplifiedchinese.GBK,     // as GBK is a superset of HZGB2312, so just use GBK
	"gb18030":      simplifiedchinese.GB18030, // GB18030 Use for parse QQ business mail message
	"iso-2022-jp":  japanese.ISO2022JP,
	"iso-8859-1":   charmap.ISO8859_1,
	"iso-8859-2":   charmap.ISO8859_2,
	"iso-8859-3":   charmap.ISO8859_3,
	"iso-8859-4":   charmap.ISO8859_4,
	"iso-8859-9":   charmap.ISO8859_9,
	"iso-8859-10":  charmap.ISO8859_10,
	"iso-8859-13":  charmap.ISO8859_13,
	"iso-8859-14":  charmap.ISO8859_14,
	"iso-8859-15":  charmap.ISO8859_15,
	"iso-8859-16":  charmap.ISO8859_16,
	"koi8-r":       charmap.KOI8R,
	"shift_jis":    japanese.ShiftJIS,
	"windows-1250": charmap.Windows1250,
	"windows-1251": charmap.Windows1251,
	"windows-1252": charmap.Windows1252,
}

// Reader returns an io.Reader that converts the provided charset to UTF-8.
func Reader(charset string, input io.Reader) (io.Reader, error) {
	charset = strings.ToLower(charset)
	// "ascii" is not in the spec but is common
	if charset == "utf-8" || charset == "us-ascii" || charset == "ascii" {
		return input, nil
	}
	if enc, ok := charsets[charset]; ok {
		return enc.NewDecoder().Reader(input), nil
	}
	return nil, fmt.Errorf("unhandled charset %q", charset)
}

// RegisterEncoding registers an encoding. This is intended to be called from
// the init function in packages that want to support additional charsets.
func RegisterEncoding(name string, enc encoding.Encoding) {
	charsets[name] = enc
}
<commit_msg>Add non standart ansi_x3.110-1983 encoding<commit_after>// Package charset provides functions to decode and encode charsets.
package charset

import (
	"fmt"
	"io"
	"strings"

	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/charmap"
	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/encoding/traditionalchinese"
)

var charsets = map[string]encoding.Encoding{
	"big5":         traditionalchinese.Big5,
	"euc-jp":       japanese.EUCJP,
	"gbk":          simplifiedchinese.GBK,
	"gb2312":       simplifiedchinese.GBK,     // as GBK is a superset of HZGB2312, so just use GBK
	"gb18030":      simplifiedchinese.GB18030, // GB18030 Use for parse QQ business mail message
	"iso-2022-jp":  japanese.ISO2022JP,
	"iso-8859-1":   charmap.ISO8859_1,
	"iso-8859-2":   charmap.ISO8859_2,
	"iso-8859-3":   charmap.ISO8859_3,
	"iso-8859-4":   charmap.ISO8859_4,
	"iso-8859-9":   charmap.ISO8859_9,
	"iso-8859-10":  charmap.ISO8859_10,
	"iso-8859-13":  charmap.ISO8859_13,
	"iso-8859-14":  charmap.ISO8859_14,
	"iso-8859-15":  charmap.ISO8859_15,
	"iso-8859-16":  charmap.ISO8859_16,
	"koi8-r":       charmap.KOI8R,
	"shift_jis":    japanese.ShiftJIS,
	"windows-1250": charmap.Windows1250,
	"windows-1251": charmap.Windows1251,
	"windows-1252": charmap.Windows1252,
	"ansi_x3.110-1983": charmap.ISO8859_1,
}

// Reader returns an io.Reader that converts the provided charset to UTF-8.
func Reader(charset string, input io.Reader) (io.Reader, error) {
	charset = strings.ToLower(charset)
	// "ascii" is not in the spec but is common
	if charset == "utf-8" || charset == "us-ascii" || charset == "ascii" {
		return input, nil
	}
	if enc, ok := charsets[charset]; ok {
		return enc.NewDecoder().Reader(input), nil
	}
	return nil, fmt.Errorf("unhandled charset %q", charset)
}

// RegisterEncoding registers an encoding. This is intended to be called from
// the init function in packages that want to support additional charsets.
func RegisterEncoding(name string, enc encoding.Encoding) {
	charsets[name] = enc
}
<|endoftext|>


<commit_before>package pooly

import (
	"sync"
	"time"
)

type Computer interface {
	Compute(float64) float64
}

type Selecter interface {
	Select(map[string]*Host) *Host
}

type ServiceConfig struct {
	PoolConfig

	PrespawnConns        uint
	CloseDeadline        time.Duration
	DecayDuration        time.Duration
	MemoizeScoreDuration time.Duration
	ScoreCalculator      Computer
	BanditStrategy       Selecter
}

type Service struct {
	*ServiceConfig

	sync.RWMutex
	name    string
	hosts   map[string]*Host
	decay   *time.Ticker
	memoize *time.Ticker
	add, rm chan string
	stop    chan struct{}
}

func NewService(name string, c *ServiceConfig) *Service {
	if c == nil {
		c = new(ServiceConfig)
	}
	if c.PrespawnConns == 0 {
		c.PrespawnConns = DefaultPrespawnConns
	}
	if c.CloseDeadline == 0 {
		c.CloseDeadline = DefaultCloseDeadline
	}
	if c.DecayDuration == 0 {
		c.DecayDuration = DefaultDecayDuration
	}
	if c.MemoizeScoreDuration == 0 {
		c.MemoizeScoreDuration = DefaultMemoizeScoreDuration
	}
	if c.BanditStrategy == nil {
		c.BanditStrategy = NewRoundRobin()
	}

	s := &Service{
		ServiceConfig: c,
		name:          name,
		hosts:         make(map[string]*Host),
		add:           make(chan string),
		rm:            make(chan string),
		stop:          make(chan struct{}),
	}
	if _, ok := s.BanditStrategy.(*RoundRobin); !ok {
		s.decay = time.NewTicker(c.DecayDuration / seriesNum)
		s.memoize = time.NewTicker(c.MemoizeScoreDuration)
	}

	go s.serve()
	return s
}

func (s *Service) serve() {
	var decay, memoize <-chan time.Time

	if s.decay != nil {
		decay = s.decay.C
	}
	if s.memoize != nil {
		memoize = s.memoize.C
	}
	for {
		select {
		case a := <-s.add:
			s.newHost(a)
		case a := <-s.rm:
			s.deleteHost(a)
		case <-decay:
			for _, h := range s.hosts {
				h.decay()
			}
		case <-memoize:
			// XXX lock to prevent selecting hosts during scores computation
			//s.Lock()
			for _, h := range s.hosts {
				h.computeScore(s.ScoreCalculator)
			}
			//c.Unlock()
		case <-s.stop:
			for a := range s.hosts {
				s.deleteHost(a)
			}
			if s.decay != nil {
				s.decay.Stop()
			}
			if s.memoize != nil {
				s.memoize.Stop()
			}
			return
		}
	}
}

func (s *Service) newHost(a string) {
	s.Lock()
	if h := s.hosts[a]; h != nil {
		s.Unlock()
		return
	}

	p := NewPool(a, &s.PoolConfig)
	p.New(s.PrespawnConns)
	s.hosts[a] = &Host{
		pool:       p,
		timeSeries: make([]serie, 1, seriesNum),
		score:      -1,
	}
	s.Unlock()
}

func (s *Service) deleteHost(a string) {
	s.Lock()
	h := s.hosts[a]
	delete(s.hosts, a)
	s.Unlock()

	if h == nil {
		return
	}
	go func() {
		time.AfterFunc(s.CloseDeadline, func() {
			h.pool.ForceClose()
		})
		h.pool.Close()
	}()
}

func (s *Service) Name() string {
	return s.name
}

func (s *Service) Add(address string) {
	s.add <- address
}

func (s *Service) Remove(address string) {
	s.rm <- address
}

func (s *Service) GetConn() (*Conn, error) {
	s.RLock()
	if len(s.hosts) == 0 {
		return nil, ErrNoHostAvailable
	}
	h := s.BanditStrategy.Select(s.hosts)
	s.RUnlock()

	c, err := h.pool.Get()
	if err != nil {
		// Pool is closed or timed out, demote the host and start over
		h.rate(HostDown)
		return s.GetConn()
	}

	c.setHost(h)
	return c, nil
}

func (s *Service) Status() map[string]int32 {
	s.RLock()
	m := make(map[string]int32, len(s.hosts))
	for a, h := range s.hosts {
		m[a] = h.pool.ActiveConns()
	}
	s.RUnlock()
	return m
}

func (s *Service) Close() {
	close(s.stop)
}
<commit_msg>Oops :/<commit_after>package pooly

import (
	"sync"
	"time"
)

type Computer interface {
	Compute(float64) float64
}

type Selecter interface {
	Select(map[string]*Host) *Host
}

type ServiceConfig struct {
	PoolConfig

	PrespawnConns        uint
	CloseDeadline        time.Duration
	DecayDuration        time.Duration
	MemoizeScoreDuration time.Duration
	ScoreCalculator      Computer
	BanditStrategy       Selecter
}

type Service struct {
	*ServiceConfig

	sync.RWMutex
	name    string
	hosts   map[string]*Host
	decay   *time.Ticker
	memoize *time.Ticker
	add, rm chan string
	stop    chan struct{}
}

func NewService(name string, c *ServiceConfig) *Service {
	if c == nil {
		c = new(ServiceConfig)
	}
	if c.PrespawnConns == 0 {
		c.PrespawnConns = DefaultPrespawnConns
	}
	if c.CloseDeadline == 0 {
		c.CloseDeadline = DefaultCloseDeadline
	}
	if c.DecayDuration == 0 {
		c.DecayDuration = DefaultDecayDuration
	}
	if c.MemoizeScoreDuration == 0 {
		c.MemoizeScoreDuration = DefaultMemoizeScoreDuration
	}
	if c.BanditStrategy == nil {
		c.BanditStrategy = NewRoundRobin()
	}

	s := &Service{
		ServiceConfig: c,
		name:          name,
		hosts:         make(map[string]*Host),
		add:           make(chan string),
		rm:            make(chan string),
		stop:          make(chan struct{}),
	}
	if _, ok := s.BanditStrategy.(*RoundRobin); !ok {
		s.decay = time.NewTicker(c.DecayDuration / seriesNum)
		s.memoize = time.NewTicker(c.MemoizeScoreDuration)
	}

	go s.serve()
	return s
}

func (s *Service) serve() {
	var decay, memoize <-chan time.Time

	if s.decay != nil {
		decay = s.decay.C
	}
	if s.memoize != nil {
		memoize = s.memoize.C
	}
	for {
		select {
		case a := <-s.add:
			s.newHost(a)
		case a := <-s.rm:
			s.deleteHost(a)
		case <-decay:
			for _, h := range s.hosts {
				h.decay()
			}
		case <-memoize:
			// XXX lock to prevent selecting hosts during scores computation
			//s.Lock()
			for _, h := range s.hosts {
				h.computeScore(s.ScoreCalculator)
			}
			//c.Unlock()
		case <-s.stop:
			for a := range s.hosts {
				s.deleteHost(a)
			}
			if s.decay != nil {
				s.decay.Stop()
			}
			if s.memoize != nil {
				s.memoize.Stop()
			}
			return
		}
	}
}

func (s *Service) newHost(a string) {
	s.Lock()
	if h := s.hosts[a]; h != nil {
		s.Unlock()
		return
	}

	p := NewPool(a, &s.PoolConfig)
	p.New(s.PrespawnConns)
	s.hosts[a] = &Host{
		pool:       p,
		timeSeries: make([]serie, 1, seriesNum),
		score:      -1,
	}
	s.Unlock()
}

func (s *Service) deleteHost(a string) {
	s.Lock()
	h := s.hosts[a]
	delete(s.hosts, a)
	s.Unlock()

	if h == nil {
		return
	}
	go func() {
		time.AfterFunc(s.CloseDeadline, func() {
			h.pool.ForceClose()
		})
		h.pool.Close()
	}()
}

func (s *Service) Name() string {
	return s.name
}

func (s *Service) Add(address string) {
	s.add <- address
}

func (s *Service) Remove(address string) {
	s.rm <- address
}

func (s *Service) GetConn() (*Conn, error) {
	s.RLock()
	if len(s.hosts) == 0 {
		s.RUnlock()
		return nil, ErrNoHostAvailable
	}
	h := s.BanditStrategy.Select(s.hosts)
	s.RUnlock()

	c, err := h.pool.Get()
	if err != nil {
		// Pool is closed or timed out, demote the host and start over
		h.rate(HostDown)
		return s.GetConn()
	}

	c.setHost(h)
	return c, nil
}

func (s *Service) Status() map[string]int32 {
	s.RLock()
	m := make(map[string]int32, len(s.hosts))
	for a, h := range s.hosts {
		m[a] = h.pool.ActiveConns()
	}
	s.RUnlock()
	return m
}

func (s *Service) Close() {
	close(s.stop)
}
<|endoftext|>