<commit_before>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"fmt"
	"html/template"
	"net/http"
	_ "net/http/pprof"
	"sort"
	"strconv"
	"time"
	"unsafe"

	"github.com/google/syzkaller/cover"
	"github.com/google/syzkaller/prog"
	"github.com/google/syzkaller/sys"
)

func (mgr *Manager) initHttp() {
	http.HandleFunc("/", mgr.httpInfo)
	http.HandleFunc("/corpus", mgr.httpCorpus)
	http.HandleFunc("/cover", mgr.httpCover)
	http.HandleFunc("/prio", mgr.httpPrio)
	logf(0, "serving http on http://%v", mgr.cfg.Http)
	go http.ListenAndServe(mgr.cfg.Http, nil)
}

func (mgr *Manager) httpInfo(w http.ResponseWriter, r *http.Request) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	uptime := time.Since(mgr.startTime)
	data := &UIData{
		CorpusSize:  len(mgr.corpus),
		TriageQueue: len(mgr.candidates),
		Uptime:      fmt.Sprintf("%v", uptime),
	}

	type CallCov struct {
		count int
		cov   cover.Cover
	}
	calls := make(map[string]*CallCov)
	for _, inp := range mgr.corpus {
		if calls[inp.Call] == nil {
			calls[inp.Call] = new(CallCov)
		}
		cc := calls[inp.Call]
		cc.count++
		cc.cov = cover.Union(cc.cov, cover.Cover(inp.Cover))
		data.CorpusCoverMem += len(inp.Cover) * int(unsafe.Sizeof(inp.Cover[0]))
	}
	for _, cov := range mgr.corpusCover {
		data.CallCoverMem += len(cov) * int(unsafe.Sizeof(cov[0]))
	}

	secs := uint64(uptime) / 1e9
	for k, v := range mgr.stats {
		val := ""
		if x := v / secs; x >= 10 {
			val = fmt.Sprintf("%v/sec", x)
		} else if x := v * 60 / secs; x >= 10 {
			val = fmt.Sprintf("%v/min", x)
		} else {
			x := v * 60 * 60 / secs
			val = fmt.Sprintf("%v/hour", x)
		}
		data.Stats = append(data.Stats, UIStat{Name: k, Value: val})
	}
	sort.Sort(UIStatArray(data.Stats))

	var cov cover.Cover
	for c, cc := range calls {
		cov = cover.Union(cov, cc.cov)
		data.Calls = append(data.Calls, UICallType{c, cc.count, len(cc.cov)})
	}
	sort.Sort(UICallTypeArray(data.Calls))
	data.CoverSize = len(cov)

	if err := htmlTemplate.Execute(w, data); err != nil {
		http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError)
	}
}

func (mgr *Manager) httpCorpus(w http.ResponseWriter, r *http.Request) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	var data []UIInput
	call := r.FormValue("call")
	for i, inp := range mgr.corpus {
		if call != inp.Call {
			continue
		}
		p, err := prog.Deserialize(inp.Prog)
		if err != nil {
			http.Error(w, fmt.Sprintf("failed to deserialize program: %v", err), http.StatusInternalServerError)
		}
		data = append(data, UIInput{
			Short: p.String(),
			Full:  string(inp.Prog),
			Cover: len(inp.Cover),
			N:     i,
		})
	}
	sort.Sort(UIInputArray(data))

	if err := corpusTemplate.Execute(w, data); err != nil {
		http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError)
	}
}

func (mgr *Manager) httpCover(w http.ResponseWriter, r *http.Request) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	var cov cover.Cover
	call := r.FormValue("call")
	if n, err := strconv.Atoi(call); err == nil && n < len(mgr.corpus) {
		cov = mgr.corpus[n].Cover
	} else {
		for _, inp := range mgr.corpus {
			if call == "" || call == inp.Call {
				cov = cover.Union(cov, cover.Cover(inp.Cover))
			}
		}
	}

	if err := generateCoverHtml(w, mgr.cfg.Vmlinux, cov); err != nil {
		http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError)
	}
}

func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	mgr.minimizeCorpus()
	call := r.FormValue("call")
	idx := -1
	for i, c := range sys.Calls {
		if c.CallName == call {
			idx = i
			break
		}
	}
	if idx == -1 {
		http.Error(w, fmt.Sprintf("unknown call: %v", call), http.StatusInternalServerError)
		return
	}

	data := &UIPrioData{Call: call}
	for i, p := range mgr.prios[idx] {
		data.Prios = append(data.Prios, UIPrio{sys.Calls[i].Name, p})
	}
	sort.Sort(UIPrioArray(data.Prios))

	if err := prioTemplate.Execute(w, data); err != nil {
		http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError)
	}
}

type UIData struct {
	CorpusSize     int
	TriageQueue    int
	CoverSize      int
	CorpusCoverMem int
	CallCoverMem   int
	Uptime         string
	Stats          []UIStat
	Calls          []UICallType
}

type UIStat struct {
	Name  string
	Value string
}

type UICallType struct {
	Name   string
	Inputs int
	Cover  int
}

type UIInput struct {
	Short string
	Full  string
	Calls int
	Cover int
	N     int
}

type UICallTypeArray []UICallType

func (a UICallTypeArray) Len() int           { return len(a) }
func (a UICallTypeArray) Less(i, j int) bool { return a[i].Name  a[j].Cover }
func (a UIInputArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

type UIStatArray []UIStat

func (a UIStatArray) Len() int           { return len(a) }
func (a UIStatArray) Less(i, j int) bool { return a[i].Name < a[j].Name }
func (a UIStatArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

var htmlTemplate = template.Must(template.New("").Parse(`
<!doctype html>

    <title>syzkaller</title>

Uptime: {{.Uptime}}

Corpus: {{.CorpusSize}}

Triage queue len: {{.TriageQueue}}

Cover mem: {{.CorpusCoverMem}} + {{.CallCoverMem}}

Cover: {{.CoverSize}}

Stats:

{{range $stat := $.Stats}}
	{{$stat.Name}}: {{$stat.Value}}

{{end}}

{{range $c := $.Calls}}
	{{$c.Name}} inputs:{{$c.Inputs}} cover:{{$c.Cover}} prio

{{end}}

`))

var corpusTemplate = template.Must(template.New("").Parse(`
<!doctype html>

    <title>syzkaller corpus</title>

{{range $c := $}}
	{{$c.Short}} cover:{{$c.Cover}}

{{end}}

`))

type UIPrioData struct {
	Call  string
	Prios []UIPrio
}

type UIPrio struct {
	Call string
	Prio float32
}

type UIPrioArray []UIPrio

func (a UIPrioArray) Len() int           { return len(a) }
func (a UIPrioArray) Less(i, j int) bool { return a[i].Prio > a[j].Prio }
func (a UIPrioArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

var prioTemplate = template.Must(template.New("").Parse(`
<!doctype html>

    <title>syzkaller priorities</title>

Priorities for {{$.Call}}

{{range $p := $.Prios}}
	{{printf "%.4f\t%s" $p.Prio $p.Call}}

{{end}}

`))
<commit_msg>manager: do GC after cover profile generation<commit_after>// Copyright 2015 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.

package main

import (
	"fmt"
	"html/template"
	"net/http"
	_ "net/http/pprof"
	"runtime"
	"sort"
	"strconv"
	"time"
	"unsafe"

	"github.com/google/syzkaller/cover"
	"github.com/google/syzkaller/prog"
	"github.com/google/syzkaller/sys"
)

func (mgr *Manager) initHttp() {
	http.HandleFunc("/", mgr.httpInfo)
	http.HandleFunc("/corpus", mgr.httpCorpus)
	http.HandleFunc("/cover", mgr.httpCover)
	http.HandleFunc("/prio", mgr.httpPrio)
	logf(0, "serving http on http://%v", mgr.cfg.Http)
	go http.ListenAndServe(mgr.cfg.Http, nil)
}

func (mgr *Manager) httpInfo(w http.ResponseWriter, r *http.Request) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	uptime := time.Since(mgr.startTime)
	data := &UIData{
		CorpusSize:  len(mgr.corpus),
		TriageQueue: len(mgr.candidates),
		Uptime:      fmt.Sprintf("%v", uptime),
	}

	type CallCov struct {
		count int
		cov   cover.Cover
	}
	calls := make(map[string]*CallCov)
	for _, inp := range mgr.corpus {
		if calls[inp.Call] == nil {
			calls[inp.Call] = new(CallCov)
		}
		cc := calls[inp.Call]
		cc.count++
		cc.cov = cover.Union(cc.cov, cover.Cover(inp.Cover))
		data.CorpusCoverMem += len(inp.Cover) * int(unsafe.Sizeof(inp.Cover[0]))
	}
	for _, cov := range mgr.corpusCover {
		data.CallCoverMem += len(cov) * int(unsafe.Sizeof(cov[0]))
	}

	secs := uint64(uptime) / 1e9
	for k, v := range mgr.stats {
		val := ""
		if x := v / secs; x >= 10 {
			val = fmt.Sprintf("%v/sec", x)
		} else if x := v * 60 / secs; x >= 10 {
			val = fmt.Sprintf("%v/min", x)
		} else {
			x := v * 60 * 60 / secs
			val = fmt.Sprintf("%v/hour", x)
		}
		data.Stats = append(data.Stats, UIStat{Name: k, Value: val})
	}
	sort.Sort(UIStatArray(data.Stats))

	var cov cover.Cover
	for c, cc := range calls {
		cov = cover.Union(cov, cc.cov)
		data.Calls = append(data.Calls, UICallType{c, cc.count, len(cc.cov)})
	}
	sort.Sort(UICallTypeArray(data.Calls))
	data.CoverSize = len(cov)

	if err := htmlTemplate.Execute(w, data); err != nil {
		http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError)
	}
}

func (mgr *Manager) httpCorpus(w http.ResponseWriter, r *http.Request) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	var data []UIInput
	call := r.FormValue("call")
	for i, inp := range mgr.corpus {
		if call != inp.Call {
			continue
		}
		p, err := prog.Deserialize(inp.Prog)
		if err != nil {
			http.Error(w, fmt.Sprintf("failed to deserialize program: %v", err), http.StatusInternalServerError)
		}
		data = append(data, UIInput{
			Short: p.String(),
			Full:  string(inp.Prog),
			Cover: len(inp.Cover),
			N:     i,
		})
	}
	sort.Sort(UIInputArray(data))

	if err := corpusTemplate.Execute(w, data); err != nil {
		http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError)
	}
}

func (mgr *Manager) httpCover(w http.ResponseWriter, r *http.Request) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	var cov cover.Cover
	call := r.FormValue("call")
	if n, err := strconv.Atoi(call); err == nil && n < len(mgr.corpus) {
		cov = mgr.corpus[n].Cover
	} else {
		for _, inp := range mgr.corpus {
			if call == "" || call == inp.Call {
				cov = cover.Union(cov, cover.Cover(inp.Cover))
			}
		}
	}

	if err := generateCoverHtml(w, mgr.cfg.Vmlinux, cov); err != nil {
		http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError)
	}
	runtime.GC()
}

func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) {
	mgr.mu.Lock()
	defer mgr.mu.Unlock()

	mgr.minimizeCorpus()
	call := r.FormValue("call")
	idx := -1
	for i, c := range sys.Calls {
		if c.CallName == call {
			idx = i
			break
		}
	}
	if idx == -1 {
		http.Error(w, fmt.Sprintf("unknown call: %v", call), http.StatusInternalServerError)
		return
	}

	data := &UIPrioData{Call: call}
	for i, p := range mgr.prios[idx] {
		data.Prios = append(data.Prios, UIPrio{sys.Calls[i].Name, p})
	}
	sort.Sort(UIPrioArray(data.Prios))

	if err := prioTemplate.Execute(w, data); err != nil {
		http.Error(w, fmt.Sprintf("failed to execute template: %v", err), http.StatusInternalServerError)
	}
}

type UIData struct {
	CorpusSize     int
	TriageQueue    int
	CoverSize      int
	CorpusCoverMem int
	CallCoverMem   int
	Uptime         string
	Stats          []UIStat
	Calls          []UICallType
}

type UIStat struct {
	Name  string
	Value string
}

type UICallType struct {
	Name   string
	Inputs int
	Cover  int
}

