<commit_before>package main

import (
	"fmt"
	"github.com/miekg/dns"
	"net"
	"sort"
	"strings"
)

type MXCheck struct {
	NS []NSData
	MX []MXData
	Report
}

type MXData struct {
	Name  string
	IP    string
	MX    []dns.RR
	MXIP  map[string][]net.IP
	Error string
}

func (c *MXCheck) Scan(domain string) {
	for _, ns := range c.NS {
		for _, nsip := range ns.IP {
			data := MXData{Name: ns.Name, IP: nsip.String(), MXIP: make(map[string][]net.IP)}
			mx, _, err := queryRRset(domain, dns.TypeMX, nsip.String(), true)
			if err != nil {
				data.Error = fmt.Sprintf("MX check failed on %s: %s", nsip.String(), err)
				c.MX = append(c.MX, data)
				break
			}
			if len(mx) == 0 {
				data.Error = fmt.Sprintf("MX check failed on %s: %s", nsip.String(), "no records found")
				c.MX = append(c.MX, data)
				break
			}
			data.MX = mx
			// TODO only lookup once
			for _, mx := range data.MX {
				data.MXIP[mx.(*dns.MX).Mx] = append(data.MXIP[mx.(*dns.MX).Mx], getIP(mx.(*dns.MX).Mx, dns.TypeA, resolver)...)
				data.MXIP[mx.(*dns.MX).Mx] = append(data.MXIP[mx.(*dns.MX).Mx], getIP(mx.(*dns.MX).Mx, dns.TypeAAAA, resolver)...)
			}
			c.MX = append(c.MX, data)
		}
	}
}

func (c *MXCheck) Identical() ReportResult {
	m := make(map[string][]string)
	for _, ns := range c.MX {
		mxstr := []string{}
		if ns.MX != nil {
			for _, mx := range ns.MX {
				mxstr = append(mxstr, mx.String()+"\n\t ")
			}
			sort.Strings(mxstr)
			m[strings.Join(mxstr, "")] = append(m[strings.Join(mxstr, "")], ns.IP)
		}
	}
	res := ReportResult{}
	if len(m) > 1 {
		res.Result = fmt.Sprintf("FAIL: MX not identical\n")
		res.Status = false
		for k, v := range m {
			res.Result += fmt.Sprintf("\t %s\n\t %s\n", v, k)
		}
	} else {
		res.Result = "OK  : MX of all nameservers are identical"
		res.Status = true
	}
	return res
}

func (c *MXCheck) checkRFC1918() bool {
	for _, mx := range c.MX {
		if len(mx.MXIP) > 0 {
			for _, ips := range mx.MXIP {
				for _, ip := range ips {
					if isRFC1918(ip) {
						return true
					}
				}
			}
		}
	}
	return false
}

func (c *MXCheck) checkDuplicateIP() map[string][]string {
	m := make(map[string][]string)
	for _, mx := range c.MX {
		if len(mx.MXIP) > 0 {
			for name, ips := range mx.MXIP {
				for _, ip := range ips {
					m[ip.String()] = append(m[ip.String()], name)
				}
			}
			break
		}
	}
	return m
}

func (c *MXCheck) Values() []ReportResult {
	var results []ReportResult
	var rrset []dns.RR
	for _, ns := range c.MX {
		if ns.MX != nil {
			rrset = ns.MX
			break
		}
	}
	if len(rrset) > 1 {
		records := []string{}
		for _, rr := range rrset {
			records = append(records, rr.String())
		}
		results = append(results, ReportResult{Result: "OK  : Multiple MX records found",
			Status: true, Records: records})
	} else {
		results = append(results, ReportResult{Result: fmt.Sprintf("WARN: Only %v MX record found. Extra records increases reliability", len(rrset)),
			Status: false})
	}

	if !c.checkRFC1918() {
		results = append(results, ReportResult{Result: "OK  : Your MX records have public / routable addresses.",
			Status: true})
	} else {
		results = append(results, ReportResult{Result: "FAIL: Some of your MX records have non-routable (RFC1918) addresses.",
			Status: false})
	}

	m := c.checkDuplicateIP()
	duplicate := false
	for k, v := range m {
		if len(v) > 1 {
			results = append(results, ReportResult{Result: fmt.Sprintf("WARN: Same IP %s is used by multiple MX records %v.", k, v),
				Status: false})
			duplicate = true
		}
	}
	if !duplicate {
		results = append(results, ReportResult{Result: "OK  : Your MX records resolve to different ips.",
			Status: false})

	}
	//TODO
	// cname check
	// multiple subnets
	return results
}

func (c *MXCheck) CreateReport(domain string) {
	c.Scan(domain)
	c.Report.Type = "MX"
	c.Report.Result = append(c.Report.Result, c.Identical())
	c.Report.Result = append(c.Report.Result, c.Values()...)
}
<commit_msg>Add cname, reverse check (MXcheck)<commit_after>package main

import (
	"fmt"
	"github.com/miekg/dns"
	"net"
	"sort"
	"strings"
)

type MXCheck struct {
	NS []NSData
	MX []MXData
	Report
}

type MXData struct {
	Name  string
	IP    string
	MX    []dns.RR
	MXIP  map[string][]net.IP
	Error string
}

func (c *MXCheck) Scan(domain string) {
	for _, ns := range c.NS {
		for _, nsip := range ns.IP {
			data := MXData{Name: ns.Name, IP: nsip.String(), MXIP: make(map[string][]net.IP)}
			mx, _, err := queryRRset(domain, dns.TypeMX, nsip.String(), true)
			if err != nil {
				data.Error = fmt.Sprintf("MX check failed on %s: %s", nsip.String(), err)
				c.MX = append(c.MX, data)
				break
			}
			if len(mx) == 0 {
				data.Error = fmt.Sprintf("MX check failed on %s: %s", nsip.String(), "no records found")
				c.MX = append(c.MX, data)
				break
			}
			data.MX = mx
			// TODO only lookup once
			for _, mx := range data.MX {
				data.MXIP[mx.(*dns.MX).Mx] = append(data.MXIP[mx.(*dns.MX).Mx], getIP(mx.(*dns.MX).Mx, dns.TypeA, resolver)...)
				data.MXIP[mx.(*dns.MX).Mx] = append(data.MXIP[mx.(*dns.MX).Mx], getIP(mx.(*dns.MX).Mx, dns.TypeAAAA, resolver)...)
			}
			c.MX = append(c.MX, data)
		}
	}
}

func (c *MXCheck) Identical() ReportResult {
	m := make(map[string][]string)
	for _, ns := range c.MX {
		mxstr := []string{}
		if ns.MX != nil {
			for _, mx := range ns.MX {
				mxstr = append(mxstr, mx.String()+"\n\t ")
			}
			sort.Strings(mxstr)
			m[strings.Join(mxstr, "")] = append(m[strings.Join(mxstr, "")], ns.IP)
		}
	}
	res := ReportResult{}
	if len(m) > 1 {
		res.Result = fmt.Sprintf("FAIL: MX not identical\n")
		res.Status = false
		for k, v := range m {
			res.Result += fmt.Sprintf("\t %s\n\t %s\n", v, k)
		}
	} else {
		res.Result = "OK  : MX of all nameservers are identical"
		res.Status = true
	}
	return res
}

func (c *MXCheck) checkRFC1918() bool {
	for _, mx := range c.MX {
		if len(mx.MXIP) > 0 {
			for _, ips := range mx.MXIP {
				for _, ip := range ips {
					if isRFC1918(ip) {
						return true
					}
				}
			}
		}
	}
	return false
}

func (c *MXCheck) checkDuplicateIP() map[string][]string {
	m := make(map[string][]string)
	for _, mx := range c.MX {
		if len(mx.MXIP) > 0 {
			for name, ips := range mx.MXIP {
				for _, ip := range ips {
					m[ip.String()] = append(m[ip.String()], name)
				}
			}
			break
		}
	}
	return m
}

func (c *MXCheck) CheckCNAME() []ReportResult {
	rep := []ReportResult{}
	m := make(map[string]bool)
	for _, mx := range c.MX {
		if len(mx.MX) > 0 {
			for mxName := range mx.MXIP {
				// skip lookup if already done
				if _, ok := m[mxName]; ok {
					break
				}
				res, err := query(dns.Fqdn(mxName), dns.TypeA, resolver, true)
				if err != nil {
					break
				}
				cname := extractRR(res.Msg.Answer, dns.TypeCNAME)
				if len(cname) > 0 {
					rep = append(rep, ReportResult{Result: fmt.Sprintf("FAIL: Your MX (%s) is a CNAME.", mxName),
						Status: false})
				}
				res, err = query(dns.Fqdn(mxName), dns.TypeAAAA, resolver, true)
				if err != nil {
					break
				}
				cname = extractRR(res.Msg.Answer, dns.TypeCNAME)
				if len(cname) > 0 {
					rep = append(rep, ReportResult{Result: fmt.Sprintf("FAIL: Your MX (%s) is a CNAME.", mxName),
						Status: false})
				}
				m[mxName] = true
			}
		}
	}
	if len(rep) == 0 {
		rep = append(rep, ReportResult{Result: "OK  : No CNAMEs found for your MX records",
			Status: true})
	}
	return rep
}

func (c *MXCheck) CheckReverse() []ReportResult {
	rep := []ReportResult{}
	m := make(map[string]bool)
	for _, mx := range c.MX {
		if len(mx.MXIP) > 0 {
			for name, ips := range mx.MXIP {
				for _, ip := range ips {
					rev, _ := dns.ReverseAddr(ip.String())
					res, _, err := queryRRset(rev, dns.TypePTR, resolver, true)
					if err != nil {
						break
					}
					if len(res) > 0 {
						m[name] = true
					} else {
						m[name] = false
					}
				}
			}
			break
		}
	}
	for name, reverse := range m {
		if !reverse {
			rep = append(rep, ReportResult{Result: fmt.Sprintf("WARN: Reverse PTR lookup for MX %s failed.", name),
				Status: false})
		}
	}
	if len(rep) == 0 {
		rep = append(rep, ReportResult{Result: "OK  : All MX records have reverse PTR records",
			Status: true})
	}
	return rep
}

func (c *MXCheck) Values() []ReportResult {
	var results []ReportResult
	var rrset []dns.RR
	for _, ns := range c.MX {
		if ns.MX != nil {
			rrset = ns.MX
			break
		}
	}
	if len(rrset) > 1 {
		records := []string{}
		for _, rr := range rrset {
			records = append(records, rr.String())
		}
		results = append(results, ReportResult{Result: "OK  : Multiple MX records found",
			Status: true, Records: records})
	} else {
		results = append(results, ReportResult{Result: fmt.Sprintf("WARN: Only %v MX record found. Extra records increases reliability", len(rrset)),
			Status: false})
	}

	if !c.checkRFC1918() {
		results = append(results, ReportResult{Result: "OK  : Your MX records have public / routable addresses.",
			Status: true})
	} else {
		results = append(results, ReportResult{Result: "FAIL: Some of your MX records have non-routable (RFC1918) addresses.",
			Status: false})
	}

	m := c.checkDuplicateIP()
	duplicate := false
	for k, v := range m {
		if len(v) > 1 {
			results = append(results, ReportResult{Result: fmt.Sprintf("WARN: Same IP %s is used by multiple MX records %v.", k, v),
				Status: false})
			duplicate = true
		}
	}
	if !duplicate {
		results = append(results, ReportResult{Result: "OK  : Your MX records resolve to different ips.",
			Status: false})

	}
	//TODO
	// cname check
	// multiple subnets
	return results
}

func (c *MXCheck) CreateReport(domain string) {
	c.Scan(domain)
	c.Report.Type = "MX"
	c.Report.Result = append(c.Report.Result, c.Identical())
	c.Report.Result = append(c.Report.Result, c.Values()...)
	c.Report.Result = append(c.Report.Result, c.CheckCNAME()...)
	c.Report.Result = append(c.Report.Result, c.CheckReverse()...)
}
<|endoftext|>


<commit_before>// +build js

package tests

import (
	"testing"
)

func TestVariadicNil(t *testing.T) {
	printVari := func(strs ...string) []string {
		return strs
	}

	if v := printVari(); v != nil {
		t.Errorf("expected printVari() to be %v; got: %v", nil, v)
	}
}
<commit_msg>Address feedback<commit_after>package tests

import (
	"testing"
)

func TestVariadicNil(t *testing.T) {
	printVari := func(strs ...string) []string {
		return strs
	}

	if got := printVari(); got != nil {
		t.Errorf("expected printVari() to be %v; got: %v", nil, got)
	}
}
<|endoftext|>


