<commit_before>// Package dht implements a distributed hash table that satisfies the ipfs routing
// interface. This DHT is modeled after kademlia with Coral and S/Kademlia modifications.
package dht

import (
	"bytes"
	"crypto/rand"
	"errors"
	"fmt"
	"sync"
	"time"

	host "github.com/jbenet/go-ipfs/p2p/host"
	peer "github.com/jbenet/go-ipfs/p2p/peer"
	protocol "github.com/jbenet/go-ipfs/p2p/protocol"
	routing "github.com/jbenet/go-ipfs/routing"
	pb "github.com/jbenet/go-ipfs/routing/dht/pb"
	kb "github.com/jbenet/go-ipfs/routing/kbucket"
	u "github.com/jbenet/go-ipfs/util"
	"github.com/jbenet/go-ipfs/util/eventlog"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
	ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
)

var log = eventlog.Logger("dht")

var ProtocolDHT protocol.ID = "/ipfs/dht"

const doPinging = false

// NumBootstrapQueries defines the number of random dht queries to do to
// collect members of the routing table.
const NumBootstrapQueries = 5

// TODO. SEE https://github.com/jbenet/node-ipfs/blob/master/submodules/ipfs-dht/index.js

// IpfsDHT is an implementation of Kademlia with Coral and S/Kademlia modifications.
// It is used to implement the base IpfsRouting module.
type IpfsDHT struct {
	host      host.Host      // the network services we need
	self      peer.ID        // Local peer (yourself)
	peerstore peer.Peerstore // Peer Registry

	datastore ds.ThreadSafeDatastore // Local data

	routingTable *kb.RoutingTable // Array of routing tables for differently distanced nodes
	providers    *ProviderManager

	birth    time.Time  // When this peer started up
	diaglock sync.Mutex // lock to make diagnostics work better

	// record validator funcs
	Validators map[string]ValidatorFunc

	ctxgroup.ContextGroup
}

// NewDHT creates a new DHT object with the given peer as the 'local' host
func NewDHT(ctx context.Context, h host.Host, dstore ds.ThreadSafeDatastore) *IpfsDHT {
	dht := new(IpfsDHT)
	dht.datastore = dstore
	dht.self = h.ID()
	dht.peerstore = h.Peerstore()
	dht.ContextGroup = ctxgroup.WithContext(ctx)
	dht.host = h
	h.SetStreamHandler(ProtocolDHT, dht.handleNewStream)

	dht.providers = NewProviderManager(dht.Context(), dht.self)
	dht.AddChildGroup(dht.providers)

	dht.routingTable = kb.NewRoutingTable(20, kb.ConvertPeerID(dht.self), time.Minute, dht.peerstore)
	dht.birth = time.Now()

	dht.Validators = make(map[string]ValidatorFunc)
	dht.Validators["pk"] = ValidatePublicKeyRecord

	if doPinging {
		dht.Children().Add(1)
		go dht.PingRoutine(time.Second * 10)
	}
	return dht
}

// LocalPeer returns the peer.Peer of the dht.
func (dht *IpfsDHT) LocalPeer() peer.ID {
	return dht.self
}

// log returns the dht's logger
func (dht *IpfsDHT) log() eventlog.EventLogger {
	return log.Prefix("dht(%s)", dht.self)
}

// Connect to a new peer at the given address, ping and add to the routing table
func (dht *IpfsDHT) Connect(ctx context.Context, npeer peer.ID) error {
	// TODO: change interface to accept a PeerInfo as well.
	if err := dht.host.Connect(ctx, peer.PeerInfo{ID: npeer}); err != nil {
		return err
	}

	// Ping new peer to register in their routing table
	// NOTE: this should be done better...
	if err := dht.Ping(ctx, npeer); err != nil {
		return fmt.Errorf("failed to ping newly connected peer: %s\n", err)
	}
	log.Event(ctx, "connect", dht.self, npeer)
	dht.Update(ctx, npeer)
	return nil
}

// putValueToPeer stores the given key/value pair at the peer 'p'
func (dht *IpfsDHT) putValueToPeer(ctx context.Context, p peer.ID,
	key u.Key, rec *pb.Record) error {

	pmes := pb.NewMessage(pb.Message_PUT_VALUE, string(key), 0)
	pmes.Record = rec
	rpmes, err := dht.sendRequest(ctx, p, pmes)
	if err != nil {
		return err
	}

	if !bytes.Equal(rpmes.GetRecord().Value, pmes.GetRecord().Value) {
		return errors.New("value not put correctly")
	}
	return nil
}

// putProvider sends a message to peer 'p' saying that the local node
// can provide the value of 'key'
func (dht *IpfsDHT) putProvider(ctx context.Context, p peer.ID, key string) error {

	pmes := pb.NewMessage(pb.Message_ADD_PROVIDER, string(key), 0)

	// add self as the provider
	pi := dht.peerstore.PeerInfo(dht.self)
	pmes.ProviderPeers = pb.PeerInfosToPBPeers(dht.host.Network(), []peer.PeerInfo{pi})

	err := dht.sendMessage(ctx, p, pmes)
	if err != nil {
		return err
	}

	log.Debugf("%s putProvider: %s for %s (%s)", dht.self, p, u.Key(key), pi.Addrs)

	return nil
}

// getValueOrPeers queries a particular peer p for the value for
// key. It returns either the value or a list of closer peers.
// NOTE: it will update the dht's peerstore with any new addresses
// it finds for the given peer.
func (dht *IpfsDHT) getValueOrPeers(ctx context.Context, p peer.ID,
	key u.Key) ([]byte, []peer.PeerInfo, error) {

	pmes, err := dht.getValueSingle(ctx, p, key)
	if err != nil {
		return nil, nil, err
	}

	if record := pmes.GetRecord(); record != nil {
		// Success! We were given the value
		log.Debug("getValueOrPeers: got value")

		// make sure record is valid.
		err = dht.verifyRecordOnline(ctx, record)
		if err != nil {
			log.Error("Received invalid record!")
			return nil, nil, err
		}
		return record.GetValue(), nil, nil
	}

	// Perhaps we were given closer peers
	peers := pb.PBPeersToPeerInfos(pmes.GetCloserPeers())
	if len(peers) > 0 {
		log.Debug("getValueOrPeers: peers")
		return nil, peers, nil
	}

	log.Warning("getValueOrPeers: routing.ErrNotFound")
	return nil, nil, routing.ErrNotFound
}

// getValueSingle simply performs the get value RPC with the given parameters
func (dht *IpfsDHT) getValueSingle(ctx context.Context, p peer.ID,
	key u.Key) (*pb.Message, error) {

	pmes := pb.NewMessage(pb.Message_GET_VALUE, string(key), 0)
	return dht.sendRequest(ctx, p, pmes)
}

// getLocal attempts to retrieve the value from the datastore
func (dht *IpfsDHT) getLocal(key u.Key) ([]byte, error) {

	log.Debug("getLocal %s", key)
	v, err := dht.datastore.Get(key.DsKey())
	if err != nil {
		return nil, err
	}
	log.Debug("found in db")

	byt, ok := v.([]byte)
	if !ok {
		return nil, errors.New("value stored in datastore not []byte")
	}
	rec := new(pb.Record)
	err = proto.Unmarshal(byt, rec)
	if err != nil {
		return nil, err
	}

	// TODO: 'if paranoid'
	if u.Debug {
		err = dht.verifyRecordLocally(rec)
		if err != nil {
			log.Errorf("local record verify failed: %s", err)
			return nil, err
		}
	}

	return rec.GetValue(), nil
}

// putLocal stores the key value pair in the datastore
func (dht *IpfsDHT) putLocal(key u.Key, value []byte) error {
	rec, err := dht.makePutRecord(key, value)
	if err != nil {
		return err
	}
	data, err := proto.Marshal(rec)
	if err != nil {
		return err
	}

	return dht.datastore.Put(key.DsKey(), data)
}

// Update signals the routingTable to Update its last-seen status
// on the given peer.
func (dht *IpfsDHT) Update(ctx context.Context, p peer.ID) {
	log.Event(ctx, "updatePeer", p)
	dht.routingTable.Update(p)
}

// FindLocal looks for a peer with a given ID connected to this dht and returns the peer and the table it was found in.
func (dht *IpfsDHT) FindLocal(id peer.ID) peer.PeerInfo {
	p := dht.routingTable.Find(id)
	if p != "" {
		return dht.peerstore.PeerInfo(p)
	}
	return peer.PeerInfo{}
}

// findPeerSingle asks peer 'p' if they know where the peer with id 'id' is
func (dht *IpfsDHT) findPeerSingle(ctx context.Context, p peer.ID, id peer.ID) (*pb.Message, error) {
	pmes := pb.NewMessage(pb.Message_FIND_NODE, string(id), 0)
	return dht.sendRequest(ctx, p, pmes)
}

func (dht *IpfsDHT) findProvidersSingle(ctx context.Context, p peer.ID, key u.Key) (*pb.Message, error) {
	pmes := pb.NewMessage(pb.Message_GET_PROVIDERS, string(key), 0)
	return dht.sendRequest(ctx, p, pmes)
}

// nearestPeersToQuery returns the routing tables closest peers.
func (dht *IpfsDHT) nearestPeersToQuery(pmes *pb.Message, count int) []peer.ID {
	key := u.Key(pmes.GetKey())
	closer := dht.routingTable.NearestPeers(kb.ConvertKey(key), count)
	return closer
}

// betterPeerToQuery returns nearestPeersToQuery, but iff closer than self.
func (dht *IpfsDHT) betterPeersToQuery(pmes *pb.Message, p peer.ID, count int) []peer.ID {
	closer := dht.nearestPeersToQuery(pmes, count)

	// no node? nil
	if closer == nil {
		return nil
	}

	// == to self? thats bad
	for _, p := range closer {
		if p == dht.self {
			log.Error("Attempted to return self! this shouldnt happen...")
			return nil
		}
	}

	var filtered []peer.ID
	for _, clp := range closer {
		// Dont send a peer back themselves
		if p == clp {
			continue
		}

		// must all be closer than self
		key := u.Key(pmes.GetKey())
		if !kb.Closer(dht.self, clp, key) {
			filtered = append(filtered, clp)
		}
	}

	// ok seems like closer nodes
	return filtered
}

func (dht *IpfsDHT) ensureConnectedToPeer(ctx context.Context, p peer.ID) error {
	if p == dht.self {
		return errors.New("attempting to ensure connection to self")
	}

	// dial connection
	return dht.host.Connect(ctx, peer.PeerInfo{ID: p})
}

// PingRoutine periodically pings nearest neighbors.
func (dht *IpfsDHT) PingRoutine(t time.Duration) {
	defer dht.Children().Done()

	tick := time.Tick(t)
	for {
		select {
		case <-tick:
			id := make([]byte, 16)
			rand.Read(id)
			peers := dht.routingTable.NearestPeers(kb.ConvertKey(u.Key(id)), 5)
			for _, p := range peers {
				ctx, _ := context.WithTimeout(dht.Context(), time.Second*5)
				err := dht.Ping(ctx, p)
				if err != nil {
					log.Errorf("Ping error: %s", err)
				}
			}
		case <-dht.Closing():
			return
		}
	}
}

// Bootstrap builds up list of peers by requesting random peer IDs
func (dht *IpfsDHT) Bootstrap(ctx context.Context, queries int) error {

	// bootstrap sequentially, as results will compound
	for i := 0; i < NumBootstrapQueries; i++ {
		id := make([]byte, 16)
		rand.Read(id)
		pi, err := dht.FindPeer(ctx, peer.ID(id))
		if err == routing.ErrNotFound {
			// this isn't an error. this is precisely what we expect.
		} else if err != nil {
			log.Errorf("Bootstrap peer error: %s", err)
		} else {
			// woah, we got a peer under a random id? it _cannot_ be valid.
			log.Errorf("dht seemingly found a peer at a random bootstrap id (%s)...", pi)
		}
	}
	return nil
}
<commit_msg>dht: bootstrap query logging<commit_after>// Package dht implements a distributed hash table that satisfies the ipfs routing
// interface. This DHT is modeled after kademlia with Coral and S/Kademlia modifications.
package dht