type UIInput struct {
	Short string
	Full  string
	Calls int
	Cover int
	N     int
}

type UICallTypeArray []UICallType

func (a UICallTypeArray) Len() int           { return len(a) }
func (a UICallTypeArray) Less(i, j int) bool { return a[i].Name  a[j].Cover }
func (a UIInputArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

type UIStatArray []UIStat

func (a UIStatArray) Len() int           { return len(a) }
func (a UIStatArray) Less(i, j int) bool { return a[i].Name < a[j].Name }
func (a UIStatArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

var htmlTemplate = template.Must(template.New("").Parse(`
<!doctype html>

    <title>syzkaller</title>

Uptime: {{.Uptime}}

Corpus: {{.CorpusSize}}

Triage queue len: {{.TriageQueue}}

Cover mem: {{.CorpusCoverMem}} + {{.CallCoverMem}}

Cover: {{.CoverSize}}

Stats:

{{range $stat := $.Stats}}
	{{$stat.Name}}: {{$stat.Value}}

{{end}}

{{range $c := $.Calls}}
	{{$c.Name}} inputs:{{$c.Inputs}} cover:{{$c.Cover}} prio

{{end}}

`))

var corpusTemplate = template.Must(template.New("").Parse(`
<!doctype html>

    <title>syzkaller corpus</title>

{{range $c := $}}
	{{$c.Short}} cover:{{$c.Cover}}

{{end}}

`))

type UIPrioData struct {
	Call  string
	Prios []UIPrio
}

type UIPrio struct {
	Call string
	Prio float32
}

type UIPrioArray []UIPrio

func (a UIPrioArray) Len() int           { return len(a) }
func (a UIPrioArray) Less(i, j int) bool { return a[i].Prio > a[j].Prio }
func (a UIPrioArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }

var prioTemplate = template.Must(template.New("").Parse(`
<!doctype html>

    <title>syzkaller priorities</title>

Priorities for {{$.Call}}

{{range $p := $.Prios}}
	{{printf "%.4f\t%s" $p.Prio $p.Call}}

{{end}}

`))
<|endoftext|>


<commit_before>package yorm

import (
	"database/sql"
	"reflect"
	"strings"
	"time"
)

type tableSetter struct {
	table    string
	dests    []interface{}
	columns  []*column
	pkColumn *column
}

var (
	//TimeType time's reflect type.
	TimeType = reflect.TypeOf(time.Time{})

	// one struct reflect to a table query setter
	tableMap = map[reflect.Value]*tableSetter{}
)

func newTableSetter(ri reflect.Value) (*tableSetter, error) {
	if q, ok := tableMap[ri]; ok {
		return q, nil
	}
	if ri.Kind() != reflect.Ptr {
		return nil, ErrNonPtr
	}
	if ri.IsNil() {
		return nil, ErrNotSupported
	}
	q := new(tableSetter)
	table, cs := structToTable(reflect.Indirect(ri).Interface())
	var err error
	q.pkColumn, err = findPkColumn(cs)
	if q.pkColumn == nil {
		tableMap[ri] = nil
		return nil, err
	}
	q.table = table
	q.columns = cs
	q.dests = make([]interface{}, len(cs))
	for k, v := range cs {
		q.dests[k] = newPtrInterface(v.typ)
	}
	tableMap[ri] = q
	return q, nil
}

func findPkColumn(cs []*column) (*column, error) {
	var c *column
	var idColumn *column
	isPk := false

	for _, v := range cs {
		if strings.ToLower(v.name) == "id" {
			idColumn = v
		}
		if v.isPK {
			if isPk {
				return c, ErrDuplicatePkColumn
			}
			isPk = true
			c = v
		}
	}
	if c == nil && idColumn != nil {
		idColumn.isPK = true
		idColumn.isAuto = true
		c = idColumn
	}
	if c == nil {
		return nil, ErrNonePkColumn
	}
	return c, nil
}

func newPtrInterface(t reflect.Type) interface{} {
	k := t.Kind()
	var ti interface{}
	switch k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		fallthrough
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		ti = new(sql.NullInt64)
	case reflect.String:
		ti = new(sql.NullString)
	case reflect.Float32, reflect.Float64:
		ti = new(sql.NullFloat64)
	case reflect.Struct:
		switch t {
		case TimeType:
			ti = new(sql.NullString)
		}
	}
	return ti
}

func scanValue(sc sqlScanner, q *tableSetter, st reflect.Value) error {
	err := sc.Scan(q.dests...)
	if err != nil {
		return err
	}
	for idx, c := range q.columns {
		// different assign func here
		switch c.typ.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			fallthrough
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			sqlValue := sql.NullInt64(*(q.dests[idx].(*sql.NullInt64)))
			if !sqlValue.Valid {
				continue
			}
			st.Field(c.fieldNum).SetInt(sqlValue.Int64)
		case reflect.String:
			sqlValue := sql.NullString(*(q.dests[idx].(*sql.NullString)))
			if !sqlValue.Valid {
				continue
			}
			st.Field(c.fieldNum).SetString(sqlValue.String)
		case reflect.Float32, reflect.Float64:
			sqlValue := sql.NullFloat64(*(q.dests[idx].(*sql.NullFloat64)))
			if !sqlValue.Valid {
				continue
			}
			st.Field(c.fieldNum).SetFloat(sqlValue.Float64)
		case reflect.Struct:
			switch c.typ {
			case TimeType:
				sqlValue := sql.NullString(*(q.dests[idx].(*sql.NullString)))
				if !sqlValue.Valid {
					continue
				}
				timeStr := sqlValue.String
				var layout string
				if len(timeStr) == 10 {
					layout = shortSimpleTimeFormat
				}
				if len(timeStr) == 19 {
					layout = longSimpleTimeFormat
				}
				timeTime, err := time.ParseInLocation(layout, timeStr, time.Local)
				if timeTime.IsZero() {
					return err
				}
				st.Field(c.fieldNum).Set(reflect.ValueOf(timeTime))
			}
		}
	}
	return nil
}
<commit_msg>bug table fixed<commit_after>package yorm

import (
	"database/sql"
	"reflect"
	"strings"
	"sync"
	"time"
)

type tableSetter struct {
	table    string
	dests    []interface{}
	columns  []*column
	pkColumn *column
}

var (
	//TimeType time's reflect type.
	TimeType = reflect.TypeOf(time.Time{})

	// one struct reflect to a table query setter
	tableMap = map[reflect.Value]*tableSetter{}
	//table lock
	tableRWLock sync.RWMutex
)

func newTableSetter(ri reflect.Value) (*tableSetter, error) {
	tableRWLock.Lock()
	defer tableRWLock.Unlock()
	if q, ok := tableMap[ri]; ok {
		return q, nil
	}
	if ri.Kind() != reflect.Ptr {
		return nil, ErrNonPtr
	}
	if ri.IsNil() {
		return nil, ErrNotSupported
	}
	q := new(tableSetter)
	table, cs := structToTable(reflect.Indirect(ri).Interface())
	var err error
	q.pkColumn, err = findPkColumn(cs)
	if q.pkColumn == nil {
		tableMap[ri] = nil
		return nil, err
	}
	q.table = table
	q.columns = cs
	q.dests = make([]interface{}, len(cs))
	for k, v := range cs {
		q.dests[k] = newPtrInterface(v.typ)
	}
	tableMap[ri] = q
	return q, nil
}

func findPkColumn(cs []*column) (*column, error) {
	var c *column
	var idColumn *column
	isPk := false

	for _, v := range cs {
		if strings.ToLower(v.name) == "id" {
			idColumn = v
		}
		if v.isPK {
			if isPk {
				return c, ErrDuplicatePkColumn
			}
			isPk = true
			c = v
		}
	}
	if c == nil && idColumn != nil {
		idColumn.isPK = true
		idColumn.isAuto = true
		c = idColumn
	}
	if c == nil {
		return nil, ErrNonePkColumn
	}
	return c, nil
}

func newPtrInterface(t reflect.Type) interface{} {
	k := t.Kind()
	var ti interface{}
	switch k {
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		fallthrough
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		ti = new(sql.NullInt64)
	case reflect.String:
		ti = new(sql.NullString)
	case reflect.Float32, reflect.Float64:
		ti = new(sql.NullFloat64)
	case reflect.Struct:
		switch t {
		case TimeType:
			ti = new(sql.NullString)
		}
	}
	return ti
}

func scanValue(sc sqlScanner, q *tableSetter, st reflect.Value) error {
	err := sc.Scan(q.dests...)
	if err != nil {
		return err
	}
	for idx, c := range q.columns {
		// different assign func here
		switch c.typ.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
			fallthrough
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			sqlValue := sql.NullInt64(*(q.dests[idx].(*sql.NullInt64)))
			if !sqlValue.Valid {
				continue
			}
			st.Field(c.fieldNum).SetInt(sqlValue.Int64)
		case reflect.String:
			sqlValue := sql.NullString(*(q.dests[idx].(*sql.NullString)))
			if !sqlValue.Valid {
				continue
			}
			st.Field(c.fieldNum).SetString(sqlValue.String)
		case reflect.Float32, reflect.Float64:
			sqlValue := sql.NullFloat64(*(q.dests[idx].(*sql.NullFloat64)))
			if !sqlValue.Valid {
				continue
			}
			st.Field(c.fieldNum).SetFloat(sqlValue.Float64)
		case reflect.Struct:
			switch c.typ {
			case TimeType:
				sqlValue := sql.NullString(*(q.dests[idx].(*sql.NullString)))
				if !sqlValue.Valid {
					continue
				}
				timeStr := sqlValue.String
				var layout string
				if len(timeStr) == 10 {
					layout = shortSimpleTimeFormat
				}
				if len(timeStr) == 19 {
					layout = longSimpleTimeFormat
				}
				timeTime, err := time.ParseInLocation(layout, timeStr, time.Local)
				if timeTime.IsZero() {
					return err
				}
				st.Field(c.fieldNum).Set(reflect.ValueOf(timeTime))
			}
		}
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright © 2016 Abcum Ltd
//
// 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 syncr

import (
	"io"
)

type Syncable interface {
	io.Reader
	io.Writer
	io.Seeker
	io.Closer
	Sync() error
}
<commit_msg>Add Godoc comments<commit_after>// Copyright © 2016 Abcum Ltd
//
// 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 syncr

import (
	"io"
)

// Syncable is an interface which represents an append-only data stream
// storage type for reading and writing data on local or remote storage.
type Syncable interface {
	io.Reader
	io.Writer
	io.Seeker
	io.Closer
	Sync() error
}
<|endoftext|>


<commit_before><commit_msg>fixed recharge structure<commit_after><|endoftext|>


<commit_before><commit_msg>Schedule series for flushing if there is more than one chunk<commit_after><|endoftext|>


<commit_before>package gollection_test

import (
	"testing"

	"github.com/azihsoyn/gollection"
	"github.com/stretchr/testify/assert"
)

func TestDistinct(t *testing.T) {
	assert := assert.New(t)
	arr := []int{1, 2, 3, 1, 2, 3}
	expect := []int{1, 2, 3}

	res, err := gollection.New(arr).Distinct().Result()
	assert.NoError(err)
	assert.Equal(expect, res)
}

func TestDistinct_NotSlice(t *testing.T) {
	assert := assert.New(t)
	_, err := gollection.New("not slice value").Distinct().Result()
	assert.Error(err)
}

func TestDistinct_HavingError(t *testing.T) {
	assert := assert.New(t)
	_, err := gollection.New("not slice value").Distinct().Distinct().Result()
	assert.Error(err)
}

func TestDistinctBy(t *testing.T) {
	assert := assert.New(t)
	arr := []string{"aaa", "bb", "c", "ddd", "ee", "f"}
	expect := []string{"aaa", "bb", "c"}

	res, err := gollection.New(arr).DistinctBy(func(v interface{}) interface{} {
		return len(v.(string))
	}).Result()
	assert.NoError(err)
	assert.Equal(expect, res)
}

func TestDistinctBy_NotSlice(t *testing.T) {
	assert := assert.New(t)
	_, err := gollection.New("not slice value").DistinctBy(func(v interface{}) interface{} {
		return v
	}).Result()
	assert.Error(err)
}

func TestDistinctBy_HavingError(t *testing.T) {
	assert := assert.New(t)
	_, err := gollection.New("not slice value").DistinctBy(func(v interface{}) interface{} {
		return v
	}).Distinct().Result()
	assert.Error(err)
}
<commit_msg>fix test<commit_after>package gollection_test

import (
	"testing"

	"github.com/azihsoyn/gollection"
	"github.com/stretchr/testify/assert"
)

func TestDistinct(t *testing.T) {
	assert := assert.New(t)
	arr := []int{1, 2, 3, 1, 2, 3}
	expect := []int{1, 2, 3}

	res, err := gollection.New(arr).Distinct().Result()
	assert.NoError(err)
	assert.Equal(expect, res)
}

func TestDistinct_NotSlice(t *testing.T) {
	assert := assert.New(t)
	_, err := gollection.New("not slice value").Distinct().Result()
	assert.Error(err)
}

func TestDistinct_HavingError(t *testing.T) {
	assert := assert.New(t)
	_, err := gollection.New("not slice value").Distinct().Distinct().Result()
	assert.Error(err)
}

func TestDistinctBy(t *testing.T) {
	assert := assert.New(t)
	arr := []string{"aaa", "bb", "c", "ddd", "ee", "f"}
	expect := []string{"aaa", "bb", "c"}

	res, err := gollection.New(arr).DistinctBy(func(v interface{}) interface{} {
		return len(v.(string))
	}).Result()
	assert.NoError(err)
	assert.Equal(expect, res)
}

func TestDistinctBy_NotSlice(t *testing.T) {
	assert := assert.New(t)
	_, err := gollection.New("not slice value").DistinctBy(func(v interface{}) interface{} {
		return v
	}).Result()
	assert.Error(err)
}

func TestDistinctBy_HavingError(t *testing.T) {
	assert := assert.New(t)
	_, err := gollection.New("not slice value").
		DistinctBy(func(v interface{}) interface{} {
		return v
	}).
		DistinctBy(func(v interface{}) interface{} {
		return v
	}).
		Result()
	assert.Error(err)
}
<|endoftext|>


<commit_before>// +build daemon

package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/autogen/dockerversion"
	"github.com/docker/docker/builder"
	"github.com/docker/docker/builtins"
	"github.com/docker/docker/daemon"
	_ "github.com/docker/docker/daemon/execdriver/lxc"
	_ "github.com/docker/docker/daemon/execdriver/native"
	"github.com/docker/docker/engine"
	"github.com/docker/docker/pkg/homedir"
	flag "github.com/docker/docker/pkg/mflag"
	"github.com/docker/docker/pkg/signal"
	"github.com/docker/docker/registry"
	"github.com/docker/docker/utils"
)