<commit_before>package gocassa

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"

	"github.com/gocql/gocql"
	"github.com/google/btree"
)

// MockKeySpace implements the KeySpace interface and constructs in-memory tables.
type mockKeySpace struct {
	k
}

type mockOp struct {
	funcs []func() error
}

func newOp(f func() error) mockOp {
	return mockOp{
		funcs: []func() error{f},
	}
}

func (m mockOp) Add(ops ...Op) Op {
	for _, o := range ops {
		m.funcs = append(m.funcs, o.(*mockOp).funcs...)
	}
	return m
}

func (m mockOp) Run() error {
	for _, f := range m.funcs {
		err := f()
		if err != nil {
			return err
		}
	}
	return nil
}

func (m mockOp) RunAtomically() error {
	return m.Run()
}

func (ks *mockKeySpace) NewTable(name string, entity interface{}, fields map[string]interface{}, keys Keys) Table {
	return &MockTable{
		name:   name,
		entity: entity,
		keys:   keys,
		rows:   map[rowKey]*btree.BTree{},
	}
}

func NewMockKeySpace() KeySpace {
	ks := &mockKeySpace{}
	ks.tableFactory = ks
	return ks
}

// MockTable implements the Table interface and stores rows in-memory.
type MockTable struct {
	// rows is mapping from row key to column group key to column map
	name   string
	rows   map[rowKey]*btree.BTree
	entity interface{}
	keys   Keys
}

type rowKey string
type superColumn struct {
	Key     *keyPart
	Columns map[string]interface{}
}

func (c *superColumn) Less(item btree.Item) bool {
	other, ok := item.(*superColumn)
	if !ok {
		return false
	}

	return c.Key.Less(other.Key)
}

type keyPart struct {
	Key   string
	Value interface{}
	Tail  *keyPart
}

func (k *keyPart) Prepend(key string, value interface{}) *keyPart {
	return &keyPart{Key: key, Value: value, Tail: k}
}

func (k *keyPart) Less(other *keyPart) bool {
	for part, other := k, other; part != nil && other != nil; part, other = part.Tail, other.Tail {
		cmp := bytes.Compare(part.Bytes(), other.Bytes())
		if cmp == 0 {
			continue
		}
		return cmp < 0
	}

	return false
}

func (k *keyPart) Bytes() []byte {
	typeInfo := &gocql.TypeInfo{Type: cassaType(k.Value)}
	// FIXME handle err
	marshalled, _ := gocql.Marshal(typeInfo, k.Value)
	return marshalled
}

func (k *keyPart) RowKey() rowKey {
	buf := bytes.Buffer{}

	for part := k; part != nil; part = part.Tail {
		buf.Write(part.Bytes())
	}

	return rowKey(buf.String())
}

func (k *keyPart) ToSuperColumn() *superColumn {
	return &superColumn{Key: k}
}

func (t *MockTable) zero() interface{} {
	return reflect.New(reflect.TypeOf(t.entity)).Interface()
}

func (t *MockTable) keyFromColumnValues(columns map[string]interface{}, keys []string) (*keyPart, error) {
	var key *keyPart

	for _, column := range keys {
		value, ok := columns[column]

		if !ok {
			return nil, fmt.Errorf("Missing mandatory PRIMARY KEY part %s", column)
		}
		key = key.Prepend(column, value)
	}

	return key, nil
}

func (t *MockTable) Name() string {
	return t.name
}

func (t *MockTable) getOrCreateRow(rowKey *keyPart) *btree.BTree {
	row := t.rows[rowKey.RowKey()]
	if row == nil {
		row = btree.New(2)
		t.rows[rowKey.RowKey()] = row
	}
	return row
}

func (t *MockTable) getOrCreateColumnGroup(rowKey, superColumnKey *keyPart) map[string]interface{} {
	row := t.getOrCreateRow(rowKey)
	scol := superColumnKey.ToSuperColumn()

	if row.Has(scol) {
		return row.Get(scol).(*superColumn).Columns
	}
	row.ReplaceOrInsert(scol)
	scol.Columns = map[string]interface{}{}

	return scol.Columns
}

func (t *MockTable) SetWithOptions(i interface{}, options Options) Op {
	return newOp(func() error {
		columns, ok := toMap(i)
		if !ok {
			return errors.New("Can't create: value not understood")
		}

		rowKey, err := t.keyFromColumnValues(columns, t.keys.PartitionKeys)
		if err != nil {
			return err
		}

		superColumnKey, err := t.keyFromColumnValues(columns, t.keys.ClusteringColumns)
		if err != nil {
			return err
		}

		superColumn := t.getOrCreateColumnGroup(rowKey, superColumnKey)

		for k, v := range columns {
			superColumn[k] = v
		}
		return nil
	})
}

func (t *MockTable) Set(i interface{}) Op {
	return t.SetWithOptions(i, Options{})
}

func (t *MockTable) Where(relations ...Relation) Filter {
	return &MockFilter{
		table:     t,
		relations: relations,
	}
}

func (t *MockTable) Create() error {
	return nil
}

func (t *MockTable) CreateStatement() (string, error) {
	return "", nil
}

func (t *MockTable) Recreate() error {
	return nil
}

// MockFilter implements the Filter interface and works with MockTable.
type MockFilter struct {
	table     *MockTable
	relations []Relation
}

func (f *MockFilter) Query() Query {
	return &MockQuery{
		filter: f,
	}
}

func (f *MockFilter) rowMatch(row map[string]interface{}) bool {
	for _, relation := range f.relations {
		value := row[relation.key]
		if !relation.accept(value) {
			return false
		}
	}
	return true
}

func (f *MockFilter) keyRelationMap() map[string]Relation {
	result := map[string]Relation{}

	for _, relation := range f.relations {
		result[relation.key] = relation
	}

	return result
}

func (f *MockFilter) keysFromRelations(keys []string) ([]*keyPart, error) {
	keyRelationMap := f.keyRelationMap()
	var rowKey *keyPart
	var result []*keyPart

	for i, key := range keys {
		lastKey := i == len(keys)-1
		relation, ok := keyRelationMap[key]

		if !ok {
			return nil, fmt.Errorf("Missing mandatory PRIMARY KEY part %s", key)
		}

		if relation.op != equality && !(lastKey && relation.op == in) {
			return nil, fmt.Errorf("Invalid use of PK %s", key)
		}

		if !lastKey {
			rowKey = rowKey.Prepend(key, relation.terms[0])
		} else {
			for _, term := range relation.terms {
				result = append(result, rowKey.Prepend(relation.key, term))
			}
		}
	}

	return result, nil
}

func (f *MockFilter) UpdateWithOptions(m map[string]interface{}, options Options) Op {
	return newOp(func() error {
		rowKeys, err := f.keysFromRelations(f.table.keys.PartitionKeys)
		if err != nil {
			return err
		}

		for _, rowKey := range rowKeys {
			superColumnKeys, err := f.keysFromRelations(f.table.keys.ClusteringColumns)
			if err != nil {
				return err
			}

			for _, superColumnKey := range superColumnKeys {
				superColumn := f.table.getOrCreateColumnGroup(rowKey, superColumnKey)

				for _, keyPart := range []*keyPart{rowKey, superColumnKey} {
					for k := keyPart; k != nil; k = k.Tail {
						superColumn[k.Key] = k.Value
					}
				}

				for key, value := range m {
					superColumn[key] = value
				}
			}
		}

		return nil
	})
}

func (f *MockFilter) Update(m map[string]interface{}) Op {
	return f.UpdateWithOptions(m, Options{})
}

func (f *MockFilter) Delete() Op {
	return newOp(func() error {
		rowKeys, err := f.keysFromRelations(f.table.keys.PartitionKeys)
		if err != nil {
			return err
		}

		for _, rowKey := range rowKeys {
			row := f.table.rows[rowKey.RowKey()]
			if row == nil {
				return nil
			}

			superColumnKeys, err := f.keysFromRelations(f.table.keys.ClusteringColumns)
			if err != nil {
				return err
			}

			for _, superColumnKey := range superColumnKeys {
				row.Delete(superColumnKey.ToSuperColumn())
			}
		}

		return nil
	})
}

// MockQuery implements the Query interface and works with MockFilter.
type MockQuery struct {
	filter *MockFilter
	limit  int
}

func (q *MockQuery) Read(out interface{}) Op {
	return newOp(func() error {
		rowKeys, err := q.filter.keysFromRelations(q.filter.table.keys.PartitionKeys)
		if err != nil {
			return err
		}

		var result []map[string]interface{}
		for _, rowKey := range rowKeys {
			row := q.filter.table.rows[rowKey.RowKey()]
			if row == nil {
				continue
			}

			row.Ascend(func(item btree.Item) bool {
				columns := item.(*superColumn).Columns
				if q.filter.rowMatch(columns) {
					result = append(result, columns)
				}

				return true
			})
		}

		if q.limit > 0 {
			result = result[:q.limit]
		}

		return q.assignResult(result, out)
	})
}

func (q *MockQuery) assignResult(records interface{}, out interface{}) error {
	bytes, err := json.Marshal(records)
	if err != nil {
		return err
	}
	return json.Unmarshal(bytes, out)
}

func (q *MockQuery) ReadOne(out interface{}) Op {
	return newOp(func() error {
		slicePtrVal := reflect.New(reflect.SliceOf(reflect.ValueOf(out).Elem().Type()))

		err := q.Read(slicePtrVal.Interface()).Run()
		if err != nil {
			return err
		}

		sliceVal := slicePtrVal.Elem()
		if sliceVal.Len() < 1 {
			return fmt.Errorf("Not found")
		}
		q.assignResult(sliceVal.Index(0).Interface(), out)
		return nil
	})
}

func (q *MockQuery) Limit(limit int) Query {
	q.limit = limit
	return q
}
<commit_msg>Add protocol version in mock to fix panic.<commit_after>package gocassa

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"reflect"

	"github.com/gocql/gocql"
	"github.com/google/btree"
)

// MockKeySpace implements the KeySpace interface and constructs in-memory tables.
type mockKeySpace struct {
	k
}

type mockOp struct {
	funcs []func() error
}

func newOp(f func() error) mockOp {
	return mockOp{
		funcs: []func() error{f},
	}
}

func (m mockOp) Add(ops ...Op) Op {
	for _, o := range ops {
		m.funcs = append(m.funcs, o.(*mockOp).funcs...)
	}
	return m
}

func (m mockOp) Run() error {
	for _, f := range m.funcs {
		err := f()
		if err != nil {
			return err
		}
	}
	return nil
}

func (m mockOp) RunAtomically() error {
	return m.Run()
}

func (ks *mockKeySpace) NewTable(name string, entity interface{}, fields map[string]interface{}, keys Keys) Table {
	return &MockTable{
		name:   name,
		entity: entity,
		keys:   keys,
		rows:   map[rowKey]*btree.BTree{},
	}
}

func NewMockKeySpace() KeySpace {
	ks := &mockKeySpace{}
	ks.tableFactory = ks
	return ks
}

// MockTable implements the Table interface and stores rows in-memory.
type MockTable struct {
	// rows is mapping from row key to column group key to column map
	name   string
	rows   map[rowKey]*btree.BTree
	entity interface{}
	keys   Keys
}

type rowKey string
type superColumn struct {
	Key     *keyPart
	Columns map[string]interface{}
}

func (c *superColumn) Less(item btree.Item) bool {
	other, ok := item.(*superColumn)
	if !ok {
		return false
	}

	return c.Key.Less(other.Key)
}

type keyPart struct {
	Key   string
	Value interface{}
	Tail  *keyPart
}

func (k *keyPart) Prepend(key string, value interface{}) *keyPart {
	return &keyPart{Key: key, Value: value, Tail: k}
}

func (k *keyPart) Less(other *keyPart) bool {
	for part, other := k, other; part != nil && other != nil; part, other = part.Tail, other.Tail {
		cmp := bytes.Compare(part.Bytes(), other.Bytes())
		if cmp == 0 {
			continue
		}
		return cmp < 0
	}

	return false
}

func (k *keyPart) Bytes() []byte {
	typeInfo := &gocql.TypeInfo{
		Proto: 0x03,
		Type:  cassaType(k.Value),
	}
	// FIXME handle err
	marshalled, _ := gocql.Marshal(typeInfo, k.Value)
	return marshalled
}

func (k *keyPart) RowKey() rowKey {
	buf := bytes.Buffer{}

	for part := k; part != nil; part = part.Tail {
		buf.Write(part.Bytes())
	}

	return rowKey(buf.String())
}

