<commit_before>package raft

import (
	"fmt"
	"io"
	"sync"
	"time"
)

// Future is used to represent an action that may occur in the future.
type Future interface {
	// Error blocks until the future arrives and then
	// returns the error status of the future.
	// This may be called any number of times - all
	// calls will return the same value.
	// Note that it is not OK to call this method
	// twice concurrently on the same Future instance.
	Error() error
}

// IndexFuture is used for future actions that can result in a raft log entry
// being created.
type IndexFuture interface {
	Future

	// Index holds the index of the newly applied log entry.
	// This must not be called until after the Error method has returned.
	Index() uint64
}

// ApplyFuture is used for Apply and can return the FSM response.
type ApplyFuture interface {
	IndexFuture

	// Response returns the FSM response as returned
	// by the FSM.Apply method. This must not be called
	// until after the Error method has returned.
	Response() interface{}
}

// ConfigurationFuture is used for GetConfiguration and can return the
// latest configuration in use by Raft.
type ConfigurationFuture interface {
	IndexFuture

	// Configuration contains the latest configuration. This must
	// not be called until after the Error method has returned.
	Configuration() Configuration
}

// SnapshotFuture is used for waiting on a user-triggered snapshot to complete.
type SnapshotFuture interface {
	Future

	// Open is a function you can call to access the underlying snapshot and
	// its metadata. This must not be called until after the Error method
	// has returned.
	Open() (*SnapshotMeta, io.ReadCloser, error)
}

// LeadershipTransferFuture is used for waiting on a user-triggered leadership
// transfer to complete.
type LeadershipTransferFuture interface {
	Future
}

// errorFuture is used to return a static error.
type errorFuture struct {
	err error
}

func (e errorFuture) Error() error {
	return e.err
}

func (e errorFuture) Response() interface{} {
	return nil
}

func (e errorFuture) Index() uint64 {
	return 0
}

// deferError can be embedded to allow a future
// to provide an error in the future.
type deferError struct {
	err        error
	errCh      chan error
	responded  bool
	ShutdownCh chan struct{}
}

func (d *deferError) init() {
	d.errCh = make(chan error, 1)
}

func (d *deferError) Error() error {
	if d.err != nil {
		// Note that when we've received a nil error, this
		// won't trigger, but the channel is closed after
		// send so we'll still return nil below.
		return d.err
	}
	if d.errCh == nil {
		panic("waiting for response on nil channel")
	}
	select {
	case d.err = <-d.errCh:
	case <-d.ShutdownCh:
		d.err = ErrRaftShutdown
	}
	return d.err
}

func (d *deferError) respond(err error) {
	if d.errCh == nil {
		return
	}
	if d.responded {
		return
	}
	d.errCh <- err
	close(d.errCh)
	d.responded = true
}

// There are several types of requests that cause a configuration entry to
// be appended to the log. These are encoded here for leaderLoop() to process.
// This is internal to a single server.
type configurationChangeFuture struct {
	logFuture
	req configurationChangeRequest
}

// bootstrapFuture is used to attempt a live bootstrap of the cluster. See the
// Raft object's BootstrapCluster member function for more details.
type bootstrapFuture struct {
	deferError

	// configuration is the proposed bootstrap configuration to apply.
	configuration Configuration
}

// logFuture is used to apply a log entry and waits until
// the log is considered committed.
type logFuture struct {
	deferError
	log      Log
	response interface{}
	dispatch time.Time
}

func (l *logFuture) Response() interface{} {
	return l.response
}

func (l *logFuture) Index() uint64 {
	return l.log.Index
}

type shutdownFuture struct {
	raft *Raft
}

func (s *shutdownFuture) Error() error {
	if s.raft == nil {
		return nil
	}
	s.raft.waitShutdown()
	if closeable, ok := s.raft.trans.(WithClose); ok {
		closeable.Close()
	}
	return nil
}

// userSnapshotFuture is used for waiting on a user-triggered snapshot to
// complete.
type userSnapshotFuture struct {
	deferError

	// opener is a function used to open the snapshot. This is filled in
	// once the future returns with no error.
	opener func() (*SnapshotMeta, io.ReadCloser, error)
}

// Open is a function you can call to access the underlying snapshot and its
// metadata.
func (u *userSnapshotFuture) Open() (*SnapshotMeta, io.ReadCloser, error) {
	if u.opener == nil {
		return nil, nil, fmt.Errorf("no snapshot available")
	}
	// Invalidate the opener so it can't get called multiple times,
	// which isn't generally safe.
	defer func() {
		u.opener = nil
	}()
	return u.opener()
}

// userRestoreFuture is used for waiting on a user-triggered restore of an
// external snapshot to complete.
type userRestoreFuture struct {
	deferError

	// meta is the metadata that belongs with the snapshot.
	meta *SnapshotMeta

	// reader is the interface to read the snapshot contents from.
	reader io.Reader
}

// reqSnapshotFuture is used for requesting a snapshot start.
// It is only used internally.
type reqSnapshotFuture struct {
	deferError

	// snapshot details provided by the FSM runner before responding
	index    uint64
	term     uint64
	snapshot FSMSnapshot
}

// restoreFuture is used for requesting an FSM to perform a
// snapshot restore. Used internally only.
type restoreFuture struct {
	deferError
	ID string
}

// verifyFuture is used to verify the current node is still
// the leader. This is to prevent a stale read.
type verifyFuture struct {
	deferError
	notifyCh   chan *verifyFuture
	quorumSize int
	votes      int
	voteLock   sync.Mutex
}

// leadershipTransferFuture is used to track the progress of a leadership
// transfer internally.
type leadershipTransferFuture struct {
	deferError

	ID      *ServerID
	Address *ServerAddress
}

// configurationsFuture is used to retrieve the current configurations. This is
// used to allow safe access to this information outside of the main thread.
type configurationsFuture struct {
	deferError
	configurations configurations
}

// Configuration returns the latest configuration in use by Raft.
func (c *configurationsFuture) Configuration() Configuration {
	return c.configurations.latest
}

// Index returns the index of the latest configuration in use by Raft.
func (c *configurationsFuture) Index() uint64 {
	return c.configurations.latestIndex
}

// vote is used to respond to a verifyFuture.
// This may block when responding on the notifyCh.
func (v *verifyFuture) vote(leader bool) {
	v.voteLock.Lock()
	defer v.voteLock.Unlock()

	// Guard against having notified already
	if v.notifyCh == nil {
		return
	}

	if leader {
		v.votes++
		if v.votes >= v.quorumSize {
			v.notifyCh <- v
			v.notifyCh = nil
		}
	} else {
		v.notifyCh <- v
		v.notifyCh = nil
	}
}

// appendFuture is used for waiting on a pipelined append
// entries RPC.
type appendFuture struct {
	deferError
	start time.Time
	args  *AppendEntriesRequest
	resp  *AppendEntriesResponse
}

func (a *appendFuture) Start() time.Time {
	return a.start
}

func (a *appendFuture) Request() *AppendEntriesRequest {
	return a.args
}

func (a *appendFuture) Response() *AppendEntriesResponse {
	return a.resp
}
<commit_msg>Document how FSM.Apply errors are retrieved from a Future<commit_after>package raft

import (
	"fmt"
	"io"
	"sync"
	"time"
)

// Future is used to represent an action that may occur in the future.
type Future interface {
	// Error blocks until the future arrives and then returns the error status
	// of the future. This may be called any number of times - all calls will
	// return the same value, however is not OK to call this method twice
	// concurrently on the same Future instance.
	// Error will only return generic errors related to raft, such
	// as ErrLeadershipLost, or ErrRaftShutdown. Some operations, such as
	// ApplyLog, may also return errors from other methods.
	Error() error
}

// IndexFuture is used for future actions that can result in a raft log entry
// being created.
type IndexFuture interface {
	Future

	// Index holds the index of the newly applied log entry.
	// This must not be called until after the Error method has returned.
	Index() uint64
}

// ApplyFuture is used for Apply and can return the FSM response.
type ApplyFuture interface {
	IndexFuture

	// Response returns the FSM response as returned by the FSM.Apply method. This
	// must not be called until after the Error method has returned.
	// Note that if FSM.Apply returns an error, it will be returned by Response,
	// and not by the Error method, so it is always important to check Response
	// for errors from the FSM.
	Response() interface{}
}

// ConfigurationFuture is used for GetConfiguration and can return the
// latest configuration in use by Raft.
type ConfigurationFuture interface {
	IndexFuture

	// Configuration contains the latest configuration. This must
	// not be called until after the Error method has returned.
	Configuration() Configuration
}

// SnapshotFuture is used for waiting on a user-triggered snapshot to complete.
type SnapshotFuture interface {
	Future

	// Open is a function you can call to access the underlying snapshot and
	// its metadata. This must not be called until after the Error method
	// has returned.
	Open() (*SnapshotMeta, io.ReadCloser, error)
}

// LeadershipTransferFuture is used for waiting on a user-triggered leadership
// transfer to complete.
type LeadershipTransferFuture interface {
	Future
}

// errorFuture is used to return a static error.
type errorFuture struct {
	err error
}

func (e errorFuture) Error() error {
	return e.err
}

func (e errorFuture) Response() interface{} {
	return nil
}

func (e errorFuture) Index() uint64 {
	return 0
}

// deferError can be embedded to allow a future
// to provide an error in the future.
type deferError struct {
	err        error
	errCh      chan error
	responded  bool
	ShutdownCh chan struct{}
}

func (d *deferError) init() {
	d.errCh = make(chan error, 1)
}

func (d *deferError) Error() error {
	if d.err != nil {
		// Note that when we've received a nil error, this
		// won't trigger, but the channel is closed after
		// send so we'll still return nil below.
		return d.err
	}
	if d.errCh == nil {
		panic("waiting for response on nil channel")
	}
	select {
	case d.err = <-d.errCh:
	case <-d.ShutdownCh:
		d.err = ErrRaftShutdown
	}
	return d.err
}

func (d *deferError) respond(err error) {
	if d.errCh == nil {
		return
	}
	if d.responded {
		return
	}
	d.errCh <- err
	close(d.errCh)
	d.responded = true
}

// There are several types of requests that cause a configuration entry to
// be appended to the log. These are encoded here for leaderLoop() to process.
// This is internal to a single server.
type configurationChangeFuture struct {
	logFuture
	req configurationChangeRequest
}

// bootstrapFuture is used to attempt a live bootstrap of the cluster. See the
// Raft object's BootstrapCluster member function for more details.
type bootstrapFuture struct {
	deferError

	// configuration is the proposed bootstrap configuration to apply.
	configuration Configuration
}

// logFuture is used to apply a log entry and waits until
// the log is considered committed.
type logFuture struct {
	deferError
	log      Log
	response interface{}
	dispatch time.Time
}

func (l *logFuture) Response() interface{} {
	return l.response
}

func (l *logFuture) Index() uint64 {
	return l.log.Index
}

type shutdownFuture struct {
	raft *Raft
}