const CanDaemon = true

var (
	daemonCfg   = &daemon.Config{}
	registryCfg = &registry.Options{}
)

func init() {
	daemonCfg.InstallFlags()
	registryCfg.InstallFlags()
}

func migrateKey() (err error) {
	// Migrate trust key if exists at ~/.docker/key.json and owned by current user
	oldPath := filepath.Join(homedir.Get(), ".docker", defaultTrustKeyFile)
	newPath := filepath.Join(getDaemonConfDir(), defaultTrustKeyFile)
	if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && utils.IsFileOwner(oldPath) {
		defer func() {
			// Ensure old path is removed if no error occurred
			if err == nil {
				err = os.Remove(oldPath)
			} else {
				log.Warnf("Key migration failed, key file not removed at %s", oldPath)
			}
		}()

		if err := os.MkdirAll(getDaemonConfDir(), os.FileMode(0644)); err != nil {
			return fmt.Errorf("Unable to create daemon configuration directory: %s", err)
		}

		newFile, err := os.OpenFile(newPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
		if err != nil {
			return fmt.Errorf("error creating key file %q: %s", newPath, err)
		}
		defer newFile.Close()

		oldFile, err := os.Open(oldPath)
		if err != nil {
			return fmt.Errorf("error opening key file %q: %s", oldPath, err)
		}
		defer oldFile.Close()

		if _, err := io.Copy(newFile, oldFile); err != nil {
			return fmt.Errorf("error copying key: %s", err)
		}

		log.Infof("Migrated key from %s to %s", oldPath, newPath)
	}

	return nil
}

func mainDaemon() {
	if flag.NArg() != 0 {
		flag.Usage()
		return
	}
	eng := engine.New()
	signal.Trap(eng.Shutdown)

	if err := migrateKey(); err != nil {
		log.Fatal(err)
	}
	daemonCfg.TrustKeyPath = *flTrustKey

	// Load builtins
	if err := builtins.Register(eng); err != nil {
		log.Fatal(err)
	}

	// load registry service
	if err := registry.NewService(registryCfg).Install(eng); err != nil {
		log.Fatal(err)
	}

	// load the daemon in the background so we can immediately start
	// the http api so that connections don't fail while the daemon
	// is booting
	daemonWait := make(chan struct{})
	go func() {
		defer func() {
			close(daemonWait)
		}()
		d, err := daemon.NewDaemon(daemonCfg, eng)
		if err != nil {
			log.Error(err)
			return
		}

		log.Infof("docker daemon: %s %s; execdriver: %s; graphdriver: %s",
			dockerversion.VERSION,
			dockerversion.GITCOMMIT,
			d.ExecutionDriver().Name(),
			d.GraphDriver().String(),
		)

		if err := d.Install(eng); err != nil {
			log.Error(err)
			return
		}

		b := &builder.BuilderJob{eng, d}
		b.Install()

		// after the daemon is done setting up we can tell the api to start
		// accepting connections
		if err := eng.Job("acceptconnections").Run(); err != nil {
			log.Error(err)
			return
		}

		log.Debugf("daemon finished")
	}()

	// Serve api
	job := eng.Job("serveapi", flHosts...)
	job.SetenvBool("Logging", true)
	job.SetenvBool("EnableCors", daemonCfg.EnableCors)
	job.Setenv("CorsHeaders", daemonCfg.CorsHeaders)
	job.Setenv("Version", dockerversion.VERSION)
	job.Setenv("SocketGroup", daemonCfg.SocketGroup)

	job.SetenvBool("Tls", *flTls)
	job.SetenvBool("TlsVerify", *flTlsVerify)
	job.Setenv("TlsCa", *flCa)
	job.Setenv("TlsCert", *flCert)
	job.Setenv("TlsKey", *flKey)
	job.SetenvBool("BufferRequests", true)
	err := job.Run()

	// Wait for the daemon startup goroutine to finish
	// This makes sure we can actually cleanly shutdown the daemon
	log.Infof("waiting for daemon to initialize")
	<-daemonWait
	eng.Shutdown()
	if err != nil {
		// log errors here so the log output looks more consistent
		log.Fatalf("shutting down daemon due to errors: %v", err)
	}

}
<commit_msg>cleanup defer func<commit_after>// +build daemon

package main

import (
	"fmt"
	"io"
	"os"
	"path/filepath"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/docker/autogen/dockerversion"
	"github.com/docker/docker/builder"
	"github.com/docker/docker/builtins"
	"github.com/docker/docker/daemon"
	_ "github.com/docker/docker/daemon/execdriver/lxc"
	_ "github.com/docker/docker/daemon/execdriver/native"
	"github.com/docker/docker/engine"
	"github.com/docker/docker/pkg/homedir"
	flag "github.com/docker/docker/pkg/mflag"
	"github.com/docker/docker/pkg/signal"
	"github.com/docker/docker/registry"
	"github.com/docker/docker/utils"
)

const CanDaemon = true

var (
	daemonCfg   = &daemon.Config{}
	registryCfg = &registry.Options{}
)

func init() {
	daemonCfg.InstallFlags()
	registryCfg.InstallFlags()
}

func migrateKey() (err error) {
	// Migrate trust key if exists at ~/.docker/key.json and owned by current user
	oldPath := filepath.Join(homedir.Get(), ".docker", defaultTrustKeyFile)
	newPath := filepath.Join(getDaemonConfDir(), defaultTrustKeyFile)
	if _, statErr := os.Stat(newPath); os.IsNotExist(statErr) && utils.IsFileOwner(oldPath) {
		defer func() {
			// Ensure old path is removed if no error occurred
			if err == nil {
				err = os.Remove(oldPath)
			} else {
				log.Warnf("Key migration failed, key file not removed at %s", oldPath)
			}
		}()

		if err := os.MkdirAll(getDaemonConfDir(), os.FileMode(0644)); err != nil {
			return fmt.Errorf("Unable to create daemon configuration directory: %s", err)
		}

		newFile, err := os.OpenFile(newPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
		if err != nil {
			return fmt.Errorf("error creating key file %q: %s", newPath, err)
		}
		defer newFile.Close()

		oldFile, err := os.Open(oldPath)
		if err != nil {
			return fmt.Errorf("error opening key file %q: %s", oldPath, err)
		}
		defer oldFile.Close()

		if _, err := io.Copy(newFile, oldFile); err != nil {
			return fmt.Errorf("error copying key: %s", err)
		}

		log.Infof("Migrated key from %s to %s", oldPath, newPath)
	}

	return nil
}

func mainDaemon() {
	if flag.NArg() != 0 {
		flag.Usage()
		return
	}
	eng := engine.New()
	signal.Trap(eng.Shutdown)

	if err := migrateKey(); err != nil {
		log.Fatal(err)
	}
	daemonCfg.TrustKeyPath = *flTrustKey

	// Load builtins
	if err := builtins.Register(eng); err != nil {
		log.Fatal(err)
	}

	// load registry service
	if err := registry.NewService(registryCfg).Install(eng); err != nil {
		log.Fatal(err)
	}

	// load the daemon in the background so we can immediately start
	// the http api so that connections don't fail while the daemon
	// is booting
	daemonWait := make(chan struct{})
	go func() {
		defer close(daemonWait)

		d, err := daemon.NewDaemon(daemonCfg, eng)
		if err != nil {
			log.Error(err)
			return
		}

		log.Infof("docker daemon: %s %s; execdriver: %s; graphdriver: %s",
			dockerversion.VERSION,
			dockerversion.GITCOMMIT,
			d.ExecutionDriver().Name(),
			d.GraphDriver().String(),
		)

		if err := d.Install(eng); err != nil {
			log.Error(err)
			return
		}

		b := &builder.BuilderJob{eng, d}
		b.Install()

		// after the daemon is done setting up we can tell the api to start
		// accepting connections
		if err := eng.Job("acceptconnections").Run(); err != nil {
			log.Error(err)
			return
		}

		log.Debugf("daemon finished")
	}()

	// Serve api
	job := eng.Job("serveapi", flHosts...)
	job.SetenvBool("Logging", true)
	job.SetenvBool("EnableCors", daemonCfg.EnableCors)
	job.Setenv("CorsHeaders", daemonCfg.CorsHeaders)
	job.Setenv("Version", dockerversion.VERSION)
	job.Setenv("SocketGroup", daemonCfg.SocketGroup)

	job.SetenvBool("Tls", *flTls)
	job.SetenvBool("TlsVerify", *flTlsVerify)
	job.Setenv("TlsCa", *flCa)
	job.Setenv("TlsCert", *flCert)
	job.Setenv("TlsKey", *flKey)
	job.SetenvBool("BufferRequests", true)
	err := job.Run()

	// Wait for the daemon startup goroutine to finish
	// This makes sure we can actually cleanly shutdown the daemon
	log.Infof("waiting for daemon to initialize")
	<-daemonWait
	eng.Shutdown()
	if err != nil {
		// log errors here so the log output looks more consistent
		log.Fatalf("shutting down daemon due to errors: %v", err)
	}

}
<|endoftext|>


<commit_before>// Copyright 2015 The Vanadium 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 discovery defines types and interfaces for discovering services.
//
// TODO(jhahn): This is a work in progress and can change without notice.
package discovery

import (
	"v.io/v23/context"
	"v.io/v23/security"
)

// T is the interface for discovery operations; it is the client side library
// for the discovery service.
type T interface {
	Advertiser
	Scanner
	Closer
}

// Advertiser is the interface for advertising services.
type Advertiser interface {
	// Advertise advertises the service to be discovered by "Scanner" implementations.
	// visibility is used to limit the principals that can see the advertisement. An
	// empty set means that there are no restrictions on visibility (i.e, equivalent
	// to []security.BlessingPattern{security.AllPrincipals}). Advertising will continue
	// until the context is canceled or exceeds its deadline and the returned channel
	// will be closed when it stops.
	//
	// If service.InstanceId is not specified, a random 128 bit (16 byte) UUID will be
	// assigned to it. Any change to service will not be applied after advertising starts.
	//
	// It is an error to have simultaneously active advertisements for two identical
	// instances (service.InstanceId).
	Advertise(ctx *context.T, service *Service, visibility []security.BlessingPattern) (<-chan struct{}, error)
}

// AdvertiseCloser is the interface that groups the Advertise and Close methods.
type AdvertiseCloser interface {
	Advertiser
	Closer
}

// Scanner is the interface for scanning services.
type Scanner interface {
	// Scan scans services that match the query and returns the channel on which
	// new discovered services can be read. Scanning will continue until the context
	// is canceled or exceeds its deadline.
	//
	// The query is a WHERE expression of syncQL query against scanned services, where
	// keys are InstanceIds and values are Services.
	//
	// Examples
	//
	//    v.InstanceName = "v.io/i"
	//    v.InstanceName = "v.io/i" AND v.Attrs["a"] = "v"
	//    v.Attrs["a"] = "v1" OR v.Attrs["a"] = "v2"
	//
	// SyncQL tutorial at:
	//    https://github.com/vanadium/docs/blob/master/tutorials/syncql-tutorial.md
	Scan(ctx *context.T, query string) (<-chan Update, error)
}

// ScanCloser is the interface that groups the Scan and Close methods.
type ScanCloser interface {
	Scanner
	Closer
}

// Closer is the interface that wraps the Close method.
type Closer interface {
	// Close closes all active tasks.
	Close()
}
<commit_msg>TBR: discovery: fix a typo in comments.<commit_after>// Copyright 2015 The Vanadium 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 discovery defines types and interfaces for discovering services.
//
// TODO(jhahn): This is a work in progress and can change without notice.
package discovery

import (
	"v.io/v23/context"
	"v.io/v23/security"
)

// T is the interface for discovery operations; it is the client side library
// for the discovery service.
type T interface {
	Advertiser
	Scanner
	Closer
}

// Advertiser is the interface for advertising services.
type Advertiser interface {
	// Advertise advertises the service to be discovered by "Scanner" implementations.
	// visibility is used to limit the principals that can see the advertisement. An
	// empty set means that there are no restrictions on visibility (i.e, equivalent
	// to []security.BlessingPattern{security.AllPrincipals}). Advertising will continue
	// until the context is canceled or exceeds its deadline and the returned channel
	// will be closed when it stops.
	//
	// If service.InstanceId is not specified, a random 128 bit (16 byte) UUID will be
	// assigned to it. Any change to service will not be applied after advertising starts.
	//
	// It is an error to have simultaneously active advertisements for two identical
	// instances (service.InstanceId).
	Advertise(ctx *context.T, service *Service, visibility []security.BlessingPattern) (<-chan struct{}, error)
}

// AdvertiseCloser is the interface that groups the Advertise and Close methods.
type AdvertiseCloser interface {
	Advertiser
	Closer
}

// Scanner is the interface for scanning services.
type Scanner interface {
	// Scan scans services that match the query and returns the channel on which
	// new discovered services can be read. Scanning will continue until the context
	// is canceled or exceeds its deadline.
	//
	// The query is a WHERE expression of syncQL query against scanned services, where
	// keys are InstanceIds and values are Services.
	//
	// Examples
	//
	//    v.InterfaceName = "v.io/i"
	//    v.InterfaceName = "v.io/i" AND v.Attrs["a"] = "v"
	//    v.Attrs["a"] = "v1" OR v.Attrs["a"] = "v2"
	//
	// SyncQL tutorial at:
	//    https://github.com/vanadium/docs/blob/master/tutorials/syncql-tutorial.md
	Scan(ctx *context.T, query string) (<-chan Update, error)
}

// ScanCloser is the interface that groups the Scan and Close methods.
type ScanCloser interface {
	Scanner
	Closer
}

// Closer is the interface that wraps the Close method.
type Closer interface {
	// Close closes all active tasks.
	Close()
}
<|endoftext|>


<commit_before>// display.go

package display

import (
	"math/rand"
	"time"

	"github.com/nsf/termbox-go"
)

const (
	padding int = 2
)

var currentFile, currentLine []rune
var width, height, currentScroll, currentCursor int
var Color termbox.Attribute
var highlights [][]int
var topBar bool
var Log func([]rune)
var LogS func(string)

// Ranges over the currentFile and
// returns the positions of each rune.
func overLines(str []rune, f func(int, int, int, rune)) {
	var x, y int
	for i, r := range str {
		f(i, x, y, r)
		if r == '\n' || x >= (width-(3*padding)) {
			y++
			x = 0
		} else { // not a newline
			x++
		}
	}
}

func viewHeight() int {
	return height - 3 // right now, just one extra line.
}

func Draw() {
	termbox.Clear(0, 0)
	DrawBox()

	var offset, highindex, lasty int
	var highlighting bool

	if topBar {
		offset = 4
	}

	charactersMissed, section := viewSection()
	for highindex < len(highlights) && highlights[highindex][1] < charactersMissed {
		highindex++
	}
	overLines(section, func(i, x, y int, r rune) {
		i = i + charactersMissed
		var light []int
	Retry:
		if highindex < len(highlights) {
			light = highlights[highindex]
			if len(light) != 2 {
				highindex++
				goto Retry
			}
		}
		switch {
		case highindex >= len(highlights):
			highlighting = false
		case i < light[0]:
			highlighting = false
		case i < light[1]-1:
			highlighting = true
		case i == light[1]-1 && light[1]-light[0] == 1:
			highlighting = true
			highindex++
		default:
			highindex++
		}
		back := termbox.ColorDefault
		front := termbox.ColorDefault
		if highlighting {
			back = termbox.Attribute(0xff)
			front = termbox.ColorBlack
		}
		// if r != '\n' {
		lasty = y
		termbox.SetCell(x+padding, y+offset, r, front, back)
	})
	for j := lasty + 5; j < height; j++ {
		termbox.SetCell(padding, j, '~', termbox.ColorWhite, termbox.ColorDefault)
	}
	termbox.Flush()
}

func fill(x, y, w, h int, cell termbox.Cell) {
	for ly := 0; ly < h; ly++ {
		for lx := 0; lx < w; lx++ {
			termbox.SetCell(x+lx, y+ly, cell.Ch, cell.Fg, cell.Bg)
		}
	}
}

func DrawBox() {
	var offset int
	if topBar {
		offset = height - 4
	}
	color := Color
	edit_box_width := width - 4
	midx := 2
	midy := height - 2 - offset
	termbox.SetCell(midx-1, midy, '│', color, 0)
	termbox.SetCell(midx+edit_box_width, midy, '│', color, 0)
	termbox.SetCell(midx-1, midy-1, '┌', color, 0)
	termbox.SetCell(midx-1, midy+1, '└', color, 0)
	termbox.SetCell(midx+edit_box_width, midy-1, '┐', color, 0)
	termbox.SetCell(midx+edit_box_width, midy+1, '┘', color, 0)
	fill(midx, midy-1, edit_box_width, 1, termbox.Cell{Ch: '─', Fg: color})
	fill(midx, midy+1, edit_box_width, 1, termbox.Cell{Ch: '─', Fg: color})
	DrawLine()
}

func ScrollDown() {
	if currentScroll < numberOfLines() {
		currentScroll++
	}
	Draw()
}

func ScrollUp() {
	if currentScroll != 0 {
		currentScroll--
	}
	Draw()
}

func viewSection() (int, []rune) {
	var start, end, charactersMissed int
	overLines(currentFile, func(i, x, y int, r rune) {
		if y < currentScroll {
			charactersMissed++
		}
		if y == currentScroll && x == 0 {
			start = i
		}
		if y == currentScroll+viewHeight() && x == 0 {
			end = i - 1
		}
	})
	if end == 0 { // Didn't reach the end.
		end = len(currentFile) - 2 // why minus 2?
	}
	if start > end {
		start = end
	}
	if len(currentFile) <= 1 {
		return charactersMissed, currentFile
	}
	return charactersMissed, currentFile[start:end]
}

func numberOfLines() int {
	var a int
	overLines(currentFile, func(i, x, y int, r rune) {
		a = y
	})
	return a
}

func Reset() {
	termbox.Close()
}

func Highlight(scopes [][]int) {
	highlights = scopes
}

func Resize() {
	termbox.Flush()
	width, height = termbox.Size()
}

func Init(bar bool) {
	rand.Seed(int64(time.Now().Nanosecond()))
	termbox.SetOutputMode(termbox.Output256)
	termbox.Init()
	Resize()
	topBar = bar
}

func LineWidth() int {
	return width - 6 - 1
}

func DrawLine() {
	x := 3
	var offset int
	if topBar {
		offset = height - 4 //w/e
	}
	y := height - 2 - offset

	termbox.SetCursor(x+currentCursor, y)

	// ClearLine
	for i := x; i < width-2; i++ {
		termbox.SetCell(i, y, ' ', 0, 0)
	}

	// Fill it in
	for _, r := range currentLine {
		termbox.SetCell(x, y, r, 0, 0)
		x++
	}
	termbox.Flush()
}

func RandomColor() {
	Color = termbox.Attribute(rand.Intn(255))
}

func SetCursor(x int) {
	currentCursor = x
}

func Flush() {
	termbox.Flush()
}

func ShowLine(line []rune) {
	currentLine = line
}

func ShowFile(file []rune) {
	currentFile = file
}

func Show(main []rune, line []rune) {
	currentFile = main
	currentLine = line
}
<commit_msg>Last character of file appears<commit_after>// display.go

package display

import (
	"math/rand"
	"time"

	"github.com/nsf/termbox-go"
)

const (
	padding int = 2
)

var currentFile, currentLine []rune
var width, height, currentScroll, currentCursor int
var Color termbox.Attribute
var highlights [][]int
var topBar bool
var Log func([]rune)
var LogS func(string)

// Ranges over the currentFile and
// returns the positions of each rune.
func overLines(str []rune, f func(int, int, int, rune)) {
	var x, y int
	Log(str)
	for i, r := range str {
		f(i, x, y, r)
		if r == '\n' || x >= (width-(3*padding)) {
			y++
			x = 0
		} else { // not a newline
			x++
		}
	}
}

func viewHeight() int {
	return height - 3 // right now, just one extra line.
}

func Draw() {
	termbox.Clear(0, 0)
	DrawBox()

	var offset, highindex, lasty int
	var highlighting bool

	if topBar {
		offset = 4
	}

	charactersMissed, section := viewSection()
	for highindex < len(highlights) && highlights[highindex][1] < charactersMissed {
		highindex++
	}
	overLines(section, func(i, x, y int, r rune) {
		i = i + charactersMissed
		var light []int
	Retry:
		if highindex < len(highlights) {
			light = highlights[highindex]
			if len(light) != 2 {
				highindex++
				goto Retry
			}
		}
		switch {
		case highindex >= len(highlights):
			highlighting = false
		case i < light[0]:
			highlighting = false
		case i < light[1]-1:
			highlighting = true
		case i == light[1]-1 && light[1]-light[0] == 1:
			highlighting = true
			highindex++
		default:
			highindex++
		}
		back := termbox.ColorDefault
		front := termbox.ColorDefault
		if highlighting {
			back = termbox.Attribute(0xff)
			front = termbox.ColorBlack
		}
		lasty = y
		termbox.SetCell(x+padding, y+offset, r, front, back)
	})
	for j := lasty + 5; j < height; j++ {
		termbox.SetCell(padding, j, '~', termbox.ColorWhite, termbox.ColorDefault)
	}
	termbox.Flush()
}

func fill(x, y, w, h int, cell termbox.Cell) {
	for ly := 0; ly < h; ly++ {
		for lx := 0; lx < w; lx++ {
			termbox.SetCell(x+lx, y+ly, cell.Ch, cell.Fg, cell.Bg)
		}
	}
}

func DrawBox() {
	var offset int
	if topBar {
		offset = height - 4
	}
	color := Color
	edit_box_width := width - 4
	midx := 2
	midy := height - 2 - offset
	termbox.SetCell(midx-1, midy, '│', color, 0)
	termbox.SetCell(midx+edit_box_width, midy, '│', color, 0)
	termbox.SetCell(midx-1, midy-1, '┌', color, 0)
	termbox.SetCell(midx-1, midy+1, '└', color, 0)
	termbox.SetCell(midx+edit_box_width, midy-1, '┐', color, 0)
	termbox.SetCell(midx+edit_box_width, midy+1, '┘', color, 0)
	fill(midx, midy-1, edit_box_width, 1, termbox.Cell{Ch: '─', Fg: color})
	fill(midx, midy+1, edit_box_width, 1, termbox.Cell{Ch: '─', Fg: color})
	DrawLine()
}

func ScrollDown() {
	if currentScroll < numberOfLines() {
		currentScroll++
	}
	Draw()
}

func ScrollUp() {
	if currentScroll != 0 {
		currentScroll--
	}
	Draw()
}

func viewSection() (int, []rune) {
	var start, end, charactersMissed int
	overLines(currentFile, func(i, x, y int, r rune) {
		if y < currentScroll {
			charactersMissed++
		}
		if y == currentScroll && x == 0 {
			start = i
		}
		if y == currentScroll+viewHeight() && x == 0 {
			end = i - 1
		}
	})
	if end == 0 { // Didn't reach the end.
		end = len(currentFile) - 2 // why minus 2?
	}
	if start > end {
		start = end
	}
	if len(currentFile) <= 1 {
		return charactersMissed, currentFile
	}
	return charactersMissed, currentFile[start : end+1]
}

func numberOfLines() int {
	var a int
	overLines(currentFile, func(i, x, y int, r rune) {
		a = y
	})
	return a
}

func Reset() {
	termbox.Close()
}

func Highlight(scopes [][]int) {
	highlights = scopes
}

func Resize() {
	termbox.Flush()
	width, height = termbox.Size()
}

func Init(bar bool) {
	rand.Seed(int64(time.Now().Nanosecond()))
	termbox.SetOutputMode(termbox.Output256)
	termbox.Init()
	Resize()
	topBar = bar
}

func LineWidth() int {
	return width - 6 - 1
}

func DrawLine() {
	x := 3
	var offset int
	if topBar {
		offset = height - 4 //w/e
	}
	y := height - 2 - offset

	termbox.SetCursor(x+currentCursor, y)

	// ClearLine
	for i := x; i < width-2; i++ {
		termbox.SetCell(i, y, ' ', 0, 0)
	}

	// Fill it in
	for _, r := range currentLine {
		termbox.SetCell(x, y, r, 0, 0)
		x++
	}
	termbox.Flush()
}

func RandomColor() {
	Color = termbox.Attribute(rand.Intn(255))
}

func SetCursor(x int) {
	currentCursor = x
}

func Flush() {
	termbox.Flush()
}

func ShowLine(line []rune) {
	currentLine = line
}

func ShowFile(file []rune) {
	currentFile = file
}

func Show(main []rune, line []rune) {
	currentFile = main
	currentLine = line
}
<|endoftext|>


<commit_before>package commands

import (
	"fmt"
	"io"
	"path"
	"strings"

	"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/cheggaaa/pb"

	cmds "github.com/ipfs/go-ipfs/commands"
	files "github.com/ipfs/go-ipfs/commands/files"
	core "github.com/ipfs/go-ipfs/core"
	coreunix "github.com/ipfs/go-ipfs/core/coreunix"
	importer "github.com/ipfs/go-ipfs/importer"
	"github.com/ipfs/go-ipfs/importer/chunk"
	dag "github.com/ipfs/go-ipfs/merkledag"
	pin "github.com/ipfs/go-ipfs/pin"
	ft "github.com/ipfs/go-ipfs/unixfs"
	u "github.com/ipfs/go-ipfs/util"
)

// Error indicating the max depth has been exceded.
var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")

// how many bytes of progress to wait before sending a progress update message
const progressReaderIncrement = 1024 * 256

const (
	progressOptionName = "progress"
	wrapOptionName     = "wrap-with-directory"
)

type AddedObject struct {
	Name  string
	Hash  string `json:",omitempty"`
	Bytes int64  `json:",omitempty"`
}

var AddCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Add an object to ipfs.",
		ShortDescription: `
Adds contents of <path> to ipfs. Use -r to add directories.
Note that directories are added recursively, to form the ipfs
MerkleDAG. A smarter partial add with a staging area (like git)
remains to be implemented.
`,
	},

	Arguments: []cmds.Argument{
		cmds.FileArg("path", true, true, "The path to a file to be added to IPFS").EnableRecursive().EnableStdin(),
	},
	Options: []cmds.Option{
		cmds.OptionRecursivePath, // a builtin option that allows recursive paths (-r, --recursive)
		cmds.BoolOption("quiet", "q", "Write minimal output"),
		cmds.BoolOption(progressOptionName, "p", "Stream progress data"),
		cmds.BoolOption(wrapOptionName, "w", "Wrap files with a directory object"),
		cmds.BoolOption("t", "trickle", "Use trickle-dag format for dag generation"),
	},
	PreRun: func(req cmds.Request) error {
		if quiet, _, _ := req.Option("quiet").Bool(); quiet {
			return nil
		}

		req.SetOption(progressOptionName, true)

		sizeFile, ok := req.Files().(files.SizeFile)
		if !ok {
			// we don't need to error, the progress bar just won't know how big the files are
			return nil
		}

		size, err := sizeFile.Size()
		if err != nil {
			// see comment above
			return nil
		}
		log.Debugf("Total size of file being added: %v\n", size)
		req.Values()["size"] = size

		return nil
	},
	Run: func(req cmds.Request, res cmds.Response) {
		n, err := req.Context().GetNode()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		progress, _, _ := req.Option(progressOptionName).Bool()
		wrap, _, _ := req.Option(wrapOptionName).Bool()

		outChan := make(chan interface{}, 8)
		res.SetOutput((<-chan interface{})(outChan))

		go func() {
			defer close(outChan)

			for {
				file, err := req.Files().NextFile()
				if err != nil && err != io.EOF {
					res.SetError(err, cmds.ErrNormal)
					return
				}
				if file == nil { // done
					return
				}

				rootnd, err := addFile(n, file, outChan, progress, wrap)
				if err != nil {
					res.SetError(err, cmds.ErrNormal)
					return
				}

				rnk, err := rootnd.Key()
				if err != nil {
					res.SetError(err, cmds.ErrNormal)
					return
				}

				mp := n.Pinning.GetManual()
				mp.RemovePinWithMode(rnk, pin.Indirect)
				mp.PinWithMode(rnk, pin.Recursive)

				err = n.Pinning.Flush()
				if err != nil {
					res.SetError(err, cmds.ErrNormal)
					return
				}
			}
		}()
	},
	PostRun: func(req cmds.Request, res cmds.Response) {
		if res.Error() != nil {
			return
		}
		outChan, ok := res.Output().(<-chan interface{})
		if !ok {
			res.SetError(u.ErrCast(), cmds.ErrNormal)
			return
		}
		res.SetOutput(nil)

		quiet, _, err := req.Option("quiet").Bool()
		if err != nil {
			res.SetError(u.ErrCast(), cmds.ErrNormal)
			return
		}

		size := int64(0)
		s, found := req.Values()["size"]
		if found {
			size = s.(int64)
		}
		showProgressBar := !quiet && size >= progressBarMinSize

		var bar *pb.ProgressBar
		var terminalWidth int
		if showProgressBar {
			bar = pb.New64(size).SetUnits(pb.U_BYTES)
			bar.ManualUpdate = true
			bar.Start()

			// the progress bar lib doesn't give us a way to get the width of the output,
			// so as a hack we just use a callback to measure the output, then git rid of it
			terminalWidth = 0
			bar.Callback = func(line string) {
				terminalWidth = len(line)
				bar.Callback = nil
				bar.Output = res.Stderr()
				log.Infof("terminal width: %v\n", terminalWidth)
			}
			bar.Update()
		}

		lastFile := ""
		var totalProgress, prevFiles, lastBytes int64

		for out := range outChan {
			output := out.(*AddedObject)
			if len(output.Hash) > 0 {
				if showProgressBar {
					// clear progress bar line before we print "added x" output
					fmt.Fprintf(res.Stderr(), "\r%s\r", strings.Repeat(" ", terminalWidth))
				}
				if quiet {
					fmt.Fprintf(res.Stdout(), "%s\n", output.Hash)
				} else {
					fmt.Fprintf(res.Stdout(), "added %s %s\n", output.Hash, output.Name)
				}

			} else {
				log.Debugf("add progress: %v %v\n", output.Name, output.Bytes)

				if !showProgressBar {
					continue
				}

				if len(lastFile) == 0 {
					lastFile = output.Name
				}
				if output.Name != lastFile || output.Bytes < lastBytes {
					prevFiles += lastBytes
					lastFile = output.Name
				}
				lastBytes = output.Bytes
				delta := prevFiles + lastBytes - totalProgress
				totalProgress = bar.Add64(delta)
			}

			if showProgressBar {
				bar.Update()
			}
		}
	},
	Type: AddedObject{},
}