func (k *keyPart) ToSuperColumn() *superColumn {
	return &superColumn{Key: k}
}

func (t *MockTable) zero() interface{} {
	return reflect.New(reflect.TypeOf(t.entity)).Interface()
}

func (t *MockTable) keyFromColumnValues(columns map[string]interface{}, keys []string) (*keyPart, error) {
	var key *keyPart

	for _, column := range keys {
		value, ok := columns[column]

		if !ok {
			return nil, fmt.Errorf("Missing mandatory PRIMARY KEY part %s", column)
		}
		key = key.Prepend(column, value)
	}

	return key, nil
}

func (t *MockTable) Name() string {
	return t.name
}

func (t *MockTable) getOrCreateRow(rowKey *keyPart) *btree.BTree {
	row := t.rows[rowKey.RowKey()]
	if row == nil {
		row = btree.New(2)
		t.rows[rowKey.RowKey()] = row
	}
	return row
}

func (t *MockTable) getOrCreateColumnGroup(rowKey, superColumnKey *keyPart) map[string]interface{} {
	row := t.getOrCreateRow(rowKey)
	scol := superColumnKey.ToSuperColumn()

	if row.Has(scol) {
		return row.Get(scol).(*superColumn).Columns
	}
	row.ReplaceOrInsert(scol)
	scol.Columns = map[string]interface{}{}

	return scol.Columns
}

func (t *MockTable) SetWithOptions(i interface{}, options Options) Op {
	return newOp(func() error {
		columns, ok := toMap(i)
		if !ok {
			return errors.New("Can't create: value not understood")
		}

		rowKey, err := t.keyFromColumnValues(columns, t.keys.PartitionKeys)
		if err != nil {
			return err
		}

		superColumnKey, err := t.keyFromColumnValues(columns, t.keys.ClusteringColumns)
		if err != nil {
			return err
		}

		superColumn := t.getOrCreateColumnGroup(rowKey, superColumnKey)

		for k, v := range columns {
			superColumn[k] = v
		}
		return nil
	})
}

func (t *MockTable) Set(i interface{}) Op {
	return t.SetWithOptions(i, Options{})
}

func (t *MockTable) Where(relations ...Relation) Filter {
	return &MockFilter{
		table:     t,
		relations: relations,
	}
}

func (t *MockTable) Create() error {
	return nil
}

func (t *MockTable) CreateStatement() (string, error) {
	return "", nil
}

func (t *MockTable) Recreate() error {
	return nil
}

// MockFilter implements the Filter interface and works with MockTable.
type MockFilter struct {
	table     *MockTable
	relations []Relation
}

func (f *MockFilter) Query() Query {
	return &MockQuery{
		filter: f,
	}
}

func (f *MockFilter) rowMatch(row map[string]interface{}) bool {
	for _, relation := range f.relations {
		value := row[relation.key]
		if !relation.accept(value) {
			return false
		}
	}
	return true
}

func (f *MockFilter) keyRelationMap() map[string]Relation {
	result := map[string]Relation{}

	for _, relation := range f.relations {
		result[relation.key] = relation
	}

	return result
}

func (f *MockFilter) keysFromRelations(keys []string) ([]*keyPart, error) {
	keyRelationMap := f.keyRelationMap()
	var rowKey *keyPart
	var result []*keyPart

	for i, key := range keys {
		lastKey := i == len(keys)-1
		relation, ok := keyRelationMap[key]

		if !ok {
			return nil, fmt.Errorf("Missing mandatory PRIMARY KEY part %s", key)
		}

		if relation.op != equality && !(lastKey && relation.op == in) {
			return nil, fmt.Errorf("Invalid use of PK %s", key)
		}

		if !lastKey {
			rowKey = rowKey.Prepend(key, relation.terms[0])
		} else {
			for _, term := range relation.terms {
				result = append(result, rowKey.Prepend(relation.key, term))
			}
		}
	}

	return result, nil
}

func (f *MockFilter) UpdateWithOptions(m map[string]interface{}, options Options) Op {
	return newOp(func() error {
		rowKeys, err := f.keysFromRelations(f.table.keys.PartitionKeys)
		if err != nil {
			return err
		}

		for _, rowKey := range rowKeys {
			superColumnKeys, err := f.keysFromRelations(f.table.keys.ClusteringColumns)
			if err != nil {
				return err
			}

			for _, superColumnKey := range superColumnKeys {
				superColumn := f.table.getOrCreateColumnGroup(rowKey, superColumnKey)

				for _, keyPart := range []*keyPart{rowKey, superColumnKey} {
					for k := keyPart; k != nil; k = k.Tail {
						superColumn[k.Key] = k.Value
					}
				}

				for key, value := range m {
					superColumn[key] = value
				}
			}
		}

		return nil
	})
}

func (f *MockFilter) Update(m map[string]interface{}) Op {
	return f.UpdateWithOptions(m, Options{})
}

func (f *MockFilter) Delete() Op {
	return newOp(func() error {
		rowKeys, err := f.keysFromRelations(f.table.keys.PartitionKeys)
		if err != nil {
			return err
		}

		for _, rowKey := range rowKeys {
			row := f.table.rows[rowKey.RowKey()]
			if row == nil {
				return nil
			}

			superColumnKeys, err := f.keysFromRelations(f.table.keys.ClusteringColumns)
			if err != nil {
				return err
			}

			for _, superColumnKey := range superColumnKeys {
				row.Delete(superColumnKey.ToSuperColumn())
			}
		}

		return nil
	})
}

// MockQuery implements the Query interface and works with MockFilter.
type MockQuery struct {
	filter *MockFilter
	limit  int
}

func (q *MockQuery) Read(out interface{}) Op {
	return newOp(func() error {
		rowKeys, err := q.filter.keysFromRelations(q.filter.table.keys.PartitionKeys)
		if err != nil {
			return err
		}

		var result []map[string]interface{}
		for _, rowKey := range rowKeys {
			row := q.filter.table.rows[rowKey.RowKey()]
			if row == nil {
				continue
			}

			row.Ascend(func(item btree.Item) bool {
				columns := item.(*superColumn).Columns
				if q.filter.rowMatch(columns) {
					result = append(result, columns)
				}

				return true
			})
		}

		if q.limit > 0 {
			result = result[:q.limit]
		}

		return q.assignResult(result, out)
	})
}

func (q *MockQuery) assignResult(records interface{}, out interface{}) error {
	bytes, err := json.Marshal(records)
	if err != nil {
		return err
	}
	return json.Unmarshal(bytes, out)
}

func (q *MockQuery) ReadOne(out interface{}) Op {
	return newOp(func() error {
		slicePtrVal := reflect.New(reflect.SliceOf(reflect.ValueOf(out).Elem().Type()))

		err := q.Read(slicePtrVal.Interface()).Run()
		if err != nil {
			return err
		}

		sliceVal := slicePtrVal.Elem()
		if sliceVal.Len() < 1 {
			return fmt.Errorf("Not found")
		}
		q.assignResult(sliceVal.Index(0).Interface(), out)
		return nil
	})
}

func (q *MockQuery) Limit(limit int) Query {
	q.limit = limit
	return q
}
<|endoftext|>


<commit_before>package RiverFS

import (
	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	//"github.com/goraft/raft"
	"os"
	"sync"
)

type RootDir struct {
	Dir *Dir
}

func NewRootDir() (r *RootDir) {
	r = &RootDir{Dir: NewDir()}
	return
}

func (nf *RootDir) Root() (fs.Node, fuse.Error) {
	return nf.Dir, nil
}

type Node struct {
	Name string
	Mode os.FileMode
}

func (n *Node) Attr() fuse.Attr {
	return fuse.Attr{Mode: n.Mode}
}

func (n *Node) Setattr(req *fuse.SetattrRequest, resp *fuse.SetattrResponse, intr fs.Intr) fuse.Error {
	n.Mode = req.Mode
	return nil
}

type Dir struct {
	Node
	rwmut    sync.RWMutex
	Children map[string]fs.Node
}

func NewDir() (d *Dir) {
	d = &Dir{}
	d.Node = Node{}
	d.Mode = os.ModeDir
	d.Children = make(map[string]fs.Node)
	return
}

func (d *Dir) Add(name string, n fs.Node) {
	//TODO: consensous
	//TODO: Check if exists and error
	d.rwmut.Lock()
	d.Children[name] = n
	d.rwmut.Unlock()

}

func (d *Dir) Rm(name string) {
	//TODO: consensous
	//TODO: Check if exists and error
	//TODO: clean up disk space
	d.rwmut.Lock()
	delete(d.Children, name)
	d.rwmut.Unlock()

}

func (d *Dir) Mkdir(req *fuse.MkdirRequest, intr fs.Intr) (n fs.Node, ferr fuse.Error) {
	ndir := NewDir()
	ndir.Name = req.Name
	ndir.Mode = req.Mode
	d.Add(req.Name, ndir)
	return ndir, nil

}

func (d *Dir) Remove(req *fuse.RemoveRequest, intr fs.Intr) fuse.Error {
	d.Rm(req.Name)
	return nil
}

func (d *Dir) Rename(req *fuse.RenameRequest, newDir fs.Node, intr fs.Intr) fuse.Error {

	d.rwmut.RLock()
	node, ok := d.Children[req.OldName]
	d.rwmut.RUnlock()
	if !ok {
		return fuse.ENOENT
	}
	d.Rm(req.OldName)

	switch node.(type) {
	case *Dir:
		node.(*Dir).Name = req.NewName
	case *File:
		node.(*File).Name = req.NewName
	}

	newDir.(*Dir).Add(req.NewName, node)

	return nil

}

func (d *Dir) Create(req *fuse.CreateRequest, resp *fuse.CreateResponse, intr fs.Intr) (fs.Node, fs.Handle, fuse.Error) {

	n := &File{}
	n.Mode = req.Mode
	n.Name = req.Name
	d.Add(req.Name, n)
	return n, n, nil
}

// func (d *Dir) Mknod(req *fuse.MknodRequest, intr fs.Intr) (n fs.Node, ferr fuse.Error) {
// 	switch {
// 	case req.Mode.IsDir():
// 		n = NewDir()
// 	case req.Mode.IsRegular():
// 		n = &File{}
// 	default:
// 		return n, fuse.ENOSYS
// 	}
// 	n.(*Node).Mode = req.Mode
// 	n.(*Node).Name = req.Name
// 	d.Add(req.Name, n)
// 	return
// }

func (d *Dir) Lookup(name string, intr fs.Intr) (fs fs.Node, err fuse.Error) {
	d.rwmut.RLock()
	fs, ok := d.Children[name]
	d.rwmut.RUnlock()
	if !ok {
		return nil, fuse.ENOENT
	}

	return
}

func (d *Dir) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
	var out []fuse.Dirent

	d.rwmut.RLock()
	for name, node := range d.Children {
		de := fuse.Dirent{Name: name}
		switch node.(type) {
		case *Dir:
			de.Type = fuse.DT_Dir
		case *File:
			de.Type = fuse.DT_Dir
		}
		out = append(out, de)
	}
	d.rwmut.RUnlock()

	return out, nil
}

type File struct {
	Node
}

func (f *File) ReadAll(intr fs.Intr) (out []byte, ferr fuse.Error) {
	//Place holder code
	return []byte("I AM A FILE!!!!11!!!\n"), ferr
}

func (f *File) WriteAll(in []byte, intr fs.Intr) fuse.Error {
	return nil
}
<commit_msg>all needed fs stuff except file io working via fuse<commit_after>package RiverFS

import (
	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	//"github.com/goraft/raft"
	"os"
	"sync"
)

type RootDir struct {
	Dir *Dir
}

func NewRootDir() (r *RootDir) {
	r = &RootDir{Dir: NewDir()}
	return
}

func (nf *RootDir) Root() (fs.Node, fuse.Error) {
	return nf.Dir, nil
}

type Node struct {
	Name string
	Mode os.FileMode
}

func (n *Node) Attr() fuse.Attr {
	return fuse.Attr{Mode: n.Mode}
}

func (n *Node) Setattr(req *fuse.SetattrRequest, resp *fuse.SetattrResponse, intr fs.Intr) fuse.Error {
	n.Mode = req.Mode
	return nil
}

type Dir struct {
	Node
	rwmut    sync.RWMutex
	Children map[string]fs.Node
}

func NewDir() (d *Dir) {
	d = &Dir{}
	d.Node = Node{}
	d.Mode = os.ModeDir
	d.Children = make(map[string]fs.Node)
	return
}

func (d *Dir) Add(name string, n fs.Node) {
	//TODO: consensous
	//TODO: Check if exists and error
	d.rwmut.Lock()
	d.Children[name] = n
	d.rwmut.Unlock()

}