func (s *shutdownFuture) Error() error {
	if s.raft == nil {
		return nil
	}
	s.raft.waitShutdown()
	if closeable, ok := s.raft.trans.(WithClose); ok {
		closeable.Close()
	}
	return nil
}

// userSnapshotFuture is used for waiting on a user-triggered snapshot to
// complete.
type userSnapshotFuture struct {
	deferError

	// opener is a function used to open the snapshot. This is filled in
	// once the future returns with no error.
	opener func() (*SnapshotMeta, io.ReadCloser, error)
}

// Open is a function you can call to access the underlying snapshot and its
// metadata.
func (u *userSnapshotFuture) Open() (*SnapshotMeta, io.ReadCloser, error) {
	if u.opener == nil {
		return nil, nil, fmt.Errorf("no snapshot available")
	}
	// Invalidate the opener so it can't get called multiple times,
	// which isn't generally safe.
	defer func() {
		u.opener = nil
	}()
	return u.opener()
}

// userRestoreFuture is used for waiting on a user-triggered restore of an
// external snapshot to complete.
type userRestoreFuture struct {
	deferError

	// meta is the metadata that belongs with the snapshot.
	meta *SnapshotMeta

	// reader is the interface to read the snapshot contents from.
	reader io.Reader
}

// reqSnapshotFuture is used for requesting a snapshot start.
// It is only used internally.
type reqSnapshotFuture struct {
	deferError

	// snapshot details provided by the FSM runner before responding
	index    uint64
	term     uint64
	snapshot FSMSnapshot
}

// restoreFuture is used for requesting an FSM to perform a
// snapshot restore. Used internally only.
type restoreFuture struct {
	deferError
	ID string
}

// verifyFuture is used to verify the current node is still
// the leader. This is to prevent a stale read.
type verifyFuture struct {
	deferError
	notifyCh   chan *verifyFuture
	quorumSize int
	votes      int
	voteLock   sync.Mutex
}

// leadershipTransferFuture is used to track the progress of a leadership
// transfer internally.
type leadershipTransferFuture struct {
	deferError

	ID      *ServerID
	Address *ServerAddress
}

// configurationsFuture is used to retrieve the current configurations. This is
// used to allow safe access to this information outside of the main thread.
type configurationsFuture struct {
	deferError
	configurations configurations
}

// Configuration returns the latest configuration in use by Raft.
func (c *configurationsFuture) Configuration() Configuration {
	return c.configurations.latest
}

// Index returns the index of the latest configuration in use by Raft.
func (c *configurationsFuture) Index() uint64 {
	return c.configurations.latestIndex
}

// vote is used to respond to a verifyFuture.
// This may block when responding on the notifyCh.
func (v *verifyFuture) vote(leader bool) {
	v.voteLock.Lock()
	defer v.voteLock.Unlock()

	// Guard against having notified already
	if v.notifyCh == nil {
		return
	}

	if leader {
		v.votes++
		if v.votes >= v.quorumSize {
			v.notifyCh <- v
			v.notifyCh = nil
		}
	} else {
		v.notifyCh <- v
		v.notifyCh = nil
	}
}

// appendFuture is used for waiting on a pipelined append
// entries RPC.
type appendFuture struct {
	deferError
	start time.Time
	args  *AppendEntriesRequest
	resp  *AppendEntriesResponse
}

func (a *appendFuture) Start() time.Time {
	return a.start
}

func (a *appendFuture) Request() *AppendEntriesRequest {
	return a.args
}

func (a *appendFuture) Response() *AppendEntriesResponse {
	return a.resp
}
<|endoftext|>


<commit_before>package index

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

	storage "code.google.com/p/google-api-go-client/storage/v1"
)

type Directory struct {
	Bucket  string
	Prefix  string
	SubDirs map[string]*Directory
	Objects map[string]*storage.Object
	Updated time.Time
}

func NewDirectory(rawURL string) (*Directory, error) {
	gsURL, err := url.Parse(rawURL)
	if err != nil {
		return nil, err
	}

	if gsURL.Scheme != "gs" {
		return nil, fmt.Errorf("URL missing gs:// scheme prefix: %q", rawURL)
	}
	if gsURL.Host == "" {
		return nil, fmt.Errorf("URL missing bucket name: %q", rawURL)
	}

	// Object name prefix must never start with / but always end with /
	gsURL.Path = strings.TrimLeft(gsURL.Path, "/")
	if gsURL.Path != "" && !strings.HasSuffix(gsURL.Path, "/") {
		gsURL.Path += "/"
	}

	return &Directory{
		Bucket:  gsURL.Host,
		Prefix:  gsURL.Path,
		SubDirs: make(map[string]*Directory),
		Objects: make(map[string]*storage.Object),
	}, nil
}

func (d *Directory) AddObject(obj *storage.Object) error {
	name := strings.TrimPrefix(obj.Name, d.Prefix)
	split := strings.SplitAfterN(name, "/", 2)

	// Propagate update time to parent directories, excluding indexes.
	// Used to detect when indexes should be regenerated.
	if split[len(split)-1] != "index.html" {
		objUpdated, err := time.Parse(time.RFC3339, obj.Updated)
		if err != nil {
			return err
		}
		if d.Updated.Before(objUpdated) {
			d.Updated = objUpdated
		}
	}

	// Save object locally if it has no slash or only ends in slash
	if len(split) == 1 || len(split[1]) == 0 {
		d.Objects[name] = obj
		return nil
	}

	sub, ok := d.SubDirs[split[0]]
	if !ok {
		sub = &Directory{
			Bucket:  d.Bucket,
			Prefix:  d.Prefix + split[0],
			SubDirs: make(map[string]*Directory),
			Objects: make(map[string]*storage.Object),
		}
		d.SubDirs[split[0]] = sub
	}

	return sub.AddObject(obj)
}

func (d *Directory) NeedsIndex() bool {
	if index, ok := d.Objects["index.html"]; ok {
		indexUpdated, err := time.Parse(time.RFC3339, index.Updated)
		return err != nil || d.Updated.After(indexUpdated)
	}
	return true
}
<commit_msg>Support parsing sub-second timestamps<commit_after>package index

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

	storage "code.google.com/p/google-api-go-client/storage/v1"
)

type Directory struct {
	Bucket  string
	Prefix  string
	SubDirs map[string]*Directory
	Objects map[string]*storage.Object
	Updated time.Time
}

func NewDirectory(rawURL string) (*Directory, error) {
	gsURL, err := url.Parse(rawURL)
	if err != nil {
		return nil, err
	}

	if gsURL.Scheme != "gs" {
		return nil, fmt.Errorf("URL missing gs:// scheme prefix: %q", rawURL)
	}
	if gsURL.Host == "" {
		return nil, fmt.Errorf("URL missing bucket name: %q", rawURL)
	}

	// Object name prefix must never start with / but always end with /
	gsURL.Path = strings.TrimLeft(gsURL.Path, "/")
	if gsURL.Path != "" && !strings.HasSuffix(gsURL.Path, "/") {
		gsURL.Path += "/"
	}

	return &Directory{
		Bucket:  gsURL.Host,
		Prefix:  gsURL.Path,
		SubDirs: make(map[string]*Directory),
		Objects: make(map[string]*storage.Object),
	}, nil
}

func (d *Directory) AddObject(obj *storage.Object) error {
	name := strings.TrimPrefix(obj.Name, d.Prefix)
	split := strings.SplitAfterN(name, "/", 2)

	// Propagate update time to parent directories, excluding indexes.
	// Used to detect when indexes should be regenerated.
	if split[len(split)-1] != "index.html" {
		objUpdated, err := time.Parse(time.RFC3339Nano, obj.Updated)
		if err != nil {
			return err
		}
		if d.Updated.Before(objUpdated) {
			d.Updated = objUpdated
		}
	}

	// Save object locally if it has no slash or only ends in slash
	if len(split) == 1 || len(split[1]) == 0 {
		d.Objects[name] = obj
		return nil
	}

	sub, ok := d.SubDirs[split[0]]
	if !ok {
		sub = &Directory{
			Bucket:  d.Bucket,
			Prefix:  d.Prefix + split[0],
			SubDirs: make(map[string]*Directory),
			Objects: make(map[string]*storage.Object),
		}
		d.SubDirs[split[0]] = sub
	}

	return sub.AddObject(obj)
}

func (d *Directory) NeedsIndex() bool {
	if index, ok := d.Objects["index.html"]; ok {
		indexUpdated, err := time.Parse(time.RFC3339Nano, index.Updated)
		return err != nil || d.Updated.After(indexUpdated)
	}
	return true
}
<|endoftext|>


<commit_before>package main

import (
	"reflect"
	"regexp"
	"testing"
)

func regexTest(regex *regexp.Regexp, test string, expected []string, t *testing.T) {
	result := regex.FindStringSubmatch(test)
	if !reflect.DeepEqual(result, expected) {
		t.Errorf("regex   : %s\nexpected: %v\ngot     : %v\n", regex, expected, result)
	}
}

func Test_ParseOption(t *testing.T) {
	re := regexp.MustCompile(regexOption)
	regexTest(re,
		"\\db foo",
		[]string{"\\db foo", "db", "foo"},
		t)
	regexTest(re,
		"\\db foo1",
		[]string{"\\db foo1", "db", "foo1"},
		t)
}

func Test_ParseInsert(t *testing.T) {
	re := regexp.MustCompile(regexInsert)
	regexTest(re,
		"insert into bar (col) values (1)",
		[]string{"insert into bar (col) values (1)", "bar", "(col)", "1"},
		t)
	regexTest(re,
		"insert into demo values (1406231160000, 0, 10)",
		[]string{"insert into demo values (1406231160000, 0, 10)", "demo", "", "1406231160000, 0, 10"},
		t)
}
<commit_msg>better output in regex parsing dumps<commit_after>package main

import (
	"github.com/davecgh/go-spew/spew"
	"reflect"
	"regexp"
	"testing"
)

func regexTest(regex *regexp.Regexp, test string, expected []string, t *testing.T) {
	result := regex.FindStringSubmatch(test)
	if !reflect.DeepEqual(result, expected) {
		t.Errorf("regex   : %s\n", regex)
		t.Errorf("subject : %s\n", test)
		t.Errorf("expected: %v\n", spew.Sdump(expected))
		t.Errorf("got     : %v\n", spew.Sdump(result))
	}
}

func Test_ParseOption(t *testing.T) {
	re := regexp.MustCompile(regexOption)
	regexTest(re,
		"\\db foo",
		[]string{"\\db foo", "db", "foo"},
		t)
	regexTest(re,
		"\\db foo1",
		[]string{"\\db foo1", "db", "foo1"},
		t)
}

func Test_ParseInsert(t *testing.T) {
	re := regexp.MustCompile(regexInsert)
	regexTest(re,
		"insert into bar (col) values (1)",
		[]string{"insert into bar (col) values (1)", "bar", "(col)", "1"},
		t)
	regexTest(re,
		"insert into demo values (1406231160000, 0, 10)",
		[]string{"insert into demo values (1406231160000, 0, 10)", "demo", "", "1406231160000, 0, 10"},
		t)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
)