import (
	"bytes"
	"crypto/rand"
	"errors"
	"fmt"
	"sync"
	"time"

	host "github.com/jbenet/go-ipfs/p2p/host"
	peer "github.com/jbenet/go-ipfs/p2p/peer"
	protocol "github.com/jbenet/go-ipfs/p2p/protocol"
	routing "github.com/jbenet/go-ipfs/routing"
	pb "github.com/jbenet/go-ipfs/routing/dht/pb"
	kb "github.com/jbenet/go-ipfs/routing/kbucket"
	u "github.com/jbenet/go-ipfs/util"
	"github.com/jbenet/go-ipfs/util/eventlog"

	context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
	"github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
	ctxgroup "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-ctxgroup"
	ds "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-datastore"
)

var log = eventlog.Logger("dht")

var ProtocolDHT protocol.ID = "/ipfs/dht"

const doPinging = false

// NumBootstrapQueries defines the number of random dht queries to do to
// collect members of the routing table.
const NumBootstrapQueries = 5

// TODO. SEE https://github.com/jbenet/node-ipfs/blob/master/submodules/ipfs-dht/index.js

// IpfsDHT is an implementation of Kademlia with Coral and S/Kademlia modifications.
// It is used to implement the base IpfsRouting module.
type IpfsDHT struct {
	host      host.Host      // the network services we need
	self      peer.ID        // Local peer (yourself)
	peerstore peer.Peerstore // Peer Registry

	datastore ds.ThreadSafeDatastore // Local data

	routingTable *kb.RoutingTable // Array of routing tables for differently distanced nodes
	providers    *ProviderManager

	birth    time.Time  // When this peer started up
	diaglock sync.Mutex // lock to make diagnostics work better

	// record validator funcs
	Validators map[string]ValidatorFunc

	ctxgroup.ContextGroup
}

// NewDHT creates a new DHT object with the given peer as the 'local' host
func NewDHT(ctx context.Context, h host.Host, dstore ds.ThreadSafeDatastore) *IpfsDHT {
	dht := new(IpfsDHT)
	dht.datastore = dstore
	dht.self = h.ID()
	dht.peerstore = h.Peerstore()
	dht.ContextGroup = ctxgroup.WithContext(ctx)
	dht.host = h
	h.SetStreamHandler(ProtocolDHT, dht.handleNewStream)

	dht.providers = NewProviderManager(dht.Context(), dht.self)
	dht.AddChildGroup(dht.providers)

	dht.routingTable = kb.NewRoutingTable(20, kb.ConvertPeerID(dht.self), time.Minute, dht.peerstore)
	dht.birth = time.Now()

	dht.Validators = make(map[string]ValidatorFunc)
	dht.Validators["pk"] = ValidatePublicKeyRecord

	if doPinging {
		dht.Children().Add(1)
		go dht.PingRoutine(time.Second * 10)
	}
	return dht
}

// LocalPeer returns the peer.Peer of the dht.
func (dht *IpfsDHT) LocalPeer() peer.ID {
	return dht.self
}

// log returns the dht's logger
func (dht *IpfsDHT) log() eventlog.EventLogger {
	return log.Prefix("dht(%s)", dht.self)
}

// Connect to a new peer at the given address, ping and add to the routing table
func (dht *IpfsDHT) Connect(ctx context.Context, npeer peer.ID) error {
	// TODO: change interface to accept a PeerInfo as well.
	if err := dht.host.Connect(ctx, peer.PeerInfo{ID: npeer}); err != nil {
		return err
	}

	// Ping new peer to register in their routing table
	// NOTE: this should be done better...
	if err := dht.Ping(ctx, npeer); err != nil {
		return fmt.Errorf("failed to ping newly connected peer: %s\n", err)
	}
	log.Event(ctx, "connect", dht.self, npeer)
	dht.Update(ctx, npeer)
	return nil
}

// putValueToPeer stores the given key/value pair at the peer 'p'
func (dht *IpfsDHT) putValueToPeer(ctx context.Context, p peer.ID,
	key u.Key, rec *pb.Record) error {

	pmes := pb.NewMessage(pb.Message_PUT_VALUE, string(key), 0)
	pmes.Record = rec
	rpmes, err := dht.sendRequest(ctx, p, pmes)
	if err != nil {
		return err
	}

	if !bytes.Equal(rpmes.GetRecord().Value, pmes.GetRecord().Value) {
		return errors.New("value not put correctly")
	}
	return nil
}

// putProvider sends a message to peer 'p' saying that the local node
// can provide the value of 'key'
func (dht *IpfsDHT) putProvider(ctx context.Context, p peer.ID, key string) error {

	pmes := pb.NewMessage(pb.Message_ADD_PROVIDER, string(key), 0)

	// add self as the provider
	pi := dht.peerstore.PeerInfo(dht.self)
	pmes.ProviderPeers = pb.PeerInfosToPBPeers(dht.host.Network(), []peer.PeerInfo{pi})

	err := dht.sendMessage(ctx, p, pmes)
	if err != nil {
		return err
	}

	log.Debugf("%s putProvider: %s for %s (%s)", dht.self, p, u.Key(key), pi.Addrs)

	return nil
}

// getValueOrPeers queries a particular peer p for the value for
// key. It returns either the value or a list of closer peers.
// NOTE: it will update the dht's peerstore with any new addresses
// it finds for the given peer.
func (dht *IpfsDHT) getValueOrPeers(ctx context.Context, p peer.ID,
	key u.Key) ([]byte, []peer.PeerInfo, error) {

	pmes, err := dht.getValueSingle(ctx, p, key)
	if err != nil {
		return nil, nil, err
	}

	if record := pmes.GetRecord(); record != nil {
		// Success! We were given the value
		log.Debug("getValueOrPeers: got value")

		// make sure record is valid.
		err = dht.verifyRecordOnline(ctx, record)
		if err != nil {
			log.Error("Received invalid record!")
			return nil, nil, err
		}
		return record.GetValue(), nil, nil
	}

	// Perhaps we were given closer peers
	peers := pb.PBPeersToPeerInfos(pmes.GetCloserPeers())
	if len(peers) > 0 {
		log.Debug("getValueOrPeers: peers")
		return nil, peers, nil
	}

	log.Warning("getValueOrPeers: routing.ErrNotFound")
	return nil, nil, routing.ErrNotFound
}

// getValueSingle simply performs the get value RPC with the given parameters
func (dht *IpfsDHT) getValueSingle(ctx context.Context, p peer.ID,
	key u.Key) (*pb.Message, error) {

	pmes := pb.NewMessage(pb.Message_GET_VALUE, string(key), 0)
	return dht.sendRequest(ctx, p, pmes)
}

// getLocal attempts to retrieve the value from the datastore
func (dht *IpfsDHT) getLocal(key u.Key) ([]byte, error) {

	log.Debug("getLocal %s", key)
	v, err := dht.datastore.Get(key.DsKey())
	if err != nil {
		return nil, err
	}
	log.Debug("found in db")

	byt, ok := v.([]byte)
	if !ok {
		return nil, errors.New("value stored in datastore not []byte")
	}
	rec := new(pb.Record)
	err = proto.Unmarshal(byt, rec)
	if err != nil {
		return nil, err
	}

	// TODO: 'if paranoid'
	if u.Debug {
		err = dht.verifyRecordLocally(rec)
		if err != nil {
			log.Errorf("local record verify failed: %s", err)
			return nil, err
		}
	}

	return rec.GetValue(), nil
}

// putLocal stores the key value pair in the datastore
func (dht *IpfsDHT) putLocal(key u.Key, value []byte) error {
	rec, err := dht.makePutRecord(key, value)
	if err != nil {
		return err
	}
	data, err := proto.Marshal(rec)
	if err != nil {
		return err
	}

	return dht.datastore.Put(key.DsKey(), data)
}

// Update signals the routingTable to Update its last-seen status
// on the given peer.
func (dht *IpfsDHT) Update(ctx context.Context, p peer.ID) {
	log.Event(ctx, "updatePeer", p)
	dht.routingTable.Update(p)
}

// FindLocal looks for a peer with a given ID connected to this dht and returns the peer and the table it was found in.
func (dht *IpfsDHT) FindLocal(id peer.ID) peer.PeerInfo {
	p := dht.routingTable.Find(id)
	if p != "" {
		return dht.peerstore.PeerInfo(p)
	}
	return peer.PeerInfo{}
}

// findPeerSingle asks peer 'p' if they know where the peer with id 'id' is
func (dht *IpfsDHT) findPeerSingle(ctx context.Context, p peer.ID, id peer.ID) (*pb.Message, error) {
	pmes := pb.NewMessage(pb.Message_FIND_NODE, string(id), 0)
	return dht.sendRequest(ctx, p, pmes)
}

func (dht *IpfsDHT) findProvidersSingle(ctx context.Context, p peer.ID, key u.Key) (*pb.Message, error) {
	pmes := pb.NewMessage(pb.Message_GET_PROVIDERS, string(key), 0)
	return dht.sendRequest(ctx, p, pmes)
}

// nearestPeersToQuery returns the routing tables closest peers.
func (dht *IpfsDHT) nearestPeersToQuery(pmes *pb.Message, count int) []peer.ID {
	key := u.Key(pmes.GetKey())
	closer := dht.routingTable.NearestPeers(kb.ConvertKey(key), count)
	return closer
}

// betterPeerToQuery returns nearestPeersToQuery, but iff closer than self.
func (dht *IpfsDHT) betterPeersToQuery(pmes *pb.Message, p peer.ID, count int) []peer.ID {
	closer := dht.nearestPeersToQuery(pmes, count)

	// no node? nil
	if closer == nil {
		return nil
	}

	// == to self? thats bad
	for _, p := range closer {
		if p == dht.self {
			log.Error("Attempted to return self! this shouldnt happen...")
			return nil
		}
	}

	var filtered []peer.ID
	for _, clp := range closer {
		// Dont send a peer back themselves
		if p == clp {
			continue
		}

		// must all be closer than self
		key := u.Key(pmes.GetKey())
		if !kb.Closer(dht.self, clp, key) {
			filtered = append(filtered, clp)
		}
	}

	// ok seems like closer nodes
	return filtered
}

func (dht *IpfsDHT) ensureConnectedToPeer(ctx context.Context, p peer.ID) error {
	if p == dht.self {
		return errors.New("attempting to ensure connection to self")
	}

	// dial connection
	return dht.host.Connect(ctx, peer.PeerInfo{ID: p})
}

// PingRoutine periodically pings nearest neighbors.
func (dht *IpfsDHT) PingRoutine(t time.Duration) {
	defer dht.Children().Done()

	tick := time.Tick(t)
	for {
		select {
		case <-tick:
			id := make([]byte, 16)
			rand.Read(id)
			peers := dht.routingTable.NearestPeers(kb.ConvertKey(u.Key(id)), 5)
			for _, p := range peers {
				ctx, _ := context.WithTimeout(dht.Context(), time.Second*5)
				err := dht.Ping(ctx, p)
				if err != nil {
					log.Errorf("Ping error: %s", err)
				}
			}
		case <-dht.Closing():
			return
		}
	}
}

// Bootstrap builds up list of peers by requesting random peer IDs
func (dht *IpfsDHT) Bootstrap(ctx context.Context, queries int) error {

	randomID := func() peer.ID {
		// 16 random bytes is not a valid peer id. it may be fine becuase
		// the dht will rehash to its own keyspace anyway.
		id := make([]byte, 16)
		rand.Read(id)
		return peer.ID(id)
	}

	// bootstrap sequentially, as results will compound
	for i := 0; i < queries; i++ {
		id := randomID()
		log.Debugf("Bootstrapping query (%d/%d) to random ID: %s", i, queries, id)
		p, err := dht.FindPeer(ctx, id)
		if err == routing.ErrNotFound {
			// this isn't an error. this is precisely what we expect.
		} else if err != nil {
			log.Errorf("Bootstrap peer error: %s", err)
		} else {
			// woah, we got a peer under a random id? it _cannot_ be valid.
			log.Errorf("dht seemingly found a peer at a random bootstrap id (%s)...", p)
		}
	}
	return nil
}
<|endoftext|>


<commit_before><commit_msg>fix the inline key test<commit_after><|endoftext|>


<commit_before>package healthcheck

import (
	"github.com/btcsuite/btclog"
	"github.com/lightningnetwork/lnd/build"
)

// Subsystem defines the logging code for this subsystem.
const Subsystem = "HLCK"