func add(n *core.IpfsNode, reader io.Reader) (*dag.Node, error) {
	node, err := importer.BuildDagFromReader(
		reader,
		n.DAG,
		chunk.DefaultSplitter,
		importer.PinIndirectCB(n.Pinning.GetManual()),
	)
	if err != nil {
		return nil, err
	}

	return node, nil
}

func addFile(n *core.IpfsNode, file files.File, out chan interface{}, progress bool, wrap bool) (*dag.Node, error) {
	if file.IsDirectory() {
		return addDir(n, file, out, progress)
	}

	// if the progress flag was specified, wrap the file so that we can send
	// progress updates to the client (over the output channel)
	var reader io.Reader = file
	if progress {
		reader = &progressReader{file: file, out: out}
	}

	if wrap {
		p, dagnode, err := coreunix.AddWrapped(n, reader, path.Base(file.FileName()))
		if err != nil {
			return nil, err
		}
		out <- &AddedObject{
			Hash: p,
			Name: file.FileName(),
		}
		return dagnode, nil
	}

	dagnode, err := add(n, reader)
	if err != nil {
		return nil, err
	}

	log.Infof("adding file: %s", file.FileName())
	if err := outputDagnode(out, file.FileName(), dagnode); err != nil {
		return nil, err
	}
	return dagnode, nil
}