func (d *Dir) Rm(name string) {
	//TODO: consensous
	//TODO: Check if exists and error
	//TODO: clean up disk space
	d.rwmut.Lock()
	delete(d.Children, name)
	d.rwmut.Unlock()

}

func (d *Dir) Mkdir(req *fuse.MkdirRequest, intr fs.Intr) (n fs.Node, ferr fuse.Error) {
	ndir := NewDir()
	ndir.Name = req.Name
	ndir.Mode = req.Mode
	d.Add(req.Name, ndir)
	return ndir, nil

}

func (d *Dir) Remove(req *fuse.RemoveRequest, intr fs.Intr) fuse.Error {
	d.Rm(req.Name)
	return nil
}

func (d *Dir) Rename(req *fuse.RenameRequest, newDir fs.Node, intr fs.Intr) fuse.Error {

	d.rwmut.RLock()
	node, ok := d.Children[req.OldName]
	d.rwmut.RUnlock()
	if !ok {
		return fuse.ENOENT
	}
	d.Rm(req.OldName)

	switch node.(type) {
	case *Dir:
		node.(*Dir).Name = req.NewName
	case *File:
		node.(*File).Name = req.NewName
	}

	newDir.(*Dir).Add(req.NewName, node)

	return nil

}

func (d *Dir) Create(req *fuse.CreateRequest, resp *fuse.CreateResponse, intr fs.Intr) (fs.Node, fs.Handle, fuse.Error) {

	n := &File{}
	n.Mode = req.Mode
	n.Name = req.Name
	d.Add(req.Name, n)
	return n, n, nil
}

func (d *Dir) Lookup(name string, intr fs.Intr) (fs fs.Node, err fuse.Error) {
	d.rwmut.RLock()
	fs, ok := d.Children[name]
	d.rwmut.RUnlock()
	if !ok {
		return nil, fuse.ENOENT
	}

	return
}

func (d *Dir) ReadDir(intr fs.Intr) ([]fuse.Dirent, fuse.Error) {
	var out []fuse.Dirent

	d.rwmut.RLock()
	for name, node := range d.Children {
		de := fuse.Dirent{Name: name}
		switch node.(type) {
		case *Dir:
			de.Type = fuse.DT_Dir
		case *File:
			de.Type = fuse.DT_Dir
		}
		out = append(out, de)
	}
	d.rwmut.RUnlock()

	return out, nil
}

type File struct {
	Node
}

func (f *File) ReadAll(intr fs.Intr) (out []byte, ferr fuse.Error) {
	//Place holder code
	return []byte("I AM A FILE!!!!11!!!\n"), ferr
}

func (f *File) WriteAll(in []byte, intr fs.Intr) fuse.Error {
	return nil
}
<|endoftext|>


<commit_before>package router

import (
	"bytes"
	"fmt"
	"log"
	"math/rand"
	"net"
	"time"
)

const (
	InitialInterval = 5 * time.Second
	MaxInterval     = 10 * time.Minute
)

type ConnectionMaker struct {
	ourself        *LocalPeer
	peers          *Peers
	targets        map[string]*Target
	cmdLineAddress map[string]bool
	actionChan     chan<- ConnectionMakerAction
}

// Information about an address where we may find a peer
type Target struct {
	attempting  bool          // are we currently attempting to connect there?
	tryAfter    time.Time     // next time to try this address
	tryInterval time.Duration // backoff time on next failure
}

type ConnectionMakerAction func() bool

func NewConnectionMaker(ourself *LocalPeer, peers *Peers) *ConnectionMaker {
	return &ConnectionMaker{
		ourself:        ourself,
		peers:          peers,
		cmdLineAddress: make(map[string]bool),
		targets:        make(map[string]*Target)}
}

func (cm *ConnectionMaker) Start() {
	actionChan := make(chan ConnectionMakerAction, ChannelSize)
	cm.actionChan = actionChan
	go cm.queryLoop(actionChan)
}

func (cm *ConnectionMaker) InitiateConnection(address string) {
	cm.actionChan <- func() bool {
		cm.cmdLineAddress[NormalisePeerAddr(address)] = true
		return true
	}
}

func (cm *ConnectionMaker) ForgetConnection(address string) {
	cm.actionChan <- func() bool {
		delete(cm.cmdLineAddress, NormalisePeerAddr(address))
		return false
	}
}

func (cm *ConnectionMaker) ConnectionTerminated(address string) {
	cm.actionChan <- func() bool {
		if target, found := cm.targets[address]; found {
			target.attempting = false
			target.tryAfter, target.tryInterval = tryAfter(target.tryInterval)
		}
		return true
	}
}

func (cm *ConnectionMaker) Refresh() {
	cm.actionChan <- func() bool { return true }
}

func (cm *ConnectionMaker) String() string {
	resultChan := make(chan string, 0)
	cm.actionChan <- func() bool {
		var buf bytes.Buffer
		for address, target := range cm.targets {
			var fmtStr string
			if target.attempting {
				fmtStr = "%s (trying since %v)\n"
			} else {
				fmtStr = "%s (next try at %v)\n"
			}
			fmt.Fprintf(&buf, fmtStr, address, target.tryAfter)
		}
		resultChan <- buf.String()
		return false
	}
	return <-resultChan
}

func (cm *ConnectionMaker) queryLoop(actionChan <-chan ConnectionMakerAction) {
	timer := time.NewTimer(MaxDuration)
	run := func() { timer.Reset(cm.checkStateAndAttemptConnections()) }
	for {
		select {
		case action := <-actionChan:
			if action() {
				run()
			}
		case <-timer.C:
			run()
		}
	}
}

func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration {
	validTarget := make(map[string]bool)

	// copy the set of things we are connected to, so we can access them without locking
	ourConnectedPeers := make(map[PeerName]bool)
	ourConnectedTargets := make(map[string]bool)
	for _, conn := range cm.ourself.Connections() {
		ourConnectedPeers[conn.Remote().Name] = true
		ourConnectedTargets[conn.RemoteTCPAddr()] = true
	}

	addTarget := func(address string) {
		if !ourConnectedTargets[address] {
			validTarget[address] = true
			cm.addTarget(address)
		}
	}

	// Add command-line targets that are not connected
	for address := range cm.cmdLineAddress {
		addTarget(address)
	}

	// Add targets for peers that someone else is connected to, but we
	// aren't
	cm.peers.ForEach(func(peer *Peer) {
		for _, conn := range peer.Connections() {
			otherPeer := conn.Remote().Name
			if otherPeer == cm.ourself.Name || ourConnectedPeers[otherPeer] {
				continue
			}
			address := conn.RemoteTCPAddr()
			// try both portnumber of connection and standard port.  Don't use remote side of inbound connection.
			if conn.Outbound() {
				addTarget(address)
			}
			if host, _, err := net.SplitHostPort(address); err == nil {
				addTarget(NormalisePeerAddr(host))
			}
		}
	})

	return cm.connectToTargets(validTarget, ourConnectedTargets)
}

func (cm *ConnectionMaker) addTarget(address string) {
	if _, found := cm.targets[address]; !found {
		target := &Target{}
		target.tryAfter, target.tryInterval = tryImmediately()
		cm.targets[address] = target
	}
}

func (cm *ConnectionMaker) connectToTargets(validTarget map[string]bool, ourConnectedTargets map[string]bool) time.Duration {
	now := time.Now() // make sure we catch items just added
	after := MaxDuration
	for address, target := range cm.targets {
		if ourConnectedTargets[address] {
			delete(cm.targets, address)
			continue
		}
		if target.attempting {
			continue
		}
		if !validTarget[address] {
			delete(cm.targets, address)
			continue
		}
		switch duration := target.tryAfter.Sub(now); {
		case duration <= 0:
			target.attempting = true
			go cm.attemptConnection(address, cm.cmdLineAddress[address])
		case duration < after:
			after = duration
		}
	}
	return after
}

func (cm *ConnectionMaker) attemptConnection(address string, acceptNewPeer bool) {
	log.Printf("->[%s] attempting connection\n", address)
	if err := cm.ourself.CreateConnection(address, acceptNewPeer); err != nil {
		log.Printf("->[%s] error during connection attempt: %v\n", address, err)
		cm.ConnectionTerminated(address)
	}
}

func tryImmediately() (time.Time, time.Duration) {
	interval := time.Duration(rand.Int63n(int64(InitialInterval)))
	return time.Now(), interval
}

func tryAfter(interval time.Duration) (time.Time, time.Duration) {
	interval += time.Duration(rand.Int63n(int64(interval)))
	if interval > MaxInterval {
		interval = MaxInterval
	}
	return time.Now().Add(interval), interval
}
<commit_msg>act immediately on `weave connect`ing existing addresses we simply reset the vars controlling backoff for that address Note that we do not interrupt any current connection attempt, since that is hard.<commit_after>package router

import (
	"bytes"
	"fmt"
	"log"
	"math/rand"
	"net"
	"time"
)

const (
	InitialInterval = 5 * time.Second
	MaxInterval     = 10 * time.Minute
)

type ConnectionMaker struct {
	ourself        *LocalPeer
	peers          *Peers
	targets        map[string]*Target
	cmdLineAddress map[string]bool
	actionChan     chan<- ConnectionMakerAction
}

// Information about an address where we may find a peer
type Target struct {
	attempting  bool          // are we currently attempting to connect there?
	tryAfter    time.Time     // next time to try this address
	tryInterval time.Duration // backoff time on next failure
}

type ConnectionMakerAction func() bool

func NewConnectionMaker(ourself *LocalPeer, peers *Peers) *ConnectionMaker {
	return &ConnectionMaker{
		ourself:        ourself,
		peers:          peers,
		cmdLineAddress: make(map[string]bool),
		targets:        make(map[string]*Target)}
}

func (cm *ConnectionMaker) Start() {
	actionChan := make(chan ConnectionMakerAction, ChannelSize)
	cm.actionChan = actionChan
	go cm.queryLoop(actionChan)
}

func (cm *ConnectionMaker) InitiateConnection(address string) {
	cm.actionChan <- func() bool {
		cm.cmdLineAddress[NormalisePeerAddr(address)] = true
		if target, found := cm.targets[address]; found {
			target.tryAfter, target.tryInterval = tryImmediately()
		}
		return true
	}
}

func (cm *ConnectionMaker) ForgetConnection(address string) {
	cm.actionChan <- func() bool {
		delete(cm.cmdLineAddress, NormalisePeerAddr(address))
		return false
	}
}

func (cm *ConnectionMaker) ConnectionTerminated(address string) {
	cm.actionChan <- func() bool {
		if target, found := cm.targets[address]; found {
			target.attempting = false
			target.tryAfter, target.tryInterval = tryAfter(target.tryInterval)
		}
		return true
	}
}

func (cm *ConnectionMaker) Refresh() {
	cm.actionChan <- func() bool { return true }
}

func (cm *ConnectionMaker) String() string {
	resultChan := make(chan string, 0)
	cm.actionChan <- func() bool {
		var buf bytes.Buffer
		for address, target := range cm.targets {
			var fmtStr string
			if target.attempting {
				fmtStr = "%s (trying since %v)\n"
			} else {
				fmtStr = "%s (next try at %v)\n"
			}
			fmt.Fprintf(&buf, fmtStr, address, target.tryAfter)
		}
		resultChan <- buf.String()
		return false
	}
	return <-resultChan
}

func (cm *ConnectionMaker) queryLoop(actionChan <-chan ConnectionMakerAction) {
	timer := time.NewTimer(MaxDuration)
	run := func() { timer.Reset(cm.checkStateAndAttemptConnections()) }
	for {
		select {
		case action := <-actionChan:
			if action() {
				run()
			}
		case <-timer.C:
			run()
		}
	}
}

func (cm *ConnectionMaker) checkStateAndAttemptConnections() time.Duration {
	validTarget := make(map[string]bool)

	// copy the set of things we are connected to, so we can access them without locking
	ourConnectedPeers := make(map[PeerName]bool)
	ourConnectedTargets := make(map[string]bool)
	for _, conn := range cm.ourself.Connections() {
		ourConnectedPeers[conn.Remote().Name] = true
		ourConnectedTargets[conn.RemoteTCPAddr()] = true
	}

	addTarget := func(address string) {
		if !ourConnectedTargets[address] {
			validTarget[address] = true
			cm.addTarget(address)
		}
	}

	// Add command-line targets that are not connected
	for address := range cm.cmdLineAddress {
		addTarget(address)
	}

	// Add targets for peers that someone else is connected to, but we
	// aren't
	cm.peers.ForEach(func(peer *Peer) {
		for _, conn := range peer.Connections() {
			otherPeer := conn.Remote().Name
			if otherPeer == cm.ourself.Name || ourConnectedPeers[otherPeer] {
				continue
			}
			address := conn.RemoteTCPAddr()
			// try both portnumber of connection and standard port.  Don't use remote side of inbound connection.
			if conn.Outbound() {
				addTarget(address)
			}
			if host, _, err := net.SplitHostPort(address); err == nil {
				addTarget(NormalisePeerAddr(host))
			}
		}
	})

	return cm.connectToTargets(validTarget, ourConnectedTargets)
}