// log is a logger that is initialized with no output filters.  This
// means the package will not perform any logging by default until the caller
// requests it.
var log btclog.Logger

// The default amount of logging is none.
func init() {
	UseLogger(build.NewSubLogger(Subsystem, nil))
}

// DisableLog disables all library log output.  Logging output is disabled
// by default until UseLogger is called.
func DisableLog() {
	UseLogger(btclog.Disabled)
}

// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using btclog.
func UseLogger(logger btclog.Logger) {
	log = logger
}
<commit_msg>healthcheck: disable default healthcheck logger<commit_after>package healthcheck

import (
	"github.com/btcsuite/btclog"
)

// Subsystem defines the logging code for this subsystem.
const Subsystem = "HLCK"

// log is a logger that is initialized with no output filters.  This
// means the package will not perform any logging by default until the caller
// requests it.
var log = btclog.Disabled

// DisableLog disables all library log output.  Logging output is disabled
// by default until UseLogger is called.
func DisableLog() {
	UseLogger(btclog.Disabled)
}

// UseLogger uses a specified Logger to output package logging info.
// This should be used in preference to SetLogWriter if the caller is also
// using btclog.
func UseLogger(logger btclog.Logger) {
	log = logger
}
<|endoftext|>


<commit_before>package helpers

import (
	"C"
	"bytes"
	_ "image/jpeg"
	_ "image/png"
	"time"

	"image"
	"strings"

	"github.com/lucasb-eyer/go-colorful"
	"github.com/ungerik/go-cairo"
)

// Creates a Collage PNG Image from internet image urls (PNG or JPEG).
// imageUrls		: a slice with all image URLs. Empty strings will create an empty space in the collage.
// descriptions		: a slice with text that will be written on each tile. Can be empty.
// width			: the width of the result collage image.
// height			: the height of the result collage image.
// tileWidth		: the width of each tile image.
// tileHeight		: the height of each tile image.
// backgroundColour	: the background colour as a hex string.
func CollageFromUrls(imageUrls, descriptions []string, width, height, tileWidth, tileHeight int, backgroundColour string) (collageBytes []byte) {
	imageDataArray := make([][]byte, 0)
	// download images
	for _, imageUrl := range imageUrls {
		if imageUrl == "" {
			imageDataArray = append(imageDataArray, nil)
			continue
		}
		imageData, err := NetGetUAWithErrorAndTimeout(imageUrl, DEFAULT_UA, 15*time.Second)
		RelaxLog(err)
		if err == nil {
			imageDataArray = append(imageDataArray, imageData)
		} else {
			imageDataArray = append(imageDataArray, nil)
		}
	}

	// create surface with given background colour
	backgroundColourRGB, _ := colorful.Hex(backgroundColour)
	cairoSurface := cairo.NewSurface(cairo.FORMAT_RGB24, width, height)
	cairoSurface.SetSourceRGB(backgroundColourRGB.R, backgroundColourRGB.G, backgroundColourRGB.B)
	cairoSurface.Paint()

	var posX, posY int

	for i, imageData := range imageDataArray {
		// switch tile to new line if required
		if posX > 0 && posX+tileWidth > width {
			posY += tileHeight
			posX = 0
		}
		// draw image on tile if image exists
		if imageData != nil && len(imageData) > 0 {
			tileImage, _, err := image.Decode(bytes.NewReader(imageData))
			RelaxLog(err)
			if err == nil {
				tileSurface := cairo.NewSurfaceFromImage(tileImage)
				cairoSurface.SetSourceSurface(tileSurface, float64(posX), float64(posY))
				cairoSurface.Paint()
			}
		}
		// draw description on tile if description exists
		if len(descriptions) > i {
			// setup font and variables
			cairoSurface.SelectFontFace("UnDotum", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
			var offset, fontSize int
			// split description in lines
			lines := strings.Split(descriptions[i], "\n")
			for _, line := range lines {
				// clean line
				line = strings.TrimSpace(line)
				// reset font size
				fontSize = 28
				// adjust font size to fit tile
				for {
					// gather dimensions of line with current font size
					cairoSurface.SetFontSize(float64(fontSize))
					extend := cairoSurface.TextExtents(line)
					// break if line fits into tile, or font size is <= 10
					if extend.Width < float64(tileWidth)-6-6 || fontSize <= 10 {
						break
					}
					// try a smaller font
					fontSize--
				}
				// draw text
				cairoSurface.SetSourceRGB(1, 1, 1) // white
				cairoSurface.MoveTo(float64(posX+6), float64(posY+6+fontSize+offset))
				cairoSurface.ShowText(line)
				// draw white outline to improve readability
				cairoSurface.MoveTo(float64(posX+6), float64(posY+6+fontSize+offset))
				cairoSurface.TextPath(line)
				cairoSurface.SetSourceRGB(0, 0, 0) // black
				cairoSurface.SetLineWidth(4.5)
				cairoSurface.Stroke()
				// draw black outline to make text bold
				cairoSurface.MoveTo(float64(posX+6), float64(posY+6+fontSize+offset))
				cairoSurface.TextPath(line)
				cairoSurface.SetSourceRGB(1, 1, 1) // white
				cairoSurface.SetLineWidth(2.5)
				cairoSurface.Stroke()
				// switch to new line
				offset += fontSize + 6
			}
		}
		// switch to next tile
		posX += tileWidth
	}

	// write surface to byte slice and return it
	bytesData, _ := cairoSurface.WriteToPNGStream()
	return bytesData
}
<commit_msg>[collage] add CollageFromBytes so that requesting from url isn't required<commit_after>package helpers

import (
	"C"
	"bytes"
	_ "image/jpeg"
	_ "image/png"
	"time"

	"image"
	"strings"

	"github.com/lucasb-eyer/go-colorful"
	"github.com/ungerik/go-cairo"
)

// Creates a Collage PNG Image from internet image urls (PNG or JPEG).
// imageUrls		: a slice with all image URLs. Empty strings will create an empty space in the collage.
// descriptions		: a slice with text that will be written on each tile. Can be empty.
// width			: the width of the result collage image.
// height			: the height of the result collage image.
// tileWidth		: the width of each tile image.
// tileHeight		: the height of each tile image.
// backgroundColour	: the background colour as a hex string.
func CollageFromUrls(imageUrls, descriptions []string, width, height, tileWidth, tileHeight int, backgroundColour string) (collageBytes []byte) {
	imageDataArray := make([][]byte, 0)
	// download images
	for _, imageUrl := range imageUrls {
		if imageUrl == "" {
			imageDataArray = append(imageDataArray, nil)
			continue
		}
		imageData, err := NetGetUAWithErrorAndTimeout(imageUrl, DEFAULT_UA, 15*time.Second)
		RelaxLog(err)
		if err == nil {
			imageDataArray = append(imageDataArray, imageData)
		} else {
			imageDataArray = append(imageDataArray, nil)
		}
	}

	return CollageFromBytes(imageDataArray, descriptions, width, height, tileWidth, tileHeight, backgroundColour)
}

// Creates a Collage PNG Image from image []byte (PNG or JPEG).
// imageDataArray   : a slice of all image []byte data
// descriptions		: a slice with text that will be written on each tile. Can be empty.
// width			: the width of the result collage image.
// height			: the height of the result collage image.
// tileWidth		: the width of each tile image.
// tileHeight		: the height of each tile image.
// backgroundColour	: the background colour as a hex string.
func CollageFromBytes(imageDataArray [][]byte, descriptions []string, width, height, tileWidth, tileHeight int, backgroundColour string) (collageBytes []byte) {

	// create surface with given background colour
	backgroundColourRGB, _ := colorful.Hex(backgroundColour)
	cairoSurface := cairo.NewSurface(cairo.FORMAT_RGB24, width, height)
	cairoSurface.SetSourceRGB(backgroundColourRGB.R, backgroundColourRGB.G, backgroundColourRGB.B)
	cairoSurface.Paint()

	var posX, posY int

	for i, imageData := range imageDataArray {
		// switch tile to new line if required
		if posX > 0 && posX+tileWidth > width {
			posY += tileHeight
			posX = 0
		}
		// draw image on tile if image exists
		if imageData != nil && len(imageData) > 0 {
			tileImage, _, err := image.Decode(bytes.NewReader(imageData))
			RelaxLog(err)
			if err == nil {
				tileSurface := cairo.NewSurfaceFromImage(tileImage)
				cairoSurface.SetSourceSurface(tileSurface, float64(posX), float64(posY))
				cairoSurface.Paint()
			}
		}
		// draw description on tile if description exists
		if len(descriptions) > i {
			// setup font and variables
			cairoSurface.SelectFontFace("UnDotum", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
			var offset, fontSize int
			// split description in lines
			lines := strings.Split(descriptions[i], "\n")
			for _, line := range lines {
				// clean line
				line = strings.TrimSpace(line)
				// reset font size
				fontSize = 28
				// adjust font size to fit tile
				for {
					// gather dimensions of line with current font size
					cairoSurface.SetFontSize(float64(fontSize))
					extend := cairoSurface.TextExtents(line)
					// break if line fits into tile, or font size is <= 10
					if extend.Width < float64(tileWidth)-6-6 || fontSize <= 10 {
						break
					}
					// try a smaller font
					fontSize--
				}
				// draw text
				cairoSurface.SetSourceRGB(1, 1, 1) // white
				cairoSurface.MoveTo(float64(posX+6), float64(posY+6+fontSize+offset))
				cairoSurface.ShowText(line)
				// draw white outline to improve readability
				cairoSurface.MoveTo(float64(posX+6), float64(posY+6+fontSize+offset))
				cairoSurface.TextPath(line)
				cairoSurface.SetSourceRGB(0, 0, 0) // black
				cairoSurface.SetLineWidth(4.5)
				cairoSurface.Stroke()
				// draw black outline to make text bold
				cairoSurface.MoveTo(float64(posX+6), float64(posY+6+fontSize+offset))
				cairoSurface.TextPath(line)
				cairoSurface.SetSourceRGB(1, 1, 1) // white
				cairoSurface.SetLineWidth(2.5)
				cairoSurface.Stroke()
				// switch to new line
				offset += fontSize + 6
			}
		}
		// switch to next tile
		posX += tileWidth
	}

	// write surface to byte slice and return it
	bytesData, _ := cairoSurface.WriteToPNGStream()
	return bytesData
}
<|endoftext|>


<commit_before>// Package hipchat provides a client for using the HipChat API v2.
package hipchat

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"

	"github.com/google/go-querystring/query"
)

const (
	defaultBaseURL = "https://api.hipchat.com/v2/"
)

// Client manages the communication with the HipChat API.
type Client struct {
	authToken string
	BaseURL   *url.URL
	client    *http.Client
	// Room gives access to the /room part of the API.
	Room *RoomService
	// User gives access to the /user part of the API.
	User *UserService
	// Emoticon gives access to the /emoticon part of the API.
	Emoticon *EmoticonService
}

// Links represents the HipChat default links.
type Links struct {
	Self string `json:"self"`
}

// PageLinks represents the HipChat page links.
type PageLinks struct {
	Links
	Prev string `json:"prev"`
	Next string `json:"next"`
}

// ID represents a HipChat id.
// Use a separate struct because it can be a string or a int.
type ID struct {
	ID string `json:"id"`
}

// ListOptions  specifies the optional parameters to various List methods that
// support pagination.
type ListOptions struct {
	// For paginated results, represents the first page to display.
	StartIndex int `url:"start-index,omitempty"`
	// For paginated results, reprensents the number of items per page.
	MaxResults int `url:"max-results,omitempty"`
}

type Color string

const (
	ColorYellow Color = "yellow"
	ColorGreen  Color = "green"
	ColorRed    Color = "red"
	ColorPurple Color = "purple"
	ColorGray   Color = "gray"
	ColorRandom Color = "random"
)

// AuthTest can be set to true to test an auth token.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/auth#auth_test
var AuthTest = false

// AuthTestResponse will contain the server response of any
// API calls if AuthTest=true.
var AuthTestResponse = map[string]interface{}{}

// NewClient returns a new HipChat API client. You must provide a valid
// AuthToken retrieved from your HipChat account.
func NewClient(authToken string) *Client {
	baseURL, err := url.Parse(defaultBaseURL)
	if err != nil {
		panic(err)
	}

	c := &Client{
		authToken: authToken,
		BaseURL:   baseURL,
		client:    http.DefaultClient,
	}
	c.Room = &RoomService{client: c}
	c.User = &UserService{client: c}
	c.Emoticon = &EmoticonService{client: c}
	return c
}

// SetHTTPClient sets the HTTP client for performing API requests.
// If a nil httpClient is provided, http.DefaultClient will be used.
func (c *Client) SetHTTPClient(httpClient *http.Client) {
	if httpClient == nil {
		c.client = http.DefaultClient
	} else {
		c.client = httpClient
	}
}

// NewRequest creates an API request. This method can be used to performs
// API request not implemented in this library. Otherwise it should not be
// be used directly.
// Relative URLs should always be specified without a preceding slash.
func (c *Client) NewRequest(method, urlStr string, opt interface{}, body interface{}) (*http.Request, error) {
	rel, err := addOptions(urlStr, opt)
	if err != nil {
		return nil, err
	}

	if AuthTest {
		// Add the auth_test param
		values := rel.Query()
		values.Add("auth_test", strconv.FormatBool(AuthTest))
		rel.RawQuery = values.Encode()
	}

	u := c.BaseURL.ResolveReference(rel)

	buf := new(bytes.Buffer)
	if body != nil {
		err := json.NewEncoder(buf).Encode(body)
		if err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Authorization", "Bearer "+c.authToken)
	req.Header.Add("Content-Type", "application/json")
	return req, nil
}

// NewFileUploadRequest creates an API request to upload a file.
// This method manually formats the request as multipart/related with a single part
// of content-type application/json and a second part containing the file to be sent.
// Relative URLs should always be specified without a preceding slash.
func (c *Client) NewFileUploadRequest(method, urlStr string, v interface{}) (*http.Request, error) {
	rel, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)

	shareFileReq, ok := v.(*ShareFileRequest)
	if !ok {
		return nil, errors.New("ShareFileRequest corrupted")
	}
	path := shareFileReq.Path
	message := shareFileReq.Message

	// Resolve home path
	if strings.HasPrefix(path, "~") {
		usr, _ := user.Current()
		path = strings.Replace(path, "~", usr.HomeDir, 1)
	}

	// Check if file exists
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return nil, err
	}

	// Read file and encode to base 64
	file, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	b64 := base64.StdEncoding.EncodeToString(file)
	contentType := mime.TypeByExtension(filepath.Ext(path))

	// Set proper filename
	filename := shareFileReq.Filename
	if filename == "" {
		filename = filepath.Base(path)
	} else if filepath.Ext(filename) != filepath.Ext(path) {
		filename = filepath.Base(filename) + filepath.Ext(path)
	}

	// Build request body
	body := "--hipfileboundary\n" +
		"Content-Type: application/json; charset=UTF-8\n" +
		"Content-Disposition: attachment; name=\"metadata\"\n\n" +
		"{\"message\": \"" + message + "\"}\n" +
		"--hipfileboundary\n" +
		"Content-Type: " + contentType + " charset=UTF-8\n" +
		"Content-Transfer-Encoding: base64\n" +
		"Content-Disposition: attachment; name=file; filename=" + filename + "\n\n" +
		b64 + "\n" +
		"--hipfileboundary\n"

	b := &bytes.Buffer{}
	b.Write([]byte(body))

	req, err := http.NewRequest(method, u.String(), b)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Authorization", "Bearer "+c.authToken)
	req.Header.Add("Content-Type", "multipart/related; boundary=hipfileboundary")

	return req, err
}