func addDir(n *core.IpfsNode, dir files.File, out chan interface{}, progress bool) (*dag.Node, error) {
	log.Infof("adding directory: %s", dir.FileName())

	tree := &dag.Node{Data: ft.FolderPBData()}

	for {
		file, err := dir.NextFile()
		if err != nil && err != io.EOF {
			return nil, err
		}
		if file == nil {
			break
		}

		node, err := addFile(n, file, out, progress, false)
		if err != nil {
			return nil, err
		}

		_, name := path.Split(file.FileName())

		err = tree.AddNodeLink(name, node)
		if err != nil {
			return nil, err
		}
	}

	err := outputDagnode(out, dir.FileName(), tree)
	if err != nil {
		return nil, err
	}

	k, err := n.DAG.Add(tree)
	if err != nil {
		return nil, err
	}

	n.Pinning.GetManual().PinWithMode(k, pin.Indirect)

	return tree, nil
}

// outputDagnode sends dagnode info over the output channel
func outputDagnode(out chan interface{}, name string, dn *dag.Node) error {
	o, err := getOutput(dn)
	if err != nil {
		return err
	}

	out <- &AddedObject{
		Hash: o.Hash,
		Name: name,
	}

	return nil
}

type progressReader struct {
	file         files.File
	out          chan interface{}
	bytes        int64
	lastProgress int64
}

func (i *progressReader) Read(p []byte) (int, error) {
	n, err := i.file.Read(p)

	i.bytes += int64(n)
	if i.bytes-i.lastProgress >= progressReaderIncrement || err == io.EOF {
		i.lastProgress = i.bytes
		i.out <- &AddedObject{
			Name:  i.file.FileName(),
			Bytes: i.bytes,
		}
	}

	return n, err
}
<commit_msg>Wired up the trickle dag flag for the add command<commit_after>package commands