func (cm *ConnectionMaker) addTarget(address string) {
	if _, found := cm.targets[address]; !found {
		target := &Target{}
		target.tryAfter, target.tryInterval = tryImmediately()
		cm.targets[address] = target
	}
}

func (cm *ConnectionMaker) connectToTargets(validTarget map[string]bool, ourConnectedTargets map[string]bool) time.Duration {
	now := time.Now() // make sure we catch items just added
	after := MaxDuration
	for address, target := range cm.targets {
		if ourConnectedTargets[address] {
			delete(cm.targets, address)
			continue
		}
		if target.attempting {
			continue
		}
		if !validTarget[address] {
			delete(cm.targets, address)
			continue
		}
		switch duration := target.tryAfter.Sub(now); {
		case duration <= 0:
			target.attempting = true
			go cm.attemptConnection(address, cm.cmdLineAddress[address])
		case duration < after:
			after = duration
		}
	}
	return after
}

func (cm *ConnectionMaker) attemptConnection(address string, acceptNewPeer bool) {
	log.Printf("->[%s] attempting connection\n", address)
	if err := cm.ourself.CreateConnection(address, acceptNewPeer); err != nil {
		log.Printf("->[%s] error during connection attempt: %v\n", address, err)
		cm.ConnectionTerminated(address)
	}
}

func tryImmediately() (time.Time, time.Duration) {
	interval := time.Duration(rand.Int63n(int64(InitialInterval)))
	return time.Now(), interval
}

func tryAfter(interval time.Duration) (time.Time, time.Duration) {
	interval += time.Duration(rand.Int63n(int64(interval)))
	if interval > MaxInterval {
		interval = MaxInterval
	}
	return time.Now().Add(interval), interval
}
<|endoftext|>


<commit_before>package webmock

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/textproto"
	"net/url"
	"regexp"
	"time"
)

type Client struct {
	codebase string
	authFunc func(*http.Request) error
	client   *http.Client
	writer   io.Writer
	observer func(code int, method, endpoint string, elapsed time.Duration)
}

func (c *Client) Do(method, path string, values url.Values, body interface{}, opts ...func(r *http.Request)) (*http.Response, error) {
	// -- Create the Request ------------------------------------------------
	//
	urlStr := c.urlStr(path, values)
	r := newReader(body)
	req, err := http.NewRequest(method, urlStr, r)
	if err != nil {
		return nil, err
	}

	// -- Configure Request -------------------------------------------------
	//
	if err = c.authFunc(req); err != nil {
		return nil, err
	}

	for _, opt := range opts {
		opt(req)
	}

	// -- Print Request -----------------------------------------------------
	//
	buf := bytes.NewBuffer([]byte{})
	fmt.Fprintln(buf, "\n#-- Request ------------------------------------------")
	fmt.Fprintf(buf, "%v %v\n", method, urlStr)
	for key, values := range req.Header {
		for _, value := range values {
			fmt.Fprintf(buf, "%v: %v\n", key, value)
		}
	}
	if body != nil {
		io.WriteString(buf, "\n")
		io.Copy(buf, prettyReader(body))
	}

	io.Copy(c.writer, buf)

	// -- Execute Request ---------------------------------------------------
	//
	ctx, _ := context.WithTimeout(context.Background(), time.Second*10)
	req = req.WithContext(ctx)
	since := time.Now()
	resp, err := c.client.Do(req)
	if resp != nil {
		defer resp.Body.Close()
		c.observer(resp.StatusCode, req.Method, req.URL.Path, time.Now().Sub(since))
	}
	if err != nil {
		return nil, err
	}

	// -- Print Response ----------------------------------------------------
	//
	buf.Reset()
	if resp.Body != nil {
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}
		resp.Body = ioutil.NopCloser(bytes.NewReader(data))

		fmt.Fprintln(buf, "\n\n#-- Response -----------------------------------------")
		fmt.Fprintf(buf, "%v\n", resp.Status)
		for key, values := range resp.Header {
			for _, value := range values {
				fmt.Fprintf(buf, "%v: %v\n", key, value)
			}
		}
		buf.Write(data)
	}

	fmt.Fprintln(buf, "\n\n#-- End ----------------------------------------------")
	io.Copy(c.writer, buf)

	return resp, nil
}

func (c *Client) Get(path string, values url.Values) (*http.Response, error) {
	return c.Do("GET", path, values, nil)
}

func (c *Client) Post(path string, values url.Values, body interface{}) (*http.Response, error) {
	return c.Do("POST", path, values, body)
}

func (c *Client) Put(path string, values url.Values, body interface{}) (*http.Response, error) {
	return c.Do("PUT", path, values, body)
}

func (c *Client) Patch(path string, values url.Values, body interface{}) (*http.Response, error) {
	return c.Do("PATCH", path, values, body)
}

func (c *Client) Delete(path string, values url.Values) (*http.Response, error) {
	return c.Do("DELETE", path, values, nil)
}

func (c *Client) Upload(path string, values url.Values, r io.Reader, field, filename, contentType string) (*http.Response, error) {
	buf := bytes.NewBuffer([]byte{})

	mp := multipart.NewWriter(buf)

	h := textproto.MIMEHeader{}
	h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%v"; filename="%v"`, field, filename))
	h.Set("Content-Type", contentType)
	w, _ := mp.CreatePart(h)
	io.Copy(w, r)

	mp.Close()

	req, err := http.NewRequest("POST", path, bytes.NewReader(buf.Bytes()))
	if err != nil {
		return nil, fmt.Errorf("unable to generate request - %v", err)
	}

	req.Header.Set("Content-Type", mp.FormDataContentType())

	return c.client.Do(req)
}

func (c *Client) Cookie(name string) (string, bool) {
	u, err := url.Parse(c.codebase)
	if err != nil {
		return "", false
	}

	if cookies := c.client.Jar.Cookies(u); cookies != nil {
		for _, cookie := range cookies {
			if cookie.Name == name {
				return cookie.Value, true
			}
		}
	}

	return "", false
}

func New(handler http.Handler, opts ...Option) *Client {
	cookieJar, _ := cookiejar.New(nil)
	httpClient := &http.Client{
		Jar: cookieJar,
	}

	if handler != nil {
		httpClient.Transport = &roundTripper{handler: handler}
	}

	c := &Client{
		client:   httpClient,
		observer: func(code int, method, endpoint string, elapsed time.Duration) {},
		authFunc: func(req *http.Request) error { return nil },
		writer:   ioutil.Discard,
	}

	for _, opt := range opts {
		opt(c)
	}

	if c.codebase == "" {
		c.codebase = "http://localhost"
	}

	// strip trailing slashes from codebase
	pat := regexp.MustCompile(`/+$`)
	c.codebase = pat.ReplaceAllString(c.codebase, "")

	return c
}
<commit_msg>- added webmock.Endpoint to construct clients directly from swagger endpoint definitions<commit_after>package webmock

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"net/http/cookiejar"
	"net/textproto"
	"net/url"
	"regexp"
	"time"

	"github.com/altairsix/pkg/web"
	"github.com/savaki/swag/swagger"
)

type Client struct {
	codebase string
	authFunc func(*http.Request) error
	client   *http.Client
	writer   io.Writer
	observer func(code int, method, endpoint string, elapsed time.Duration)
}

func (c *Client) Do(method, path string, values url.Values, body interface{}, opts ...func(r *http.Request)) (*http.Response, error) {
	// -- Create the Request ------------------------------------------------
	//
	urlStr := c.urlStr(path, values)
	r := newReader(body)
	req, err := http.NewRequest(method, urlStr, r)
	if err != nil {
		return nil, err
	}

	// -- Configure Request -------------------------------------------------
	//
	if err = c.authFunc(req); err != nil {
		return nil, err
	}

	for _, opt := range opts {
		opt(req)
	}

	// -- Print Request -----------------------------------------------------
	//
	buf := bytes.NewBuffer([]byte{})
	fmt.Fprintln(buf, "\n#-- Request ------------------------------------------")
	fmt.Fprintf(buf, "%v %v\n", method, urlStr)
	for key, values := range req.Header {
		for _, value := range values {
			fmt.Fprintf(buf, "%v: %v\n", key, value)
		}
	}
	if body != nil {
		io.WriteString(buf, "\n")
		io.Copy(buf, prettyReader(body))
	}

	io.Copy(c.writer, buf)

	// -- Execute Request ---------------------------------------------------
	//
	ctx, _ := context.WithTimeout(context.Background(), time.Second*10)
	req = req.WithContext(ctx)
	since := time.Now()
	resp, err := c.client.Do(req)
	if resp != nil {
		defer resp.Body.Close()
		c.observer(resp.StatusCode, req.Method, req.URL.Path, time.Now().Sub(since))
	}
	if err != nil {
		return nil, err
	}

	// -- Print Response ----------------------------------------------------
	//
	buf.Reset()
	if resp.Body != nil {
		data, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			return nil, err
		}
		resp.Body = ioutil.NopCloser(bytes.NewReader(data))

		fmt.Fprintln(buf, "\n\n#-- Response -----------------------------------------")
		fmt.Fprintf(buf, "%v\n", resp.Status)
		for key, values := range resp.Header {
			for _, value := range values {
				fmt.Fprintf(buf, "%v: %v\n", key, value)
			}
		}
		buf.Write(data)
	}

	fmt.Fprintln(buf, "\n\n#-- End ----------------------------------------------")
	io.Copy(c.writer, buf)

	return resp, nil
}

func (c *Client) Get(path string, values url.Values) (*http.Response, error) {
	return c.Do("GET", path, values, nil)
}

func (c *Client) Post(path string, values url.Values, body interface{}) (*http.Response, error) {
	return c.Do("POST", path, values, body)
}

func (c *Client) Put(path string, values url.Values, body interface{}) (*http.Response, error) {
	return c.Do("PUT", path, values, body)
}

func (c *Client) Patch(path string, values url.Values, body interface{}) (*http.Response, error) {
	return c.Do("PATCH", path, values, body)
}

func (c *Client) Delete(path string, values url.Values) (*http.Response, error) {
	return c.Do("DELETE", path, values, nil)
}

func (c *Client) Upload(path string, values url.Values, r io.Reader, field, filename, contentType string) (*http.Response, error) {
	buf := bytes.NewBuffer([]byte{})

	mp := multipart.NewWriter(buf)

	h := textproto.MIMEHeader{}
	h.Set("Content-Disposition", fmt.Sprintf(`form-data; name="%v"; filename="%v"`, field, filename))
	h.Set("Content-Type", contentType)
	w, _ := mp.CreatePart(h)
	io.Copy(w, r)

	mp.Close()

	req, err := http.NewRequest("POST", path, bytes.NewReader(buf.Bytes()))
	if err != nil {
		return nil, fmt.Errorf("unable to generate request - %v", err)
	}

	req.Header.Set("Content-Type", mp.FormDataContentType())

	return c.client.Do(req)
}

func (c *Client) Cookie(name string) (string, bool) {
	u, err := url.Parse(c.codebase)
	if err != nil {
		return "", false
	}

	if cookies := c.client.Jar.Cookies(u); cookies != nil {
		for _, cookie := range cookies {
			if cookie.Name == name {
				return cookie.Value, true
			}
		}
	}

	return "", false
}

func New(handler http.Handler, opts ...Option) *Client {
	cookieJar, _ := cookiejar.New(nil)
	httpClient := &http.Client{
		Jar: cookieJar,
	}

	if handler != nil {
		httpClient.Transport = &roundTripper{handler: handler}
	}

	c := &Client{
		client:   httpClient,
		observer: func(code int, method, endpoint string, elapsed time.Duration) {},
		authFunc: func(req *http.Request) error { return nil },
		writer:   ioutil.Discard,
	}

	for _, opt := range opts {
		opt(c)
	}

	if c.codebase == "" {
		c.codebase = "http://localhost"
	}

	// strip trailing slashes from codebase
	pat := regexp.MustCompile(`/+$`)
	c.codebase = pat.ReplaceAllString(c.codebase, "")

	return c
}