// Do performs the request, the json received in the response is decoded
// and stored in the value pointed by v.
// Do can be used to perform the request created with NewRequest, as the latter
// it should be used only for API requests not implemented in this library.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	if AuthTest {
		// If AuthTest is enabled, the reponse won't be the
		// one defined in the API endpoint.
		err = json.NewDecoder(resp.Body).Decode(&AuthTestResponse)
	} else {
		if c := resp.StatusCode; c < 200 || c > 299 {
			return resp, fmt.Errorf("Server returns status %d", c)
		}

		if v != nil {
			defer resp.Body.Close()
			if w, ok := v.(io.Writer); ok {
				io.Copy(w, resp.Body)
			} else {
				err = json.NewDecoder(resp.Body).Decode(v)
			}
		}
	}
	return resp, err
}

// addOptions adds the parameters in opt as URL query parameters to s.  opt
// must be a struct whose fields may contain "url" tags.
func addOptions(s string, opt interface{}) (*url.URL, error) {
	u, err := url.Parse(s)
	if err != nil {
		return nil, err
	}
	if opt == nil {
		return u, nil
	}

	v := reflect.ValueOf(opt)
	if v.Kind() == reflect.Ptr && v.IsNil() {
		// No query string to add
		return u, nil
	}

	qs, err := query.Values(opt)
	if err != nil {
		return nil, err
	}

	u.RawQuery = qs.Encode()
	return u, nil
}
<commit_msg>Use an interface so non-default http clients can be used.<commit_after>// Package hipchat provides a client for using the HipChat API v2.
package hipchat

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net/http"
	"net/url"
	"os"
	"os/user"
	"path/filepath"
	"reflect"
	"strconv"
	"strings"

	"github.com/google/go-querystring/query"
)

const (
	defaultBaseURL = "https://api.hipchat.com/v2/"
)

// HTTPClient is an interface that allows overriding the http behavior
// by providing custom http clients
type HTTPClient interface {
	Do(req *http.Request) (res *http.Response, err error)
}

// Client manages the communication with the HipChat API.
type Client struct {
	authToken string
	BaseURL   *url.URL
	client    HTTPClient
	// Room gives access to the /room part of the API.
	Room *RoomService
	// User gives access to the /user part of the API.
	User *UserService
	// Emoticon gives access to the /emoticon part of the API.
	Emoticon *EmoticonService
}

// Links represents the HipChat default links.
type Links struct {
	Self string `json:"self"`
}

// PageLinks represents the HipChat page links.
type PageLinks struct {
	Links
	Prev string `json:"prev"`
	Next string `json:"next"`
}

// ID represents a HipChat id.
// Use a separate struct because it can be a string or a int.
type ID struct {
	ID string `json:"id"`
}

// ListOptions  specifies the optional parameters to various List methods that
// support pagination.
type ListOptions struct {
	// For paginated results, represents the first page to display.
	StartIndex int `url:"start-index,omitempty"`
	// For paginated results, reprensents the number of items per page.
	MaxResults int `url:"max-results,omitempty"`
}

type Color string

const (
	ColorYellow Color = "yellow"
	ColorGreen  Color = "green"
	ColorRed    Color = "red"
	ColorPurple Color = "purple"
	ColorGray   Color = "gray"
	ColorRandom Color = "random"
)

// AuthTest can be set to true to test an auth token.
//
// HipChat API docs: https://www.hipchat.com/docs/apiv2/auth#auth_test
var AuthTest = false

// AuthTestResponse will contain the server response of any
// API calls if AuthTest=true.
var AuthTestResponse = map[string]interface{}{}

// NewClient returns a new HipChat API client. You must provide a valid
// AuthToken retrieved from your HipChat account.
func NewClient(authToken string) *Client {
	baseURL, err := url.Parse(defaultBaseURL)
	if err != nil {
		panic(err)
	}

	c := &Client{
		authToken: authToken,
		BaseURL:   baseURL,
		client:    http.DefaultClient,
	}
	c.Room = &RoomService{client: c}
	c.User = &UserService{client: c}
	c.Emoticon = &EmoticonService{client: c}
	return c
}

// SetHTTPClient sets the HTTP client for performing API requests.
// If a nil httpClient is provided, http.DefaultClient will be used.
func (c *Client) SetHTTPClient(httpClient HTTPClient) {
	if httpClient == nil {
		c.client = http.DefaultClient
	} else {
		c.client = httpClient
	}
}

// NewRequest creates an API request. This method can be used to performs
// API request not implemented in this library. Otherwise it should not be
// be used directly.
// Relative URLs should always be specified without a preceding slash.
func (c *Client) NewRequest(method, urlStr string, opt interface{}, body interface{}) (*http.Request, error) {
	rel, err := addOptions(urlStr, opt)
	if err != nil {
		return nil, err
	}

	if AuthTest {
		// Add the auth_test param
		values := rel.Query()
		values.Add("auth_test", strconv.FormatBool(AuthTest))
		rel.RawQuery = values.Encode()
	}

	u := c.BaseURL.ResolveReference(rel)

	buf := new(bytes.Buffer)
	if body != nil {
		err := json.NewEncoder(buf).Encode(body)
		if err != nil {
			return nil, err
		}
	}

	req, err := http.NewRequest(method, u.String(), buf)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Authorization", "Bearer "+c.authToken)
	req.Header.Add("Content-Type", "application/json")
	return req, nil
}

// NewFileUploadRequest creates an API request to upload a file.
// This method manually formats the request as multipart/related with a single part
// of content-type application/json and a second part containing the file to be sent.
// Relative URLs should always be specified without a preceding slash.
func (c *Client) NewFileUploadRequest(method, urlStr string, v interface{}) (*http.Request, error) {
	rel, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)

	shareFileReq, ok := v.(*ShareFileRequest)
	if !ok {
		return nil, errors.New("ShareFileRequest corrupted")
	}
	path := shareFileReq.Path
	message := shareFileReq.Message

	// Resolve home path
	if strings.HasPrefix(path, "~") {
		usr, _ := user.Current()
		path = strings.Replace(path, "~", usr.HomeDir, 1)
	}

	// Check if file exists
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return nil, err
	}

	// Read file and encode to base 64
	file, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	b64 := base64.StdEncoding.EncodeToString(file)
	contentType := mime.TypeByExtension(filepath.Ext(path))

	// Set proper filename
	filename := shareFileReq.Filename
	if filename == "" {
		filename = filepath.Base(path)
	} else if filepath.Ext(filename) != filepath.Ext(path) {
		filename = filepath.Base(filename) + filepath.Ext(path)
	}

	// Build request body
	body := "--hipfileboundary\n" +
		"Content-Type: application/json; charset=UTF-8\n" +
		"Content-Disposition: attachment; name=\"metadata\"\n\n" +
		"{\"message\": \"" + message + "\"}\n" +
		"--hipfileboundary\n" +
		"Content-Type: " + contentType + " charset=UTF-8\n" +
		"Content-Transfer-Encoding: base64\n" +
		"Content-Disposition: attachment; name=file; filename=" + filename + "\n\n" +
		b64 + "\n" +
		"--hipfileboundary\n"

	b := &bytes.Buffer{}
	b.Write([]byte(body))

	req, err := http.NewRequest(method, u.String(), b)
	if err != nil {
		return nil, err
	}

	req.Header.Add("Authorization", "Bearer "+c.authToken)
	req.Header.Add("Content-Type", "multipart/related; boundary=hipfileboundary")

	return req, err
}

// Do performs the request, the json received in the response is decoded
// and stored in the value pointed by v.
// Do can be used to perform the request created with NewRequest, as the latter
// it should be used only for API requests not implemented in this library.
func (c *Client) Do(req *http.Request, v interface{}) (*http.Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	if AuthTest {
		// If AuthTest is enabled, the reponse won't be the
		// one defined in the API endpoint.
		err = json.NewDecoder(resp.Body).Decode(&AuthTestResponse)
	} else {
		if c := resp.StatusCode; c < 200 || c > 299 {
			return resp, fmt.Errorf("Server returns status %d", c)
		}

		if v != nil {
			defer resp.Body.Close()
			if w, ok := v.(io.Writer); ok {
				io.Copy(w, resp.Body)
			} else {
				err = json.NewDecoder(resp.Body).Decode(v)
			}
		}
	}
	return resp, err
}

// addOptions adds the parameters in opt as URL query parameters to s.  opt
// must be a struct whose fields may contain "url" tags.
func addOptions(s string, opt interface{}) (*url.URL, error) {
	u, err := url.Parse(s)
	if err != nil {
		return nil, err
	}
	if opt == nil {
		return u, nil
	}

	v := reflect.ValueOf(opt)
	if v.Kind() == reflect.Ptr && v.IsNil() {
		// No query string to add
		return u, nil
	}

	qs, err := query.Values(opt)
	if err != nil {
		return nil, err
	}

	u.RawQuery = qs.Encode()
	return u, nil
}
<|endoftext|>