type Option struct {
	listen  bool
	netType bool
	timeout int
	host    string
	port    string
}

func GetArgs() (args Option) {
	flag.BoolVar(&args.listen, "l", false, "Listen mode, for inbound connects")
	flag.BoolVar(&args.netType, "u", false, "UDP mode")
	flag.IntVar(&args.timeout, "w", 0, "secs Timeout for connects and final net reads")
	//flag.StringVar(&args.laddr, "s", "127", "Local source address")

	flag.Parse()
	args.host = flag.Arg(0)
	args.port = flag.Arg(1)
	return
}
<commit_msg>add input with port range<commit_after>package main

import (
	"flag"
	"strings"
)

type Option struct {
	listen  bool
	netType bool
	timeout int
	host    string
	port    []string
}

func GetArgs() (args Option) {
	flag.BoolVar(&args.listen, "l", false, "Listen mode, for inbound connects")
	flag.BoolVar(&args.netType, "u", false, "UDP mode")
	flag.IntVar(&args.timeout, "w", 0, "secs Timeout for connects and final net reads")
	//flag.StringVar(&args.laddr, "s", "127", "Local source address")

	flag.Parse()
	args.host = flag.Arg(0)
	args.port = strings.Split(flag.Arg(1), "-")
	return
}
<|endoftext|>


<commit_before>package aws

import (
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

// How long to sleep if a limit-exceeded event happens
var routeTargetValidationError = errors.New("Error: more than 1 target specified. Only 1 of gateway_id, " +
	"nat_gateway_id, instance_id, network_interface_id, route_table_id or " +
	"vpc_peering_connection_id is allowed.")

// AWS Route resource Schema declaration
func resourceAwsRoute() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsRouteCreate,
		Read:   resourceAwsRouteRead,
		Update: resourceAwsRouteUpdate,
		Delete: resourceAwsRouteDelete,
		Exists: resourceAwsRouteExists,

		Schema: map[string]*schema.Schema{
			"destination_cidr_block": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"destination_prefix_list_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"gateway_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"nat_gateway_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"instance_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"instance_owner_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"network_interface_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"origin": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"state": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"route_table_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"vpc_peering_connection_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
		},
	}
}

func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	var numTargets int
	var setTarget string
	allowedTargets := []string{
		"gateway_id",
		"nat_gateway_id",
		"instance_id",
		"network_interface_id",
		"vpc_peering_connection_id",
	}

	// Check if more than 1 target is specified
	for _, target := range allowedTargets {
		if len(d.Get(target).(string)) > 0 {
			numTargets++
			setTarget = target
		}
	}

	if numTargets > 1 {
		return routeTargetValidationError
	}

	createOpts := &ec2.CreateRouteInput{}
	// Formulate CreateRouteInput based on the target type
	switch setTarget {
	case "gateway_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			GatewayId:            aws.String(d.Get("gateway_id").(string)),
		}
	case "nat_gateway_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NatGatewayId:         aws.String(d.Get("nat_gateway_id").(string)),
		}
	case "instance_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			InstanceId:           aws.String(d.Get("instance_id").(string)),
		}
	case "network_interface_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NetworkInterfaceId:   aws.String(d.Get("network_interface_id").(string)),
		}
	case "vpc_peering_connection_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:           aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock:   aws.String(d.Get("destination_cidr_block").(string)),
			VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
		}
	default:
		return fmt.Errorf("Error: invalid target type specified.")
	}
	log.Printf("[DEBUG] Route create config: %s", createOpts)

	// Create the route
	var err error

	err = resource.Retry(2*time.Minute, func() *resource.RetryError {
		_, err = conn.CreateRoute(createOpts)

		if err != nil {
			ec2err, ok := err.(awserr.Error)
			if !ok {
				return resource.NonRetryableError(err)
			}
			if ec2err.Code() == "InvalidParameterException" {
				log.Printf("[DEBUG] Trying to create route again: %q", ec2err.Message())
				return resource.RetryableError(err)
			}

			return resource.NonRetryableError(err)
		}

		return nil
	})
	if err != nil {
		return fmt.Errorf("Error creating route: %s", err)
	}

	var route *ec2.Route
	err = resource.Retry(15*time.Second, func() *resource.RetryError {
		route, err = findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string))
		return resource.RetryableError(err)
	})
	if err != nil {
		return fmt.Errorf("Error finding route after creating it: %s", err)
	}

	d.SetId(routeIDHash(d, route))
	resourceAwsRouteSetResourceData(d, route)
	return nil
}

func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	route, err := findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string))
	if err != nil {
		return err
	}
	resourceAwsRouteSetResourceData(d, route)
	return nil
}

func resourceAwsRouteSetResourceData(d *schema.ResourceData, route *ec2.Route) {
	d.Set("destination_prefix_list_id", route.DestinationPrefixListId)
	d.Set("gateway_id", route.GatewayId)
	d.Set("nat_gateway_id", route.NatGatewayId)
	d.Set("instance_id", route.InstanceId)
	d.Set("instance_owner_id", route.InstanceOwnerId)
	d.Set("network_interface_id", route.NetworkInterfaceId)
	d.Set("origin", route.Origin)
	d.Set("state", route.State)
	d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)
}

func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	var numTargets int
	var setTarget string
	allowedTargets := []string{
		"gateway_id",
		"nat_gateway_id",
		"instance_id",
		"network_interface_id",
		"vpc_peering_connection_id",
	}
	replaceOpts := &ec2.ReplaceRouteInput{}

	// Check if more than 1 target is specified
	for _, target := range allowedTargets {
		if len(d.Get(target).(string)) > 0 {
			numTargets++
			setTarget = target
		}
	}

	if numTargets > 1 {
		return routeTargetValidationError
	}

	// Formulate ReplaceRouteInput based on the target type
	switch setTarget {
	case "gateway_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			GatewayId:            aws.String(d.Get("gateway_id").(string)),
		}
	case "nat_gateway_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NatGatewayId:         aws.String(d.Get("nat_gateway_id").(string)),
		}
	case "instance_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			InstanceId:           aws.String(d.Get("instance_id").(string)),
			//NOOP: Ensure we don't blow away network interface id that is set after instance is launched
			NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)),
		}
	case "network_interface_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NetworkInterfaceId:   aws.String(d.Get("network_interface_id").(string)),
		}
	case "vpc_peering_connection_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:           aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock:   aws.String(d.Get("destination_cidr_block").(string)),
			VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
		}
	default:
		return fmt.Errorf("Error: invalid target type specified.")
	}
	log.Printf("[DEBUG] Route replace config: %s", replaceOpts)

	// Replace the route
	_, err := conn.ReplaceRoute(replaceOpts)
	if err != nil {
		return err
	}

	return nil
}

func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	deleteOpts := &ec2.DeleteRouteInput{
		RouteTableId:         aws.String(d.Get("route_table_id").(string)),
		DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
	}
	log.Printf("[DEBUG] Route delete opts: %s", deleteOpts)

	var err error
	err = resource.Retry(5*time.Minute, func() *resource.RetryError {
		log.Printf("[DEBUG] Trying to delete route with opts %s", deleteOpts)
		resp, err := conn.DeleteRoute(deleteOpts)
		log.Printf("[DEBUG] Route delete result: %s", resp)

		if err == nil {
			return nil
		}

		ec2err, ok := err.(awserr.Error)
		if !ok {
			return resource.NonRetryableError(err)
		}
		if ec2err.Code() == "InvalidParameterException" {
			log.Printf("[DEBUG] Trying to delete route again: %q",
				ec2err.Message())
			return resource.RetryableError(err)
		}

		return resource.NonRetryableError(err)
	})

	if err != nil {
		return err
	}

	d.SetId("")
	return nil
}

func resourceAwsRouteExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	conn := meta.(*AWSClient).ec2conn
	routeTableId := d.Get("route_table_id").(string)

	findOpts := &ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&routeTableId},
	}

	res, err := conn.DescribeRouteTables(findOpts)
	if err != nil {
		return false, fmt.Errorf("Error while checking if route exists: %s", err)
	}

	if len(res.RouteTables) < 1 || res.RouteTables[0] == nil {
		log.Printf("[WARN] Route table %s is gone, so route does not exist.",
			routeTableId)
		return false, nil
	}

	cidr := d.Get("destination_cidr_block").(string)
	for _, route := range (*res.RouteTables[0]).Routes {
		if route.DestinationCidrBlock != nil && *route.DestinationCidrBlock == cidr {
			return true, nil
		}
	}

	return false, nil
}

// Create an ID for a route
func routeIDHash(d *schema.ResourceData, r *ec2.Route) string {
	return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock))
}

// Helper: retrieve a route
func findResourceRoute(conn *ec2.EC2, rtbid string, cidr string) (*ec2.Route, error) {
	routeTableID := rtbid

	findOpts := &ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&routeTableID},
	}

	resp, err := conn.DescribeRouteTables(findOpts)
	if err != nil {
		return nil, err
	}

	if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil {
		return nil, fmt.Errorf("Route table %s is gone, so route does not exist.",
			routeTableID)
	}

	for _, route := range (*resp.RouteTables[0]).Routes {
		if route.DestinationCidrBlock != nil && *route.DestinationCidrBlock == cidr {
			return route, nil
		}
	}

	return nil, fmt.Errorf(
		`error finding matching route for Route table (%s) and destination CIDR block (%s)`,
		rtbid, cidr)
}
<commit_msg>provider/aws: Refresh `aws_route` from state if `aws_route_table` not (#8443)<commit_after>package aws

import (
	"errors"
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/service/ec2"
	"github.com/hashicorp/terraform/helper/hashcode"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/helper/schema"
)

// How long to sleep if a limit-exceeded event happens
var routeTargetValidationError = errors.New("Error: more than 1 target specified. Only 1 of gateway_id, " +
	"nat_gateway_id, instance_id, network_interface_id, route_table_id or " +
	"vpc_peering_connection_id is allowed.")

// AWS Route resource Schema declaration
func resourceAwsRoute() *schema.Resource {
	return &schema.Resource{
		Create: resourceAwsRouteCreate,
		Read:   resourceAwsRouteRead,
		Update: resourceAwsRouteUpdate,
		Delete: resourceAwsRouteDelete,
		Exists: resourceAwsRouteExists,

		Schema: map[string]*schema.Schema{
			"destination_cidr_block": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
				ForceNew: true,
			},

			"destination_prefix_list_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"gateway_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"nat_gateway_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"instance_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"instance_owner_id": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"network_interface_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
				Computed: true,
			},

			"origin": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"state": &schema.Schema{
				Type:     schema.TypeString,
				Computed: true,
			},

			"route_table_id": &schema.Schema{
				Type:     schema.TypeString,
				Required: true,
			},

			"vpc_peering_connection_id": &schema.Schema{
				Type:     schema.TypeString,
				Optional: true,
			},
		},
	}
}