import (
	"fmt"
	"io"
	"path"
	"strings"

	"github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/cheggaaa/pb"

	cmds "github.com/ipfs/go-ipfs/commands"
	files "github.com/ipfs/go-ipfs/commands/files"
	core "github.com/ipfs/go-ipfs/core"
	coreunix "github.com/ipfs/go-ipfs/core/coreunix"
	importer "github.com/ipfs/go-ipfs/importer"
	"github.com/ipfs/go-ipfs/importer/chunk"
	dag "github.com/ipfs/go-ipfs/merkledag"
	pin "github.com/ipfs/go-ipfs/pin"
	ft "github.com/ipfs/go-ipfs/unixfs"
	u "github.com/ipfs/go-ipfs/util"
)

// Error indicating the max depth has been exceded.
var ErrDepthLimitExceeded = fmt.Errorf("depth limit exceeded")

// how many bytes of progress to wait before sending a progress update message
const progressReaderIncrement = 1024 * 256

const (
	progressOptionName = "progress"
	trickleOptionName  = "trickle"
	wrapOptionName     = "wrap-with-directory"
)

type AddedObject struct {
	Name  string
	Hash  string `json:",omitempty"`
	Bytes int64  `json:",omitempty"`
}

var AddCmd = &cmds.Command{
	Helptext: cmds.HelpText{
		Tagline: "Add an object to ipfs.",
		ShortDescription: `
Adds contents of <path> to ipfs. Use -r to add directories.
Note that directories are added recursively, to form the ipfs
MerkleDAG. A smarter partial add with a staging area (like git)
remains to be implemented.
`,
	},

	Arguments: []cmds.Argument{
		cmds.FileArg("path", true, true, "The path to a file to be added to IPFS").EnableRecursive().EnableStdin(),
	},
	Options: []cmds.Option{
		cmds.OptionRecursivePath, // a builtin option that allows recursive paths (-r, --recursive)
		cmds.BoolOption("quiet", "q", "Write minimal output"),
		cmds.BoolOption(progressOptionName, "p", "Stream progress data"),
		cmds.BoolOption(wrapOptionName, "w", "Wrap files with a directory object"),
		cmds.BoolOption(trickleOptionName, "t", "Use trickle-dag format for dag generation"),
	},
	PreRun: func(req cmds.Request) error {
		if quiet, _, _ := req.Option("quiet").Bool(); quiet {
			return nil
		}

		req.SetOption(progressOptionName, true)

		sizeFile, ok := req.Files().(files.SizeFile)
		if !ok {
			// we don't need to error, the progress bar just won't know how big the files are
			return nil
		}

		size, err := sizeFile.Size()
		if err != nil {
			// see comment above
			return nil
		}
		log.Debugf("Total size of file being added: %v\n", size)
		req.Values()["size"] = size

		return nil
	},
	Run: func(req cmds.Request, res cmds.Response) {
		n, err := req.Context().GetNode()
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		progress, _, _ := req.Option(progressOptionName).Bool()
		trickle, _, _ := req.Option(trickleOptionName).Bool()
		wrap, _, _ := req.Option(wrapOptionName).Bool()

		outChan := make(chan interface{}, 8)
		res.SetOutput((<-chan interface{})(outChan))

		go func() {
			defer close(outChan)

			for {
				file, err := req.Files().NextFile()
				if err != nil && err != io.EOF {
					res.SetError(err, cmds.ErrNormal)
					return
				}
				if file == nil { // done
					return
				}

				rootnd, err := addFile(n, file, outChan, progress, wrap, trickle)
				if err != nil {
					res.SetError(err, cmds.ErrNormal)
					return
				}

				rnk, err := rootnd.Key()
				if err != nil {
					res.SetError(err, cmds.ErrNormal)
					return
				}

				mp := n.Pinning.GetManual()
				mp.RemovePinWithMode(rnk, pin.Indirect)
				mp.PinWithMode(rnk, pin.Recursive)

				err = n.Pinning.Flush()
				if err != nil {
					res.SetError(err, cmds.ErrNormal)
					return
				}
			}
		}()
	},
	PostRun: func(req cmds.Request, res cmds.Response) {
		if res.Error() != nil {
			return
		}
		outChan, ok := res.Output().(<-chan interface{})
		if !ok {
			res.SetError(u.ErrCast(), cmds.ErrNormal)
			return
		}
		res.SetOutput(nil)

		quiet, _, err := req.Option("quiet").Bool()
		if err != nil {
			res.SetError(u.ErrCast(), cmds.ErrNormal)
			return
		}

		size := int64(0)
		s, found := req.Values()["size"]
		if found {
			size = s.(int64)
		}
		showProgressBar := !quiet && size >= progressBarMinSize

		var bar *pb.ProgressBar
		var terminalWidth int
		if showProgressBar {
			bar = pb.New64(size).SetUnits(pb.U_BYTES)
			bar.ManualUpdate = true
			bar.Start()

			// the progress bar lib doesn't give us a way to get the width of the output,
			// so as a hack we just use a callback to measure the output, then git rid of it
			terminalWidth = 0
			bar.Callback = func(line string) {
				terminalWidth = len(line)
				bar.Callback = nil
				bar.Output = res.Stderr()
				log.Infof("terminal width: %v\n", terminalWidth)
			}
			bar.Update()
		}

		lastFile := ""
		var totalProgress, prevFiles, lastBytes int64

		for out := range outChan {
			output := out.(*AddedObject)
			if len(output.Hash) > 0 {
				if showProgressBar {
					// clear progress bar line before we print "added x" output
					fmt.Fprintf(res.Stderr(), "\r%s\r", strings.Repeat(" ", terminalWidth))
				}
				if quiet {
					fmt.Fprintf(res.Stdout(), "%s\n", output.Hash)
				} else {
					fmt.Fprintf(res.Stdout(), "added %s %s\n", output.Hash, output.Name)
				}

			} else {
				log.Debugf("add progress: %v %v\n", output.Name, output.Bytes)

				if !showProgressBar {
					continue
				}

				if len(lastFile) == 0 {
					lastFile = output.Name
				}
				if output.Name != lastFile || output.Bytes < lastBytes {
					prevFiles += lastBytes
					lastFile = output.Name
				}
				lastBytes = output.Bytes
				delta := prevFiles + lastBytes - totalProgress
				totalProgress = bar.Add64(delta)
			}

			if showProgressBar {
				bar.Update()
			}
		}
	},
	Type: AddedObject{},
}

func add(n *core.IpfsNode, reader io.Reader, useTrickle bool) (*dag.Node, error) {
	var node *dag.Node
	var err error
	if useTrickle {
		node, err = importer.BuildTrickleDagFromReader(
			reader,
			n.DAG,
			chunk.DefaultSplitter,
			importer.PinIndirectCB(n.Pinning.GetManual()),
		)
	} else {
		node, err = importer.BuildDagFromReader(
			reader,
			n.DAG,
			chunk.DefaultSplitter,
			importer.PinIndirectCB(n.Pinning.GetManual()),
		)
	}

	if err != nil {
		return nil, err
	}

	return node, nil
}

func addFile(n *core.IpfsNode, file files.File, out chan interface{}, progress bool, wrap bool, useTrickle bool) (*dag.Node, error) {
	if file.IsDirectory() {
		return addDir(n, file, out, progress, useTrickle)
	}

	// if the progress flag was specified, wrap the file so that we can send
	// progress updates to the client (over the output channel)
	var reader io.Reader = file
	if progress {
		reader = &progressReader{file: file, out: out}
	}

	if wrap {
		p, dagnode, err := coreunix.AddWrapped(n, reader, path.Base(file.FileName()))
		if err != nil {
			return nil, err
		}
		out <- &AddedObject{
			Hash: p,
			Name: file.FileName(),
		}
		return dagnode, nil
	}

	dagnode, err := add(n, reader, useTrickle)
	if err != nil {
		return nil, err
	}

	log.Infof("adding file: %s", file.FileName())
	if err := outputDagnode(out, file.FileName(), dagnode); err != nil {
		return nil, err
	}
	return dagnode, nil
}

func addDir(n *core.IpfsNode, dir files.File, out chan interface{}, progress bool, useTrickle bool) (*dag.Node, error) {
	log.Infof("adding directory: %s", dir.FileName())

	tree := &dag.Node{Data: ft.FolderPBData()}

	for {
		file, err := dir.NextFile()
		if err != nil && err != io.EOF {
			return nil, err
		}
		if file == nil {
			break
		}

		node, err := addFile(n, file, out, progress, false, useTrickle)
		if err != nil {
			return nil, err
		}

		_, name := path.Split(file.FileName())

		err = tree.AddNodeLink(name, node)
		if err != nil {
			return nil, err
		}
	}

	err := outputDagnode(out, dir.FileName(), tree)
	if err != nil {
		return nil, err
	}

	k, err := n.DAG.Add(tree)
	if err != nil {
		return nil, err
	}

	n.Pinning.GetManual().PinWithMode(k, pin.Indirect)

	return tree, nil
}

// outputDagnode sends dagnode info over the output channel
func outputDagnode(out chan interface{}, name string, dn *dag.Node) error {
	o, err := getOutput(dn)
	if err != nil {
		return err
	}

	out <- &AddedObject{
		Hash: o.Hash,
		Name: name,
	}

	return nil
}

type progressReader struct {
	file         files.File
	out          chan interface{}
	bytes        int64
	lastProgress int64
}

func (i *progressReader) Read(p []byte) (int, error) {
	n, err := i.file.Read(p)

	i.bytes += int64(n)
	if i.bytes-i.lastProgress >= progressReaderIncrement || err == io.EOF {
		i.lastProgress = i.bytes
		i.out <- &AddedObject{
			Name:  i.file.FileName(),
			Bytes: i.bytes,
		}
	}

	return n, err
}
<|endoftext|>


<commit_before>//go:build !windows
// +build !windows

package termios

import (
	"golang.org/x/sys/unix"

	"github.com/lxc/lxd/shared"
)

// #include <termios.h>
import "C"

// State contains the state of a terminal.
type State struct {
	Termios unix.Termios
}

// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
	_, err := GetState(fd)
	return err == nil
}

// GetState returns the current state of a terminal which may be useful to restore the terminal after a signal.
func GetState(fd int) (*State, error) {
	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
	if err != nil {
		return nil, err
	}

	state := State{}
	state.Termios = *termios

	return &state, nil
}

// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (int, int, error) {
	winsize, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
	if err != nil {
		return -1, -1, err
	}

	return int(winsize.Col), int(winsize.Row), nil
}

func copyTermios(state *State, cTermios *C.struct_termios) {
	cTermios.c_iflag = C.tcflag_t(state.Termios.Iflag)
	cTermios.c_oflag = C.tcflag_t(state.Termios.Oflag)
	cTermios.c_cflag = C.tcflag_t(state.Termios.Cflag)
	cTermios.c_lflag = C.tcflag_t(state.Termios.Lflag)
	cTermios.c_line = C.cc_t(state.Termios.Line)
	cTermios.c_ispeed = C.speed_t(state.Termios.Ispeed)
	cTermios.c_ospeed = C.speed_t(state.Termios.Ospeed)

	for i := 0; i < len(state.Termios.Cc) && i < C.NCCS; i++ {
		cTermios.c_cc[i] = C.uchar(i)
	}
}

// MakeRaw put the terminal connected to the given file descriptor into raw mode and returns the previous state of the terminal so that it can be restored.
func MakeRaw(fd int) (*State, error) {
	var err error
	var oldState, newState *State

	oldState, err = GetState(fd)
	if err != nil {
		return nil, err
	}

	err = shared.DeepCopy(&oldState, &newState)
	if err != nil {
		return nil, err
	}

	var cTermios C.struct_termios
	copyTermios(newState, &cTermios)
	C.cfmakeraw(&cTermios)

	err = Restore(fd, newState)
	if err != nil {
		return nil, err
	}

	return oldState, nil
}

// Restore restores the terminal connected to the given file descriptor to a previous state.
func Restore(fd int, state *State) error {
	var cTermios C.struct_termios
	copyTermios(state, &cTermios)
	ret, err := C.tcsetattr(C.int(fd), C.TCSANOW, &cTermios)
	if ret != 0 {
		return err.(unix.Errno)
	}

	return nil
}
<commit_msg>Revert "shared/termios: manually copy termios settings between Go and C"<commit_after>//go:build !windows
// +build !windows

package termios