<commit_before>package cloudflare

import (
	"encoding/json"
	"fmt"
)

/*
Create a DNS record.

API reference:
  https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record
  POST /zones/:zone_identifier/dns_records
*/
func (api *API) CreateDNSRecord(zone string, rr DNSRecord) error {
	z, err := api.ListZones(zone)
	if err != nil {
		return err
	}
	// TODO(jamesog): This is brittle, fix it
	zid := z[0].ID
	uri := "/zones/" + zid + "/dns_records"
	res, err := api.makeRequest("POST", uri, rr)
	if err != nil {
		fmt.Println("Error with makeRequest")
		return err
	}
	var r DNSRecordResponse
	err = json.Unmarshal(res, &r)
	if err != nil {
		fmt.Println("Error with unmarshal")
		return err
	}
	return nil
}

/*
Fetches DNS records for a zone.

API reference:
  https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
  GET /zones/:zone_identifier/dns_records
*/
func (api *API) DNSRecords(zone string) ([]DNSRecord, error) {
	z, err := api.ListZones(zone)
	if err != nil {
		return []DNSRecord{}, err
	}
	// TODO(jamesog): This is brittle, fix it
	zid := z[0].ID
	uri := "/zones/" + zid + "/dns_records"
	res, err := api.makeRequest("GET", uri, nil)
	if err != nil {
		return []DNSRecord{}, err
	}
	var r DNSListResponse
	err = json.Unmarshal(res, &r)
	if err != nil {
		return []DNSRecord{}, err
	}
	return r.Result, nil
}

// https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details
// GET /zones/:zone_identifier/dns_records/:identifier
func (api *API) DNSRecord() {
}

/*
Change a DNS record.

API reference:
  https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
  PUT /zones/:zone_identifier/dns_records/:identifier
*/
func (api *API) UpdateDNSRecord(zone, id string) error {
	return nil
}

/*
Delete a DNS record.

API reference:
  https://api.cloudflare.com/#dns-records-for-a-zone-delete-dns-record
  DELETE /zones/:zone_identifier/dns_records/:identifier
*/
func (api *API) DeleteDNSRecord(zone, id string) error {
	z, err := api.ListZones(zone)
	if err != nil {
		return err
	}
	// TODO(jamesog): This is brittle, fix it
	zid := z[0].ID
	uri := "/zones/" + zid + "/dns_records/" + id
	res, err := api.makeRequest("DELETE", uri, nil)
	if err != nil {
		fmt.Println("Error with makeRequest")
		return err
	}
	var r DNSRecordResponse
	err = json.Unmarshal(res, &r)
	if err != nil {
		fmt.Println("Error with unmarshal")
		return err
	}
	return nil
}
<commit_msg>DNSRecords: Implement record filtering<commit_after>package cloudflare

import (
	"encoding/json"
	"fmt"
	"net/url"
)

/*
Create a DNS record.

API reference:
  https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record
  POST /zones/:zone_identifier/dns_records
*/
func (api *API) CreateDNSRecord(zone string, rr DNSRecord) error {
	z, err := api.ListZones(zone)
	if err != nil {
		return err
	}
	// TODO(jamesog): This is brittle, fix it
	zid := z[0].ID
	uri := "/zones/" + zid + "/dns_records"
	res, err := api.makeRequest("POST", uri, rr)
	if err != nil {
		fmt.Println("Error with makeRequest")
		return err
	}
	var r DNSRecordResponse
	err = json.Unmarshal(res, &r)
	if err != nil {
		fmt.Println("Error with unmarshal")
		return err
	}
	return nil
}

/*
Fetches DNS records for a zone.

API reference:
  https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
  GET /zones/:zone_identifier/dns_records
*/
func (api *API) DNSRecords(zone string, rr DNSRecord) ([]DNSRecord, error) {
	z, err := api.ListZones(zone)
	if err != nil {
		return []DNSRecord{}, err
	}
	// TODO(jamesog): This is brittle, fix it
	zid := z[0].ID

	// Construct a query string
	v := url.Values{}
	if rr.Name != "" {
		v.Set("name", rr.Name)
	}
	if rr.Type != "" {
		v.Set("type", rr.Type)
	}
	if rr.Content != "" {
		v.Set("content", rr.Content)
	}
	var query string
	if len(v) > 0 {
		query = "?" + v.Encode()
	}
	uri := "/zones/" + zid + "/dns_records" + query
	res, err := api.makeRequest("GET", uri, nil)
	if err != nil {
		return []DNSRecord{}, err
	}
	var r DNSListResponse
	err = json.Unmarshal(res, &r)
	if err != nil {
		return []DNSRecord{}, err
	}
	return r.Result, nil
}

// https://api.cloudflare.com/#dns-records-for-a-zone-dns-record-details
// GET /zones/:zone_identifier/dns_records/:identifier
func (api *API) DNSRecord() {
}

/*
Change a DNS record.

API reference:
  https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
  PUT /zones/:zone_identifier/dns_records/:identifier
*/
func (api *API) UpdateDNSRecord(zone, id string) error {
	return nil
}