// Endpoint constructs a client directly from a swagger endpoint
func Endpoint(endpoint *swagger.Endpoint, opts ...Option) *Client {
	router := web.NewRouter()
	h := endpoint.Handler.(web.HandlerFunc)
	router.Handle(endpoint.Method, endpoint.Path, h)
	return New(router, opts...)
}
<|endoftext|>


<commit_before>package kana

// Trie is a trie data structure
type Trie struct {
	children map[string]*Trie
	letter   string
	values   []string
}

// Build a trie for efficient retrieval of entries
func newTrie() *Trie {
	return &Trie{map[string]*Trie{}, "", []string{}}
}

// Insert a value into the trie
func (t *Trie) insert(letters, value string) {
	lettersRune := []rune(letters)

	// loop through letters in argument word
	for l, letter := range lettersRune {

		letterStr := string(letter)

		// if letter in children
		if t.children[letterStr] != nil {
			t = t.children[letterStr]
		} else {
			// not found, so add letter to children
			t.children[letterStr] = &Trie{map[string]*Trie{}, "", []string{}}
			t = t.children[letterStr]
		}

		if l == len(lettersRune)-1 {
			// last letter, save value and exit
			t.values = append(t.values, value)
			break
		}
	}
}

// Search for a string in the Trie.
//
// Returns the corresponding array of strings if found,
// or an empty array otherwise.
func (t *Trie) search(srch string) (found []string) {
	srchRune := []rune(srch)

	for l, letter := range srchRune {
		letterString := string(letter)
		if t.children[letterString] != nil {
			t = t.children[letterString]
		} else {
			found = []string{""}
			return found
		}
		if l == len(srchRune)-1 {
			found = t.values
		}
	}
	return found
}

// Convert a given string to the corresponding values
// in the trie. This performed in a greedy fashion,
// replacing the longest valid string it can find at any
// given point.
func (t *Trie) convert(origin string) (result string) {
	root := t
	originRune := []rune(origin)
	result = ""

	for l := 0; l < len(originRune); l++ {
		t = root
		foundVal := ""
		depth := 0
		for i := 0; i+l < len(originRune); i++ {
			letter := string(originRune[l+i])
			if t.children[letter] == nil {
				// not found
				break
			}
			if len(t.children[letter].values) > 0 {
				foundVal = t.children[letter].values[0]
				depth = i
			}
			t = t.children[letter]
		}
		if foundVal != "" {
			result += foundVal
			l += depth
		} else {
			result += string(originRune[l : l+1])
		}
	}
	return result
}
<commit_msg>remove unused code<commit_after>package kana

// Trie is a trie data structure
type Trie struct {
	children map[string]*Trie
	letter   string
	values   []string
}

// Build a trie for efficient retrieval of entries
func newTrie() *Trie {
	return &Trie{map[string]*Trie{}, "", []string{}}
}

// Insert a value into the trie
func (t *Trie) insert(letters, value string) {
	lettersRune := []rune(letters)

	// loop through letters in argument word
	for l, letter := range lettersRune {

		letterStr := string(letter)

		// if letter in children
		if t.children[letterStr] != nil {
			t = t.children[letterStr]
		} else {
			// not found, so add letter to children
			t.children[letterStr] = &Trie{map[string]*Trie{}, "", []string{}}
			t = t.children[letterStr]
		}

		if l == len(lettersRune)-1 {
			// last letter, save value and exit
			t.values = append(t.values, value)
			break
		}
	}
}

// Convert a given string to the corresponding values
// in the trie. This performed in a greedy fashion,
// replacing the longest valid string it can find at any
// given point.
func (t *Trie) convert(origin string) (result string) {
	root := t
	originRune := []rune(origin)
	result = ""

	for l := 0; l < len(originRune); l++ {
		t = root
		foundVal := ""
		depth := 0
		for i := 0; i+l < len(originRune); i++ {
			letter := string(originRune[l+i])
			if t.children[letter] == nil {
				// not found
				break
			}
			if len(t.children[letter].values) > 0 {
				foundVal = t.children[letter].values[0]
				depth = i
			}
			t = t.children[letter]
		}
		if foundVal != "" {
			result += foundVal
			l += depth
		} else {
			result += string(originRune[l : l+1])
		}
	}
	return result
}
<|endoftext|>


<commit_before>package main

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
)

// NodeVersion is the current node version
var NodeVersion = "?"

// RunScript runs some node code
func (p *Plugins) RunScript(script string) (cmd *exec.Cmd, done func()) {
	useTmpFile := true
	cacheTmp := filepath.Join(CacheHome, "tmp")
	os.MkdirAll(cacheTmp, 0755)
	f, err := ioutil.TempFile(cacheTmp, "heroku-script-")
	if err != nil {
		useTmpFile = false
		LogIfError(err)
	}
	defer f.Close()
	if _, err := f.WriteString(script); err != nil {
		useTmpFile = false
		LogIfError(err)
	}
	if useTmpFile {
		cmd = exec.Command(nodeBinPath(), f.Name())
	} else {
		cmd = exec.Command(nodeBinPath(), "-e", script)
	}
	cmd.Env = append([]string{"NODE_PATH=" + p.modulesPath()}, os.Environ()...)
	return cmd, func() {
		os.Remove(f.Name())
	}
}

func nodeBinPath() string {
	b := os.Getenv("HEROKU_NODE_PATH")
	ext := ""
	if runtime.GOOS == WINDOWS {
		ext = ".exe"
	}
	if b == "" {
		b = filepath.Join(AppDir, "lib", "node"+ext)
	}
	if exists, _ := FileExists(b); !exists {
		var err error
		Debugf("node not found in %s. Using node from PATH\n", b)
		b, err = exec.LookPath("node" + ext)
		must(err)
	}
	return b
}

func (p *Plugins) modulesPath() string {
	return filepath.Join(p.Path, "node_modules")
}
<commit_msg>only delete file if it existed<commit_after>package main

import (
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
)

// NodeVersion is the current node version
var NodeVersion = "?"

// RunScript runs some node code
func (p *Plugins) RunScript(script string) (cmd *exec.Cmd, done func()) {
	useTmpFile := true
	cacheTmp := filepath.Join(CacheHome, "tmp")
	os.MkdirAll(cacheTmp, 0755)
	f, err := ioutil.TempFile(cacheTmp, "heroku-script-")
	if err != nil {
		useTmpFile = false
		LogIfError(err)
	}
	defer f.Close()
	if _, err := f.WriteString(script); err != nil {
		useTmpFile = false
		LogIfError(err)
	}
	if useTmpFile {
		cmd = exec.Command(nodeBinPath(), f.Name())
	} else {
		cmd = exec.Command(nodeBinPath(), "-e", script)
	}
	cmd.Env = append([]string{"NODE_PATH=" + p.modulesPath()}, os.Environ()...)
	return cmd, func() {
		if f != nil {
			os.Remove(f.Name())
		}
	}
}

func nodeBinPath() string {
	b := os.Getenv("HEROKU_NODE_PATH")
	ext := ""
	if runtime.GOOS == WINDOWS {
		ext = ".exe"
	}
	if b == "" {
		b = filepath.Join(AppDir, "lib", "node"+ext)
	}
	if exists, _ := FileExists(b); !exists {
		var err error
		Debugf("node not found in %s. Using node from PATH\n", b)
		b, err = exec.LookPath("node" + ext)
		must(err)
	}
	return b
}

func (p *Plugins) modulesPath() string {
	return filepath.Join(p.Path, "node_modules")
}
<|endoftext|>


<commit_before>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

package service

import (
	"fmt"
	"net/url"
	"strings"
)

// NodeClient represents the RPC connection to the Nodes service.
type NodeClient struct {
	*Client
}

// NewNodeClient returns a new Node Client.
func NewNodeClient() *NodeClient {
	var service_ NodeClient
	service_.Client = new(Client)
	return &service_
}

type NodeInfo struct {
	Path string "path,omitempty"
	// Content type of the node.
	Type        string
	Title       string
	ShortTitle  string
	Description string
	// Order of the node compared to its siblings.
	Order int
	// Don't show the node in navigations if Hide is true.
	Hide bool
}

// PathToID returns an ID for the given node based on it's path.
//
// The ID is simply the path of the node with all slashes replaced by two
// underscores and the result prefixed with "node-".
//
// PathToID will panic if the path is not set.
//
// For example, a node with path "/foo/bar" will get the ID "node-__foo__bar".
func (n NodeInfo) PathToID() string {
	if len(n.Path) == 0 {
		panic("Can't calculate ID of node with unset path.")
	}
	return "node-" + strings.Replace(n.Path, "/", "__", -1)
}

// A request to be processed by a nodes service.
type Request struct {
	// Site name
	Site string
	// The requested node.
	Node NodeInfo
	// The query values of the request URL.
	Query url.Values
	// Method of the request (GET,POST,...).
	Method string
	// User session
	Session Session
	// Action to perform (e.g. "edit").
	Action string
	// FormData stores the requests form data.
	FormData url.Values
}

// Response to a node request.
type Response struct {
	// The html content to be embedded in the root template.
	Body []byte
	// Raw must be set to true if Body should not be embedded in the root
	// template. The content type will be automatically detected.
	Raw bool
	// If set, redirect to this target using error 303 'see other'.
	Redirect string
	// The node as received by GetRequest, possibly with some fields
	// updated (e.g. modified title).
	//
	// If nil, the original node data is used.
	Node *NodeInfo
}

// Write appends the given bytes to the body of the response.
func (r *Response) Write(p []byte) (n int, err error) {
	r.Body = append(r.Body, p...)
	return len(p), nil
}

// Request performs the given request.
func (s *NodeClient) Request(req *Request) (*Response, error) {
	var res Response
	err := s.RPCClient.Call("Node.Request", req, &res)
	if err != nil {
		return nil, fmt.Errorf("node: RPC error for Request:", err)
	}
	return &res, nil
}

// GetNodeType returns all supported node types.
func (s *NodeClient) GetNodeTypes() ([]string, error) {
	var res []string
	err := s.RPCClient.Call("Node.GetNodeTypes", 0, &res)
	if err != nil {
		return nil, fmt.Errorf("node: RPC error for Request:", err)
	}
	return res, nil
}

/*

func (m *NodeRPC) GetRequest(arg int, reply *client.Request) error {
	if m.Worker.Ticket != nil {
		return errors.New("monsti: Still waiting for response to last request.")
	}
	ticket := <-m.Worker.Tickets
	m.Worker.Ticket = &ticket
	request := client.Request{
		Method:  m.Worker.Ticket.Request.Method,
		Node:    m.Worker.Ticket.Node,
		Query:   m.Worker.Ticket.Request.URL.Query(),
		Session: m.Worker.Ticket.Session,
		Action:  m.Worker.Ticket.Action}
	*reply = request
	return nil
}

func (m *NodeRPC) SendResponse(res client.Response, reply *int) error {
	m.Worker.Ticket.ResponseChan <- res
	m.Worker.Ticket = nil
	return nil
}
*/
<commit_msg>Cleanup.<commit_after>// This file is part of Monsti, a web content management system.
// Copyright 2012-2013 Christian Neumann
//
// Monsti is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option) any
// later version.
//
// Monsti is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
// details.
//
// You should have received a copy of the GNU Affero General Public License
// along with Monsti.  If not, see <http://www.gnu.org/licenses/>.

package service

import (
	"fmt"
	"net/url"
	"strings"
)

// NodeClient represents the RPC connection to the Nodes service.
type NodeClient struct {
	*Client
}

// NewNodeClient returns a new Node Client.
func NewNodeClient() *NodeClient {
	var service_ NodeClient
	service_.Client = new(Client)
	return &service_
}

type NodeInfo struct {
	Path string "path,omitempty"
	// Content type of the node.
	Type        string
	Title       string
	ShortTitle  string
	Description string
	// Order of the node compared to its siblings.
	Order int
	// Don't show the node in navigations if Hide is true.
	Hide bool
}

// PathToID returns an ID for the given node based on it's path.
//
// The ID is simply the path of the node with all slashes replaced by two
// underscores and the result prefixed with "node-".
//
// PathToID will panic if the path is not set.
//
// For example, a node with path "/foo/bar" will get the ID "node-__foo__bar".
func (n NodeInfo) PathToID() string {
	if len(n.Path) == 0 {
		panic("Can't calculate ID of node with unset path.")
	}
	return "node-" + strings.Replace(n.Path, "/", "__", -1)
}