func resourceAwsRouteCreate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	var numTargets int
	var setTarget string
	allowedTargets := []string{
		"gateway_id",
		"nat_gateway_id",
		"instance_id",
		"network_interface_id",
		"vpc_peering_connection_id",
	}

	// Check if more than 1 target is specified
	for _, target := range allowedTargets {
		if len(d.Get(target).(string)) > 0 {
			numTargets++
			setTarget = target
		}
	}

	if numTargets > 1 {
		return routeTargetValidationError
	}

	createOpts := &ec2.CreateRouteInput{}
	// Formulate CreateRouteInput based on the target type
	switch setTarget {
	case "gateway_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			GatewayId:            aws.String(d.Get("gateway_id").(string)),
		}
	case "nat_gateway_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NatGatewayId:         aws.String(d.Get("nat_gateway_id").(string)),
		}
	case "instance_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			InstanceId:           aws.String(d.Get("instance_id").(string)),
		}
	case "network_interface_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NetworkInterfaceId:   aws.String(d.Get("network_interface_id").(string)),
		}
	case "vpc_peering_connection_id":
		createOpts = &ec2.CreateRouteInput{
			RouteTableId:           aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock:   aws.String(d.Get("destination_cidr_block").(string)),
			VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
		}
	default:
		return fmt.Errorf("Error: invalid target type specified.")
	}
	log.Printf("[DEBUG] Route create config: %s", createOpts)

	// Create the route
	var err error

	err = resource.Retry(2*time.Minute, func() *resource.RetryError {
		_, err = conn.CreateRoute(createOpts)

		if err != nil {
			ec2err, ok := err.(awserr.Error)
			if !ok {
				return resource.NonRetryableError(err)
			}
			if ec2err.Code() == "InvalidParameterException" {
				log.Printf("[DEBUG] Trying to create route again: %q", ec2err.Message())
				return resource.RetryableError(err)
			}

			return resource.NonRetryableError(err)
		}

		return nil
	})
	if err != nil {
		return fmt.Errorf("Error creating route: %s", err)
	}

	var route *ec2.Route
	err = resource.Retry(15*time.Second, func() *resource.RetryError {
		route, err = findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string))
		return resource.RetryableError(err)
	})
	if err != nil {
		return fmt.Errorf("Error finding route after creating it: %s", err)
	}

	d.SetId(routeIDHash(d, route))
	resourceAwsRouteSetResourceData(d, route)
	return nil
}

func resourceAwsRouteRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	route, err := findResourceRoute(conn, d.Get("route_table_id").(string), d.Get("destination_cidr_block").(string))
	if err != nil {
		if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() == "InvalidRouteTableID.NotFound" {
			log.Printf("[WARN] AWS RouteTable not found. Removing Route from state")
			d.SetId("")
			return nil
		}
		return err
	}
	resourceAwsRouteSetResourceData(d, route)
	return nil
}

func resourceAwsRouteSetResourceData(d *schema.ResourceData, route *ec2.Route) {
	d.Set("destination_prefix_list_id", route.DestinationPrefixListId)
	d.Set("gateway_id", route.GatewayId)
	d.Set("nat_gateway_id", route.NatGatewayId)
	d.Set("instance_id", route.InstanceId)
	d.Set("instance_owner_id", route.InstanceOwnerId)
	d.Set("network_interface_id", route.NetworkInterfaceId)
	d.Set("origin", route.Origin)
	d.Set("state", route.State)
	d.Set("vpc_peering_connection_id", route.VpcPeeringConnectionId)
}

func resourceAwsRouteUpdate(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn
	var numTargets int
	var setTarget string
	allowedTargets := []string{
		"gateway_id",
		"nat_gateway_id",
		"instance_id",
		"network_interface_id",
		"vpc_peering_connection_id",
	}
	replaceOpts := &ec2.ReplaceRouteInput{}

	// Check if more than 1 target is specified
	for _, target := range allowedTargets {
		if len(d.Get(target).(string)) > 0 {
			numTargets++
			setTarget = target
		}
	}

	if numTargets > 1 {
		return routeTargetValidationError
	}

	// Formulate ReplaceRouteInput based on the target type
	switch setTarget {
	case "gateway_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			GatewayId:            aws.String(d.Get("gateway_id").(string)),
		}
	case "nat_gateway_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NatGatewayId:         aws.String(d.Get("nat_gateway_id").(string)),
		}
	case "instance_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			InstanceId:           aws.String(d.Get("instance_id").(string)),
			//NOOP: Ensure we don't blow away network interface id that is set after instance is launched
			NetworkInterfaceId: aws.String(d.Get("network_interface_id").(string)),
		}
	case "network_interface_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:         aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
			NetworkInterfaceId:   aws.String(d.Get("network_interface_id").(string)),
		}
	case "vpc_peering_connection_id":
		replaceOpts = &ec2.ReplaceRouteInput{
			RouteTableId:           aws.String(d.Get("route_table_id").(string)),
			DestinationCidrBlock:   aws.String(d.Get("destination_cidr_block").(string)),
			VpcPeeringConnectionId: aws.String(d.Get("vpc_peering_connection_id").(string)),
		}
	default:
		return fmt.Errorf("Error: invalid target type specified.")
	}
	log.Printf("[DEBUG] Route replace config: %s", replaceOpts)

	// Replace the route
	_, err := conn.ReplaceRoute(replaceOpts)
	if err != nil {
		return err
	}

	return nil
}

func resourceAwsRouteDelete(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).ec2conn

	deleteOpts := &ec2.DeleteRouteInput{
		RouteTableId:         aws.String(d.Get("route_table_id").(string)),
		DestinationCidrBlock: aws.String(d.Get("destination_cidr_block").(string)),
	}
	log.Printf("[DEBUG] Route delete opts: %s", deleteOpts)

	var err error
	err = resource.Retry(5*time.Minute, func() *resource.RetryError {
		log.Printf("[DEBUG] Trying to delete route with opts %s", deleteOpts)
		resp, err := conn.DeleteRoute(deleteOpts)
		log.Printf("[DEBUG] Route delete result: %s", resp)

		if err == nil {
			return nil
		}

		ec2err, ok := err.(awserr.Error)
		if !ok {
			return resource.NonRetryableError(err)
		}
		if ec2err.Code() == "InvalidParameterException" {
			log.Printf("[DEBUG] Trying to delete route again: %q",
				ec2err.Message())
			return resource.RetryableError(err)
		}

		return resource.NonRetryableError(err)
	})

	if err != nil {
		return err
	}

	d.SetId("")
	return nil
}

func resourceAwsRouteExists(d *schema.ResourceData, meta interface{}) (bool, error) {
	conn := meta.(*AWSClient).ec2conn
	routeTableId := d.Get("route_table_id").(string)

	findOpts := &ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&routeTableId},
	}

	res, err := conn.DescribeRouteTables(findOpts)
	if err != nil {
		return false, fmt.Errorf("Error while checking if route exists: %s", err)
	}

	if len(res.RouteTables) < 1 || res.RouteTables[0] == nil {
		log.Printf("[WARN] Route table %s is gone, so route does not exist.",
			routeTableId)
		return false, nil
	}

	cidr := d.Get("destination_cidr_block").(string)
	for _, route := range (*res.RouteTables[0]).Routes {
		if route.DestinationCidrBlock != nil && *route.DestinationCidrBlock == cidr {
			return true, nil
		}
	}

	return false, nil
}

// Create an ID for a route
func routeIDHash(d *schema.ResourceData, r *ec2.Route) string {
	return fmt.Sprintf("r-%s%d", d.Get("route_table_id").(string), hashcode.String(*r.DestinationCidrBlock))
}

// Helper: retrieve a route
func findResourceRoute(conn *ec2.EC2, rtbid string, cidr string) (*ec2.Route, error) {
	routeTableID := rtbid

	findOpts := &ec2.DescribeRouteTablesInput{
		RouteTableIds: []*string{&routeTableID},
	}

	resp, err := conn.DescribeRouteTables(findOpts)
	if err != nil {
		return nil, err
	}

	if len(resp.RouteTables) < 1 || resp.RouteTables[0] == nil {
		return nil, fmt.Errorf("Route table %s is gone, so route does not exist.",
			routeTableID)
	}

	for _, route := range (*resp.RouteTables[0]).Routes {
		if route.DestinationCidrBlock != nil && *route.DestinationCidrBlock == cidr {
			return route, nil
		}
	}

	return nil, fmt.Errorf(
		`error finding matching route for Route table (%s) and destination CIDR block (%s)`,
		rtbid, cidr)
}
<|endoftext|>


<commit_before>package ghooks

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
)

const (
	VERSION = 0.1
)

type Server struct {
	Port int
}

type Hook struct {
	Name string
	Func func(payload interface{})
}

type Hooks struct {
	Hooks []Hook
}

var hooks Hooks

func On(name string, handler func(payload interface{})) {
	hooks.Hooks = append(hooks.Hooks, Hook{Name: name, Func: handler})
}

func Emmit(name string, payload interface{}) {
	for _, v := range hooks.Hooks {
		if strings.EqualFold(v.Name, name) {
			v.Func(payload)
		}
	}
}

func NewServer(port int) *Server {
	return &Server{port}
}

func (s *Server) Run() error {
	fmt.Printf("ghooks server start 127.0.0.1:%d \n", s.Port)
	http.HandleFunc("/", Reciver)
	return http.ListenAndServe(":"+strconv.Itoa(s.Port), nil)
}

func Reciver(w http.ResponseWriter, req *http.Request) {
	if req.Method == "GET" {
		http.Error(w, "Method Not Allowd", http.StatusMethodNotAllowed)
		return
	}

	event := req.Header.Get("X-GitHub-Event")

	if event == "" {
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}

	var payload interface{}
	decoder := json.NewDecoder(req.Body)
	decoder.Decode(&payload)

	Emmit(event, payload)
	w.WriteHeader(http.StatusOK)
}
<commit_msg>Add Error handling<commit_after>package ghooks

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strconv"
	"strings"
)

const (
	VERSION = 0.1
)

type Server struct {
	Port int
}

type Hook struct {
	Name string
	Func func(payload interface{})
}

type Hooks struct {
	Hooks []Hook
}

var hooks Hooks

func On(name string, handler func(payload interface{})) {
	hooks.Hooks = append(hooks.Hooks, Hook{Name: name, Func: handler})
}

func Emmit(name string, payload interface{}) {
	for _, v := range hooks.Hooks {
		if strings.EqualFold(v.Name, name) {
			v.Func(payload)
		}
	}
}

func NewServer(port int) *Server {
	return &Server{port}
}

func (s *Server) Run() error {
	fmt.Printf("ghooks server start 127.0.0.1:%d \n", s.Port)
	http.HandleFunc("/", Reciver)
	return http.ListenAndServe(":"+strconv.Itoa(s.Port), nil)
}