/*
Delete a DNS record.

API reference:
  https://api.cloudflare.com/#dns-records-for-a-zone-delete-dns-record
  DELETE /zones/:zone_identifier/dns_records/:identifier
*/
func (api *API) DeleteDNSRecord(zone, id string) error {
	z, err := api.ListZones(zone)
	if err != nil {
		return err
	}
	// TODO(jamesog): This is brittle, fix it
	zid := z[0].ID
	uri := "/zones/" + zid + "/dns_records/" + id
	res, err := api.makeRequest("DELETE", uri, nil)
	if err != nil {
		fmt.Println("Error with makeRequest")
		return err
	}
	var r DNSRecordResponse
	err = json.Unmarshal(res, &r)
	if err != nil {
		fmt.Println("Error with unmarshal")
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// 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 ebiten provides graphics and input API to develop a 2D game.
//
// You can start the game by calling the function RunGame.
//
//	// Game implements ebiten.Game interface.
//	type Game struct{}
//
//	// Update proceeds the game state.
//	// Update is called every tick (1/60 [s] by default).
//	func (g *Game) Update() error {
//	    // Write your game's logical update.
//	    return nil
//	}
//
//	// Draw draws the game screen.
//	// Draw is called every frame (typically 1/60[s] for 60Hz display).
//	func (g *Game) Draw(screen *ebiten.Image) {
//	    // Write your game's rendering.
//	}
//
//	// Layout takes the outside size (e.g., the window size) and returns the (logical) screen size.
//	// If you don't have to adjust the screen size with the outside size, just return a fixed size.
//	func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
//	    return 320, 240
//	}
//
//	func main() {
//	    game := &Game{}
//	    // Specify the window size as you like. Here, a doubled size is specified.
//	    ebiten.SetWindowSize(640, 480)
//	    ebiten.SetWindowTitle("Your game's title")
//	    // Call ebiten.RunGame to start your game loop.
//	    if err := ebiten.RunGame(game); err != nil {
//	        log.Fatal(err)
//	    }
//	}
//
// In the API document, 'the main thread' means the goroutine in init(), main() and their callees without 'go'
// statement. It is assured that 'the main thread' runs on the OS main thread. There are some Ebitengine functions (e.g.,
// DeviceScaleFactor) that must be called on the main thread under some conditions (typically, before ebiten.RunGame
// is called).
//
// # Environment variables
//
// `EBITENGINE_SCREENSHOT_KEY` environment variable specifies the key
// to take a screenshot. For example, if you run your game with
// `EBITENGINE_SCREENSHOT_KEY=q`, you can take a game screen's screenshot
// by pressing Q key. This works only on desktops.
//
// `EBITENGINE_INTERNAL_IMAGES_KEY` environment variable specifies the key
// to dump all the internal images. This is valid only when the build tag
// 'ebitenginedebug' is specified. This works only on desktops.
//
// `EBITENGINE_GRAPHICS_LIBRARY` environment variable specifies the graphics library.
// If the specified graphics library is not available, RunGame returns an error.
// This environment variable can also be set programmatically through os.Setenv before RunGame is called.
// This can take one of the following value:
//
//	"auto":    Ebitengine chooses the graphics library automatically. This is the default value.
//	"opengl":  OpenGL, OpenGL ES, or WebGL.
//	"directx": DirectX. This works only on Windows.
//	"metal":   Metal. This works only on macOS or iOS.
//
// `EBITENGINE_DIRECTX` environment variable specifies various parameters for DirectX.
// You can specify multiple values separated by a comma. The default value is empty (i.e. no parameters).
//
//	"warp":  Use WARP (i.e. software rendering).
//	"debug": Use a debug layer.
//
// # Build tags
//
// `ebitenginedebug` outputs a log of graphics commands. This is useful to know what happens in Ebitengine. In general, the
// number of graphics commands affects the performance of your game.
//
// `ebitenginewebgl1` forces to use WebGL 1 on browsers.
//
// `ebitenginesinglethread` disables Ebitengine's thread safety to unlock maximum performance. If you use this you will have
// to manage threads yourself. Functions like IsKeyPressed will no longer be concurrent-safe with this build tag.
// They must be called from the main thread or the same goroutine as the given game's callback functions like Update
// to RunGame.
package ebiten
<commit_msg>ebiten: add a comment about microsoftgdk<commit_after>// Copyright 2014 Hajime Hoshi
//
// 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 ebiten provides graphics and input API to develop a 2D game.
//
// You can start the game by calling the function RunGame.
//
//	// Game implements ebiten.Game interface.
//	type Game struct{}
//
//	// Update proceeds the game state.
//	// Update is called every tick (1/60 [s] by default).
//	func (g *Game) Update() error {
//	    // Write your game's logical update.
//	    return nil
//	}
//
//	// Draw draws the game screen.
//	// Draw is called every frame (typically 1/60[s] for 60Hz display).
//	func (g *Game) Draw(screen *ebiten.Image) {
//	    // Write your game's rendering.
//	}
//
//	// Layout takes the outside size (e.g., the window size) and returns the (logical) screen size.
//	// If you don't have to adjust the screen size with the outside size, just return a fixed size.
//	func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
//	    return 320, 240
//	}
//
//	func main() {
//	    game := &Game{}
//	    // Specify the window size as you like. Here, a doubled size is specified.
//	    ebiten.SetWindowSize(640, 480)
//	    ebiten.SetWindowTitle("Your game's title")
//	    // Call ebiten.RunGame to start your game loop.
//	    if err := ebiten.RunGame(game); err != nil {
//	        log.Fatal(err)
//	    }
//	}
//
// In the API document, 'the main thread' means the goroutine in init(), main() and their callees without 'go'
// statement. It is assured that 'the main thread' runs on the OS main thread. There are some Ebitengine functions (e.g.,
// DeviceScaleFactor) that must be called on the main thread under some conditions (typically, before ebiten.RunGame
// is called).
//
// # Environment variables
//
// `EBITENGINE_SCREENSHOT_KEY` environment variable specifies the key
// to take a screenshot. For example, if you run your game with
// `EBITENGINE_SCREENSHOT_KEY=q`, you can take a game screen's screenshot
// by pressing Q key. This works only on desktops.
//
// `EBITENGINE_INTERNAL_IMAGES_KEY` environment variable specifies the key
// to dump all the internal images. This is valid only when the build tag
// 'ebitenginedebug' is specified. This works only on desktops.
//
// `EBITENGINE_GRAPHICS_LIBRARY` environment variable specifies the graphics library.
// If the specified graphics library is not available, RunGame returns an error.
// This environment variable can also be set programmatically through os.Setenv before RunGame is called.
// This can take one of the following value:
//
//	"auto":    Ebitengine chooses the graphics library automatically. This is the default value.
//	"opengl":  OpenGL, OpenGL ES, or WebGL.
//	"directx": DirectX. This works only on Windows.
//	"metal":   Metal. This works only on macOS or iOS.
//
// `EBITENGINE_DIRECTX` environment variable specifies various parameters for DirectX.
// You can specify multiple values separated by a comma. The default value is empty (i.e. no parameters).
//
//	"warp":  Use WARP (i.e. software rendering).
//	"debug": Use a debug layer.
//
// # Build tags
//
// `ebitenginedebug` outputs a log of graphics commands. This is useful to know what happens in Ebitengine. In general, the
// number of graphics commands affects the performance of your game.
//
// `ebitenginewebgl1` forces to use WebGL 1 on browsers.
//
// `ebitenginesinglethread` disables Ebitengine's thread safety to unlock maximum performance. If you use this you will have
// to manage threads yourself. Functions like IsKeyPressed will no longer be concurrent-safe with this build tag.
// They must be called from the main thread or the same goroutine as the given game's callback functions like Update
// to RunGame.
//
// `microsoftgdk` is for Microsoft GDK (Xbox).
package ebiten
<|endoftext|>


<commit_before>// Package podcast is an iTunes and RSS 2.0 podcast generator for GoLang that
// enforces strict compliance by using its simple interface.
//
// [![GoDoc](https://godoc.org/github.com/eduncan911/podcast?status.svg)](https://godoc.org/github.com/eduncan911/podcast) [![Build Status](https://travis-ci.org/eduncan911/podcast.svg?branch=master)](https://travis-ci.org/eduncan911/podcast) [![Go Report Card](https://goreportcard.com/badge/github.com/eduncan911/podcast)](https://goreportcard.com/report/github.com/eduncan911/podcast)
//
// Full documentation with detailed examples located at https://godoc.org/github.com/eduncan911/podcast
//
// Usage
//
//     $ go get -u github.com/eduncan911/podcast
//
// The API exposes a number of method receivers on structs that implements the
// logic required to comply with the specifications and ensure a compliant feed.
// A number of overrides occur to help with iTunes visibility of your episodes.
//
// Notably, the [Podcast.AddItem(i Item)](#Podcast.AddItem) function performs most of the
// heavy lifting by taking the [Item](#Item) input and performing validation, overrides
// and duplicate setters through the feed.
//
//
// See the detailed Examples in the GoDocs for complete usage.
//
// Extensibility
//
// In no way are you restricted in having full control over your feeds.  You may
// choose to skip the API methods and instead use the structs directly.  The
// fields have been grouped by RSS 2.0 and iTunes fields.
//
// iTunes specific fields are all prefixed with the letter `I`.
//
// References
//
// RSS 2.0: https://cyber.harvard.edu/rss/rss.html
//
// Podcasts: https://help.apple.com/itc/podcasts_connect/#/itca5b22233
package podcast
<commit_msg>adding release notes<commit_after>// Package podcast is an iTunes and RSS 2.0 podcast generator for GoLang that
// enforces strict compliance by using its simple interface.
//
// Full documentation with detailed examples located at https://godoc.org/github.com/eduncan911/podcast
//
// Usage
//
//     $ go get -u github.com/eduncan911/podcast
//
// The API exposes a number of method receivers on structs that implements the
// logic required to comply with the specifications and ensure a compliant feed.
// A number of overrides occur to help with iTunes visibility of your episodes.
//
// Notably, the [Podcast.AddItem(i Item)](#Podcast.AddItem) function performs most of the
// heavy lifting by taking the [Item](#Item) input and performing validation, overrides
// and duplicate setters through the feed.
//
// See the detailed Examples in the GoDocs for complete usage.
//
// Extensibility
//
// In no way are you restricted in having full control over your feeds.  You may
// choose to skip the API methods and instead use the structs directly.  The
// fields have been grouped by RSS 2.0 and iTunes fields.
//
// iTunes specific fields are all prefixed with the letter `I`.
//
// References
//
// RSS 2.0: https://cyber.harvard.edu/rss/rss.html
//
// Podcasts: https://help.apple.com/itc/podcasts_connect/#/itca5b22233
//
// Release Notes
//
// 1.0.0
// * Initial release with 97% coverage (can't mock xml Encoder 3 lines of code).
// * Full documentation and full examples.
//
package podcast
<|endoftext|>


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

/*
gopy-gen generates language bindings that make it possible to call Go code
and pass objects from Java.

Using gopy-gen

gopy-gen takes a Go package and generates bindings for all of the exported
symbols. The exported symbols define the cross-language interface.

The gopy-gen tool generates both an API stub in Python, and binding code in
Go. Start with a Go package:

	package hi

	import "fmt"

	func Hello(name string) {
		fmt.Println("Hello, %s!\n", name)
	}

*/
package main
<commit_msg>doc: typo<commit_after>// Copyright 2015 The go-python Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
gopy-gen generates language bindings that make it possible to call Go code
and pass objects from Python.

Using gopy-gen

gopy-gen takes a Go package and generates bindings for all of the exported
symbols. The exported symbols define the cross-language interface.

The gopy-gen tool generates both an API stub in Python, and binding code in
Go. Start with a Go package:

	package hi

	import "fmt"

	func Hello(name string) {
		fmt.Println("Hello, %s!\n", name)
	}

*/
package main
<|endoftext|>


<commit_before>// Package image provides libraries and commands to interact with containers images.
//
// 	package main
//
// 	import (
// 		"fmt"
//
// 		"github.com/containers/image/docker"
// 	)
//
// 	func main() {
// 		ref, err := docker.ParseReference("//fedora")
// 		if err != nil {
// 			panic(err)
// 		}
//  	ctx := context.Background()
// 		img, err := ref.NewImage(ctx)
// 		if err != nil {
// 			panic(err)
// 		}
// 		defer img.Close()
// 		b, _, err := img.Manifest(ctx)
// 		if err != nil {
// 			panic(err)
// 		}
// 		fmt.Printf("%s", string(b))
// 	}
//
// TODO(runcom)
package image
<commit_msg>Fix the example in doc.go<commit_after>// Package image provides libraries and commands to interact with containers images.
//
// package main
//
// import (
// 	"context"
// 	"fmt"
//
// 	"github.com/containers/image/docker"
// )
//
// func main() {
// 	ref, err := docker.ParseReference("//fedora")
// 	if err != nil {
// 		panic(err)
// 	}
// 	ctx := context.Background()
// 	img, err := ref.NewImage(ctx, nil)
// 	if err != nil {
// 		panic(err)
// 	}
// 	defer img.Close()
// 	b, _, err := img.Manifest(ctx)
// 	if err != nil {
// 		panic(err)
// 	}
// 	fmt.Printf("%s", string(b))
// }
//
//
// TODO(runcom)
package image
<|endoftext|>


<commit_before>/*
Package Signals generates, stores, downloads and manipulates abstract signals, when imported it can then be used with specific real-world quantities.

Definition of a 'signal'

	A varying value of some property, as it depends, uniquely, on some parameter.
	The controlling parameter is generally unbounded, and the property bounded.

see; https://en.wikibooks.org/wiki/Signals_and_Systems/Definition_of_Signals_and_Systems.

Fundamental Types

x :- the 'parameter' designed to be used as if it were unbounded (+ve and -ve), with unitX near the centre of its precision range.
y :- the 'property', a value between limits, +unitY and -unitY.

(the underlying types of x and y are kept hidden to enable simple generation of optimised packages with different ranges/precisions.)

Interfaces

Signal

has one method, property, which returning a 'y' value from an 'x' value parameter

fundamentally procedural, calculated as needed, so that any 'x' value returns a 'y' value.

changes to parameters effect returned values from any other Signals composed from them.

saved/loaded, lossily, as PCM data. (PCM data can be encoded and saved in a Waveform Audio File Format (wav) file.)

saved/loaded from a go code binary (gob) file, (and signals can stream data, including gob files.) making for a basic interpreted signal language.

LimitedSignal

a Signal with an additional method; MaxX(), that returns the 'x' value above which the Signal can be assumed to return zero, effectively the Signals end.

when required, an 'x' value of zero is regarded as a Signals start.

PeriodicSignal

a Signal with an additional method; Period(), returning the 'x' length over which it repeats.

or when required any fundamental wavelength

or the sample spacing for one of the PCM Signal types.

PeriodicLimitedSignal

both above, and is implemented by the PCM Signal types.

*/
package signals

/*
Implementation details.

x and y are not exported, separating their abstract nature from an importing packages concrete implementation and allowing flexibility in representation, if needed they can be made through provided exposed functions.
x and y are encoded as non-floating types, so resolution doesn't vary with value. By changing unitX the precision of a value can be directly effected, and the overall range can be altered, making for a basic ability to 'float' the range of the variable, just not automatically.

*/
<commit_msg>comment<commit_after>/*
This Package generates, stores, downloads and manipulates abstract signals, when imported it can then be used with specific real-world quantities.

Definition of a 'signal'

	A varying value of some property, as it depends, uniquely, on some parameter.
	The controlling parameter is generally unbounded, and the property bounded.

see; https://en.wikibooks.org/wiki/Signals_and_Systems/Definition_of_Signals_and_Systems.

Types

x (int)

the 'parameter' designed to be used as if it were unbounded (+ve and -ve), with unitX near the centre of its precision range.

y (int)

the 'property', a value between limits, +unitY and -unitY.

(the underlying types of x and y are kept hidden to enable simple generation of optimised packages with different ranges/precisions.)

Signal (Interface{})

has one method, property(x)y, which returns a 'y' value from an 'x' value parameter.

fundamentally procedural, calculated as needed, so that any 'x' value returns a 'y' value.

changes to parameters effect returned values from any other Signals composed from them.

saved/loaded, lossily, as PCM data. (PCM data can be Waveform Audio File Format ,.wav file.)

saved/loaded from a go code binary (.gob) file, (and signals can stream data, including gob files.) making for a basic interpreted signal language.

LimitedSignal (Interface{})

a Signal with an additional method; MaxX(), that returns the 'x' value above which the Signal can be assumed to return zero, effectively the Signals end.

when required, an 'x' value of zero is regarded as a Signals start.

PeriodicSignal (Interface{})

a Signal with an additional method; Period(), returning the 'x' length over which it repeats.

or when required any fundamental wavelength

or the sample spacing for one of the PCM Signal types.

PeriodicLimitedSignal Interface{})

both above, and is implemented by the PCM Signal types.

*/
package signals

/*
Implementation details.

x and y are not exported, separating their abstract nature from an importing packages concrete implementation and allowing flexibility in representation, if needed they can be made through provided exposed functions.
x and y are encoded as non-floating types, so resolution doesn't vary with value. By changing unitX the precision of a value can be directly effected, and the overall range can be altered, making for a basic ability to 'float' the range of the variable, just not automatically.

*/
<|endoftext|>


<commit_before>/*
Package forget provides an in-memory cache for arbitrary, binary data.

Caching

The cache identifies items by their keys. It stores them with individual expiration time (TTL). The associated
content is stored in binary format.  Storing a new item with the same key, overrides the previous one A cached
item can be retrieved or deleted with its key. As a special use case, it is possible to store only keys, where
the useful information is whether a key exists or not. If a new item doesn't fit in the free space, the least
recently used item is evicted (LRU).

Keyspaces

Keyspaces, when used (see NewCacheSpaces()), allow some optimization of the LRU eviction mechanism. Items that
are more expensive to produce but less frequently accessed than others, can be stored in different keyspaces.
When eviction is required, the cache tries to evict enough items from the same keyspace as the one currently
being filled. When using keyspaces, the same key can appear in different keyspaces pointing to different items.

Memory

The cache allocates all the used memory on start. To support parallel access, it splits the allocated memory
into segments. There are typically as many segments as the maximum of NumCPU() and GOMAXPROCS(). The maximum
size of a stored item is the total cache size divided by the number of segments.

The segments are split into chunks. One cached item can span over multiple chunks, but the chunks cannot be
shared between the items. This means that the cache is almost never fully utilized. The chunk size is an
initialization option, it typically should be a 'couple of times' smaller than the expected size of the 'bulk'
of the cached items.

The cache counts the size of the item keys in the used space, but there is some lookup metadata that is not
counted: ~24 bytes for each chunk and ~120 bytes for each item.

IO

The associated data of the keys can be accessed for read, seek and write through the standard Go interfaces. As
a shortcut, the data can be retrieved or set as a single byte slice, too. When using the IO interfaces, the item
data can be accessed concurrently, and reading from an item can be started before the write has finished. When
the reader reaches a point that was not yet filled by the writer, it blocks, and continues only when more data
was written, or returns with EOF once the write was finished.

While writing an item, chunks are continuously assigned to the item from the free range of allocated memory. If
there are no free chunks, the cache evicts enough of the least recently used items. The cache doesn't evict
those items that are currently being read by an unclosed reader. Similarly, when deleting an item or overwriting
one, if it has active readers associated with it, the item is only marked for delete, but the active readers can
finish reading from it.

Monitoring

The cache provides statistics about its internal state, including metrics like item count, effective and used
size, active readers and writers. When configured, it also provides change notifications. Depending on the
configured notification mask, it can send events about: cache hit/miss, evictions, allocation failures, etc.
*/
package forget
<commit_msg>fix doc<commit_after>/*
Package forget provides an in-memory cache for arbitrary, binary data.

Caching

The cache identifies items by their keys. It stores them with individual expiration time (TTL). The associated
content is stored in binary format.  Storing a new item with the same key, overrides the previous one. A cached
item can be retrieved or deleted with its key. As a special use case, it is possible to store only keys, where
the useful information is whether a key exists or not. If a new item doesn't fit in the free space, the least
recently used item is evicted (LRU).

Keyspaces

Keyspaces, when used (see NewCacheSpaces()), allow some optimization of the LRU eviction mechanism. Items that
are more expensive to produce but less frequently accessed than others, can be stored in different keyspaces.
When eviction is required, the cache tries to evict enough items from the same keyspace as the one currently
being filled. When using keyspaces, the same key can appear in different keyspaces pointing to different items.

Memory

The cache allocates all the used memory on start. To support parallel access, it splits the allocated memory
into segments. There are typically as many segments as the maximum of NumCPU() and GOMAXPROCS(). The maximum
size of a stored item is the total cache size divided by the number of segments.

The segments are split into chunks. One cached item can span over multiple chunks, but the chunks cannot be
shared between the items. This means that the cache is almost never fully utilized. The chunk size is an
initialization option, it typically should be a 'couple of times' smaller than the expected size of the 'bulk'
of the cached items.

The cache counts the size of the item keys in the used space, but there is some lookup metadata that is not
counted: ~24 bytes for each chunk and ~120 bytes for each item.

IO

The associated data of the keys can be accessed for read, seek and write through the standard Go interfaces. As
a shortcut, the data can be retrieved or set as a single byte slice, too. When using the IO interfaces, the item
data can be accessed concurrently, and reading from an item can be started before the write has finished. When
the reader reaches a point that was not yet filled by the writer, it blocks, and continues only when more data
was written, or returns with EOF once the write was finished.

While writing an item, chunks are continuously assigned to the item from the free range of allocated memory. If
there are no free chunks, the cache evicts enough of the least recently used items. The cache doesn't evict
those items that are currently being read by an unclosed reader. Similarly, when deleting an item or overwriting
one, if it has active readers associated with it, the item is only marked for delete, but the active readers can
finish reading from it.

Monitoring

The cache provides statistics about its internal state, including metrics like item count, effective and used
size, active readers and writers. When configured, it also provides change notifications. Depending on the
configured notification mask, it can send events about: cache hit/miss, evictions, allocation failures, etc.
*/
package forget
<|endoftext|>


<commit_before>// functions and methods related to the autoscaler

package master

import (
	"log"
	"math"
	"sort"

	"github.com/aaronang/cong-the-ripper/lib"
)

// runController runs one iteration
func (m *Master) runController() {
	err := float64(m.countRequiredSlots() - m.countTotalSlots())

	dt := m.controller.dt.Seconds()
	m.controller.integral = m.controller.integral + err*dt
	derivative := (err - m.controller.prevErr) / dt
	output := m.controller.kp*err +
		m.controller.ki*m.controller.integral +
		m.controller.kd*derivative
	m.controller.prevErr = err

	// output is the error in terms of number of resources/slots
	// we convert it to adjustment to represent the number of instances
	adjustment := int(math.Ceil((output / float64(lib.MaxSlotsPerInstance)) - 1.11e-16))
	log.Printf("[autoscaler] err: %v, output: %v, adjustment: %v\n", err, output, adjustment)
	m.adjustInstanceCount(adjustment)
}

func (m *Master) adjustInstanceCount(n int) {
	if n > 0 {
		go func() {
			_, err := createSlaves(m.svc, n, "8080", m.ip, m.port)
			if err != nil {
				log.Println("[autoscaler] Failed to create slaves", err)
			} else {
				log.Printf("[autoscaler] %v instances created successfully\n", n)
				// no need to report back to the master loop
				// because it should start receiving heartbeat messages
			}
		}()
	} else {
		// negate n to represent the (positive) number of instances to kill
		n = -n
		if n == 0 {
			log.Println("[autoscaler] n is 0 in adjustInstanceCount")
			return
		}

		// kills n least loaded slaves, the killed slaves may have unfinished tasks
		// but the master should detect missing heartbeats and restart the tasks
		ips := sortInstancesByTaskCount(m.instances)[:n]
		go func() {
			_, err := terminateSlaves(m.svc, instancesFromIPs(m.svc, ips))
			if err != nil {
				log.Println("[autoscaler] Failed to terminate slaves", err)
			} else {
				log.Printf("[autoscaler] %v instances terminated successfully", n)
				// again, no need to report success/failure
				// because heartbeat messages will stop
			}
		}()
	}
}

func (m *Master) maxSlots() int {
	// TODO do we set the manually or it's a property of AWS?
	return 20 * lib.MaxSlotsPerInstance
}

func (m *Master) countRequiredSlots() int {
	cnt := 0
	for _, v := range m.jobs {
		cnt += lib.Min(len(v.tasks), v.maxTasks)
	}
	if cnt > m.maxSlots() {
		return m.maxSlots()
	}
	return cnt
}

func (m *Master) countTotalSlots() int {
	cnt := 0
	for _, i := range m.instances {
		cnt += i.maxSlots
	}
	return cnt
}

func sortInstancesByTaskCount(instances map[string]slave) []string {
	pairs := make([]ipSlavePair, len(instances))
	var i int
	for k, v := range instances {
		pairs[i].slave = v
		pairs[i].ip = k
		i++
	}

	sort.Sort(byTaskCount(pairs))

	ips := make([]string, len(pairs))
	for i := range ips {
		ips[i] = pairs[i].ip
	}
	return ips
}

type ipSlavePair struct {
	ip    string
	slave slave
}

type byTaskCount []ipSlavePair

func (a byTaskCount) Len() int {
	return len(a)
}

func (a byTaskCount) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}

func (a byTaskCount) Less(i, j int) bool {
	return len(a[i].slave.tasks) < len(a[j].slave.tasks)
}
<commit_msg>Change v to j for jobs<commit_after>// functions and methods related to the autoscaler

package master

import (
	"log"
	"math"
	"sort"

	"github.com/aaronang/cong-the-ripper/lib"
)

// runController runs one iteration
func (m *Master) runController() {
	err := float64(m.countRequiredSlots() - m.countTotalSlots())

	dt := m.controller.dt.Seconds()
	m.controller.integral = m.controller.integral + err*dt
	derivative := (err - m.controller.prevErr) / dt
	output := m.controller.kp*err +
		m.controller.ki*m.controller.integral +
		m.controller.kd*derivative
	m.controller.prevErr = err

	// output is the error in terms of number of resources/slots
	// we convert it to adjustment to represent the number of instances
	adjustment := int(math.Ceil((output / float64(lib.MaxSlotsPerInstance)) - 1.11e-16))
	log.Printf("[autoscaler] err: %v, output: %v, adjustment: %v\n", err, output, adjustment)
	m.adjustInstanceCount(adjustment)
}

func (m *Master) adjustInstanceCount(n int) {
	if n > 0 {
		go func() {
			_, err := createSlaves(m.svc, n, "8080", m.ip, m.port)
			if err != nil {
				log.Println("[autoscaler] Failed to create slaves", err)
			} else {
				log.Printf("[autoscaler] %v instances created successfully\n", n)
				// no need to report back to the master loop
				// because it should start receiving heartbeat messages
			}
		}()
	} else {
		// negate n to represent the (positive) number of instances to kill
		n = -n
		if n == 0 {
			log.Println("[autoscaler] n is 0 in adjustInstanceCount")
			return
		}

		// kills n least loaded slaves, the killed slaves may have unfinished tasks
		// but the master should detect missing heartbeats and restart the tasks
		ips := sortInstancesByTaskCount(m.instances)[:n]
		go func() {
			_, err := terminateSlaves(m.svc, instancesFromIPs(m.svc, ips))
			if err != nil {
				log.Println("[autoscaler] Failed to terminate slaves", err)
			} else {
				log.Printf("[autoscaler] %v instances terminated successfully", n)
				// again, no need to report success/failure
				// because heartbeat messages will stop
			}
		}()
	}
}

func (m *Master) maxSlots() int {
	// TODO do we set the manually or it's a property of AWS?
	return 20 * lib.MaxSlotsPerInstance
}

func (m *Master) countRequiredSlots() int {
	cnt := 0
	for _, j := range m.jobs {
		cnt += lib.Min(len(j.tasks), j.maxTasks)
	}
	if cnt > m.maxSlots() {
		return m.maxSlots()
	}
	return cnt
}

func (m *Master) countTotalSlots() int {
	cnt := 0
	for _, i := range m.instances {
		cnt += i.maxSlots
	}
	return cnt
}

func sortInstancesByTaskCount(instances map[string]slave) []string {
	pairs := make([]ipSlavePair, len(instances))
	var i int
	for k, v := range instances {
		pairs[i].slave = v
		pairs[i].ip = k
		i++
	}

	sort.Sort(byTaskCount(pairs))

	ips := make([]string, len(pairs))
	for i := range ips {
		ips[i] = pairs[i].ip
	}
	return ips
}

type ipSlavePair struct {
	ip    string
	slave slave
}

type byTaskCount []ipSlavePair

func (a byTaskCount) Len() int {
	return len(a)
}

func (a byTaskCount) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}