// A request to be processed by a nodes service.
type Request struct {
	// Site name
	Site string
	// The requested node.
	Node NodeInfo
	// The query values of the request URL.
	Query url.Values
	// Method of the request (GET,POST,...).
	Method string
	// User session
	Session Session
	// Action to perform (e.g. "edit").
	Action string
	// FormData stores the requests form data.
	FormData url.Values
}

// Response to a node request.
type Response struct {
	// The html content to be embedded in the root template.
	Body []byte
	// Raw must be set to true if Body should not be embedded in the root
	// template. The content type will be automatically detected.
	Raw bool
	// If set, redirect to this target using error 303 'see other'.
	Redirect string
	// The node as received by GetRequest, possibly with some fields
	// updated (e.g. modified title).
	//
	// If nil, the original node data is used.
	Node *NodeInfo
}

// Write appends the given bytes to the body of the response.
func (r *Response) Write(p []byte) (n int, err error) {
	r.Body = append(r.Body, p...)
	return len(p), nil
}

// Request performs the given request.
func (s *NodeClient) Request(req *Request) (*Response, error) {
	var res Response
	err := s.RPCClient.Call("Node.Request", req, &res)
	if err != nil {
		return nil, fmt.Errorf("node: RPC error for Request:", err)
	}
	return &res, nil
}

// GetNodeType returns all supported node types.
func (s *NodeClient) GetNodeTypes() ([]string, error) {
	var res []string
	err := s.RPCClient.Call("Node.GetNodeTypes", 0, &res)
	if err != nil {
		return nil, fmt.Errorf("node: RPC error for Request:", err)
	}
	return res, nil
}
<|endoftext|>


<commit_before>// Copyright © 2016 Zlatko Čalušić
//
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.

package sysinfo

import (
	"bufio"
	"crypto/rand"
	"fmt"
	"os"
	"strings"
	"time"
)

// Node information.
type Node struct {
	Hostname   string `json:"hostname,omitempty"`
	MachineID  string `json:"machineid,omitempty"`
	Hypervisor string `json:"hypervisor,omitempty"`
	Timezone   string `json:"timezone,omitempty"`
}

func (si *SysInfo) getHostname() {
	si.Node.Hostname = slurpFile("/proc/sys/kernel/hostname")
}

func (si *SysInfo) getSetMachineID() {
	const pathSystemdMachineID = "/etc/machine-id"
	const pathDbusMachineID = "/var/lib/dbus/machine-id"

	systemdMachineID := slurpFile(pathSystemdMachineID)
	dbusMachineID := slurpFile(pathDbusMachineID)

	if systemdMachineID != "" && dbusMachineID != "" {
		// All OK, just return the machine id.
		if systemdMachineID == dbusMachineID {
			si.Node.MachineID = systemdMachineID
			return
		}

		// They both exist, but they don't match! Copy systemd machine id to DBUS machine id.
		spewFile(pathDbusMachineID, systemdMachineID, 0444)
		si.Node.MachineID = systemdMachineID
		return
	}

	// Copy DBUS machine id to non-existent systemd machine id.
	if systemdMachineID == "" && dbusMachineID != "" {
		spewFile(pathSystemdMachineID, dbusMachineID, 0444)
		si.Node.MachineID = dbusMachineID
		return
	}

	// Copy systemd machine id to non-existent DBUS machine id.
	if systemdMachineID != "" && dbusMachineID == "" {
		spewFile(pathDbusMachineID, systemdMachineID, 0444)
		si.Node.MachineID = systemdMachineID
		return
	}

	// Generate and write fresh new machine ID to both locations, conforming to the DBUS specification:
	// https://dbus.freedesktop.org/doc/dbus-specification.html#uuids

	random := make([]byte, 12)
	if _, err := rand.Read(random); err != nil {
		return
	}
	newMachineID := fmt.Sprintf("%x%x", random, time.Now().Unix())

	spewFile(pathSystemdMachineID, newMachineID, 0444)
	spewFile(pathDbusMachineID, newMachineID, 0444)
	si.Node.MachineID = newMachineID
}

func (si *SysInfo) getTimezone() {
	if fi, err := os.Lstat("/etc/localtime"); err == nil {
		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
			if tzfile, err := os.Readlink("/etc/localtime"); err == nil {
				if strings.HasPrefix(tzfile, "/usr/share/zoneinfo/") {
					si.Node.Timezone = strings.TrimPrefix(tzfile, "/usr/share/zoneinfo/")
					return
				}
			}
		}
	}

	if timezone := slurpFile("/etc/timezone"); timezone != "" {
		si.Node.Timezone = timezone
		return
	}

	if f, err := os.Open("/etc/sysconfig/clock"); err == nil {
		defer f.Close()
		s := bufio.NewScanner(f)
		for s.Scan() {
			if sl := strings.Split(s.Text(), "="); len(sl) == 2 {
				if sl[0] == "ZONE" {
					si.Node.Timezone = strings.Trim(sl[1], `"`)
					return
				}
			}
		}
	}
}

func (si *SysInfo) getNodeInfo() {
	si.getHostname()
	si.getSetMachineID()
	si.getHypervisor()
	si.getTimezone()
}
<commit_msg>Handle case when /etc/localtime is a relative symlink<commit_after>// Copyright © 2016 Zlatko Čalušić
//
// Use of this source code is governed by an MIT-style license that can be found in the LICENSE file.

package sysinfo

import (
	"bufio"
	"crypto/rand"
	"fmt"
	"os"
	"strings"
	"time"
)

// Node information.
type Node struct {
	Hostname   string `json:"hostname,omitempty"`
	MachineID  string `json:"machineid,omitempty"`
	Hypervisor string `json:"hypervisor,omitempty"`
	Timezone   string `json:"timezone,omitempty"`
}

func (si *SysInfo) getHostname() {
	si.Node.Hostname = slurpFile("/proc/sys/kernel/hostname")
}

func (si *SysInfo) getSetMachineID() {
	const pathSystemdMachineID = "/etc/machine-id"
	const pathDbusMachineID = "/var/lib/dbus/machine-id"

	systemdMachineID := slurpFile(pathSystemdMachineID)
	dbusMachineID := slurpFile(pathDbusMachineID)

	if systemdMachineID != "" && dbusMachineID != "" {
		// All OK, just return the machine id.
		if systemdMachineID == dbusMachineID {
			si.Node.MachineID = systemdMachineID
			return
		}

		// They both exist, but they don't match! Copy systemd machine id to DBUS machine id.
		spewFile(pathDbusMachineID, systemdMachineID, 0444)
		si.Node.MachineID = systemdMachineID
		return
	}

	// Copy DBUS machine id to non-existent systemd machine id.
	if systemdMachineID == "" && dbusMachineID != "" {
		spewFile(pathSystemdMachineID, dbusMachineID, 0444)
		si.Node.MachineID = dbusMachineID
		return
	}

	// Copy systemd machine id to non-existent DBUS machine id.
	if systemdMachineID != "" && dbusMachineID == "" {
		spewFile(pathDbusMachineID, systemdMachineID, 0444)
		si.Node.MachineID = systemdMachineID
		return
	}

	// Generate and write fresh new machine ID to both locations, conforming to the DBUS specification:
	// https://dbus.freedesktop.org/doc/dbus-specification.html#uuids

	random := make([]byte, 12)
	if _, err := rand.Read(random); err != nil {
		return
	}
	newMachineID := fmt.Sprintf("%x%x", random, time.Now().Unix())

	spewFile(pathSystemdMachineID, newMachineID, 0444)
	spewFile(pathDbusMachineID, newMachineID, 0444)
	si.Node.MachineID = newMachineID
}

func (si *SysInfo) getTimezone() {
	const zoneInfoPrefix = "/usr/share/zoneinfo/"

	if fi, err := os.Lstat("/etc/localtime"); err == nil {
		if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
			if tzfile, err := os.Readlink("/etc/localtime"); err == nil {
				tzfile = strings.TrimPrefix(tzfile, "..")
				if strings.HasPrefix(tzfile, zoneInfoPrefix) {
					si.Node.Timezone = strings.TrimPrefix(tzfile, zoneInfoPrefix)
					return
				}
			}
		}
	}

	if timezone := slurpFile("/etc/timezone"); timezone != "" {
		si.Node.Timezone = timezone
		return
	}

	if f, err := os.Open("/etc/sysconfig/clock"); err == nil {
		defer f.Close()
		s := bufio.NewScanner(f)
		for s.Scan() {
			if sl := strings.Split(s.Text(), "="); len(sl) == 2 {
				if sl[0] == "ZONE" {
					si.Node.Timezone = strings.Trim(sl[1], `"`)
					return
				}
			}
		}
	}
}

func (si *SysInfo) getNodeInfo() {
	si.getHostname()
	si.getSetMachineID()
	si.getHypervisor()
	si.getTimezone()
}
<|endoftext|>


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

// +build !darwin

package x509

/*
#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
#cgo LDFLAGS: -framework CoreFoundation -framework Security

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>

// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
//
// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
// certificates of the system. On failure, the function returns -1.
//
// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
// we've consumed its content.
int FetchPEMRoots(CFDataRef *pemRoots) {
	if (pemRoots == NULL) {
		return -1;
	}

	CFArrayRef certs = NULL;
	OSStatus err = SecTrustCopyAnchorCertificates(&certs);
	if (err != noErr) {
		return -1;
	}

	CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
	int i, ncerts = CFArrayGetCount(certs);
	for (i = 0; i < ncerts; i++) {
		CFDataRef data = NULL;
		SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
		if (cert == NULL) {
			continue;
		}

		// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
		// Once we support weak imports via cgo we should prefer that, and fall back to this
		// for older systems.
		err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
		if (err != noErr) {
			continue;
		}

		if (data != NULL) {
			CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
			CFRelease(data);
		}
	}

	CFRelease(certs);

	*pemRoots = combinedData;
	return 0;
}
*/
import "C"
import "unsafe"

func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
	return nil, nil
}

func initSystemRoots() {
	roots := NewCertPool()

	var data C.CFDataRef = nil
	err := C.FetchPEMRoots(&data)
	if err == -1 {
		return
	}

	defer C.CFRelease(C.CFTypeRef(data))
	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
	roots.AppendCertsFromPEM(buf)
	systemRoots = roots
}
<commit_msg>Travis uses gclient.<commit_after>// Copyright 2011 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.

// +build !darwin,cgo

package x509

/*
#cgo CFLAGS: -mmacosx-version-min=10.6 -D__MAC_OS_X_VERSION_MAX_ALLOWED=1060
#cgo LDFLAGS: -framework CoreFoundation -framework Security

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>

// FetchPEMRoots fetches the system's list of trusted X.509 root certificates.
//
// On success it returns 0 and fills pemRoots with a CFDataRef that contains the extracted root
// certificates of the system. On failure, the function returns -1.
//
// Note: The CFDataRef returned in pemRoots must be released (using CFRelease) after
// we've consumed its content.
int FetchPEMRoots(CFDataRef *pemRoots) {
	if (pemRoots == NULL) {
		return -1;
	}

	CFArrayRef certs = NULL;
	OSStatus err = SecTrustCopyAnchorCertificates(&certs);
	if (err != noErr) {
		return -1;
	}

	CFMutableDataRef combinedData = CFDataCreateMutable(kCFAllocatorDefault, 0);
	int i, ncerts = CFArrayGetCount(certs);
	for (i = 0; i < ncerts; i++) {
		CFDataRef data = NULL;
		SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(certs, i);
		if (cert == NULL) {
			continue;
		}

		// Note: SecKeychainItemExport is deprecated as of 10.7 in favor of SecItemExport.
		// Once we support weak imports via cgo we should prefer that, and fall back to this
		// for older systems.
		err = SecKeychainItemExport(cert, kSecFormatX509Cert, kSecItemPemArmour, NULL, &data);
		if (err != noErr) {
			continue;
		}

		if (data != NULL) {
			CFDataAppendBytes(combinedData, CFDataGetBytePtr(data), CFDataGetLength(data));
			CFRelease(data);
		}
	}

	CFRelease(certs);

	*pemRoots = combinedData;
	return 0;
}
*/
import "C"
import "unsafe"

func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
	return nil, nil
}

func initSystemRoots() {
	roots := NewCertPool()

	var data C.CFDataRef = nil
	err := C.FetchPEMRoots(&data)
	if err == -1 {
		return
	}

	defer C.CFRelease(C.CFTypeRef(data))
	buf := C.GoBytes(unsafe.Pointer(C.CFDataGetBytePtr(data)), C.int(C.CFDataGetLength(data)))
	roots.AppendCertsFromPEM(buf)
	systemRoots = roots
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"html/template"
	"log"
	"net/http"
	"os"
	"sort"
	"strings"
)