func Reciver(w http.ResponseWriter, req *http.Request) {
	if req.Method == "GET" {
		http.Error(w, "Method Not Allowd", http.StatusMethodNotAllowed)
		return
	}

	event := req.Header.Get("X-GitHub-Event")

	if event == "" {
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}

	if req.Body == nil {
		http.Error(w, "Bad Request", http.StatusBadRequest)
		return
	}

	var payload interface{}
	decoder := json.NewDecoder(req.Body)
	decoder.Decode(&payload)

	Emmit(event, payload)
	w.WriteHeader(http.StatusOK)
}
<|endoftext|>


<commit_before>package krpc

import (
	"encoding"
	"fmt"
	"reflect"

	"github.com/anacrolix/missinggo/slices"

	"github.com/anacrolix/torrent/bencode"
)

func unmarshalBencodedBinary(u encoding.BinaryUnmarshaler, b []byte) (err error) {
	var ub string
	err = bencode.Unmarshal(b, &ub)
	if err != nil {
		return
	}
	return u.UnmarshalBinary([]byte(ub))
}

type elemSizer interface {
	ElemSize() int
}

func unmarshalBinarySlice(slice elemSizer, b []byte) (err error) {
	sliceValue := reflect.ValueOf(slice).Elem()
	elemType := sliceValue.Type().Elem()
	bytesPerElem := slice.ElemSize()
	for len(b) != 0 {
		if len(b) < bytesPerElem {
			err = fmt.Errorf("%d trailing bytes < %d required for element", len(b), bytesPerElem)
			break
		}
		elem := reflect.New(elemType)
		if bu, ok := elem.Interface().(encoding.BinaryUnmarshaler); ok {
			err = bu.UnmarshalBinary(b[:bytesPerElem])
		} else if elem.Elem().Len() == bytesPerElem {
			reflect.Copy(elem.Elem(), reflect.ValueOf(b[:bytesPerElem]))
		} else {
			err = fmt.Errorf("can't unmarshal %v bytes into %v", bytesPerElem, elem.Type())
		}
		if err != nil {
			return
		}
		sliceValue.Set(reflect.Append(sliceValue, elem.Elem()))
		b = b[bytesPerElem:]
	}
	return
}

func marshalBinarySlice(slice elemSizer) (ret []byte, err error) {
	var elems []encoding.BinaryMarshaler
	slices.MakeInto(&elems, slice)
	for _, e := range elems {
		var b []byte
		b, err = e.MarshalBinary()
		if err != nil {
			return
		}
		if len(b) != slice.ElemSize() {
			panic(fmt.Sprintf("marshalled %d bytes, but expected %d", len(b), slice.ElemSize()))
		}
		ret = append(ret, b...)
	}
	return
}

func bencodeBytesResult(b []byte, err error) ([]byte, error) {
	if err != nil {
		return b, err
	}
	return bencode.Marshal(b)
}
<commit_msg>Allocate a single elem instance when unmarshalling binary slices<commit_after>package krpc

import (
	"encoding"
	"fmt"
	"reflect"

	"github.com/anacrolix/missinggo/slices"

	"github.com/anacrolix/torrent/bencode"
)

func unmarshalBencodedBinary(u encoding.BinaryUnmarshaler, b []byte) (err error) {
	var ub string
	err = bencode.Unmarshal(b, &ub)
	if err != nil {
		return
	}
	return u.UnmarshalBinary([]byte(ub))
}

type elemSizer interface {
	ElemSize() int
}

func unmarshalBinarySlice(slice elemSizer, b []byte) (err error) {
	sliceValue := reflect.ValueOf(slice).Elem()
	elemType := sliceValue.Type().Elem()
	bytesPerElem := slice.ElemSize()
	elem := reflect.New(elemType)
	for len(b) != 0 {
		if len(b) < bytesPerElem {
			err = fmt.Errorf("%d trailing bytes < %d required for element", len(b), bytesPerElem)
			break
		}
		if bu, ok := elem.Interface().(encoding.BinaryUnmarshaler); ok {
			err = bu.UnmarshalBinary(b[:bytesPerElem])
		} else if elem.Elem().Len() == bytesPerElem {
			reflect.Copy(elem.Elem(), reflect.ValueOf(b[:bytesPerElem]))
		} else {
			err = fmt.Errorf("can't unmarshal %v bytes into %v", bytesPerElem, elem.Type())
		}
		if err != nil {
			return
		}
		sliceValue.Set(reflect.Append(sliceValue, elem.Elem()))
		b = b[bytesPerElem:]
	}
	return
}

func marshalBinarySlice(slice elemSizer) (ret []byte, err error) {
	var elems []encoding.BinaryMarshaler
	slices.MakeInto(&elems, slice)
	for _, e := range elems {
		var b []byte
		b, err = e.MarshalBinary()
		if err != nil {
			return
		}
		if len(b) != slice.ElemSize() {
			panic(fmt.Sprintf("marshalled %d bytes, but expected %d", len(b), slice.ElemSize()))
		}
		ret = append(ret, b...)
	}
	return
}

func bencodeBytesResult(b []byte, err error) ([]byte, error) {
	if err != nil {
		return b, err
	}
	return bencode.Marshal(b)
}
<|endoftext|>


<commit_before>package main

import (
    "github.com/PuerkitoBio/goquery"
    "github.com/blevesearch/segment"
	"code.google.com/p/go-sqlite/go1/sqlite3"
    "fmt"
    "crypto/sha256"
	"encoding/hex"
    "log"
)

const (
	None = iota
	Number
	Letter
	Kana
	Ideo
)

type ChunkInfo struct {
  totalWords int
  chunk string
}

func excuteDemoForURL(documentURL string) {
  doc := fetchTheDocument(documentURL)

  chunks := chunkTheText(doc)
  hashes := hashTheChunks(chunks)
  success := indexTheHashes(hashes)
  if success {
	fmt.Println("Done!")
  }
}

func fetchTheDocument(documentURL string) (*goquery.Document) {
  doc, err := goquery.NewDocument(documentURL)

  if err != nil {
    log.Fatal(err)
  }
  return doc
}

func prepTheDatabase() {
  c, _ := sqlite3.Open("sqlite.db")
  c.Exec("DROP TABLE IF EXISTS block_index")
  c.Exec("CREATE TABLE block_index (block_id INTEGER PRIMARY KEY, block_hash VARCHAR(255) NOT NULL, total_words INTEGER NOT NULL)")
  c.Exec("CREATE INDEX block_hash_idx ON block_index (block_hash)")
  // go use(c)
}

func chunkTheText(doc *goquery.Document) ([]ChunkInfo) {
  var chunks []ChunkInfo
  breakAccountedFor := false
  chunk := ""
  totalWords := 0

  doc.Find("p").Each(func(i int, s *goquery.Selection) {
    text := s.Text()

    segmenter := segment.NewWordSegmenterDirect([]byte(text))
    for segmenter.Segment() {
        tokenBytes := segmenter.Bytes()
        tokenType := segmenter.Type()

		if tokenType != None   {
				chunk += segmenter.Text()
				breakAccountedFor = false
				totalWords++
		} else if tokenType == None {
				if !breakAccountedFor {
						chunk += " "
						breakAccountedFor = true
				}
		} else {
				fmt.Printf("Unknown TokenType(%d) encountered for token: %s", tokenType, tokenBytes)
		}
    }

    if err := segmenter.Err(); err != nil {
        log.Fatal(err)
    }

	if totalWords >= 50 {
	  chunks = append(chunks, ChunkInfo{totalWords, chunk})
	  // Reset for the next round
	  totalWords = 0
	  chunk = ""
	}
  })
  return chunks
}

func hashTheChunks(chunks []ChunkInfo) ([]string) {
  var hashes []string = make([]string, 0, len(chunks))

  for i, chunkInfo := range chunks {
	hasher := sha256.New()
    hasher.Write([]byte(chunkInfo.chunk))
    hash := hasher.Sum(nil)
    hashes = append(hashes, hex.EncodeToString(hash))
	fmt.Printf("\n%s\n====> %d words %s\n", chunkInfo.chunk, chunkInfo.totalWords, hashes[i])
  }

  return hashes
}

func indexTheHashes(hashes []string) (bool) {
  // TODO:
  return false
}

func main() {
    excuteDemoForURL("https://www.gutenberg.org/files/39452/39452-h/39452-h.htm")
}
<commit_msg>Some cleanup and a couple of bug fixes.<commit_after>package main

import (
    "github.com/PuerkitoBio/goquery"
    "github.com/blevesearch/segment"
	"code.google.com/p/go-sqlite/go1/sqlite3"
    "fmt"
    "crypto/sha256"
	"encoding/hex"
    "log"
	"flag"
	"strings"
)

const (
	None = iota
	Number
	Letter
	Kana
	Ideo
)

type ChunkInfo struct {
  totalWords int
  chunk string
}

func fetchTheDocument(documentURL string) (*goquery.Document) {
  doc, err := goquery.NewDocument(documentURL)

  if err != nil {
    log.Fatal(err)
  }
  return doc
}

func prepTheDatabase() {
  c, _ := sqlite3.Open("sqlite.db")
  c.Exec("DROP TABLE IF EXISTS block_index")
  c.Exec("CREATE TABLE block_index (block_id INTEGER PRIMARY KEY, block_hash VARCHAR(255) NOT NULL, total_words INTEGER NOT NULL)")
  c.Exec("CREATE INDEX block_hash_idx ON block_index (block_hash)")
  // go use(c)
}

func chunkTheText(doc *goquery.Document) ([]ChunkInfo) {
  var chunks []ChunkInfo
  breakAccountedFor := false
  chunk := ""
  totalWords := 0

  doc.Find("p,pre,div,span,h1,h2,h3").Each(func(i int, s *goquery.Selection) {
	// A bit of a bug here as this does not handle tags embedded in the text at
	// all so for instance if you have:
	// 		'... some textblah blahmore text...'
	// you will get '... some textblah blahmore text...' which most likely isn't
	// what you want. This is an area that would need to be discussed in detail
	// if this approach was to be standardized for sharng annotations or for
	// citations.
    text := s.Text()
	if	len(chunk) > 0 && !strings.HasSuffix(chunk, " ") {
	  chunk += " "
	}

    segmenter := segment.NewWordSegmenterDirect([]byte(text))
    for segmenter.Segment() {
        tokenBytes := segmenter.Bytes()
        tokenType := segmenter.Type()

		if tokenType != None   {
				chunk += segmenter.Text()
				breakAccountedFor = false
				totalWords++
		} else if tokenType == None {
				if !breakAccountedFor {
						chunk += " "
						breakAccountedFor = true
				}
		} else {
				fmt.Printf("Unknown TokenType(%d) encountered for token: %s", tokenType, tokenBytes)
		}
    }

    if err := segmenter.Err(); err != nil {
        log.Fatal(err)
    }

	if totalWords >= 50 {
	  chunks = append(chunks, ChunkInfo{totalWords, chunk})
	  // Reset for the next round
	  breakAccountedFor = false
	  totalWords = 0
	  chunk = ""
	}
  })

  // In case there is a straggler
  if len(chunk) > 0 && totalWords > 0 {
	chunks = append(chunks, ChunkInfo{totalWords, chunk})
  }

  return chunks
}