func (a byTaskCount) Less(i, j int) bool {
	return len(a[i].slave.tasks) < len(a[j].slave.tasks)
}
<|endoftext|>


<commit_before>// Copyright 2013 by Dobrosław Żybort. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package slug

import (
	"github.com/fiam/gounidecode/unidecode"
	"regexp"
	"strings"
)

var (
	// Custom substitution map
	CustomSub map[string]string
	// Custom rune substitution map
	CustomRuneSub map[rune]string

	// Maximum slug length. It's smart so it will cat slug after full word.
	// By default slugs aren't shortened.
	// If MaxLength is smaller than length of the first word, then returned
	// slug will contain only substring from the first word truncated
	// after MaxLength.
	MaxLength int
)

//=============================================================================

// Make returns slug generated from provided string. Will use "en" as language
// substitution.
func Make(s string) (slug string) {
	return MakeLang(s, "en")
}

// MakeLang returns slug generated from provided string and will use provided
// language for chars substitution.
func MakeLang(s string, lang string) (slug string) {
	slug = strings.TrimSpace(s)

	// Custom substitutions
	// Always substitute runes first
	slug = SubstituteRune(slug, CustomRuneSub)
	slug = Substitute(slug, CustomSub)

	// Process string with selected substitution language
	switch lang {
	case "de":
		slug = SubstituteRune(slug, deSub)
	case "en":
		slug = SubstituteRune(slug, enSub)
	case "pl":
		slug = SubstituteRune(slug, plSub)
	case "es":
		slug = SubstituteRune(slug, esSub)
	default: // fallback to "en" if lang not found
		slug = SubstituteRune(slug, enSub)
	}

	slug = SubstituteRune(slug, defaultSub)

	// Process all non ASCII symbols
	slug = unidecode.Unidecode(slug)

	slug = strings.ToLower(slug)

	// Process all remaining symbols
	slug = regexp.MustCompile("[^a-z0-9-_]").ReplaceAllString(slug, "-")
	slug = regexp.MustCompile("-+").ReplaceAllString(slug, "-")
	slug = strings.Trim(slug, "-")

	if MaxLength > 0 {
		slug = smartTruncate(slug)
	}

	return slug
}

// Substitute returns string with superseded all substrings from
// provided substitution map.
func Substitute(s string, sub map[string]string) (buf string) {
	buf = s
	for key, val := range sub {
		buf = strings.Replace(s, key, val, -1)
	}
	return
}

// SubstituteRune substitutes string chars with provided rune
// substitution map.
func SubstituteRune(s string, sub map[rune]string) (buf string) {
	for _, c := range s {
		if d, ok := sub[c]; ok {
			buf += d
		} else {
			buf += string(c)
		}
	}
	return
}