import (
	"unsafe"

	"golang.org/x/sys/unix"

	"github.com/lxc/lxd/shared"
)

// #include <termios.h>
import "C"

// State contains the state of a terminal.
type State struct {
	Termios unix.Termios
}

// IsTerminal returns true if the given file descriptor is a terminal.
func IsTerminal(fd int) bool {
	_, err := GetState(fd)
	return err == nil
}

// GetState returns the current state of a terminal which may be useful to restore the terminal after a signal.
func GetState(fd int) (*State, error) {
	termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios)
	if err != nil {
		return nil, err
	}

	state := State{}
	state.Termios = *termios

	return &state, nil
}

// GetSize returns the dimensions of the given terminal.
func GetSize(fd int) (int, int, error) {
	winsize, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
	if err != nil {
		return -1, -1, err
	}

	return int(winsize.Col), int(winsize.Row), nil
}

// MakeRaw put the terminal connected to the given file descriptor into raw mode and returns the previous state of the terminal so that it can be restored.
func MakeRaw(fd int) (*State, error) {
	var err error
	var oldState, newState *State

	oldState, err = GetState(fd)
	if err != nil {
		return nil, err
	}

	err = shared.DeepCopy(&oldState, &newState)
	if err != nil {
		return nil, err
	}

	C.cfmakeraw((*C.struct_termios)(unsafe.Pointer(&newState.Termios)))

	err = Restore(fd, newState)
	if err != nil {
		return nil, err
	}

	return oldState, nil
}

// Restore restores the terminal connected to the given file descriptor to a previous state.
func Restore(fd int, state *State) error {
	ret, err := C.tcsetattr(C.int(fd), C.TCSANOW, (*C.struct_termios)(unsafe.Pointer(&state.Termios)))
	if ret != 0 {
		return err.(unix.Errno)
	}

	return nil
}
<|endoftext|>


<commit_before>package fabric

import (
	"time"

	"github.com/starkandwayne/shield/core/scheduler"
	"github.com/starkandwayne/shield/core/vault"
	"github.com/starkandwayne/shield/db"
)

func Dummy(delay int) DummyFabric {
	return DummyFabric{
		delay: delay,
	}
}

type DummyFabric struct {
	delay int
}

func (f DummyFabric) Sleep() {
	if f.delay > 0 {
		time.Sleep(time.Duration(f.delay) * time.Second)
	}
}

func (f DummyFabric) Backup(task *db.Task, encryption vault.Parameters) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting a backup operation; delay is %ds", f.delay)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   target plugin:   '%s'", task.TargetPlugin)
			chore.Errorf("DUMMY>   target endpoint: '%s'", task.TargetEndpoint)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   store plugin:    '%s'", task.StorePlugin)
			chore.Errorf("DUMMY>   store endpoint:  '%s'", task.StoreEndpoint)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   compression:     '%s'", task.Compression)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   encryption type: '%s'", encryption.Type)
			chore.Errorf("DUMMY>   encryption key:  '%s'", encryption.Key)
			chore.Errorf("DUMMY>   encryption iv:   '%s'", encryption.IV)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> backup operation complete.")
			chore.UnixExit(0)
			return
		})
}

func (f DummyFabric) Restore(task *db.Task, encryption vault.Parameters) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting a restore operation; delay is %ds", f.delay)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   restore key:     '%s'", task.RestoreKey)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   target plugin:   '%s'", task.TargetPlugin)
			chore.Errorf("DUMMY>   target endpoint: '%s'", task.TargetEndpoint)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   store plugin:    '%s'", task.StorePlugin)
			chore.Errorf("DUMMY>   store endpoint:  '%s'", task.StoreEndpoint)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   compression:     '%s'", task.Compression)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   encryption type: '%s'", encryption.Type)
			chore.Errorf("DUMMY>   encryption key:  '%s'", encryption.Key)
			chore.Errorf("DUMMY>   encryption iv:   '%s'", encryption.IV)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> restore operation complete.")
			chore.UnixExit(0)
			return
		})
}

func (f DummyFabric) Status(task *db.Task) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting an agent-status operation; delay is %ds", f.delay)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> (there is no status; this is a test/dev fabric...")
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> agent-status operation complete.")
			chore.UnixExit(0)
			return
		})
}

func (f DummyFabric) Purge(task *db.Task) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting an archive purge operation; delay is %ds", f.delay)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   archive key:     '%s'", task.RestoreKey)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   store plugin:    '%s'", task.StorePlugin)
			chore.Errorf("DUMMY>   store endpoint:  '%s'", task.StoreEndpoint)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> archive purge operation complete.")
			chore.UnixExit(0)
			return
		})
}

func (f DummyFabric) TestStore(task *db.Task) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting storage test operation; delay is %ds", f.delay)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   store plugin:    '%s'", task.StorePlugin)
			chore.Errorf("DUMMY>   store endpoint:  '%s'", task.StoreEndpoint)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> storage test operation complete.")
			chore.UnixExit(0)
			return
		})
}
<commit_msg>Provide backup op details in Dummy Fabric<commit_after>package fabric

import (
	"time"

	"github.com/starkandwayne/shield/core/scheduler"
	"github.com/starkandwayne/shield/core/vault"
	"github.com/starkandwayne/shield/db"
)

func Dummy(delay int) DummyFabric {
	return DummyFabric{
		delay: delay,
	}
}

type DummyFabric struct {
	delay int
}

func (f DummyFabric) Sleep() {
	if f.delay > 0 {
		time.Sleep(time.Duration(f.delay) * time.Second)
	}
}

func (f DummyFabric) Backup(task *db.Task, encryption vault.Parameters) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting a backup operation; delay is %ds", f.delay)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   target plugin:   '%s'", task.TargetPlugin)
			chore.Errorf("DUMMY>   target endpoint: '%s'", task.TargetEndpoint)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   store plugin:    '%s'", task.StorePlugin)
			chore.Errorf("DUMMY>   store endpoint:  '%s'", task.StoreEndpoint)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   compression:     '%s'", task.Compression)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   encryption type: '%s'", encryption.Type)
			chore.Errorf("DUMMY>   encryption key:  '%s'", encryption.Key)
			chore.Errorf("DUMMY>   encryption iv:   '%s'", encryption.IV)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> backup operation complete.")
			chore.Infof(`{"key":"%s","archive_size":1337,"compression":"%s"}`,
				time.Now().Format("2006/01/02/15/04/05/2006-01-02T1504.archive"),
				task.Compression)
			chore.UnixExit(0)
			return
		})
}

func (f DummyFabric) Restore(task *db.Task, encryption vault.Parameters) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting a restore operation; delay is %ds", f.delay)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   restore key:     '%s'", task.RestoreKey)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   target plugin:   '%s'", task.TargetPlugin)
			chore.Errorf("DUMMY>   target endpoint: '%s'", task.TargetEndpoint)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   store plugin:    '%s'", task.StorePlugin)
			chore.Errorf("DUMMY>   store endpoint:  '%s'", task.StoreEndpoint)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   compression:     '%s'", task.Compression)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   encryption type: '%s'", encryption.Type)
			chore.Errorf("DUMMY>   encryption key:  '%s'", encryption.Key)
			chore.Errorf("DUMMY>   encryption iv:   '%s'", encryption.IV)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> restore operation complete.")
			chore.UnixExit(0)
			return
		})
}

func (f DummyFabric) Status(task *db.Task) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting an agent-status operation; delay is %ds", f.delay)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> (there is no status; this is a test/dev fabric...")
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> agent-status operation complete.")
			chore.UnixExit(0)
			return
		})
}

func (f DummyFabric) Purge(task *db.Task) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting an archive purge operation; delay is %ds", f.delay)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   archive key:     '%s'", task.RestoreKey)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   store plugin:    '%s'", task.StorePlugin)
			chore.Errorf("DUMMY>   store endpoint:  '%s'", task.StoreEndpoint)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> archive purge operation complete.")
			chore.UnixExit(0)
			return
		})
}

func (f DummyFabric) TestStore(task *db.Task) scheduler.Chore {
	return scheduler.NewChore(
		task.UUID,
		func(chore scheduler.Chore) {
			chore.Errorf("DUMMY> starting storage test operation; delay is %ds", f.delay)
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY>   store plugin:    '%s'", task.StorePlugin)
			chore.Errorf("DUMMY>   store endpoint:  '%s'", task.StoreEndpoint)
			f.Sleep()
			chore.Errorf("DUMMY>")
			chore.Errorf("DUMMY> storage test operation complete.")
			chore.UnixExit(0)
			return
		})
}
<|endoftext|>


<commit_before>package types

import "fmt"

// ErrIdentityNotFound indicates a non-existing identity
var ErrIdentityNotFound = fmt.Errorf("identity not found")

// ErrIdentityAlreadyExists indicates existence of an identity
var ErrIdentityAlreadyExists = fmt.Errorf("An identity with matching email already exists")

// ErrLedgerNotFound indicates a missing ledger
var ErrLedgerNotFound = fmt.Errorf("ledger not found")

// ErrTxNotFound indicates a missing transaction
var ErrTxNotFound = fmt.Errorf("transaction not found")

// ErrChainNotFound indicates a missing chain
var ErrChainNotFound = fmt.Errorf("chain not found")

// ErrZeroTransactions indicates a transaction list has zeto transactions
var ErrZeroTransactions = fmt.Errorf("zero transactions not allowed")
<commit_msg>Adds new error checker method for detecting error due to concurrent access of a previous block and attempts to use a previous block hash twice<commit_after>package types

import "fmt"
import "strings"

// ErrIdentityNotFound indicates a non-existing identity
var ErrIdentityNotFound = fmt.Errorf("identity not found")

// ErrIdentityAlreadyExists indicates existence of an identity
var ErrIdentityAlreadyExists = fmt.Errorf("An identity with matching email already exists")

// ErrLedgerNotFound indicates a missing ledger
var ErrLedgerNotFound = fmt.Errorf("ledger not found")

// ErrTxNotFound indicates a missing transaction
var ErrTxNotFound = fmt.Errorf("transaction not found")

// ErrChainNotFound indicates a missing chain
var ErrChainNotFound = fmt.Errorf("chain not found")

// ErrZeroTransactions indicates a transaction list has zeto transactions
var ErrZeroTransactions = fmt.Errorf("zero transactions not allowed")

// IsPrevBlockConcurrentAccessError checks whether an error is one created when
// attempt is made to access a previous block that is currently being updated by a concurrent transaction.
func IsPrevBlockConcurrentAccessError(err error) bool {
	return err.Error() == "failed to update previous block right sibling column. pq: could not serialize access due to concurrent update"
}

// IsDuplicatePrevHashError checks whether an error is one created when a transaction attempts to
// create a record with a prev hash value already used by a previous commited transaction.
func IsDuplicatePrevHashError(err error) bool {
	return strings.Contains(err.Error(), `pq: duplicate key value violates unique constraint "idx_name_prev_hash"`)
}
<|endoftext|>


<commit_before>package preloadlist

import (
	"io/ioutil"
	"os"
	"reflect"
	"testing"
)

func TestIndexing(t *testing.T) {
	list := PreloadList{
		Entries: []Entry{
			{
				Name:              "garron.NET",
				Mode:              "ForceHTTPS",
				IncludeSubDomains: true,
			},
			{
				Name:              "example.com",
				Mode:              "",
				IncludeSubDomains: false,
			},
			{
				Name:              "bar",
				Mode:              "ForceHTTPS",
				IncludeSubDomains: true,
			},
		},
	}

	idx := list.Index()

	if len(idx.index) != 3 {
		t.Errorf("Map has the wrong number of entries.")
	}

	_, ok := idx.Get("example")
	if ok != NotFound {
		t.Errorf("Entry should not be present.")
	}

	entry, ok := idx.Get("GARRON.net")
	if ok != ExactEntryFound {
		t.Errorf("Entry should be present.")
	}
	if entry.Mode != "ForceHTTPS" {
		t.Errorf("Map has invalid entry.")
	}

	entry, ok = idx.Get("www.garron.net")
	if ok != AncestorEntryFound {
		t.Errorf("Ancestor entry should be present.")
	}
	if entry.Name != "garron.NET" {
		t.Errorf("Wrong ancestor entry found.")
	}
	if !entry.IncludeSubDomains {
		t.Errorf("Ancestor entry does not include subdomains.")
	}

	entry, ok = idx.Get("test.example.com")
	if ok == AncestorEntryFound {
		t.Errorf("Ancestor found, but it does not include subdomains.")
	}

	entry, ok = idx.Get("foo.bar")
	if ok != AncestorEntryFound {
		t.Errorf("Ancestor entry should be present.")
	}
	if entry.Name != "bar" || entry.Mode != "ForceHTTPS" {
		t.Errorf("Wrong ancestor entry found.")
	}
	if !entry.IncludeSubDomains {
		t.Errorf("Ancestor entry does not include subdomains.")
	}

	entry, ok = idx.Get("bar")
	if ok != ExactEntryFound {
		t.Errorf("Entry should be present.")
	}
	if entry.Name != "bar" || entry.Mode != "ForceHTTPS" || !entry.IncludeSubDomains {
		t.Errorf("Wrong entry entry found.")
	}
}