func hashTheChunks(chunks []ChunkInfo) ([]string) {
  var hashes []string = make([]string, 0, len(chunks))

  for i, chunkInfo := range chunks {
	hasher := sha256.New()
    hasher.Write([]byte(chunkInfo.chunk))
    hash := hasher.Sum(nil)
    hashes = append(hashes, hex.EncodeToString(hash))
	fmt.Printf("\n%s\n====> %d words %s\n", chunkInfo.chunk, chunkInfo.totalWords, hashes[i])
  }

  return hashes
}

func indexTheHashes(hashes []string) (bool) {
  // TODO:
  return false
}

func main() {
  var documentURL string
  flag.StringVar(&documentURL, "document-url", "https://www.gutenberg.org/files/39452/39452-h/39452-h.htm", "The document URL that you wish to process.")
  flag.Parse()

  doc := fetchTheDocument(documentURL)

  chunks := chunkTheText(doc)
  hashes := hashTheChunks(chunks)
  success := indexTheHashes(hashes)
  if success {
	fmt.Println("Done!")
  }
}
<|endoftext|>


<commit_before>package main

import (
    "flag"
//    "os"

    "github.com/datamaglia/gimbal/spec"
    "github.com/datamaglia/gimbal/runner"
)

var filename = flag.String("f", "", "Read the config from a file")
var quiet = flag.Bool("q", false, "Suppress all output")

func main() {
    flag.Parse()

    config := spec.LoadJsonFile(*filename)
    runner.RunSpec(config)
}
<commit_msg>Run go fmt.<commit_after>package main

import (
	"flag"

	"github.com/datamaglia/gimbal/runner"
	"github.com/datamaglia/gimbal/spec"
)

var filename = flag.String("f", "", "Read the config from a file")
var quiet = flag.Bool("q", false, "Suppress all output")

func main() {
	flag.Parse()

	config := spec.LoadJsonFile(*filename)
	runner.RunSpec(config)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/intervention-engine/ie/models"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"os"
)

func main() {
	usernameFlag := flag.String("username", "", "username to add")
	passwordFlag := flag.String("password", "", "password to add")
	flag.Parse()

	username := *usernameFlag
	password := *passwordFlag

	newuser := &models.User{
		Username: username,
		ID:       bson.NewObjectId(),
	}
	newuser.SetPassword(password)

	mongoHost := os.Getenv("MONGO_PORT_27017_TCP_ADDR")
	if mongoHost == "" {
		mongoHost = "localhost"
	}

	session, err := mgo.Dial(mongoHost)
	if err != nil {
		panic(err)
	}

	count, err := session.DB("fhir").C("users").Find(bson.M{"username": username}).Count()
	if count > 0 {
		fmt.Printf("User %s already exists.\n", username)
		return
	}

	err = session.DB("fhir").C("users").Insert(newuser)
	if err != nil {
		panic(err)
	} else {
		fmt.Printf("Successfully added user %s.\n", username)
	}
}
<commit_msg>added support for command line arguments as commands and inputs for user administration<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"github.com/intervention-engine/ie/models"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
	"os"
	"strings"
)

func main() {

	flag.Parse()
	args := flag.Args()

	command := args[0]

	switch command {
	default:
		fmt.Println("Invalid command.")
		printUsage()
		return
	case "add":
		if len(args) == 3 {
			username := args[1]
			password := args[2]
			addUser(username, password)
		} else {
			fmt.Println("Invalid number of arguments for 'add' command.")
			printUsage()
			return
		}
	case "add_file":
		if len(args) == 2 {
			filepath := args[1]
			loadUsersFromFile(filepath)
		} else {
			fmt.Println("Invalid number of arguments for 'add_file' command.")
			printUsage()
			return
		}
	case "remove":
		if len(args) == 2 {
			username := args[1]
			removeUser(username)
		} else {
			fmt.Println("Invalid number of arguments for 'remove' command.")
			printUsage()
			return
		}
	case "remove_all":
		if len(args) == 1 {
			removeAllUsers()
		} else {
			fmt.Println("Invalid number of arguments for 'remove_all' command.")
			printUsage()
			return
		}
	case "change_pass":
		if len(args) == 3 {
			username := args[1]
			password := args[2]
			updatePassword(username, password)
		} else {
			fmt.Println("Invalid number of arguments for 'change_pass' command.")
			printUsage()
			return
		}
	}
}

func addUser(username, password string) {
	newuser := &models.User{
		Username: username,
		ID:       bson.NewObjectId(),
	}
	newuser.SetPassword(password)

	userCollection := getUserCollection()

	if userExists(username, userCollection) {
		fmt.Printf("User %s already exists.\n", username)
		return
	}

	err := userCollection.Insert(newuser)
	if err != nil {
		panic(err)
	} else {
		fmt.Printf("Successfully added user %s.\n", username)
	}
}

func loadUsersFromFile(filepath string) {
	file, err := os.Open(filepath)
	defer file.Close()
	if err != nil {
		panic(err)
	}

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		rawentry := scanner.Text()
		userentry := strings.Split(rawentry, ",")
		username := userentry[0]
		password := userentry[1]
		addUser(username, password)
	}
}

func removeUser(username string) {
	userCollection := getUserCollection()

	if userExists(username, userCollection) {
		err := userCollection.Remove(bson.M{"username": username})
		if err != nil {
			panic(err)
		} else {
			fmt.Printf("Successfully removed user %s.\n", username)
		}
	} else {
		fmt.Printf("User %s not found.\n", username)
	}
}

func removeAllUsers() {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("YOU ARE ABOUT TO REMOVE ALL USERS. ENTER 'Y' TO CONTINUE: ")
	resp, _ := reader.ReadString('\n')
	if resp == "Y\n" {
		userCollection := getUserCollection()
		userCollection.DropCollection()
		fmt.Println("Successfully removed all users.")
	} else {
		fmt.Println("User removal cancelled.")
	}

}

func updatePassword(username, password string) {
	userCollection := getUserCollection()

	if userExists(username, userCollection) {
		updated := &models.User{
			Username: username,
		}
		updated.SetPassword(password)

		_, err := userCollection.Upsert(bson.M{"username": username}, updated)
		if err != nil {
			panic(err)
		} else {
			fmt.Printf("Successfully updated password of user %s.\n", username)
		}
	} else {
		fmt.Printf("User %s not found.\n", username)
	}
}

func getUserCollection() *mgo.Collection {
	mongoHost := os.Getenv("MONGO_PORT_27017_TCP_ADDR")
	if mongoHost == "" {
		mongoHost = "localhost"
	}

	session, err := mgo.Dial(mongoHost)
	if err != nil {
		panic(err)
	}

	return session.DB("fhir").C("users")
}

func userExists(username string, collection *mgo.Collection) bool {
	count, err := collection.Find(bson.M{"username": username}).Count()
	if err != nil {
		panic(err)
	}
	return count > 0
}

func printUsage() {
	fmt.Println("Usage definition goes here.")
}
<|endoftext|>


<commit_before>// Package imgutil provides an easy way to take an image and convert any color in
// it into another color. This also allows the conversion of a color image into
// a gray scale image. Supports the image formats image supports such as png and
// jpeg. This exclusively works with RGBA's from image.
package imgutil

import (
	"fmt"
	"image"
	"image/color"
	"regexp"

	"github.com/nfnt/resize"
)

// ConvertImageColor takes an image and a color model and returns a copy
// of the image's color with provided replacement color.
func ConvertImageColor(img image.Image, m color.Model) image.Image {
	bounds := img.Bounds()
	width, height := bounds.Max.X, bounds.Max.Y
	img2 := image.NewRGBA(image.Rect(0, 0, width, height))

	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			newColor := m.Convert(img.At(x, y))
			img2.Set(x, y, newColor)
		}
	}
	return img2
}

// HexToRBGA returns a color.Color if it is provided with a hex code in the correct
// format. https://en.wikipedia.org/wiki/Web_colors
func HexToRBGA(hex1 string) (color.Color, error) {
	validHex := regexp.MustCompile(`#?\b[0-9a-fA-F]{6}\b$`)
	if !validHex.MatchString(hex1) {
		return color.RGBA{}, fmt.Errorf("invalid hex: %s", hex1)
	}
	if hex1[0] == '#' {
		hex1 = hex1[1:]
	}
	return color.RGBA{
		R: hexDigitToInt(byte(hex1[1])) + hexDigitToInt(byte(hex1[0]))*16,
		G: hexDigitToInt(byte(hex1[3])) + hexDigitToInt(byte(hex1[2]))*16,
		B: hexDigitToInt(byte(hex1[5])) + hexDigitToInt(byte(hex1[4]))*16,
		A: 255,
	}, nil
}

// ColorConverter compares a color to another. IF it matches, return
// the new color.
func ColorConverter(c1 color.Color, c2 color.Color) color.Model {
	return color.ModelFunc(func(c color.Color) color.Color {
		cR, cG, cB, cA := c.RGBA()
		c1R, c1G, c1B, c1A := c1.RGBA()
		if cR == c1R && cG == c1G && cB == c1B && cA == c1A {
			return c2
		}
		return c
	})
}

// ResizeImage takes the dimensions of an image and then the image and
// returns the image resized to that dimension. If either width or height
// is set as 0, the aspect ratio will be preserved and the counter part
// will be used as a determining factor for the size.
// Uses github.com/nfnt/resize
func ResizeImage(maxWidth, maxHeight int, img image.Image) image.Image {
	return resize.Resize(uint(maxWidth), uint(maxHeight), img, resize.NearestNeighbor)
}

func hexDigitToInt(hex byte) byte {
	switch {
	case '0' <= hex && hex <= '9':
		return hex - '0'
	case 'a' <= hex && hex <= 'f':
		return hex - 'a' + 10
	case 'A' <= hex && hex <= 'F':
		return hex - 'A' + 10
	}
	return 0
}
<commit_msg>reworded docs to be more concise<commit_after>// Package imgutil provides an easy way to take an image and convert any color in
// it into another color. This also allows the conversion of a color image into
// a gray scale image. Supports the image formats image supports such as png and
// jpeg. This exclusively works with RGBA's from image.
package imgutil

import (
	"fmt"
	"image"
	"image/color"
	"regexp"

	"github.com/nfnt/resize"
)

// ConvertImageColor takes an image and a color model and returns a copy
// of the image's color with provided replacement color.
func ConvertImageColor(img image.Image, m color.Model) image.Image {
	bounds := img.Bounds()
	width, height := bounds.Max.X, bounds.Max.Y
	img2 := image.NewRGBA(image.Rect(0, 0, width, height))

	for y := 0; y < height; y++ {
		for x := 0; x < width; x++ {
			newColor := m.Convert(img.At(x, y))
			img2.Set(x, y, newColor)
		}
	}
	return img2
}