func smartTruncate(text string) string {
	if len(text) < MaxLength {
		return text
	}

	var truncated string
	words := strings.SplitAfter(text, "-")
	// If MaxLength is smaller than length of the first word return word
	// truncated after MaxLength.
	if len(words[0]) > MaxLength {
		return words[0][:MaxLength]
	}
	for _, word := range words {
		if len(truncated)+len(word)-1 <= MaxLength {
			truncated = truncated + word
		} else {
			break
		}
	}
	return strings.Trim(truncated, "-")
}
<commit_msg>update dependency unidecode import path<commit_after>// Copyright 2013 by Dobrosław Żybort. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package slug

import (
	"gopkgs.com/unidecode.v1"
	"regexp"
	"strings"
)

var (
	// Custom substitution map
	CustomSub map[string]string
	// Custom rune substitution map
	CustomRuneSub map[rune]string

	// Maximum slug length. It's smart so it will cat slug after full word.
	// By default slugs aren't shortened.
	// If MaxLength is smaller than length of the first word, then returned
	// slug will contain only substring from the first word truncated
	// after MaxLength.
	MaxLength int
)

//=============================================================================

// Make returns slug generated from provided string. Will use "en" as language
// substitution.
func Make(s string) (slug string) {
	return MakeLang(s, "en")
}

// MakeLang returns slug generated from provided string and will use provided
// language for chars substitution.
func MakeLang(s string, lang string) (slug string) {
	slug = strings.TrimSpace(s)

	// Custom substitutions
	// Always substitute runes first
	slug = SubstituteRune(slug, CustomRuneSub)
	slug = Substitute(slug, CustomSub)

	// Process string with selected substitution language
	switch lang {
	case "de":
		slug = SubstituteRune(slug, deSub)
	case "en":
		slug = SubstituteRune(slug, enSub)
	case "pl":
		slug = SubstituteRune(slug, plSub)
	case "es":
		slug = SubstituteRune(slug, esSub)
	default: // fallback to "en" if lang not found
		slug = SubstituteRune(slug, enSub)
	}

	slug = SubstituteRune(slug, defaultSub)

	// Process all non ASCII symbols
	slug = unidecode.Unidecode(slug)

	slug = strings.ToLower(slug)

	// Process all remaining symbols
	slug = regexp.MustCompile("[^a-z0-9-_]").ReplaceAllString(slug, "-")
	slug = regexp.MustCompile("-+").ReplaceAllString(slug, "-")
	slug = strings.Trim(slug, "-")

	if MaxLength > 0 {
		slug = smartTruncate(slug)
	}

	return slug
}

// Substitute returns string with superseded all substrings from
// provided substitution map.
func Substitute(s string, sub map[string]string) (buf string) {
	buf = s
	for key, val := range sub {
		buf = strings.Replace(s, key, val, -1)
	}
	return
}

// SubstituteRune substitutes string chars with provided rune
// substitution map.
func SubstituteRune(s string, sub map[rune]string) (buf string) {
	for _, c := range s {
		if d, ok := sub[c]; ok {
			buf += d
		} else {
			buf += string(c)
		}
	}
	return
}

func smartTruncate(text string) string {
	if len(text) < MaxLength {
		return text
	}

	var truncated string
	words := strings.SplitAfter(text, "-")
	// If MaxLength is smaller than length of the first word return word
	// truncated after MaxLength.
	if len(words[0]) > MaxLength {
		return words[0][:MaxLength]
	}
	for _, word := range words {
		if len(truncated)+len(word)-1 <= MaxLength {
			truncated = truncated + word
		} else {
			break
		}
	}
	return strings.Trim(truncated, "-")
}
<|endoftext|>


<commit_before>/*
Copyright 2015 All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

const (
	progName = "s3secrets"
	version  = "v1.0.2"
	author   = "Rohith"
	email    = "gambol99@gmail.com"
)
<commit_msg>Release v1.0.3<commit_after>/*
Copyright 2015 All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

const (
	progName = "s3secrets"
	version  = "v1.0.3"
	author   = "Rohith"
	email    = "gambol99@gmail.com"
)
<|endoftext|>


<commit_before>// IPFS is a global, versioned, peer-to-peer filesystem
package ipfs
<commit_msg>doc: Add some docs explaining the sub-package layout<commit_after>/*
IPFS is a global, versioned, peer-to-peer filesystem

There are sub-packages within the ipfs package for various low-level
utilities, which are in turn assembled into:

core/...:
  The low-level API that gives consumers all the knobs they need,
  which we try hard to keep stable.
shell/...:
  The high-level API that gives consumers easy access to common
  operations (e.g. create a file node from a reader without wrapping
  with metadata). We work really hard to keep this stable.

Then on top of the core/... and shell/... Go APIs, we have:

cmd/...:
  Command-line executables
test/...:
  Integration tests, etc.

To avoid cyclic imports, imports should never pull in higher-level
APIs into a lower-level package.  For example, you could import all of
core and shell from cmd/... or test/..., but you couldn't import any
of shell from core/....
*/
package ipfs
<|endoftext|>


<commit_before>/*
Package color extends fmt.Printf with verbs for producing colored output.

Printing

Verbs:

	%h[attr...]	replaced with a SGR code that sets all of the attributes in []
			multiple attributes are + separated
	%r		an abbreviation for %h[reset]
	%a		used by Format's Insert methods to combine Formats

Errors:

If an error occurs, the generated string will contain a description of the problem, as in these examples.

	Invalid character in the highlight verb:
		Printf("%h(fgRed)%s", "hi"):		%!h(INVALID)
	No attributes in the highlight verb:
		Printf("%h[]%s", "hi"):			%!h(MISSING)
	Unknown attribute in the highlight verb:
		Printf("%h[fgGdsds]%s", "hi"):		%!h(BADATTR)
	String ended before the verb:
		Printf("%h[fg", "hi"):			%!h(SHORT)

Everything else is handled by the fmt package. You should read its documentation.

Preparing Strings

While this package is heavily optimized, processing the highlighting verbs is still very expensive. Thus, it makes more sense to process the verbs once and then store the results.

A structure named Format is used for storage. It holds the colored and stripped versions of the base format string. In the colored string, the highlight verbs are replaced with their control sequences. In contrast, the highlight verbs are completely removed in the stripped string. Why store both? If color output is enabled, the colored string is used, but if color output is disabled, then the stripped string is used.

Use the Prepare function to create the Format structures. Then, use the Printfp like functions to use them as the base format strings, or send them as part of the variadic to any print function and they will be expanded to their appropiate strings. See Prepare below for an example.

Attributes Reference

Named Colors:
	%h[xgBlack]
	%h[xgRed]
	%h[xgGreen]
	%h[xgYellow]
	%h[xgBlue]
	%h[xgMagenta]
	%h[xgCyan]
	%h[xgWhite]
	%h[xgBrightBlack]
	%h[xgBrightRed]
	%h[xgBrightGreen]
	%h[xgBrightYellow]
	%h[xgBrightBlue]
	%h[xgBrightMagenta]
	%h[xgBrightCyan]
	%h[xgBrightWhite]

	Where 'x' is either 'f' or 'b'.

256 Colors:
	%h[fgx]
	%h[bgx]

	Where x is any number from 0-255.

Modes:
	%h[reset] or the %r verb
	%h[bold]
	%h[underline]
	%h[reverse]
	%h[blink]
	%h[dim]

See http://goo.gl/LRLA7o for information on the attributes. Scroll down to the SGR section.

See http://goo.gl/fvtHLs and ISO-8613-3 (according to above document) for more information on 256 colors.
*/
package color
<commit_msg>doc.go update<commit_after>/*
Package color extends fmt.Printf with verbs for producing colored output.

Printing

Verbs:

	%h[attr...]	replaced with a SGR code that sets all of the attributes in []
			multiple attributes are + separated
	%r		an abbreviation for %h[reset]
	%a		used by Format's Insert methods to combine Formats

To print, you must first call Prepare with the format string. It will return a Format structure that represents the base string with the highlight verbs fully parsed. Why?

While this package is heavily optimized, processing the highlighting verbs is still very expensive. Thus, it makes more sense to process the verbs once and then store the results.

The Formatstructure is used for storage. It holds the colored and stripped versions of the base format string. In the colored string, the highlight verbs are replaced with their control sequences. In contrast, the highlight verbs are completely removed in the stripped string. Why store both? If color output is enabled, the colored string is used, but if color output is disabled, then the stripped string is used.

Errors:

If an error occurs, the generated string will contain a description of the problem, as in these examples.

	Invalid character in the highlight verb:
		Printf("%h(fgRed)%s", "hi"):		%!h(INVALID)
	No attributes in the highlight verb:
		Printf("%h[]%s", "hi"):			%!h(MISSING)
	Unknown attribute in the highlight verb:
		Printf("%h[fgGdsds]%s", "hi"):		%!h(BADATTR)
	String ended before the verb:
		Printf("%h[fg", "hi"):			%!h(SHORT)

Everything else is handled by the fmt package. You should read its documentation.

Preparing Strings

Attributes Reference

Named Colors:
	%h[xgBlack]
	%h[xgRed]
	%h[xgGreen]
	%h[xgYellow]
	%h[xgBlue]
	%h[xgMagenta]
	%h[xgCyan]
	%h[xgWhite]
	%h[xgBrightBlack]
	%h[xgBrightRed]
	%h[xgBrightGreen]
	%h[xgBrightYellow]
	%h[xgBrightBlue]
	%h[xgBrightMagenta]
	%h[xgBrightCyan]
	%h[xgBrightWhite]

	Where 'x' is either 'f' or 'b'.

256 Colors:
	%h[fgx]
	%h[bgx]

	Where x is any number from 0-255.

Modes:
	%h[reset] or the %r verb
	%h[bold]
	%h[underline]
	%h[reverse]
	%h[blink]
	%h[dim]

See http://goo.gl/LRLA7o for information on the attributes. Scroll down to the SGR section.

See http://goo.gl/fvtHLs and ISO-8613-3 (according to above document) for more information on 256 colors.
*/
package color
<|endoftext|>


<commit_before>/*
A portable gl layer that aims to abstract and scale.
Designed for the Go programming language to use with gocos2d.
*/
package egles

/*
TODO:
EGL wrappers 		~30% 		done
GLES2 wrappers 		 ~5% 		done
GLES wrappers 		  0% 		done

Angle,waffle, wayland, nd andriod support have
yet to be tested but are ideas currently on the road map.

*/
<commit_msg>added imports to doc.go<commit_after>/*
A portable gl layer that aims to abstract and scale.
Designed for the Go programming language to use with gocos2d.
*/
package egles

import (
	_ "github.com/mortdeus/egles/egl"
	_ "github.com/mortdeus/egles/es"
	//_ "github.com/mortdeus/egles/gl"
	_ "github.com/mortdeus/egles/khr"
	_ "github.com/mortdeus/egles/misc"
)

/*
TODO:
EGL wrappers 		~30% 		done
GLES2 wrappers 		 ~5% 		done
GLES wrappers 		  0% 		done

Angle,waffle, wayland, nd andriod support have
yet to be tested but are ideas currently on the road map.

*/
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

// Package fuse enables writing and mounting user-space file systems.
//
// The primary elements of interest are:
//
//  *  The FileSystem interface, which defines the methods a file system must
//     implement.
//
//  *  NotImplementedFileSystem, which may be embedded to obtain default
//     implementations for all methods that are not of interest to a particular
//     file system.
//
//  *  Mount, a function that allows for mounting a file system.
//
// In order to use this package to mount file systems on OS X, the system must
// have FUSE for OS X installed: http://osxfuse.github.io/
package fuse
<commit_msg>Updated doc.go, too.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

// Package fuse enables writing and mounting user-space file systems.
//
// The primary elements of interest are:
//
//  *  The FileSystem interface, which defines the methods a file system must
//     implement.
//
//  *  fuseutil.NotImplementedFileSystem, which may be embedded to obtain
//     default implementations for all methods that are not of interest to a
//     particular file system.
//
//  *  Mount, a function that allows for mounting a file system.
//
// In order to use this package to mount file systems on OS X, the system must
// have FUSE for OS X installed: http://osxfuse.github.io/
package fuse
<|endoftext|>