func TestNewFromLatest(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping test to avoid preload list download.")
	}

	list, err := NewFromLatest()
	if err != nil {
		t.Errorf("Could not retrieve preload list.")
	}

	firstEntry := list.Entries[0]
	if firstEntry.Name != "pinningtest.appspot.com" {
		t.Errorf("First entry of preload list does not have the expected name.")
	}
}

func TestNewFromChromiumURL(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping test to avoid preload list download.")
	}

	list, err := NewFromChromiumURL("https://chromium.googlesource.com/chromium/src/+/4f587d7d4532287308715d824d19e7465c9f663e/net/http/transport_security_state_static.json?format=TEXT")
	if err != nil {
		t.Error(err)
	}
	if len(list.Entries) != 3558 {
		t.Errorf("Wrong number of entries: %d", len(list.Entries))
	}
}

var (
	testJSON = `{
  "entries": [
  	// This is a comment.
    {"name": "garron.net", "include_subdomains": true, "mode": "force-https"},
    {"name": "example.com", "include_subdomains": false, "mode": "force-https"},
    {"name": "gmail.com", "mode": "force-https"},

    // Line above intentionally left blank.
    {"name": "google.com"},
    {"name": "pinned.badssl.com", "pins": "pinnymcpinnedkey"}
  ]
}`
	testParsed = PreloadList{Entries: []Entry{
		{"garron.net", "force-https", true},
		{"example.com", "force-https", false},
		{"gmail.com", "force-https", false},
		{"google.com", "", false},
		{"pinned.badssl.com", "", false}},
	}
)

func TestNewFromFile(t *testing.T) {
	f, err := ioutil.TempFile("", "preloadlist-test")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(f.Name())

	if _, err := f.Write([]byte(testJSON)); err != nil {
		t.Fatal(err)
	}

	list, err := NewFromFile(f.Name())
	if err != nil {
		t.Fatalf("Could not read preload list. %s", err)
	}

	if !reflect.DeepEqual(list, testParsed) {
		t.Errorf("Parsed list does not match expected. %#v", list)
	}
}
<commit_msg>Fix typos<commit_after>package preloadlist

import (
	"io/ioutil"
	"os"
	"reflect"
	"testing"
)

func TestIndexing(t *testing.T) {
	list := PreloadList{
		Entries: []Entry{
			{
				Name:              "garron.NET",
				Mode:              "ForceHTTPS",
				IncludeSubDomains: true,
			},
			{
				Name:              "example.com",
				Mode:              "",
				IncludeSubDomains: false,
			},
			{
				Name:              "bar",
				Mode:              "ForceHTTPS",
				IncludeSubDomains: true,
			},
		},
	}

	idx := list.Index()

	if len(idx.index) != 3 {
		t.Errorf("Map has the wrong number of entries.")
	}

	_, ok := idx.Get("example")
	if ok != NotFound {
		t.Errorf("Entry should not be present.")
	}

	entry, ok := idx.Get("GARRON.net")
	if ok != ExactEntryFound {
		t.Errorf("Entry should be present.")
	}
	if entry.Mode != "ForceHTTPS" {
		t.Errorf("Map has invalid entry.")
	}

	entry, ok = idx.Get("www.garron.net")
	if ok != AncestorEntryFound {
		t.Errorf("Ancestor entry should be present.")
	}
	if entry.Name != "garron.NET" {
		t.Errorf("Wrong ancestor entry found.")
	}
	if !entry.IncludeSubDomains {
		t.Errorf("Ancestor entry does not include subdomains.")
	}

	entry, ok = idx.Get("test.example.com")
	if ok == AncestorEntryFound {
		t.Errorf("Ancestor entry found, but it does not include subdomains.")
	}

	entry, ok = idx.Get("foo.bar")
	if ok != AncestorEntryFound {
		t.Errorf("Ancestor entry should be present.")
	}
	if entry.Name != "bar" || entry.Mode != "ForceHTTPS" {
		t.Errorf("Wrong ancestor entry found.")
	}
	if !entry.IncludeSubDomains {
		t.Errorf("Ancestor entry does not include subdomains.")
	}

	entry, ok = idx.Get("bar")
	if ok != ExactEntryFound {
		t.Errorf("Entry should be present.")
	}
	if entry.Name != "bar" || entry.Mode != "ForceHTTPS" || !entry.IncludeSubDomains {
		t.Errorf("Wrong entry found.")
	}
}

func TestNewFromLatest(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping test to avoid preload list download.")
	}

	list, err := NewFromLatest()
	if err != nil {
		t.Errorf("Could not retrieve preload list.")
	}

	firstEntry := list.Entries[0]
	if firstEntry.Name != "pinningtest.appspot.com" {
		t.Errorf("First entry of preload list does not have the expected name.")
	}
}

func TestNewFromChromiumURL(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping test to avoid preload list download.")
	}

	list, err := NewFromChromiumURL("https://chromium.googlesource.com/chromium/src/+/4f587d7d4532287308715d824d19e7465c9f663e/net/http/transport_security_state_static.json?format=TEXT")
	if err != nil {
		t.Error(err)
	}
	if len(list.Entries) != 3558 {
		t.Errorf("Wrong number of entries: %d", len(list.Entries))
	}
}

var (
	testJSON = `{
  "entries": [
  	// This is a comment.
    {"name": "garron.net", "include_subdomains": true, "mode": "force-https"},
    {"name": "example.com", "include_subdomains": false, "mode": "force-https"},
    {"name": "gmail.com", "mode": "force-https"},

    // Line above intentionally left blank.
    {"name": "google.com"},
    {"name": "pinned.badssl.com", "pins": "pinnymcpinnedkey"}
  ]
}`
	testParsed = PreloadList{Entries: []Entry{
		{"garron.net", "force-https", true},
		{"example.com", "force-https", false},
		{"gmail.com", "force-https", false},
		{"google.com", "", false},
		{"pinned.badssl.com", "", false}},
	}
)

func TestNewFromFile(t *testing.T) {
	f, err := ioutil.TempFile("", "preloadlist-test")
	if err != nil {
		t.Fatal(err)
	}
	defer os.Remove(f.Name())

	if _, err := f.Write([]byte(testJSON)); err != nil {
		t.Fatal(err)
	}

	list, err := NewFromFile(f.Name())
	if err != nil {
		t.Fatalf("Could not read preload list. %s", err)
	}

	if !reflect.DeepEqual(list, testParsed) {
		t.Errorf("Parsed list does not match expected. %#v", list)
	}
}
<|endoftext|>


<commit_before>/*
  This package is a wrapper for Martin Shepherd's, libtecla, command-line
  editing library (www.astro.caltech.edu/~mcs/tecla/).

  The latest version of libtecla may be obtained from:

      www.astro.caltech.edu/~mcs/tecla/libtecla.tar.gz

  This package is released under an MIT-style license. See LICENSE for details.
*/
package tecla

/*
#include <ctype.h>
#include <stdlib.h>

#include <libtecla.h>

static CPL_MATCH_FN(complete) {
    const char* start = line;
    int size = word_end;

    while(*start && size--) {
        if (isspace(*start++))
            continue;

        if (line[word_end] && !isspace(line[word_end]))
            return 0;

		return cpl_file_completions(cpl, NULL, line, word_end);
    }

    cpl_add_completion(cpl, line, word_end, word_end, "    ", NULL, NULL);

    return 0;
}

static GetLine* init(void) {
    GetLine* reader = new_GetLine(1024, 16384);

    gl_ignore_signal(reader, SIGINT);

    gl_customize_completion(reader, NULL, complete);

    return reader;
}

#cgo LDFLAGS:-ltecla
#cgo freebsd LDFLAGS:-lcurses
#cgo linux LDFLAGS:-lncurses
*/
import "C"
import "errors"
import "unsafe"

type Tecla struct {
	creader *C.GetLine
	cprompt *C.char
	prompts map[string]*C.char
}

func New(prompt string) *Tecla {
	prompts := make(map[string]*C.char)

	return &Tecla{C.init(), intern(prompts, prompt), prompts}
}

func (self *Tecla) ChangePrompt(prompt string) {
	self.cprompt = intern(self.prompts, prompt)
}

func (self *Tecla) ReadString(delim byte) (line string, err error) {
	var null *C.char

	cline := C.gl_get_line(self.creader, self.cprompt, null, 0)

	if cline == nil && C.gl_return_status(self.creader) == C.GLR_EOF {
		for k, v := range self.prompts {
			C.free(unsafe.Pointer(v))
			self.prompts[k] = null
		}

		self.cprompt = null
		self.creader = C.del_GetLine(self.creader)

		return "", errors.New("EOF")
	}

	return C.GoString(cline), nil
}

func intern(prompts map[string]*C.char, prompt string) *C.char {
	cprompt, ok := prompts[prompt]
	if !ok {
		cprompt = C.CString(prompt)
		prompts[prompt] = cprompt
	}

	return cprompt
}
<commit_msg>Added LDFLAGS for darwin.<commit_after>/*
  This package is a wrapper for Martin Shepherd's, libtecla, command-line
  editing library (www.astro.caltech.edu/~mcs/tecla/).

  The latest version of libtecla may be obtained from:

      www.astro.caltech.edu/~mcs/tecla/libtecla.tar.gz

  This package is released under an MIT-style license. See LICENSE for details.
*/
package tecla

/*
#include <ctype.h>
#include <stdlib.h>

#include <libtecla.h>

static CPL_MATCH_FN(complete) {
    const char* start = line;
    int size = word_end;

    while(*start && size--) {
        if (isspace(*start++))
            continue;

        if (line[word_end] && !isspace(line[word_end]))
            return 0;

		return cpl_file_completions(cpl, NULL, line, word_end);
    }

    cpl_add_completion(cpl, line, word_end, word_end, "    ", NULL, NULL);

    return 0;
}

static GetLine* init(void) {
    GetLine* reader = new_GetLine(1024, 16384);

    gl_ignore_signal(reader, SIGINT);

    gl_customize_completion(reader, NULL, complete);

    return reader;
}

#cgo LDFLAGS:-ltecla
#cgo darwin LDFLAGS:-lncurses
#cgo freebsd LDFLAGS:-lcurses
#cgo linux LDFLAGS:-lncurses
*/
import "C"
import "errors"
import "unsafe"

type Tecla struct {
	creader *C.GetLine
	cprompt *C.char
	prompts map[string]*C.char
}

func New(prompt string) *Tecla {
	prompts := make(map[string]*C.char)

	return &Tecla{C.init(), intern(prompts, prompt), prompts}
}

func (self *Tecla) ChangePrompt(prompt string) {
	self.cprompt = intern(self.prompts, prompt)
}

func (self *Tecla) ReadString(delim byte) (line string, err error) {
	var null *C.char

	cline := C.gl_get_line(self.creader, self.cprompt, null, 0)

	if cline == nil && C.gl_return_status(self.creader) == C.GLR_EOF {
		for k, v := range self.prompts {
			C.free(unsafe.Pointer(v))
			self.prompts[k] = null
		}

		self.cprompt = null
		self.creader = C.del_GetLine(self.creader)

		return "", errors.New("EOF")
	}

	return C.GoString(cline), nil
}

func intern(prompts map[string]*C.char, prompt string) *C.char {
	cprompt, ok := prompts[prompt]
	if !ok {
		cprompt = C.CString(prompt)
		prompts[prompt] = cprompt
	}

	return cprompt
}
<|endoftext|>