// HexToRBGA returns a color.Color if it is provided with a hex code in the correct
// format. https://en.wikipedia.org/wiki/Web_colors
func HexToRBGA(hex1 string) (color.Color, error) {
	validHex := regexp.MustCompile(`#?\b[0-9a-fA-F]{6}\b$`)
	if !validHex.MatchString(hex1) {
		return color.RGBA{}, fmt.Errorf("invalid hex: %s", hex1)
	}
	if hex1[0] == '#' {
		hex1 = hex1[1:]
	}
	return color.RGBA{
		R: hexDigitToInt(byte(hex1[1])) + hexDigitToInt(byte(hex1[0]))*16,
		G: hexDigitToInt(byte(hex1[3])) + hexDigitToInt(byte(hex1[2]))*16,
		B: hexDigitToInt(byte(hex1[5])) + hexDigitToInt(byte(hex1[4]))*16,
		A: 255,
	}, nil
}

// ColorConverter compares a color to another. IF it matches, return
// the new color.
func ColorConverter(c1 color.Color, c2 color.Color) color.Model {
	return color.ModelFunc(func(c color.Color) color.Color {
		cR, cG, cB, cA := c.RGBA()
		c1R, c1G, c1B, c1A := c1.RGBA()
		if cR == c1R && cG == c1G && cB == c1B && cA == c1A {
			return c2
		}
		return c
	})
}

// ResizeImage takes the dimensions of an image and then the image and
// returns a new image resized to that dimension. If either width or height
// is set as 0, the aspect ratio will be preserved and the counter part
// will be used as a determining factor for the size.
// Uses github.com/nfnt/resize
func ResizeImage(maxWidth, maxHeight int, img image.Image) image.Image {
	return resize.Resize(uint(maxWidth), uint(maxHeight), img, resize.NearestNeighbor)
}

func hexDigitToInt(hex byte) byte {
	switch {
	case '0' <= hex && hex <= '9':
		return hex - '0'
	case 'a' <= hex && hex <= 'f':
		return hex - 'a' + 10
	case 'A' <= hex && hex <= 'F':
		return hex - 'A' + 10
	}
	return 0
}
<|endoftext|>


<commit_before>// Package local implemenst the filesystem interfaces on top of the
// operating system's filesystem.
package local

import (
	"context"
	"encoding/json"
	"errors"
	"io"
	"os"
	"strings"

	"zenhack.net/go/sandstorm-filesystem/filesystem"

	grain_capnp "zenhack.net/go/sandstorm/capnp/grain"
	bridge_capnp "zenhack.net/go/sandstorm/capnp/sandstormhttpbridge"
	"zenhack.net/go/sandstorm/exp/util/bytestream"

	"zombiezen.com/go/capnproto2"
	"zombiezen.com/go/capnproto2/server"
)

var (
	InvalidArgument = errors.New("Invalid argument")
	IllegalFileName = errors.New("Illegal file name")
	OpenFailed      = errors.New("Open failed")
	NotImplemented  = errors.New("Not implemented")
)

func NewNode(path string) (*Node, error) {
	fi, err := os.Stat(path)
	if err != nil {
		return nil, err
	}
	return &Node{
		Path:       path,
		IsDir:      fi.IsDir(),
		Writable:   fi.Mode()&0200 != 0,
		Executable: fi.Mode()&0100 != 0,
	}, nil
}

type Node struct {
	IsDir      bool
	Writable   bool
	Executable bool
	Path       string
}

func (n *Node) Save(ctx context.Context, p grain_capnp.AppPersistent_save) error {
	data, err := json.Marshal(n)
	if err != nil {
		return err
	}
	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	u8list, err := capnp.NewData(res.Struct.Segment(), data)
	if err != nil {
		return err
	}
	res.SetObjectId(u8list.List.ToPtr())
	return nil
}

func (n *Node) Restore(p bridge_capnp.AppHooks_restore) error {
	ptr, err := p.Args().ObjectId()
	if err != nil {
		return err
	}
	err = json.Unmarshal(ptr.Data(), n)
	if err != nil {
		return err
	}
	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	capId := res.Struct.Segment().Message().AddCap(n.MakeClient().Client)
	res.SetCap(capnp.NewInterface(res.Struct.Segment(), capId).ToPtr())
	return nil
}

func (n *Node) Stat(ctx context.Context, p filesystem.Node_stat) error {
	fi, err := os.Stat(n.Path)
	if err != nil {
		// TODO: think about the right way to handle this.
		return err
	}
	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	info, err := res.NewInfo()
	if err != nil {
		return err
	}
	if n.IsDir {
		info.SetDir()
	} else {
		info.SetFile()
		info.File().SetSize(fi.Size())
	}
	info.SetWritable(n.Writable)
	info.SetExecutable(n.Executable)
	return nil
}

func (d *Node) List(ctx context.Context, p filesystem.Directory_list) error {
	stream := p.Args().Stream()
	file, err := os.Open(d.Path)
	if err != nil {
		// err might contain private info, e.g. where the directory
		// is rooted. So we return a generic error. It might be nice
		// to find some way to allow more information for debugging.
		return OpenFailed
	}
	defer file.Close()
	maxBufSize := 1024

	for ctx.Err() == nil {
		fis, err := file.Readdir(maxBufSize)
		if err != nil && err != io.EOF {
			return err
		}

		stream.Push(ctx, func(p filesystem.Directory_Entry_Stream_push_Params) error {
			list, err := p.NewEntries(int32(len(fis)))
			if err != nil {
				return err
			}
			for i := range fis {
				fi := fis[i]
				ent := list.At(i)
				ent.SetName(fi.Name())
				info, err := ent.NewInfo()
				if err != nil {
					return err
				}
				info.SetWritable(d.Writable && (fi.Mode()&0200 != 0))
				info.SetExecutable(fi.Mode()&0100 != 0)
				if fi.IsDir() {
					info.SetDir()
				} else {
					info.SetFile()
					info.File().SetSize(fi.Size())
				}
			}
			return nil
		})

		if err == io.EOF {
			break
		}
	}

	stream.Done(ctx, func(filesystem.Directory_Entry_Stream_done_Params) error {
		return nil
	})

	return nil
}

func (d *Node) Walk(ctx context.Context, p filesystem.Directory_walk) error {
	name, err := p.Args().Name()
	if err != nil {
		return err
	}

	if !validFileName(name) {
		return IllegalFileName
	}

	path := d.Path + "/" + name
	fi, err := os.Stat(path)
	if err != nil {
		return err
	}

	node := &Node{
		Path:       path,
		IsDir:      fi.IsDir(),
		Writable:   d.Writable && fi.Mode()&0200 != 0,
		Executable: fi.Mode()&0100 != 0,
	}

	res, err := p.AllocResults()
	if err != nil {
		return err
	}

	res.SetNode(node.MakeClient())
	return nil
}

func (d *Node) Create(ctx context.Context, p filesystem.RwDirectory_create) error {
	name, err := p.Args().Name()
	if err != nil {
		return err
	}
	if !validFileName(name) {
		return IllegalFileName
	}

	node := Node{
		Path:       d.Path + "/" + name,
		Executable: p.Args().Executable(),
		Writable:   true,
	}

	mode := os.FileMode(0644)
	if node.Executable {
		mode |= 0111
	}

	file, err := os.OpenFile(node.Path, os.O_RDWR|os.O_CREATE, mode)
	if err != nil {
		return OpenFailed
	}
	file.Close()

	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	res.SetFile(filesystem.RwFile{
		Client: node.MakeClient().Client,
	})
	return nil
}

func (d *Node) Mkdir(ctx context.Context, p filesystem.RwDirectory_mkdir) error {
	name, err := p.Args().Name()
	if err != nil {
		return err
	}
	if !validFileName(name) {
		return IllegalFileName
	}
	return os.Mkdir(d.Path+"/"+name, 0700)
}

func (d *Node) Delete(ctx context.Context, p filesystem.RwDirectory_delete) error {
	return NotImplemented
}

func validFileName(name string) bool {
	return name != "" &&
		name != "." &&
		name != ".." &&
		!strings.Contains(name, "/")
}

func (n *Node) MakeClient() filesystem.Node {
	var methods []server.Method
	if n.IsDir {
		if n.Writable {
			methods = filesystem.RwDirectory_Methods(nil, n)
		} else {
			methods = filesystem.Directory_Methods(nil, n)
		}
	} else {
		if n.Writable {
			methods = filesystem.RwFile_Methods(nil, n)
		} else {
			methods = filesystem.File_Methods(nil, n)
		}
	}
	return filesystem.Node{
		Client: capnp.NewClient(server.New(
			append(
				methods,
				grain_capnp.AppPersistent_Methods(nil, n)...,
			),
			n,
			nil,
			nil,
		)),
	}
}

func (f *Node) Write(ctx context.Context, p filesystem.RwFile_write) error {
	startAt := p.Args().StartAt()

	if startAt <= -2 {
		return InvalidArgument
	}

	file, err := os.OpenFile(f.Path, os.O_WRONLY|os.O_APPEND, 0)
	if err != nil {
		return err
	}
	if startAt == -1 {
		_, err = file.Seek(0, 2)
	} else {
		_, err = file.Seek(startAt, 0)
	}
	if err != nil {
		file.Close()
		return err
	}
	bs := bytestream.FromWriteCloser(file, nil)
	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	res.SetSink(bs)
	return nil
}

func (f *Node) SetExec(ctx context.Context, p filesystem.RwFile_setExec) error {
	exec := p.Args().Exec()
	fi, err := os.Stat(f.Path)
	// FIXME: censor error like with OpenFailed.
	if err != nil {
		return err
	}
	if exec {
		// FIXME: censor error like with OpenFailed.
		return os.Chmod(f.Path, fi.Mode()|0111)
	} else {
		// FIXME: censor error like with OpenFailed.
		return os.Chmod(f.Path, fi.Mode()&^0111)
	}
}

func (f *Node) Truncate(ctx context.Context, p filesystem.RwFile_truncate) error {
	// FIXME: cast/overflow issues.
	if err := os.Truncate(f.Path, int64(p.Args().Size())); err != nil {
		return OpenFailed
	}
	return nil
}

func (f *Node) Read(ctx context.Context, p filesystem.File_read) error {
	startAt := p.Args().StartAt()
	if startAt < 0 {
		return InvalidArgument
	}

	amount := int64(p.Args().Amount())
	if amount < 0 {
		// The go api expects a signed value, so if we get something
		// greater than an int64 can represent, we just say "read the
		// whole thing." That's a stupid amount of data, so it's always
		// going to do the same thing anyway.
		amount = 0
	}
	sink := p.Args().Sink()

	file, err := os.Open(f.Path)
	if err != nil {
		return OpenFailed
	}
	defer file.Close()

	wc := bytestream.ToWriteCloser(ctx, sink)
	_, err = file.Seek(startAt, 0)
	r := io.Reader(file)
	if amount != 0 {
		r = io.LimitReader(r, amount)
	}
	if err != nil {
		return err
	}
	_, err = io.Copy(wc, r)
	if err != nil {
		return err
	}
	wc.Close()
	return nil
}
<commit_msg>local fs: make the 'NotImplemented' error a capnp unimplemented.<commit_after>// Package local implemenst the filesystem interfaces on top of the
// operating system's filesystem.
package local