const packageTemplateString = `<!DOCTYPE html>

		<meta charset="utf-8">
		<title>{{.Repo.Name}}.{{.Repo.MajorVersion}}{{.Repo.SubPath}} - {{.Repo.GopkgPath}}</title>
		<link href='//fonts.googleapis.com/css?family=Ubuntu+Mono|Ubuntu' rel='stylesheet' >
		<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet" >
		<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" >

{{.Repo.GopkgPath}}

						 Source Code
						 API Documentation

Getting started

To get the package, execute:

go get {{.Repo.GopkgPath}}

To import this package, add the following line to your code:

import "{{.Repo.GopkgPath}}"

								{{if .CleanName}}
Refer to it as {{.CleanName}}.{{end}}

For more details, see the API documentation.

Versions

						{{ if .LatestVersions }}
							{{ range .LatestVersions }}

									v{{.Major}}
									→
									{{.}}

							{{ end }}
						{{ else }}

								v0
								→
								master

						{{ end }}

gopkg.in

`

var packageTemplate *template.Template

func gopkgVersionRoot(repo *Repo, version Version) string {
	return repo.GopkgVersionRoot(version)
}

var packageFuncs = template.FuncMap{
	"gopkgVersionRoot": gopkgVersionRoot,
}

func init() {
	var err error
	packageTemplate, err = template.New("page").Funcs(packageFuncs).Parse(packageTemplateString)
	if err != nil {
		fmt.Fprintf(os.Stderr, "fatal: parsing package template failed: %s\n", err)
		os.Exit(1)
	}
}

type packageData struct {
	Repo           *Repo
	LatestVersions VersionList // Contains only the latest version for each major
	FullVersion    Version     // Version that the major requested resolves to
	CleanName      string
}

func renderPackagePage(resp http.ResponseWriter, req *http.Request, repo *Repo) {
	data := &packageData{
		Repo: repo,
	}
	latestVersionsMap := make(map[int]Version)
	for _, v := range repo.AllVersions {
		v2, exists := latestVersionsMap[v.Major]
		if !exists || v2.Less(v) {
			latestVersionsMap[v.Major] = v
		}
	}
	data.FullVersion = latestVersionsMap[repo.MajorVersion.Major]
	data.LatestVersions = make(VersionList, 0, len(latestVersionsMap))
	for _, v := range latestVersionsMap {
		data.LatestVersions = append(data.LatestVersions, v)
	}
	sort.Sort(sort.Reverse(data.LatestVersions))

	data.CleanName = repo.Name
	if strings.HasPrefix(data.CleanName, "go-") || strings.HasPrefix(data.CleanName, "go.") {
		data.CleanName = data.CleanName[3:]
	}
	if strings.HasSuffix(data.CleanName, "-go") {
		data.CleanName = data.CleanName[:len(data.CleanName)-3]
	}
	for i, c := range data.CleanName {
		if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {
			continue
		}
		if i > 0 && (c == '_' || c >= '0' && c <= '9') {
			continue
		}
		data.CleanName = ""
		break
	}

	err := packageTemplate.Execute(resp, data)
	if err != nil {
		log.Printf("error executing tmplPackage: %s\n", err)
	}
}
<commit_msg>Screenscrap package name from godoc.org<commit_after>package main

import (
	"fmt"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"regexp"
	"sort"
)

const packageTemplateString = `<!DOCTYPE html>

		<meta charset="utf-8">
		<title>{{.Repo.Name}}.{{.Repo.MajorVersion}}{{.Repo.SubPath}} - {{.Repo.GopkgPath}}</title>
		<link href='//fonts.googleapis.com/css?family=Ubuntu+Mono|Ubuntu' rel='stylesheet' >
		<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet" >
		<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" >

{{.Repo.GopkgPath}}

						 Source Code
						 API Documentation

Getting started

To get the package, execute:

go get {{.Repo.GopkgPath}}

To import this package, add the following line to your code:

import "{{.Repo.GopkgPath}}"

								{{if .PackageName}}
Refer to it as {{.PackageName}}.{{end}}

For more details, see the API documentation.

Versions

						{{ if .LatestVersions }}
							{{ range .LatestVersions }}

									v{{.Major}}
									→
									{{.}}

							{{ end }}
						{{ else }}

								v0
								→
								master

						{{ end }}

gopkg.in

`

var packageTemplate *template.Template

func gopkgVersionRoot(repo *Repo, version Version) string {
	return repo.GopkgVersionRoot(version)
}

var packageFuncs = template.FuncMap{
	"gopkgVersionRoot": gopkgVersionRoot,
}

func init() {
	var err error
	packageTemplate, err = template.New("page").Funcs(packageFuncs).Parse(packageTemplateString)
	if err != nil {
		fmt.Fprintf(os.Stderr, "fatal: parsing package template failed: %s\n", err)
		os.Exit(1)
	}
}

type packageData struct {
	Repo           *Repo
	LatestVersions VersionList // Contains only the latest version for each major
	FullVersion    Version     // Version that the major requested resolves to
	PackageName    string      // Actual package identifier as specified in http://golang.org/ref/spec#PackageClause
}

var regexpPackageName = regexp.MustCompile(`\<h2 id="pkg-overview"\>package ([\p{L}_][\pL\p{Nd}_]*)\</h2\>`)

func renderPackagePage(resp http.ResponseWriter, req *http.Request, repo *Repo) {
	data := &packageData{
		Repo: repo,
	}
	latestVersionsMap := make(map[int]Version)
	for _, v := range repo.AllVersions {
		v2, exists := latestVersionsMap[v.Major]
		if !exists || v2.Less(v) {
			latestVersionsMap[v.Major] = v
		}
	}
	data.FullVersion = latestVersionsMap[repo.MajorVersion.Major]
	data.LatestVersions = make(VersionList, 0, len(latestVersionsMap))
	for _, v := range latestVersionsMap {
		data.LatestVersions = append(data.LatestVersions, v)
	}
	sort.Sort(sort.Reverse(data.LatestVersions))

	godocResp, err := http.Get("http://godoc.org/" + repo.GopkgPath())
	if err == nil {
		godocRespBytes, err := ioutil.ReadAll(godocResp.Body)
		godocResp.Body.Close()
		if err == nil {
			matches := regexpPackageName.FindSubmatch(godocRespBytes)
			if len(matches) == 2 {
				data.PackageName = string(matches[1])
			}
		}
	}

	err = packageTemplate.Execute(resp, data)
	if err != nil {
		log.Printf("error executing tmplPackage: %s\n", err)
	}
}
<|endoftext|>


<commit_before>package materials

import (
	"bufio"
	"os"
	"os/user"
	"path/filepath"
	"strings"
)

type Project struct {
	Name      string `json:"name" xml:"name"`
	Directory string `json:"directory" xml:"directory"`
}

type User struct {
	user     *user.User
	Projects []Project
}

func CurrentUser() (*User, error) {
	u, err := user.Current()

	if err != nil {
		return nil, err
	}

	usr := User{
		user: u,
	}

	usr.loadProjects()

	return &usr, nil
}

func (u *User) loadProjects() {
	projectsFile, err := os.Open(u.projectsFile())

	if err != nil {
		return
	}

	defer projectsFile.Close()

	scanner := bufio.NewScanner(projectsFile)
	for scanner.Scan() {
		splitLine := strings.Split(scanner.Text(), "|")
		if len(splitLine) == 2 {
			u.Projects = append(u.Projects, Project{splitLine[0], splitLine[1]})
		}
	}
}

func (u *User) projectsFile() string {
	return filepath.Join(u.user.HomeDir, ".materials", "projects")
}
<commit_msg>Cleanup code. Add ability to reload the projects.<commit_after>package materials

import (
	"bufio"
	"os"
	"os/user"
	"path/filepath"
	"strings"
)

type Project struct {
	Name      string `json:"name" xml:"name"`
	Directory string `json:"directory" xml:"directory"`
}

type User struct {
	user     *user.User
	Projects []Project
}

func CurrentUser() (*User, error) {
	u, err := user.Current()
	if err != nil {
		return nil, err
	}

	usr := User{user: u}
	usr.loadProjects()
	return &usr, nil
}

func (u *User) loadProjects() {
	projectsFile, err := os.Open(u.projectsFile())
	if err != nil {
		return
	}
	defer projectsFile.Close()

	projects := []Project{}
	scanner := bufio.NewScanner(projectsFile)
	for scanner.Scan() {
		splitLine := strings.Split(scanner.Text(), "|")
		if len(splitLine) == 2 {
			projects = append(projects, Project{splitLine[0], splitLine[1]})
		}
	}
	u.Projects = projects
}

func (u *User) ReloadProjects() {
	u.loadProjects()
}

func (u *User) projectsFile() string {
	return filepath.Join(u.user.HomeDir, ".materials", "projects")
}
<|endoftext|>


<commit_before>package gotop

import (
	"errors"
	"fmt"
	"io/ioutil"
	"strconv"
	"syscall"
	"time"
)

var (
	//Delay between samples
	Delay = 500 * time.Millisecond
)

func readFile(filename string) (string, error) {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		errorString := fmt.Sprintf("Could not read file %s .", filename)
		return "", errors.New(errorString)
	}
	return string(bytes), nil
}

type Systeminfo struct {
	Sysname  string
	Nodename string
	Release  string
	Version  string
	Machine  string
	CPUModel string
	NumCPU   int
	Memory string
}

func (s Systeminfo) String() string {
	return fmt.Sprintf("Sysname: %s\nNodename: %s\nRelease: %s\nVersion: %s\nMachine: %s\nModel: %s\nnumCPU: %d\nTotal memory:%s",
		s.Sysname, s.Nodename, s.Release, s.Version, s.Machine, s.CPUModel, s.NumCPU, s.Memory)
}

func charToStr(input [65]int8) string {
	out := make([]byte, len(input))
	for i, val := range input {
		if val == 0 {
			break
		}
		out[i] = byte(val)
	}
	return string(out)
}

func Sysinfo() Systeminfo {
	var uts syscall.Utsname
	syscall.Uname(&uts)
	sysname := charToStr(uts.Sysname)
	nodename := charToStr(uts.Nodename)
	release := charToStr(uts.Release)
	version := charToStr(uts.Version)
	machine := charToStr(uts.Machine)
	model := cpuModel()
	numCPU := numberOfCpus()
	memInfo, _ := getMemInfo()
	memory := float64(memInfo.MemTotal)/(1024*1024)
	memstr := strconv.FormatFloat(memory, 'f', 2, 64) + "GB"
	return Systeminfo{sysname, nodename, release, version, machine, model, numCPU, memstr}
}

<commit_msg>Add tabs to Systeminfo String()<commit_after>package gotop

import (
	"errors"
	"fmt"
	"io/ioutil"
	"strconv"
	"syscall"
	"time"
)

var (
	//Delay between samples
	Delay = 500 * time.Millisecond
)

func readFile(filename string) (string, error) {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		errorString := fmt.Sprintf("Could not read file %s .", filename)
		return "", errors.New(errorString)
	}
	return string(bytes), nil
}

type Systeminfo struct {
	Sysname  string
	Nodename string
	Release  string
	Version  string
	Machine  string
	CPUModel string
	NumCPU   int
	Memory   string
}

func (s Systeminfo) String() string {
	return fmt.Sprintf("Sysname: \t%s\nNodename: \t%s\nRelease: \t%s\nVersion: \t%s\nMachine: \t%s\nModel: \t\t%s\nCPU cores: \t%d\nTotal memory:\t%s",
		s.Sysname, s.Nodename, s.Release, s.Version, s.Machine, s.CPUModel, s.NumCPU, s.Memory)
}

func charToStr(input [65]int8) string {
	out := make([]byte, len(input))
	for i, val := range input {
		if val == 0 {
			break
		}
		out[i] = byte(val)
	}
	return string(out)
}

func Sysinfo() Systeminfo {
	var uts syscall.Utsname
	syscall.Uname(&uts)
	sysname := charToStr(uts.Sysname)
	nodename := charToStr(uts.Nodename)
	release := charToStr(uts.Release)
	version := charToStr(uts.Version)
	machine := charToStr(uts.Machine)
	model := cpuModel()
	numCPU := numberOfCpus()
	memInfo, _ := getMemInfo()
	memory := float64(memInfo.MemTotal) / (1024 * 1024)
	memstr := strconv.FormatFloat(memory, 'f', 2, 64) + "GB"
	return Systeminfo{sysname, nodename, release, version, machine, model, numCPU, memstr}
}
<|endoftext|>