import (
	"context"
	"encoding/json"
	"errors"
	"io"
	"os"
	"strings"

	"zenhack.net/go/sandstorm-filesystem/filesystem"

	grain_capnp "zenhack.net/go/sandstorm/capnp/grain"
	bridge_capnp "zenhack.net/go/sandstorm/capnp/sandstormhttpbridge"
	"zenhack.net/go/sandstorm/exp/util/bytestream"

	"zombiezen.com/go/capnproto2"
	"zombiezen.com/go/capnproto2/server"
)

var (
	InvalidArgument = errors.New("Invalid argument")
	IllegalFileName = errors.New("Illegal file name")
	OpenFailed      = errors.New("Open failed")
	NotImplemented  = capnp.Unimplemented("Not implemented")
)

func NewNode(path string) (*Node, error) {
	fi, err := os.Stat(path)
	if err != nil {
		return nil, err
	}
	return &Node{
		Path:       path,
		IsDir:      fi.IsDir(),
		Writable:   fi.Mode()&0200 != 0,
		Executable: fi.Mode()&0100 != 0,
	}, nil
}

type Node struct {
	IsDir      bool
	Writable   bool
	Executable bool
	Path       string
}

func (n *Node) Save(ctx context.Context, p grain_capnp.AppPersistent_save) error {
	data, err := json.Marshal(n)
	if err != nil {
		return err
	}
	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	u8list, err := capnp.NewData(res.Struct.Segment(), data)
	if err != nil {
		return err
	}
	res.SetObjectId(u8list.List.ToPtr())
	return nil
}

func (n *Node) Restore(p bridge_capnp.AppHooks_restore) error {
	ptr, err := p.Args().ObjectId()
	if err != nil {
		return err
	}
	err = json.Unmarshal(ptr.Data(), n)
	if err != nil {
		return err
	}
	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	capId := res.Struct.Segment().Message().AddCap(n.MakeClient().Client)
	res.SetCap(capnp.NewInterface(res.Struct.Segment(), capId).ToPtr())
	return nil
}

func (n *Node) Stat(ctx context.Context, p filesystem.Node_stat) error {
	fi, err := os.Stat(n.Path)
	if err != nil {
		// TODO: think about the right way to handle this.
		return err
	}
	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	info, err := res.NewInfo()
	if err != nil {
		return err
	}
	if n.IsDir {
		info.SetDir()
	} else {
		info.SetFile()
		info.File().SetSize(fi.Size())
	}
	info.SetWritable(n.Writable)
	info.SetExecutable(n.Executable)
	return nil
}

func (d *Node) List(ctx context.Context, p filesystem.Directory_list) error {
	stream := p.Args().Stream()
	file, err := os.Open(d.Path)
	if err != nil {
		// err might contain private info, e.g. where the directory
		// is rooted. So we return a generic error. It might be nice
		// to find some way to allow more information for debugging.
		return OpenFailed
	}
	defer file.Close()
	maxBufSize := 1024

	for ctx.Err() == nil {
		fis, err := file.Readdir(maxBufSize)
		if err != nil && err != io.EOF {
			return err
		}

		stream.Push(ctx, func(p filesystem.Directory_Entry_Stream_push_Params) error {
			list, err := p.NewEntries(int32(len(fis)))
			if err != nil {
				return err
			}
			for i := range fis {
				fi := fis[i]
				ent := list.At(i)
				ent.SetName(fi.Name())
				info, err := ent.NewInfo()
				if err != nil {
					return err
				}
				info.SetWritable(d.Writable && (fi.Mode()&0200 != 0))
				info.SetExecutable(fi.Mode()&0100 != 0)
				if fi.IsDir() {
					info.SetDir()
				} else {
					info.SetFile()
					info.File().SetSize(fi.Size())
				}
			}
			return nil
		})

		if err == io.EOF {
			break
		}
	}

	stream.Done(ctx, func(filesystem.Directory_Entry_Stream_done_Params) error {
		return nil
	})

	return nil
}

func (d *Node) Walk(ctx context.Context, p filesystem.Directory_walk) error {
	name, err := p.Args().Name()
	if err != nil {
		return err
	}

	if !validFileName(name) {
		return IllegalFileName
	}

	path := d.Path + "/" + name
	fi, err := os.Stat(path)
	if err != nil {
		return err
	}

	node := &Node{
		Path:       path,
		IsDir:      fi.IsDir(),
		Writable:   d.Writable && fi.Mode()&0200 != 0,
		Executable: fi.Mode()&0100 != 0,
	}

	res, err := p.AllocResults()
	if err != nil {
		return err
	}

	res.SetNode(node.MakeClient())
	return nil
}

func (d *Node) Create(ctx context.Context, p filesystem.RwDirectory_create) error {
	name, err := p.Args().Name()
	if err != nil {
		return err
	}
	if !validFileName(name) {
		return IllegalFileName
	}

	node := Node{
		Path:       d.Path + "/" + name,
		Executable: p.Args().Executable(),
		Writable:   true,
	}

	mode := os.FileMode(0644)
	if node.Executable {
		mode |= 0111
	}

	file, err := os.OpenFile(node.Path, os.O_RDWR|os.O_CREATE, mode)
	if err != nil {
		return OpenFailed
	}
	file.Close()

	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	res.SetFile(filesystem.RwFile{
		Client: node.MakeClient().Client,
	})
	return nil
}

func (d *Node) Mkdir(ctx context.Context, p filesystem.RwDirectory_mkdir) error {
	name, err := p.Args().Name()
	if err != nil {
		return err
	}
	if !validFileName(name) {
		return IllegalFileName
	}
	return os.Mkdir(d.Path+"/"+name, 0700)
}

func (d *Node) Delete(ctx context.Context, p filesystem.RwDirectory_delete) error {
	return NotImplemented
}

func validFileName(name string) bool {
	return name != "" &&
		name != "." &&
		name != ".." &&
		!strings.Contains(name, "/")
}

func (n *Node) MakeClient() filesystem.Node {
	var methods []server.Method
	if n.IsDir {
		if n.Writable {
			methods = filesystem.RwDirectory_Methods(nil, n)
		} else {
			methods = filesystem.Directory_Methods(nil, n)
		}
	} else {
		if n.Writable {
			methods = filesystem.RwFile_Methods(nil, n)
		} else {
			methods = filesystem.File_Methods(nil, n)
		}
	}
	return filesystem.Node{
		Client: capnp.NewClient(server.New(
			append(
				methods,
				grain_capnp.AppPersistent_Methods(nil, n)...,
			),
			n,
			nil,
			nil,
		)),
	}
}

func (f *Node) Write(ctx context.Context, p filesystem.RwFile_write) error {
	startAt := p.Args().StartAt()

	if startAt <= -2 {
		return InvalidArgument
	}

	file, err := os.OpenFile(f.Path, os.O_WRONLY|os.O_APPEND, 0)
	if err != nil {
		return err
	}
	if startAt == -1 {
		_, err = file.Seek(0, 2)
	} else {
		_, err = file.Seek(startAt, 0)
	}
	if err != nil {
		file.Close()
		return err
	}
	bs := bytestream.FromWriteCloser(file, nil)
	res, err := p.AllocResults()
	if err != nil {
		return err
	}
	res.SetSink(bs)
	return nil
}

func (f *Node) SetExec(ctx context.Context, p filesystem.RwFile_setExec) error {
	exec := p.Args().Exec()
	fi, err := os.Stat(f.Path)
	// FIXME: censor error like with OpenFailed.
	if err != nil {
		return err
	}
	if exec {
		// FIXME: censor error like with OpenFailed.
		return os.Chmod(f.Path, fi.Mode()|0111)
	} else {
		// FIXME: censor error like with OpenFailed.
		return os.Chmod(f.Path, fi.Mode()&^0111)
	}
}

func (f *Node) Truncate(ctx context.Context, p filesystem.RwFile_truncate) error {
	// FIXME: cast/overflow issues.
	if err := os.Truncate(f.Path, int64(p.Args().Size())); err != nil {
		return OpenFailed
	}
	return nil
}

func (f *Node) Read(ctx context.Context, p filesystem.File_read) error {
	startAt := p.Args().StartAt()
	if startAt < 0 {
		return InvalidArgument
	}

	amount := int64(p.Args().Amount())
	if amount < 0 {
		// The go api expects a signed value, so if we get something
		// greater than an int64 can represent, we just say "read the
		// whole thing." That's a stupid amount of data, so it's always
		// going to do the same thing anyway.
		amount = 0
	}
	sink := p.Args().Sink()

	file, err := os.Open(f.Path)
	if err != nil {
		return OpenFailed
	}
	defer file.Close()

	wc := bytestream.ToWriteCloser(ctx, sink)
	_, err = file.Seek(startAt, 0)
	r := io.Reader(file)
	if amount != 0 {
		r = io.LimitReader(r, amount)
	}
	if err != nil {
		return err
	}
	_, err = io.Copy(wc, r)
	if err != nil {
		return err
	}
	wc.Close()
	return nil
}
<|endoftext|>


<commit_before>// $G $F.go && $L $F.$A  # don't run it - goes forever

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

package Main

// Send the sequence 2, 3, 4, ... to channel 'ch'.
func Generate(ch *chan> int) {
  for i := 2; ; i++ {
    >ch = i  // Send 'i' to channel 'ch'.
  }
}

// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in *chan< int, out *chan> int, prime int) {
  for {
    i := <in;  // Receive value of new variable 'i' from 'in'.
    if i % prime != 0 {
      >out = i  // Send 'i' to channel 'out'.
    }
  }
}

// The prime sieve: Daisy-chain Filter processes together.
func Sieve() {
  ch := new(chan int);  // Create a new channel.
  go Generate(ch);  // Start Generate() as a subprocess.
  for {
    prime := <ch;
    printf("%d\n",  prime);
    ch1 := new(chan int);
    go Filter(ch, ch1, prime);
    ch = ch1
  }
}

func Main() {
  Sieve()
}
<commit_msg>- fixed a test - added extra basic type aliases - added select statement<commit_after>// $G $F.go && $L $F.$A  # don't run it - goes forever

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

package Main

// Send the sequence 2, 3, 4, ... to channel 'ch'.
func Generate(ch *chan> int) {
  for i := 2; ; i++ {
    >ch = i  // Send 'i' to channel 'ch'.
  }
}

// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func Filter(in *chan< int, out *chan> int, prime int) {
  for {
    i := <in;  // Receive value of new variable 'i' from 'in'.
    if i % prime != 0 {
      >out = i  // Send 'i' to channel 'out'.
    }
  }
}

// The prime sieve: Daisy-chain Filter processes together.
func Sieve() {
  ch := new(chan int);  // Create a new channel.
  go Generate(ch);  // Start Generate() as a subprocess.
  for {
    prime := <ch;
    print "%d\n",  prime;
    ch1 := new(chan int);
    go Filter(ch, ch1, prime);
    ch = ch1
  }
}

func Main() {
  Sieve()
}
<|endoftext|>