<commit_before>package main

import (
	"context"
	"flag"
	"fmt"
	"gopkg.in/olivere/elastic.v5"
	"os"
	"runtime"
	"strconv"
)

const (
	indexName = "test"
)

var (
	urlPtr      = flag.String("url", "", "elasticsearch url")
	usernamePtr = flag.String("user", "", "elasticsearch username")
	passwordPtr = flag.String("pass", "", "elasticsearch password")
)

func main() {
	flag.Parse()
	runtime.GOMAXPROCS(runtime.NumCPU())

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	if err := do(ctx); err != nil {
		fmt.Fprintf(os.Stderr, "failure: %v\n", err)
		os.Exit(1)
	}
}

type tweet struct {
	User     string
	Message  string
	Retweets int
}

func do(ctx context.Context) error {
	username := *usernamePtr
	if len(username) == 0 {
		return fmt.Errorf("parameter username missing")
	}
	password := *passwordPtr
	if len(password) == 0 {
		return fmt.Errorf("parameter password missing")
	}
	url := *urlPtr
	if len(url) == 0 {
		return fmt.Errorf("parameter url missing")
	}
	client, err := elastic.NewClient(
		elastic.SetSniff(false),
		elastic.SetURL(url),
		elastic.SetBasicAuth(username, password),
	)
	if err != nil {
		return fmt.Errorf("create client failed: %v", err)
	}
	if err := createOrOpenIndex(ctx, client, indexName); err != nil {
		return fmt.Errorf("open index %v failed: %v", indexName, err)
	}

	for i := 0; i < 100; i++ {
		t := tweet{
			User:     "olivere",
			Message:  "Take Five",
			Retweets: 0,
		}
		put1, err := client.Index().Index(indexName).Type("tweet").Id(strconv.Itoa(i)).BodyJson(t).Do(context.Background())
		if err != nil {
			return fmt.Errorf("create failed: %v", err)
		}
		if !put1.Created {
			fmt.Printf("create entry %d in index failed\n", i)
		}
	}
	fmt.Printf("create\n")
	return nil
}

func createOrOpenIndex(ctx context.Context, client *elastic.Client, index string) error {
	exists, err := client.IndexExists(index).Do(ctx)
	if err != nil {
		return fmt.Errorf("index %v not found: %v", index, err)
	}
	if !exists {
		result, err := client.CreateIndex(index).Do(ctx)
		if err != nil {
			return fmt.Errorf("create index %v failed: %v", index, err)
		}
		if !result.Acknowledged {
			return fmt.Errorf("create not acknowledged")
		}
		return nil
	}
	result, err := client.OpenIndex(index).Do(ctx)
	if err != nil {
		return fmt.Errorf("open index %v failed: %v", index, err)
	}
	if !result.Acknowledged {
		return fmt.Errorf("open not acknowledged")
	}
	return nil
}
<commit_msg>add keywords<commit_after>package main

import (
	"context"
	"flag"
	"fmt"
	"gopkg.in/olivere/elastic.v5"
	"os"
	"runtime"
	"strconv"
)

const (
	indexName = "test"
)

var (
	urlPtr      = flag.String("url", "", "elasticsearch url")
	usernamePtr = flag.String("user", "", "elasticsearch username")
	passwordPtr = flag.String("pass", "", "elasticsearch password")
)

func main() {
	flag.Parse()
	runtime.GOMAXPROCS(runtime.NumCPU())

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	if err := do(ctx); err != nil {
		fmt.Fprintf(os.Stderr, "failure: %v\n", err)
		os.Exit(1)
	}
}

type tweet struct {
	User     string
	Message  string
	Retweets int
	Keywords []string
}

func do(ctx context.Context) error {
	username := *usernamePtr
	if len(username) == 0 {
		return fmt.Errorf("parameter username missing")
	}
	password := *passwordPtr
	if len(password) == 0 {
		return fmt.Errorf("parameter password missing")
	}
	url := *urlPtr
	if len(url) == 0 {
		return fmt.Errorf("parameter url missing")
	}
	client, err := elastic.NewClient(
		elastic.SetSniff(false),
		elastic.SetURL(url),
		elastic.SetBasicAuth(username, password),
	)
	if err != nil {
		return fmt.Errorf("create client failed: %v", err)
	}
	if err := createOrOpenIndex(ctx, client, indexName); err != nil {
		return fmt.Errorf("open index %v failed: %v", indexName, err)
	}

	for i := 0; i < 100; i++ {
		t := tweet{
			User:     "olivere",
			Message:  "Take Five",
			Keywords: []string{"Foo", "Bar", fmt.Sprintf("tweet%d", i)},
			Retweets: 3 * i % 25,
		}

		put1, err := client.Index().Index(indexName).Type("tweet").Id(strconv.Itoa(i)).BodyJson(t).Do(context.Background())
		if err != nil {
			return fmt.Errorf("create failed: %v", err)
		}
		fmt.Printf("result for %d %v", i, put1)
		if !put1.Created {
			fmt.Printf("create entry %d in index failed\n", i)
		}
	}
	fmt.Printf("create\n")
	return nil
}

func createOrOpenIndex(ctx context.Context, client *elastic.Client, index string) error {
	exists, err := client.IndexExists(index).Do(ctx)
	if err != nil {
		return fmt.Errorf("index %v not found: %v", index, err)
	}
	if !exists {
		result, err := client.CreateIndex(index).Do(ctx)
		if err != nil {
			return fmt.Errorf("create index %v failed: %v", index, err)
		}
		if !result.Acknowledged {
			return fmt.Errorf("create not acknowledged")
		}
		return nil
	}
	result, err := client.OpenIndex(index).Do(ctx)
	if err != nil {
		return fmt.Errorf("open index %v failed: %v", index, err)
	}
	if !result.Acknowledged {
		return fmt.Errorf("open not acknowledged")
	}
	return nil
}
<|endoftext|>


<commit_before>package daemon

import (
	"github.com/pkg/errors"

	"github.com/havoc-io/mutagen/filesystem"
)

const (
	lockName = "daemon.lock"
)

type Lock struct {
	// locker is the daemon file lock, uniquely held by a single daemon
	// instance. Because the locking semantics vary by platform, hosting
	// processes should only attempt to create a single daemon lock at a time.
	locker *filesystem.Locker
}

func AcquireLock() (*Lock, error) {
	// Compute the lock path.
	lockPath, err := subpath(lockName)
	if err != nil {
		return nil, errors.Wrap(err, "unable to compute daemon lock path")
	}

	// Create the daemon locker and attempt to acquire the lock.
	locker, err := filesystem.NewLocker(lockPath, 0600)
	if err != nil {
		return nil, errors.Wrap(err, "unable to create daemon locker")
	} else if err = locker.Lock(false); err != nil {
		return nil, errors.Wrap(err, "unable to acquire daemon lock")
	}

	// Create the lock.
	return &Lock{
		locker: locker,
	}, nil
}

func (l *Lock) Unlock() error {
	return l.locker.Unlock()
}
<commit_msg>Removed superfluous error wrapping from daemon lock.<commit_after>package daemon

import (
	"github.com/pkg/errors"

	"github.com/havoc-io/mutagen/filesystem"
)

const (
	lockName = "daemon.lock"
)

type Lock struct {
	// locker is the daemon file lock, uniquely held by a single daemon
	// instance. Because the locking semantics vary by platform, hosting
	// processes should only attempt to create a single daemon lock at a time.
	locker *filesystem.Locker
}

func AcquireLock() (*Lock, error) {
	// Compute the lock path.
	lockPath, err := subpath(lockName)
	if err != nil {
		return nil, errors.Wrap(err, "unable to compute daemon lock path")
	}

	// Create the daemon locker and attempt to acquire the lock.
	locker, err := filesystem.NewLocker(lockPath, 0600)
	if err != nil {
		return nil, errors.Wrap(err, "unable to create daemon locker")
	} else if err = locker.Lock(false); err != nil {
		return nil, err
	}

	// Create the lock.
	return &Lock{
		locker: locker,
	}, nil
}

func (l *Lock) Unlock() error {
	return l.locker.Unlock()
}
<|endoftext|>


<commit_before>package asciidocgo

// Asciidoc Document, onced loaded from an IO, string or array
type Document struct {
	monitorData *monitorData
}

type monitorData struct {
	readTime  int
	parseTime int
}

// Error returned when accessing times on a Document not monitored
type NotMonitoredError struct {
	msg string // description of error
}

// Print description of a non-monitored error
func (e *NotMonitoredError) Error() string { return e.msg }

// Check if a Document is supposed to be monitored
func (d *Document) IsMonitored() bool {
	return (d.monitorData != nil)
}

// Setup a monitor for the document
// (or does nothing if the monitor already exists).
// Returns self, for easy composition
func (d *Document) Monitor() *Document {
	if d.monitorData == nil {
		d.monitorData = new(monitorData)
	}
	return d
}

func (d *Document) ReadTime() (readTime int, err error) {
	if d.IsMonitored() == false {
		return 0, &NotMonitoredError{"No readTime: current document is not monitored"}
	}
	return d.monitorData.readTime, nil
}

func (d *Document) ParseTime() (parseTime int, err error) {
	if d.IsMonitored() == false {
		return 0, &NotMonitoredError{"No parseTime: current document is not monitored"}
	}
	return d.monitorData.parseTime, nil
}

func (d *Document) LoadTime() (loadTime int, err error) {
	if d.IsMonitored() == false {
		return 0, &NotMonitoredError{"No loadTime: current document is not monitored"}
	}
	readTime, _ := d.ReadTime()
	parseTime, _ := d.ParseTime()
	return readTime + parseTime, nil
}
<commit_msg>Add documentation for existing time monitoring functions.<commit_after>package asciidocgo

// Asciidoc Document, onced loaded from an IO, string or array
type Document struct {
	monitorData *monitorData
}

type monitorData struct {
	readTime  int
	parseTime int
}

// Error returned when accessing times on a Document not monitored
type NotMonitoredError struct {
	msg string // description of error
}

// Print description of a non-monitored error
func (e *NotMonitoredError) Error() string { return e.msg }

// Check if a Document is supposed to be monitored
func (d *Document) IsMonitored() bool {
	return (d.monitorData != nil)
}

// Setup a monitor for the document
// (or does nothing if the monitor already exists).
// Returns self, for easy composition
func (d *Document) Monitor() *Document {
	if d.monitorData == nil {
		d.monitorData = new(monitorData)
	}
	return d
}

// Time to read the document from IO source
// Error if document didn't activated the monitoring
func (d *Document) ReadTime() (readTime int, err error) {
	if d.IsMonitored() == false {
		return 0, &NotMonitoredError{"No readTime: current document is not monitored"}
	}
	return d.monitorData.readTime, nil
}

// Time to parse the document once read from IO source
// Error if document didn't activated the monitoring
func (d *Document) ParseTime() (parseTime int, err error) {
	if d.IsMonitored() == false {
		return 0, &NotMonitoredError{"No parseTime: current document is not monitored"}
	}
	return d.monitorData.parseTime, nil
}

// Load means Read plus Parse times
// Error if document didn't activated the monitoring
func (d *Document) LoadTime() (loadTime int, err error) {
	if d.IsMonitored() == false {
		return 0, &NotMonitoredError{"No loadTime: current document is not monitored"}
	}
	readTime, _ := d.ReadTime()
	parseTime, _ := d.ParseTime()
	return readTime + parseTime, nil
}
<|endoftext|>


<commit_before>package main

import (
	"index/suffixarray"
	"io/ioutil"
	"log"
	"os"
)

func main() {
	sometext, err := ioutil.ReadFile(os.Args[1])

	if err != nil {
		log.Println(err)
	}

	index := suffixarray.New(sometext)

	offsets := index.Lookup([]byte("*"), -1)

  for _, value := range offsets[0:10] {
    log.Println(value, string(sometext[value]))
  }
}
<commit_msg>Web edit works<commit_after>package main

import (
	"index/suffixarray"
	"io/ioutil"
	"log"
	"os"
)

func main() {
	sometext, err := ioutil.ReadFile(os.Args[1])

	if err != nil {
		log.Println(err)
	}

	index := suffixarray.New(sometext)

	offsets := index.Lookup([]byte("*"), -1)

  for _, value := range offsets[0:100] {
    log.Println(value, string(sometext[value]))
  }
}
<|endoftext|>


<commit_before>package dogo

import (
	"encoding/json"
	"fmt"
	"time"
)

// Droplet respresents a digitalocean droplet.
type Droplet struct {
	ID               int       `json:"id"`
	Name             string    `json:"name"`
	ImageID          int       `json:"image_id"`
	SizeID           int       `json:"size_id"`
	RegionID         int       `json:"region_id"`
	BackupsActive    bool      `json:"backups_active"`
	IPAddress        string    `json:"ip_address"`
	PrivateIPAddress string    `json:"private_ip_address,omitempty"`
	Snapshots        []Image   `json:"snapshots,omitempty"`
	Locked           bool      `json:"locked"`
	Status           string    `json:"status"`
	CreatedAt        time.Time `json:"created_at"`
}

// GetDroplets returns all users droplets, active or otherwise.
func (c *Client) GetDroplets() ([]Droplet, error) {
	query := fmt.Sprintf("%s?client_id=%s&api_key=%s",
		DropletsEndpoint,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return nil, err
	}

	resp := struct {
		Status     string    `json:"status"`
		Droplets   []Droplet `json:"droplets"`
		ErrMessage string    `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return nil, err
	}

	if resp.Status == "ERROR" {
		return nil, fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return resp.Droplets, nil

}

// GetDroplet return an individual droplet based on the passed id.
func (c *Client) GetDroplet(id int) (Droplet, error) {
	query := fmt.Sprintf("%s/%d/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return Droplet{}, err
	}

	fmt.Println(string(body))

	resp := struct {
		Status     string  `json:"status"`
		Droplet    Droplet `json:"droplet"`
		ErrMessage string  `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return Droplet{}, err
	}

	if resp.Status == "ERROR" {
		return Droplet{}, fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return resp.Droplet, nil
}

// CreateDroplet creates a droplet based on based specs.
func (c *Client) CreateDroplet(name string, sizeID, imageID, regionID int, keys string) (Droplet, error) {
	query := fmt.Sprintf("%s/new?client_id=%s&api_key=%s&name=%s&size_id=%d&image_id=%d&region_id=%d&ssh_key_ids=%s",
		DropletsEndpoint,
		c.Auth.ClientID,
		c.Auth.APIKey,
		name,
		sizeID,
		imageID,
		regionID,
		keys)

	body, err := Request(query)
	if err != nil {
		return Droplet{}, err
	}

	resp := struct {
		Status     string  `json:"status"`
		Droplet    Droplet `json:"droplet"`
		ErrMessage string  `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return Droplet{}, err
	}

	if resp.Status == "ERROR" {
		return Droplet{}, fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return resp.Droplet, nil
}

// DestroyDroplet destroys a droplet. CAUTION - this is irreversible.
// There may be more appropriate options.
func (c *Client) DestroyDroplet(id int) error {
	query := fmt.Sprintf("%s/%d/destroy/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// ResizeDroplet droplet resizes a droplet. Sizes are based on
// the digitalocean sizes api.
func (c *Client) ResizeDroplet(id, sizeID int) error {
	query := fmt.Sprintf("%s/%d/resize/?size_id=%d&client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		sizeID,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// RebootDroplet reboots the a droplet. This is the preferred method
// to use if a server is not responding.
func (c *Client) RebootDroplet(id int) error {
	query := fmt.Sprintf("%s/%d/reboot/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// RebootDroplet rebuilds a droplet with a default image. This can be
// useful if you want to use a different image but keep the ip address
// of the droplet.
func (c *Client) RebuildDroplet(id, imageID int) error {
	query := fmt.Sprintf("%s/%d/rebuild/?image_id=%d&client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		imageID,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// StopDroplet powers off a running droplet, the droplet will remain
// in your account.
func (c *Client) StopDroplet(id int) error {
	query := fmt.Sprintf("%s/%d/power_off/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// StartDroplet powers on a powered off droplet.
func (c *Client) StartDroplet(id int) error {
	query := fmt.Sprintf("%s/%d/power_on/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// SnapshotDroplet allows you to take a snapshot of a droplet once it is
// powered off. Be aware this may reboot the droplet.
func (c *Client) SnapshotDroplet(id int, name string) error {
	query := fmt.Sprintf("%s/%d/snapshot/?name=%s&client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		name,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// RestoreDroplet allows you to restore a droplet to a previous image
// or snapshot. This will be a mirror copy of the image or snapshot to
// your droplet.
func (c *Client) RestoreDroplet(id, imageID int) error {
	query := fmt.Sprintf("%s/%d/restore/?image_id=%d&client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		imageID,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}
<commit_msg>adding ssh key works properly now<commit_after>package dogo

import (
	"encoding/json"
	"fmt"
	"strconv"
	"time"
)

// Droplet respresents a digitalocean droplet.
type Droplet struct {
	ID               int       `json:"id"`
	Name             string    `json:"name"`
	ImageID          int       `json:"image_id"`
	SizeID           int       `json:"size_id"`
	RegionID         int       `json:"region_id"`
	BackupsActive    bool      `json:"backups_active"`
	IPAddress        string    `json:"ip_address"`
	PrivateIPAddress string    `json:"private_ip_address,omitempty"`
	Snapshots        []Image   `json:"snapshots,omitempty"`
	Locked           bool      `json:"locked"`
	Status           string    `json:"status"`
	CreatedAt        time.Time `json:"created_at"`
}

// GetDroplets returns all users droplets, active or otherwise.
func (c *Client) GetDroplets() ([]Droplet, error) {
	query := fmt.Sprintf("%s?client_id=%s&api_key=%s",
		DropletsEndpoint,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return nil, err
	}

	resp := struct {
		Status     string    `json:"status"`
		Droplets   []Droplet `json:"droplets"`
		ErrMessage string    `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return nil, err
	}

	if resp.Status == "ERROR" {
		return nil, fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return resp.Droplets, nil

}

// GetDroplet return an individual droplet based on the passed id.
func (c *Client) GetDroplet(id int) (Droplet, error) {
	query := fmt.Sprintf("%s/%d/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return Droplet{}, err
	}

	fmt.Println(string(body))

	resp := struct {
		Status     string  `json:"status"`
		Droplet    Droplet `json:"droplet"`
		ErrMessage string  `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return Droplet{}, err
	}

	if resp.Status == "ERROR" {
		return Droplet{}, fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return resp.Droplet, nil
}

// CreateDroplet creates a droplet based on based specs.
func (c *Client) CreateDroplet(name string, sizeID, imageID, regionID int, keys []int) (Droplet, error) {
	// Create a string of the key ids
	var keyStr string
	for _, k := range keys {
		ks := strconv.Itoa(k)
		keyStr += ks + ","
	}

	query := fmt.Sprintf("%s/new?client_id=%s&api_key=%s&name=%s&size_id=%d&image_id=%d&region_id=%d&ssh_key_ids=%s",
		DropletsEndpoint,
		c.Auth.ClientID,
		c.Auth.APIKey,
		name,
		sizeID,
		imageID,
		regionID,
		keyStr)

	body, err := Request(query)
	if err != nil {
		return Droplet{}, err
	}

	resp := struct {
		Status     string  `json:"status"`
		Droplet    Droplet `json:"droplet"`
		ErrMessage string  `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return Droplet{}, err
	}

	if resp.Status == "ERROR" {
		return Droplet{}, fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return resp.Droplet, nil
}

// DestroyDroplet destroys a droplet. CAUTION - this is irreversible.
// There may be more appropriate options.
func (c *Client) DestroyDroplet(id int) error {
	query := fmt.Sprintf("%s/%d/destroy/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// ResizeDroplet droplet resizes a droplet. Sizes are based on
// the digitalocean sizes api.
func (c *Client) ResizeDroplet(id, sizeID int) error {
	query := fmt.Sprintf("%s/%d/resize/?size_id=%d&client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		sizeID,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// RebootDroplet reboots the a droplet. This is the preferred method
// to use if a server is not responding.
func (c *Client) RebootDroplet(id int) error {
	query := fmt.Sprintf("%s/%d/reboot/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// RebootDroplet rebuilds a droplet with a default image. This can be
// useful if you want to use a different image but keep the ip address
// of the droplet.
func (c *Client) RebuildDroplet(id, imageID int) error {
	query := fmt.Sprintf("%s/%d/rebuild/?image_id=%d&client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		imageID,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// StopDroplet powers off a running droplet, the droplet will remain
// in your account.
func (c *Client) StopDroplet(id int) error {
	query := fmt.Sprintf("%s/%d/power_off/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// StartDroplet powers on a powered off droplet.
func (c *Client) StartDroplet(id int) error {
	query := fmt.Sprintf("%s/%d/power_on/?client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// SnapshotDroplet allows you to take a snapshot of a droplet once it is
// powered off. Be aware this may reboot the droplet.
func (c *Client) SnapshotDroplet(id int, name string) error {
	query := fmt.Sprintf("%s/%d/snapshot/?name=%s&client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		name,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}

// RestoreDroplet allows you to restore a droplet to a previous image
// or snapshot. This will be a mirror copy of the image or snapshot to
// your droplet.
func (c *Client) RestoreDroplet(id, imageID int) error {
	query := fmt.Sprintf("%s/%d/restore/?image_id=%d&client_id=%s&api_key=%s",
		DropletsEndpoint,
		id,
		imageID,
		c.Auth.ClientID,
		c.Auth.APIKey)

	body, err := Request(query)
	if err != nil {
		return err
	}

	resp := struct {
		Status     string `json:"status"`
		ErrMessage string `json:"error_message"`
	}{}

	err = json.Unmarshal(body, &resp)
	if err != nil {
		return err
	}

	if resp.Status == "ERROR" {
		return fmt.Errorf("%s: %s", resp.Status, resp.ErrMessage)
	}

	return nil
}
<|endoftext|>


<commit_before>package yaml_test

import (
	"fmt"
	"reflect"
	"testing"

	"github.com/freneticmonkey/migrate/migrate/yaml"
)

// Successful Read
func TestRead(t *testing.T) {

	context := "unittest"
	definition := `
    name:     test
    charset:  latin1
    engine:   InnoDB
    id:       tbl1
    columns:
        - name:     id
          type:     int
          size:		[11]
          nullable: No
          id:       col1

        - name:     name
          type:     varchar
          size:		[64]
          nullable: No
          id:       col2

		- name:     age
		  type:     decimal
		  size:		[14,4]
		  nullable: No
		  id:       col3

		- name:     address
		  type:    	varchar
		  size:		[64]
		  nullable: No
		  id:       col4
	      default:  "not supplied"

    primaryindex:
        columns:
          - name
        isprimary: Yes
        id: pi

    secondaryindexes:
      - name: idx_id_name
        id: sc1
        columns:
            - id
            - name
    `

	tbl, err := yaml.ReadYAML(definition, context)

	if err != nil {
		t.Error(fmt.Sprintf("Parse Error: %v", err))
	}

	// Validate table properties
	if tbl.Name != "test" {
		t.Error(fmt.Sprintf("Table Name incorrect: Expected: 'test' Found: '%s'", tbl.Name))
	}

	if tbl.CharSet != "latin1" {
		t.Error(fmt.Sprintf("Table CharSet incorrect: Expected: 'latin1' Found: '%s'", tbl.CharSet))
	}

	if tbl.Engine != "InnoDB" {
		t.Error(fmt.Sprintf("Table Engine incorrect: Expected: 'InnoDB' Found: '%s'", tbl.Engine))
	}

	if tbl.ID != "tbl1" {
		t.Error(fmt.Sprintf("Table ID incorrect: Expected: 'tbl1' Found: '%s'", tbl.ID))
	}

	numCol := len(tbl.Columns)
	if numCol != 2 {
		t.Error(fmt.Sprintf("Table has invalid number of columns: Expected: 2 Found: %d", numCol))
	}

	// Validate Column Properties
	col := tbl.Columns[0]

	if col.Name != "id" {
		t.Error(fmt.Sprintf("Column Name incorrect: Expected: 'id' Found: '%s'", col.Name))
	}

	if col.Type != "int" {
		t.Error(fmt.Sprintf("Column Type incorrect: Expected: 'int' Found: '%s'", col.Type))
	}

	if col.Size[0] != 11 {
		t.Error(fmt.Sprintf("Column Size incorrect: Expected: '11' Found: '%d'", col.Size))
	}

	if col.Nullable != false {
		t.Error(fmt.Sprintf("Column Size incorrect: Expected: 'No' Found: '%t'", col.Nullable))
	}

	if col.ID != "col1" {
		t.Error(fmt.Sprintf("Column ID incorrect: Expected: 'col1' Found: '%s'", col.ID))
	}

	// Validate PrimaryKey Properties
	pi := tbl.PrimaryIndex

	if pi.Name != "" {
		t.Error(fmt.Sprintf("PrimaryKey Name incorrect: Expected: '' Found: '%s'", pi.Name))
	}

	if pi.ID != "pi" {
		t.Error(fmt.Sprintf("PrimaryKey ID incorrect: Expected: 'pi' Found: '%s'", pi.ID))
	}

	cols := []string{"name"}
	if !reflect.DeepEqual(pi.Columns, cols) {
		t.Error(fmt.Sprintf("PrimaryKey Columns incorrect: Expected: '%v' Found: '%v'", cols, pi.Columns))
	}

	numInd := len(tbl.SecondaryIndexes)
	if numInd != 1 {
		t.Error(fmt.Sprintf("Table has invalid number of indexes: Expected: 1 Found: %d", numInd))
	}

	si := tbl.SecondaryIndexes[0]

	if si.Name != "idx_id_name" {
		t.Error(fmt.Sprintf("Secondary Index Name incorrect: Expected: 'idx_id_name' Found: '%s'", si.Name))
	}

	if si.ID != "sc1" {
		t.Error(fmt.Sprintf("Secondary Index ID incorrect: Expected: 'sc1' Found: '%s'", si.ID))
	}

	cols = []string{"id", "name"}
	if !reflect.DeepEqual(si.Columns, cols) {
		t.Error(fmt.Sprintf("SecondaryIndexe Columns incorrect: Expected: '%v' Found: '%v'", cols, pi.Columns))
	}
}

// Unsuccessful Read
<commit_msg>Updated YAML Parse Test to use DeepEqual and to provide more concise tests.<commit_after>package yaml_test

import (
	"reflect"
	"testing"

	"github.com/freneticmonkey/migrate/migrate/table"
	"github.com/freneticmonkey/migrate/migrate/util"
	"github.com/freneticmonkey/migrate/migrate/yaml"
)

var tblPropertyID = "testtbl"
var tblName = "test"

type ParseTest struct {
	Str        string      // Column definition to parse
	Expected   interface{} // Expected Column defintion
	ExpectFail bool
}

var yamlTests = []ParseTest{
	// Test Table struct parsing
	{
		Str: `
        name:     test
        charset:  latin1
        engine:   InnoDB
        id:       tbl1
        autoinc:  1234
        `,
		Expected: table.Table{
			Name:    "test",
			CharSet: "latin1",
			Engine:  "InnoDB",
			ID:      "tbl1",
			AutoInc: 1234,
		},
		ExpectFail: false,
	},
	// Column Parsing
	// Single Column
	{
		Str: `
        columns:
            - name:     id
              type:     int
              size:     [11]
              nullable: No
              id:       col1
        `,
		Expected: table.Table{
			Columns: []table.Column{
				table.Column{
					ID:       "col1",
					Name:     "id",
					Type:     "int",
					Size:     []int{11},
					Nullable: false,
					AutoInc:  false,
				},
			},
		},
		ExpectFail: false,
	},
	// Multi-Column
	{
		Str: `
        columns:
            - name:     id
              type:     int
              size:     [11]
              nullable: No
              id:       col1

            - name:     name
              type:     varchar
              size:     [64]
              nullable: No
              id:       col2
        `,
		Expected: table.Table{
			Columns: []table.Column{
				table.Column{
					ID:       "col1",
					Name:     "id",
					Type:     "int",
					Size:     []int{11},
					Nullable: false,
					AutoInc:  false,
				},
				table.Column{
					ID:       "col2",
					Name:     "name",
					Type:     "varchar",
					Size:     []int{64},
					Nullable: false,
					AutoInc:  false,
				},
			},
		},
		ExpectFail: false,
	},
	// PrimaryKey Parsing
	{
		Str: `
        primaryindex:
            columns:
                - name
            isprimary: Yes
            id:        pi
        `,
		Expected: table.Table{
			PrimaryIndex: table.Index{
				ID:        "pi",
				IsPrimary: true,
				Columns:   []string{"name"},
			},
		},
		ExpectFail: false,
	},
	// Index Parsing
	{
		Str: `
        secondaryindexes:
            - name: idx_id_name
              id:   sc1
              columns:
                  - name
        `,
		Expected: table.Table{
			SecondaryIndexes: []table.Index{
				{
					ID:      "sc1",
					Name:    "idx_id_name",
					Columns: []string{"name"},
				},
			},
		},
		ExpectFail: false,
	},
	{
		Str: `
        secondaryindexes:
            - name: idx_id_name
              id:   sc1
              columns:
                  - name
                  - id
        `,
		Expected: table.Table{
			SecondaryIndexes: []table.Index{
				{
					ID:      "sc1",
					Name:    "idx_id_name",
					Columns: []string{"name", "id"},
				},
			},
		},
		ExpectFail: false,
	},
}

func validateResult(test ParseTest, result interface{}, err error, desc string, t *testing.T) {

	if !test.ExpectFail && err != nil {
		t.Errorf("%s Failed for column: '%s' with Error: '%s'", desc, test.Str, err)

	} else if !test.ExpectFail && err == nil {

		if !reflect.DeepEqual(result, test.Expected) {
			t.Errorf("%s Failed. Return object differs from expected object.", desc)
			util.LogAttentionf("%s Failed. Return object differs from expected object.", desc)
			util.LogWarn("Expected")
			util.DebugDump(test.Expected)
			util.LogWarn("Result")
			util.DebugDump(result)
		}
	} else if test.ExpectFail && err == nil {
		t.Errorf("%s Succeeded and it should have FAILED! Test String: '%s'", desc, test.Str)
	}
	// else Successfully failed :)
}

func TestYAMLParse(t *testing.T) {

	var err error
	var result table.Table

	for _, test := range yamlTests {

		result, err = yaml.ReadYAML(test.Str, "unittest")

		validateResult(test, result, err, "YAML Column Parse", t)
	}

}
<|endoftext|>


<commit_before>package azurerm

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAzureRMEventGridTopic_basic(t *testing.T) {
	ri := acctest.RandInt()
	config := testAccAzureRMEventGridTopic_basic(ri)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMEventGridTopicDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMEventGridTopicExists("azurerm_eventgrid_topic.test"),
				),
			},
		},
	})
}

func TestAccAzureRMEventGridTopic_basicWithTags(t *testing.T) {
	ri := acctest.RandInt()
	config := testAccAzureRMEventGridTopic_basicWithTags(ri)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMEventGridTopicDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMEventGridTopicExists("azurerm_eventgrid_topic.test"),
				),
			},
		},
	})
}

func testCheckAzureRMEventGridTopicDestroy(s *terraform.State) error {
	client := testAccProvider.Meta().(*ArmClient).eventGridTopicsClient

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "azurerm_eventgrid_topic" {
			continue
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup := rs.Primary.Attributes["resource_group_name"]

		resp, err := client.Get(resourceGroup, name)
		if err != nil {
			if responseWasNotFound(resp.Response) {
				return nil
			}

			return err
		}

		if resp.StatusCode != http.StatusNotFound {
			return fmt.Errorf("EventGrid Topic still exists:\n%#v", resp)
		}
	}

	return nil
}

func testCheckAzureRMEventGridTopicExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Ensure we have enough information in state to look up in API
		rs, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
		if !hasResourceGroup {
			return fmt.Errorf("Bad: no resource group found in state for EventGrid Topic: %s", name)
		}

		client := testAccProvider.Meta().(*ArmClient).eventGridTopicsClient
		resp, err := client.Get(resourceGroup, name)
		if err != nil {
			if responseWasNotFound(resp.Response) {
				return fmt.Errorf("Bad: EventGrid Topic %q (resource group: %s) does not exist", name, resourceGroup)
			}

			return fmt.Errorf("Bad: Get on eventGridTopicsClient: %s", err)
		}

		return nil
	}
}

func testAccAzureRMEventGridTopic_basic(rInt int) string {
	// currently only supported in "West Central US" & "West US 2"
	location := "westus2"
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_eventgrid_topic" "test" {
  name                = "acctesteg-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
}
`, rInt, location, rInt)
}

func testAccAzureRMEventGridTopic_basicWithTags(rInt int) string {
	// currently only supported in "West Central US" & "West US 2"
	location := "westus2"
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_eventgrid_topic" "test" {
  name                = "acctesteg-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  tags {
    "foo" = "bar"
  }
}
`, rInt, location, rInt)
}
<commit_msg>Adding checks for the optional/computed fields<commit_after>package azurerm

import (
	"fmt"
	"net/http"
	"testing"

	"github.com/hashicorp/terraform/helper/acctest"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
)

func TestAccAzureRMEventGridTopic_basic(t *testing.T) {
	resourceName := "azurerm_eventgrid_topic.test"
	ri := acctest.RandInt()
	config := testAccAzureRMEventGridTopic_basic(ri)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMEventGridTopicDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMEventGridTopicExists(resourceName),
					resource.TestCheckResourceAttrSet(resourceName, "endpoint"),
					resource.TestCheckResourceAttrSet(resourceName, "primary_access_key"),
					resource.TestCheckResourceAttrSet(resourceName, "secondary_access_key"),
				),
			},
		},
	})
}

func TestAccAzureRMEventGridTopic_basicWithTags(t *testing.T) {
	resourceName := "azurerm_eventgrid_topic.test"
	ri := acctest.RandInt()
	config := testAccAzureRMEventGridTopic_basicWithTags(ri)

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testCheckAzureRMEventGridTopicDestroy,
		Steps: []resource.TestStep{
			{
				Config: config,
				Check: resource.ComposeTestCheckFunc(
					testCheckAzureRMEventGridTopicExists(resourceName),
					resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
					resource.TestCheckResourceAttr(resourceName, "tags.foo", "bar"),
					resource.TestCheckResourceAttrSet(resourceName, "endpoint"),
					resource.TestCheckResourceAttrSet(resourceName, "primary_access_key"),
					resource.TestCheckResourceAttrSet(resourceName, "secondary_access_key"),
				),
			},
		},
	})
}

func testCheckAzureRMEventGridTopicDestroy(s *terraform.State) error {
	client := testAccProvider.Meta().(*ArmClient).eventGridTopicsClient

	for _, rs := range s.RootModule().Resources {
		if rs.Type != "azurerm_eventgrid_topic" {
			continue
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup := rs.Primary.Attributes["resource_group_name"]

		resp, err := client.Get(resourceGroup, name)
		if err != nil {
			if responseWasNotFound(resp.Response) {
				return nil
			}

			return err
		}

		if resp.StatusCode != http.StatusNotFound {
			return fmt.Errorf("EventGrid Topic still exists:\n%#v", resp)
		}
	}

	return nil
}

func testCheckAzureRMEventGridTopicExists(name string) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		// Ensure we have enough information in state to look up in API
		rs, ok := s.RootModule().Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		name := rs.Primary.Attributes["name"]
		resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"]
		if !hasResourceGroup {
			return fmt.Errorf("Bad: no resource group found in state for EventGrid Topic: %s", name)
		}

		client := testAccProvider.Meta().(*ArmClient).eventGridTopicsClient
		resp, err := client.Get(resourceGroup, name)
		if err != nil {
			if responseWasNotFound(resp.Response) {
				return fmt.Errorf("Bad: EventGrid Topic %q (resource group: %s) does not exist", name, resourceGroup)
			}

			return fmt.Errorf("Bad: Get on eventGridTopicsClient: %s", err)
		}

		return nil
	}
}

func testAccAzureRMEventGridTopic_basic(rInt int) string {
	// currently only supported in "West Central US" & "West US 2"
	location := "westus2"
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_eventgrid_topic" "test" {
  name                = "acctesteg-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
}
`, rInt, location, rInt)
}

func testAccAzureRMEventGridTopic_basicWithTags(rInt int) string {
	// currently only supported in "West Central US" & "West US 2"
	location := "westus2"
	return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
  name     = "acctestRG-%d"
  location = "%s"
}

resource "azurerm_eventgrid_topic" "test" {
  name                = "acctesteg-%d"
  location            = "${azurerm_resource_group.test.location}"
  resource_group_name = "${azurerm_resource_group.test.name}"
  tags {
    "foo" = "bar"
  }
}
`, rInt, location, rInt)
}
<|endoftext|>


<commit_before>package spvwallet

import (
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/peer"
	"github.com/btcsuite/btcd/wire"
	"time"
)

var (
	maxHash              *chainhash.Hash
	MAX_UNCONFIRMED_TIME time.Duration = time.Hour * 24 * 7
)

func init() {
	h, err := chainhash.NewHashFromStr("0000000000000000000000000000000000000000000000000000000000000000")
	if err != nil {
		log.Fatal(err)
	}
	maxHash = h
}

func (w *SPVWallet) startChainDownload(p *peer.Peer) {
	w.mutex.Lock()
	defer w.mutex.Unlock()
	if w.blockchain.ChainState() == SYNCING {
		height, _ := w.blockchain.db.Height()
		if height >= uint32(p.LastBlock()) {
			moar := w.PeerManager.CheckForMoreBlocks(height)
			if !moar {
				log.Info("Chain download complete")
				w.blockchain.SetChainState(WAITING)
				w.Rebroadcast()
				close(w.blockQueue)
			}
			return
		}
		gBlocks := wire.NewMsgGetBlocks(maxHash)
		hashes := w.blockchain.GetBlockLocatorHashes()
		gBlocks.BlockLocatorHashes = hashes
		p.QueueMessage(gBlocks, nil)
	}
}

func (w *SPVWallet) onMerkleBlock(p *peer.Peer, m *wire.MsgMerkleBlock) {
	if w.blockchain.ChainState() == SYNCING && w.PeerManager.DownloadPeer() != nil && w.PeerManager.DownloadPeer().ID() == p.ID() {
		queueHash := <-w.blockQueue
		headerHash := m.Header.BlockHash()
		if !headerHash.IsEqual(&queueHash) {
			log.Errorf("Peer%d is sending us blocks out of order", p.ID())
			p.Disconnect()
			return
		}
	}
	txids, err := checkMBlock(m)
	if err != nil {
		log.Errorf("Peer%d sent an invalid MerkleBlock", p.ID())
		p.Disconnect()
		return
	}
	newBlock, reorg, height, err := w.blockchain.CommitHeader(m.Header)
	if err != nil {
		log.Warning(err)
		return
	}
	if !newBlock {
		return
	}

	// We hit a reorg. Rollback the transactions and resync from the reorg point.
	if reorg != nil {
		err := w.txstore.processReorg(reorg.height)
		if err != nil {
			log.Error(err)
		}
		w.blockchain.SetChainState(SYNCING)
		w.blockchain.db.Put(*reorg, true)
		go w.startChainDownload(p)
		return
	}

	for _, txid := range txids {
		w.mutex.Lock()
		w.toDownload[*txid] = int32(height)
		w.mutex.Unlock()
	}
	log.Debugf("Received Merkle Block %s at height %d\n", m.Header.BlockHash().String(), height)
	if len(w.blockQueue) == 0 && w.blockchain.ChainState() == SYNCING {
		go w.startChainDownload(p)
	}
	if w.blockchain.ChainState() == WAITING {
		txns, err := w.txstore.Txns().GetAll(false)
		if err != nil {
			log.Error(err)
			return
		}
		now := time.Now()
		for _, t := range txns {
			if now.After(t.Timestamp.Add(MAX_UNCONFIRMED_TIME)) && t.Height == int32(0) {
				log.Noticef("Marking tx as dead %s", t.Txid)
				h, err := chainhash.NewHashFromStr(t.Txid)
				if err != nil {
					log.Error(err)
					continue
				}
				err = w.txstore.markAsDead(*h)
				if err != nil {
					log.Error(err)
					continue
				}
			}
		}
	}
}

func (w *SPVWallet) onTx(p *peer.Peer, m *wire.MsgTx) {
	w.mutex.RLock()
	height := w.toDownload[m.TxHash()]
	w.mutex.RUnlock()
	hits, err := w.txstore.Ingest(m, height)
	if err != nil {
		log.Errorf("Error ingesting tx: %s\n", err.Error())
		return
	}
	if hits == 0 {
		log.Debugf("Tx %s from Peer%d had no hits, filter false positive.", m.TxHash().String(), p.ID())
		w.fPositives <- p
		return
	}
	w.updateFilterAndSend(p)
	log.Infof("Tx %s from Peer%d ingested and matches %d utxo/adrs.", m.TxHash().String(), p.ID(), hits)

	// FIXME: right now the hash stays in memory forever. We need to delete it but the way the code works,
	// FIXME: doing so will cause the height to get reset to zero if a peer relays the tx to us again.
}

func (w *SPVWallet) onInv(p *peer.Peer, m *wire.MsgInv) {
	go func() {
		defer func() {
			if err := recover(); err != nil {
				log.Error(err)
			}
		}()
		for _, inv := range m.InvList {
			switch inv.Type {
			case wire.InvTypeBlock:
				// Kind of lame to send separate getData messages but this allows us
				// to take advantage of the timeout on the upper layer. Otherwise we
				// need separate timeout handling.
				inv.Type = wire.InvTypeFilteredBlock
				gData := wire.NewMsgGetData()
				gData.AddInvVect(inv)
				p.QueueMessage(gData, nil)
				if w.blockchain.ChainState() == SYNCING && w.PeerManager.DownloadPeer() != nil && w.PeerManager.DownloadPeer().ID() == p.ID() {
					w.blockQueue <- inv.Hash
				}
			case wire.InvTypeTx:
				gData := wire.NewMsgGetData()
				gData.AddInvVect(inv)
				p.QueueMessage(gData, nil)
			default:
				continue
			}

		}
	}()
}

func (w *SPVWallet) onGetData(p *peer.Peer, m *wire.MsgGetData) {
	log.Debugf("Received getdata request from Peer%d\n", p.ID())
	var sent int32
	for _, thing := range m.InvList {
		if thing.Type == wire.InvTypeTx {
			tx, _, err := w.txstore.Txns().Get(thing.Hash)
			if err != nil {
				log.Errorf("Error getting tx %s: %s", thing.Hash.String(), err.Error())
			}
			p.QueueMessage(tx, nil)
			sent++
			continue
		}
		// didn't match, so it's not something we're responding to
		log.Debugf("We only respond to tx requests, ignoring")

	}
	log.Debugf("Sent %d of %d requested items to Peer%d", sent, len(m.InvList), p.ID())
}

func (w *SPVWallet) fPositiveHandler(quit chan int) {
	for {
		select {
		case peer := <-w.fPositives:
			w.mutex.RLock()
			falsePostives, _ := w.fpAccumulator[peer.ID()]
			w.mutex.RUnlock()
			falsePostives++
			if falsePostives > 7 {
				w.updateFilterAndSend(peer)
				log.Debugf("Reset %d false positives for Peer%d\n", falsePostives, peer.ID())
				// reset accumulator
				falsePostives = 0
			}
			w.mutex.Lock()
			w.fpAccumulator[peer.ID()] = falsePostives
			w.mutex.Unlock()
		case <-quit:
			break
		}
	}
}

func (w *SPVWallet) updateFilterAndSend(p *peer.Peer) {
	filt, err := w.txstore.GimmeFilter()
	if err != nil {
		log.Errorf("Error creating filter: %s\n", err.Error())
		return
	}
	// send filter
	p.QueueMessage(filt.MsgFilterLoad(), nil)
	log.Debugf("Sent filter to Peer%d\n", p.ID())
}

func (w *SPVWallet) Rebroadcast() {
	// get all unconfirmed txs
	invMsg, err := w.txstore.GetPendingInv()
	if err != nil {
		log.Errorf("Rebroadcast error: %s", err.Error())
	}
	if len(invMsg.InvList) == 0 { // nothing to broadcast, so don't
		return
	}
	for _, peer := range w.PeerManager.connectedPeers {
		peer.QueueMessage(invMsg, nil)
	}
}
<commit_msg>Fix bug handling erroneous getdata request<commit_after>package spvwallet

import (
	"github.com/btcsuite/btcd/chaincfg/chainhash"
	"github.com/btcsuite/btcd/peer"
	"github.com/btcsuite/btcd/wire"
	"time"
)

var (
	maxHash              *chainhash.Hash
	MAX_UNCONFIRMED_TIME time.Duration = time.Hour * 24 * 7
)

func init() {
	h, err := chainhash.NewHashFromStr("0000000000000000000000000000000000000000000000000000000000000000")
	if err != nil {
		log.Fatal(err)
	}
	maxHash = h
}

func (w *SPVWallet) startChainDownload(p *peer.Peer) {
	w.mutex.Lock()
	defer w.mutex.Unlock()
	if w.blockchain.ChainState() == SYNCING {
		height, _ := w.blockchain.db.Height()
		if height >= uint32(p.LastBlock()) {
			moar := w.PeerManager.CheckForMoreBlocks(height)
			if !moar {
				log.Info("Chain download complete")
				w.blockchain.SetChainState(WAITING)
				w.Rebroadcast()
				close(w.blockQueue)
			}
			return
		}
		gBlocks := wire.NewMsgGetBlocks(maxHash)
		hashes := w.blockchain.GetBlockLocatorHashes()
		gBlocks.BlockLocatorHashes = hashes
		p.QueueMessage(gBlocks, nil)
	}
}

func (w *SPVWallet) onMerkleBlock(p *peer.Peer, m *wire.MsgMerkleBlock) {
	if w.blockchain.ChainState() == SYNCING && w.PeerManager.DownloadPeer() != nil && w.PeerManager.DownloadPeer().ID() == p.ID() {
		queueHash := <-w.blockQueue
		headerHash := m.Header.BlockHash()
		if !headerHash.IsEqual(&queueHash) {
			log.Errorf("Peer%d is sending us blocks out of order", p.ID())
			p.Disconnect()
			return
		}
	}
	txids, err := checkMBlock(m)
	if err != nil {
		log.Errorf("Peer%d sent an invalid MerkleBlock", p.ID())
		p.Disconnect()
		return
	}
	newBlock, reorg, height, err := w.blockchain.CommitHeader(m.Header)
	if err != nil {
		log.Warning(err)
		return
	}
	if !newBlock {
		return
	}

	// We hit a reorg. Rollback the transactions and resync from the reorg point.
	if reorg != nil {
		err := w.txstore.processReorg(reorg.height)
		if err != nil {
			log.Error(err)
		}
		w.blockchain.SetChainState(SYNCING)
		w.blockchain.db.Put(*reorg, true)
		go w.startChainDownload(p)
		return
	}

	for _, txid := range txids {
		w.mutex.Lock()
		w.toDownload[*txid] = int32(height)
		w.mutex.Unlock()
	}
	log.Debugf("Received Merkle Block %s at height %d\n", m.Header.BlockHash().String(), height)
	if len(w.blockQueue) == 0 && w.blockchain.ChainState() == SYNCING {
		go w.startChainDownload(p)
	}
	if w.blockchain.ChainState() == WAITING {
		txns, err := w.txstore.Txns().GetAll(false)
		if err != nil {
			log.Error(err)
			return
		}
		now := time.Now()
		for _, t := range txns {
			if now.After(t.Timestamp.Add(MAX_UNCONFIRMED_TIME)) && t.Height == int32(0) {
				log.Noticef("Marking tx as dead %s", t.Txid)
				h, err := chainhash.NewHashFromStr(t.Txid)
				if err != nil {
					log.Error(err)
					continue
				}
				err = w.txstore.markAsDead(*h)
				if err != nil {
					log.Error(err)
					continue
				}
			}
		}
	}
}

func (w *SPVWallet) onTx(p *peer.Peer, m *wire.MsgTx) {
	w.mutex.RLock()
	height := w.toDownload[m.TxHash()]
	w.mutex.RUnlock()
	hits, err := w.txstore.Ingest(m, height)
	if err != nil {
		log.Errorf("Error ingesting tx: %s\n", err.Error())
		return
	}
	if hits == 0 {
		log.Debugf("Tx %s from Peer%d had no hits, filter false positive.", m.TxHash().String(), p.ID())
		w.fPositives <- p
		return
	}
	w.updateFilterAndSend(p)
	log.Infof("Tx %s from Peer%d ingested and matches %d utxo/adrs.", m.TxHash().String(), p.ID(), hits)

	// FIXME: right now the hash stays in memory forever. We need to delete it but the way the code works,
	// FIXME: doing so will cause the height to get reset to zero if a peer relays the tx to us again.
}

func (w *SPVWallet) onInv(p *peer.Peer, m *wire.MsgInv) {
	go func() {
		defer func() {
			if err := recover(); err != nil {
				log.Error(err)
			}
		}()
		for _, inv := range m.InvList {
			switch inv.Type {
			case wire.InvTypeBlock:
				// Kind of lame to send separate getData messages but this allows us
				// to take advantage of the timeout on the upper layer. Otherwise we
				// need separate timeout handling.
				inv.Type = wire.InvTypeFilteredBlock
				gData := wire.NewMsgGetData()
				gData.AddInvVect(inv)
				p.QueueMessage(gData, nil)
				if w.blockchain.ChainState() == SYNCING && w.PeerManager.DownloadPeer() != nil && w.PeerManager.DownloadPeer().ID() == p.ID() {
					w.blockQueue <- inv.Hash
				}
			case wire.InvTypeTx:
				gData := wire.NewMsgGetData()
				gData.AddInvVect(inv)
				p.QueueMessage(gData, nil)
			default:
				continue
			}

		}
	}()
}

func (w *SPVWallet) onGetData(p *peer.Peer, m *wire.MsgGetData) {
	log.Debugf("Received getdata request from Peer%d\n", p.ID())
	var sent int32
	for _, thing := range m.InvList {
		if thing.Type == wire.InvTypeTx {
			tx, _, err := w.txstore.Txns().Get(thing.Hash)
			if err != nil {
				log.Errorf("Error getting tx %s: %s", thing.Hash.String(), err.Error())
				continue
			}
			p.QueueMessage(tx, nil)
			sent++
			continue
		}
		// didn't match, so it's not something we're responding to
		log.Debugf("We only respond to tx requests, ignoring")

	}
	log.Debugf("Sent %d of %d requested items to Peer%d", sent, len(m.InvList), p.ID())
}

func (w *SPVWallet) fPositiveHandler(quit chan int) {
	for {
		select {
		case peer := <-w.fPositives:
			w.mutex.RLock()
			falsePostives, _ := w.fpAccumulator[peer.ID()]
			w.mutex.RUnlock()
			falsePostives++
			if falsePostives > 7 {
				w.updateFilterAndSend(peer)
				log.Debugf("Reset %d false positives for Peer%d\n", falsePostives, peer.ID())
				// reset accumulator
				falsePostives = 0
			}
			w.mutex.Lock()
			w.fpAccumulator[peer.ID()] = falsePostives
			w.mutex.Unlock()
		case <-quit:
			break
		}
	}
}

func (w *SPVWallet) updateFilterAndSend(p *peer.Peer) {
	filt, err := w.txstore.GimmeFilter()
	if err != nil {
		log.Errorf("Error creating filter: %s\n", err.Error())
		return
	}
	// send filter
	p.QueueMessage(filt.MsgFilterLoad(), nil)
	log.Debugf("Sent filter to Peer%d\n", p.ID())
}

func (w *SPVWallet) Rebroadcast() {
	// get all unconfirmed txs
	invMsg, err := w.txstore.GetPendingInv()
	if err != nil {
		log.Errorf("Rebroadcast error: %s", err.Error())
	}
	if len(invMsg.InvList) == 0 { // nothing to broadcast, so don't
		return
	}
	for _, peer := range w.PeerManager.connectedPeers {
		peer.QueueMessage(invMsg, nil)
	}
}
<|endoftext|>


<commit_before>package v0

import (
	"github.com/gramework/gramework"
)

// Register sf handlers
func Register(root *gramework.SubRouter) {
	root.GET("/", "not ready yet")

	root.Sub("/auth").
		GET("/", root.Forbidden)
}
<commit_msg>sf/v0: register routes<commit_after>package v0

import (
	"github.com/gramework/gramework"
)

// Register sf handlers
func Register(root *gramework.SubRouter) {
	root.HTTP().GET("/*any", root.ToTLSHandler())

	root.GET("/", "not ready yet")

	root.Sub("/auth").
		GET("/", root.Forbidden)
}
<|endoftext|>


<commit_before>package handler

import (
	"context"
	"io"
	"time"

	"github.com/micro/go-micro/v2/errors"
	"github.com/micro/go-micro/v2/router"
	pb "github.com/micro/go-micro/v2/router/service/proto"
)

// Router implements router handler
type Router struct {
	Router router.Router
}

// Lookup looks up routes in the routing table and returns them
func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.LookupResponse) error {
	routes, err := r.Router.Lookup(
		router.QueryService(req.Query.Service),
		router.QueryNetwork(req.Query.Network),
	)
	if err != nil {
		return errors.InternalServerError("go.micro.router", "failed to lookup routes: %v", err)
	}

	respRoutes := make([]*pb.Route, 0, len(routes))
	for _, route := range routes {
		respRoute := &pb.Route{
			Service: route.Service,
			Address: route.Address,
			Gateway: route.Gateway,
			Network: route.Network,
			Router:  route.Router,
			Link:    route.Link,
			Metric:  route.Metric,
		}
		respRoutes = append(respRoutes, respRoute)
	}

	resp.Routes = respRoutes

	return nil
}

// Advertise streams router advertisements
func (r *Router) Advertise(ctx context.Context, req *pb.Request, stream pb.Router_AdvertiseStream) error {
	advertChan, err := r.Router.Advertise()
	if err != nil {
		return errors.InternalServerError("go.micro.router", "failed to get adverts: %v", err)
	}

	for advert := range advertChan {
		var events []*pb.Event
		for _, event := range advert.Events {
			route := &pb.Route{
				Service: event.Route.Service,
				Address: event.Route.Address,
				Gateway: event.Route.Gateway,
				Network: event.Route.Network,
				Router:  event.Route.Router,
				Link:    event.Route.Link,
				Metric:  event.Route.Metric,
			}
			e := &pb.Event{
				Id:        event.Id,
				Type:      pb.EventType(event.Type),
				Timestamp: event.Timestamp.UnixNano(),
				Route:     route,
			}
			events = append(events, e)
		}

		advert := &pb.Advert{
			Id:        advert.Id,
			Type:      pb.AdvertType(advert.Type),
			Timestamp: advert.Timestamp.UnixNano(),
			Events:    events,
		}

		// send the advert
		err := stream.Send(advert)
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return errors.InternalServerError("go.micro.router", "error sending message %v", err)
		}
	}

	return nil
}

// Process processes advertisements
func (r *Router) Process(ctx context.Context, req *pb.Advert, rsp *pb.ProcessResponse) error {
	events := make([]*router.Event, len(req.Events))
	for i, event := range req.Events {
		route := router.Route{
			Service: event.Route.Service,
			Address: event.Route.Address,
			Gateway: event.Route.Gateway,
			Network: event.Route.Network,
			Router:  event.Route.Router,
			Link:    event.Route.Link,
			Metric:  event.Route.Metric,
		}

		events[i] = &router.Event{
			Id:        event.Id,
			Type:      router.EventType(event.Type),
			Timestamp: time.Unix(0, event.Timestamp),
			Route:     route,
		}
	}

	advert := &router.Advert{
		Id:        req.Id,
		Type:      router.AdvertType(req.Type),
		Timestamp: time.Unix(0, req.Timestamp),
		TTL:       time.Duration(req.Ttl),
		Events:    events,
	}

	if err := r.Router.Process(advert); err != nil {
		return errors.InternalServerError("go.micro.router", "error publishing advert: %v", err)
	}

	return nil
}

// Watch streams routing table events
func (r *Router) Watch(ctx context.Context, req *pb.WatchRequest, stream pb.Router_WatchStream) error {
	watcher, err := r.Router.Watch()
	if err != nil {
		return errors.InternalServerError("go.micro.router", "failed creating event watcher: %v", err)
	}
	defer watcher.Stop()
	defer stream.Close()

	for {
		event, err := watcher.Next()
		if err == router.ErrWatcherStopped {
			return errors.InternalServerError("go.micro.router", "watcher stopped")
		}

		if err != nil {
			return errors.InternalServerError("go.micro.router", "error watching events: %v", err)
		}

		route := &pb.Route{
			Service: event.Route.Service,
			Address: event.Route.Address,
			Gateway: event.Route.Gateway,
			Network: event.Route.Network,
			Router:  event.Route.Router,
			Link:    event.Route.Link,
			Metric:  event.Route.Metric,
		}

		tableEvent := &pb.Event{
			Id:        event.Id,
			Type:      pb.EventType(event.Type),
			Timestamp: event.Timestamp.UnixNano(),
			Route:     route,
		}

		if err := stream.Send(tableEvent); err != nil {
			return err
		}
	}
}
<commit_msg>router/service: handle not found error<commit_after>package handler

import (
	"context"
	"io"
	"time"

	"github.com/micro/go-micro/v2/errors"
	"github.com/micro/go-micro/v2/router"
	pb "github.com/micro/go-micro/v2/router/service/proto"
)

// Router implements router handler
type Router struct {
	Router router.Router
}

// Lookup looks up routes in the routing table and returns them
func (r *Router) Lookup(ctx context.Context, req *pb.LookupRequest, resp *pb.LookupResponse) error {
	routes, err := r.Router.Lookup(
		router.QueryService(req.Query.Service),
		router.QueryNetwork(req.Query.Network),
	)
	if err == router.ErrRouteNotFound {
		return errors.NotFound("go.micro.router", err.Error())
	} else if err != nil {
		return errors.InternalServerError("go.micro.router", "failed to lookup routes: %v", err)
	}

	respRoutes := make([]*pb.Route, 0, len(routes))
	for _, route := range routes {
		respRoute := &pb.Route{
			Service: route.Service,
			Address: route.Address,
			Gateway: route.Gateway,
			Network: route.Network,
			Router:  route.Router,
			Link:    route.Link,
			Metric:  route.Metric,
		}
		respRoutes = append(respRoutes, respRoute)
	}

	resp.Routes = respRoutes

	return nil
}

// Advertise streams router advertisements
func (r *Router) Advertise(ctx context.Context, req *pb.Request, stream pb.Router_AdvertiseStream) error {
	advertChan, err := r.Router.Advertise()
	if err != nil {
		return errors.InternalServerError("go.micro.router", "failed to get adverts: %v", err)
	}

	for advert := range advertChan {
		var events []*pb.Event
		for _, event := range advert.Events {
			route := &pb.Route{
				Service: event.Route.Service,
				Address: event.Route.Address,
				Gateway: event.Route.Gateway,
				Network: event.Route.Network,
				Router:  event.Route.Router,
				Link:    event.Route.Link,
				Metric:  event.Route.Metric,
			}
			e := &pb.Event{
				Id:        event.Id,
				Type:      pb.EventType(event.Type),
				Timestamp: event.Timestamp.UnixNano(),
				Route:     route,
			}
			events = append(events, e)
		}

		advert := &pb.Advert{
			Id:        advert.Id,
			Type:      pb.AdvertType(advert.Type),
			Timestamp: advert.Timestamp.UnixNano(),
			Events:    events,
		}

		// send the advert
		err := stream.Send(advert)
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return errors.InternalServerError("go.micro.router", "error sending message %v", err)
		}
	}

	return nil
}

// Process processes advertisements
func (r *Router) Process(ctx context.Context, req *pb.Advert, rsp *pb.ProcessResponse) error {
	events := make([]*router.Event, len(req.Events))
	for i, event := range req.Events {
		route := router.Route{
			Service: event.Route.Service,
			Address: event.Route.Address,
			Gateway: event.Route.Gateway,
			Network: event.Route.Network,
			Router:  event.Route.Router,
			Link:    event.Route.Link,
			Metric:  event.Route.Metric,
		}

		events[i] = &router.Event{
			Id:        event.Id,
			Type:      router.EventType(event.Type),
			Timestamp: time.Unix(0, event.Timestamp),
			Route:     route,
		}
	}

	advert := &router.Advert{
		Id:        req.Id,
		Type:      router.AdvertType(req.Type),
		Timestamp: time.Unix(0, req.Timestamp),
		TTL:       time.Duration(req.Ttl),
		Events:    events,
	}

	if err := r.Router.Process(advert); err != nil {
		return errors.InternalServerError("go.micro.router", "error publishing advert: %v", err)
	}

	return nil
}

// Watch streams routing table events
func (r *Router) Watch(ctx context.Context, req *pb.WatchRequest, stream pb.Router_WatchStream) error {
	watcher, err := r.Router.Watch()
	if err != nil {
		return errors.InternalServerError("go.micro.router", "failed creating event watcher: %v", err)
	}
	defer watcher.Stop()
	defer stream.Close()

	for {
		event, err := watcher.Next()
		if err == router.ErrWatcherStopped {
			return errors.InternalServerError("go.micro.router", "watcher stopped")
		}

		if err != nil {
			return errors.InternalServerError("go.micro.router", "error watching events: %v", err)
		}

		route := &pb.Route{
			Service: event.Route.Service,
			Address: event.Route.Address,
			Gateway: event.Route.Gateway,
			Network: event.Route.Network,
			Router:  event.Route.Router,
			Link:    event.Route.Link,
			Metric:  event.Route.Metric,
		}

		tableEvent := &pb.Event{
			Id:        event.Id,
			Type:      pb.EventType(event.Type),
			Timestamp: event.Timestamp.UnixNano(),
			Route:     route,
		}

		if err := stream.Send(tableEvent); err != nil {
			return err
		}
	}
}
<|endoftext|>


<commit_before>package goesi

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"sync"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
)

// SSOAuthenticator provides interfacing to the EVE SSO. NewSSOAuthenticator is used to create
// this structure.

// [TODO] lose this mutex and allow scopes to change without conflict.
type SSOAuthenticator struct {
	httpClient *http.Client
	// Hide this...
	oauthConfig *oauth2.Config
	scopeLock   sync.Mutex
}

// Redirect type to hide oauth2 API
type CRESTToken oauth2.Token

type CRESTTokenSource oauth2.TokenSource

// NewSSOAuthenticator create a new EVE SSO Authenticator.
// Requires your application clientID, clientSecret, and redirectURL.
// RedirectURL must match exactly to what you registered with CCP.
func NewSSOAuthenticator(client *http.Client, clientID string, clientSecret string, redirectURL string, scopes []string) *SSOAuthenticator {

	if client == nil {
		return nil
	}

	c := &SSOAuthenticator{}

	c.httpClient = client

	c.oauthConfig = &oauth2.Config{
		ClientID:     clientID,
		ClientSecret: clientSecret,
		Endpoint: oauth2.Endpoint{
			AuthURL:  "https://login.eveonline.com/oauth/authorize",
			TokenURL: "https://login.eveonline.com/oauth/token",
		},
		Scopes:      scopes,
		RedirectURL: redirectURL,
	}

	return c
}

// ChangeAuthURL changes the oauth2 configuration url for authentication
func (c *SSOAuthenticator) ChangeAuthURL(url string) {
	c.oauthConfig.Endpoint.AuthURL = url
}

// ChangeTokenURL changes the oauth2 configuration url for token
func (c *SSOAuthenticator) ChangeTokenURL(url string) {
	c.oauthConfig.Endpoint.TokenURL = url
}

// AuthorizeURL returns a url for an end user to authenticate with EVE SSO
// and return success to the redirectURL.
// It is important to create a significatly unique state for this request
// and verify the state matches when returned to the redirectURL.
func (c *SSOAuthenticator) AuthorizeURL(state string, onlineAccess bool, scopes []string) string {
	var url string

	// Generate the URL
	if onlineAccess == true {
		url = c.oauthConfig.AuthCodeURL(state, oauth2.AccessTypeOnline, oauth2.SetAuthURLParam("scope", strings.Join(scopes, " ")))
	} else {
		url = c.oauthConfig.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.SetAuthURLParam("scope", strings.Join(scopes, " ")))
	}

	return url
}

// TokenExchange exchanges the code returned to the redirectURL with
// the CREST server to an access token. A caching client must be passed.
// This client MUST cache per CCP guidelines or face banning.
func (c *SSOAuthenticator) TokenExchange(code string) (*CRESTToken, error) {
	tok, err := c.oauthConfig.Exchange(createContext(c.httpClient), code)
	if err != nil {
		return nil, err
	}
	return (*CRESTToken)(tok), nil
}

// TokenSource creates a refreshable token that can be passed to ESI functions
func (c *SSOAuthenticator) TokenSource(token *CRESTToken) (CRESTTokenSource, error) {
	return (CRESTTokenSource)(c.oauthConfig.TokenSource(createContext(c.httpClient), (*oauth2.Token)(token))), nil
}

type VerifyResponse struct {
	CharacterID        int64
	CharacterName      string
	ExpiresOn          string
	Scopes             string
	TokenType          string
	CharacterOwnerHash string
}

// Verify the client and collect user information.
func (c *SSOAuthenticator) Verify(auth oauth2.TokenSource) (*VerifyResponse, error) {
	v := &VerifyResponse{}
	_, err := c.doJSON("GET", "https://login.eveonline.com/oauth/verify", nil, v, "application/json;", auth)

	if err != nil {
		return nil, err
	}
	return v, nil
}

// Creates a new http.Request for a public resource.
func (c *SSOAuthenticator) newRequest(method, urlStr string, body interface{}, mediaType string) (*http.Request, error) {
	rel, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}

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

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

	return req, nil
}

// Calls a resource from the public CREST
func (c *SSOAuthenticator) doJSON(method, urlStr string, body interface{}, v interface{}, mediaType string, auth oauth2.TokenSource) (*http.Response, error) {

	req, err := c.newRequest(method, urlStr, body, mediaType)
	if err != nil {
		return nil, err
	}

	if auth != nil {
		// We were able to grab an oauth2 token from the context
		var latestToken *oauth2.Token
		if latestToken, err = auth.Token(); err != nil {
			return nil, err
		}
		latestToken.SetAuthHeader(req)
	}

	res, err := c.executeRequest(req)
	if err != nil {
		return nil, err
	}

	defer res.Body.Close()
	buf, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	if res.StatusCode != http.StatusOK {
		return nil, errors.New(string(buf))
	}
	if err := json.Unmarshal([]byte(buf), v); err != nil {
		return nil, err
	}

	return res, nil
}

// Executes a request generated with newRequest
func (c *SSOAuthenticator) executeRequest(req *http.Request) (*http.Response, error) {
	res, err := c.httpClient.Do(req)

	if err != nil {
		return nil, err
	}
	if res.StatusCode == http.StatusOK ||
		res.StatusCode == http.StatusCreated {
		return res, nil
	} else {
		return res, errors.New(res.Status)
	}

}

// Add custom clients to the context.
func createContext(httpClient *http.Client) context.Context {
	parent := oauth2.NoContext
	ctx := context.WithValue(parent, oauth2.HTTPClient, httpClient)
	return ctx
}

// TokenToJSON helper function to convert a token to a storable format.
func TokenToJSON(token *CRESTToken) (string, error) {
	if d, err := json.Marshal(token); err != nil {
		return "", err
	} else {
		return string(d), nil
	}
}

// TokenFromJSON helper function to convert stored JSON to a token.
func TokenFromJSON(jsonStr string) (*CRESTToken, error) {
	var token CRESTToken
	if err := json.Unmarshal([]byte(jsonStr), &token); err != nil {
		return nil, err
	}
	return &token, nil
}
<commit_msg>inconsistency between SSO and ESI characterID<commit_after>package goesi

import (
	"bytes"
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"sync"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
)

// SSOAuthenticator provides interfacing to the EVE SSO. NewSSOAuthenticator is used to create
// this structure.

// [TODO] lose this mutex and allow scopes to change without conflict.
type SSOAuthenticator struct {
	httpClient *http.Client
	// Hide this...
	oauthConfig *oauth2.Config
	scopeLock   sync.Mutex
}

// Redirect type to hide oauth2 API
type CRESTToken oauth2.Token

type CRESTTokenSource oauth2.TokenSource

// NewSSOAuthenticator create a new EVE SSO Authenticator.
// Requires your application clientID, clientSecret, and redirectURL.
// RedirectURL must match exactly to what you registered with CCP.
func NewSSOAuthenticator(client *http.Client, clientID string, clientSecret string, redirectURL string, scopes []string) *SSOAuthenticator {

	if client == nil {
		return nil
	}

	c := &SSOAuthenticator{}

	c.httpClient = client

	c.oauthConfig = &oauth2.Config{
		ClientID:     clientID,
		ClientSecret: clientSecret,
		Endpoint: oauth2.Endpoint{
			AuthURL:  "https://login.eveonline.com/oauth/authorize",
			TokenURL: "https://login.eveonline.com/oauth/token",
		},
		Scopes:      scopes,
		RedirectURL: redirectURL,
	}

	return c
}

// ChangeAuthURL changes the oauth2 configuration url for authentication
func (c *SSOAuthenticator) ChangeAuthURL(url string) {
	c.oauthConfig.Endpoint.AuthURL = url
}

// ChangeTokenURL changes the oauth2 configuration url for token
func (c *SSOAuthenticator) ChangeTokenURL(url string) {
	c.oauthConfig.Endpoint.TokenURL = url
}

// AuthorizeURL returns a url for an end user to authenticate with EVE SSO
// and return success to the redirectURL.
// It is important to create a significatly unique state for this request
// and verify the state matches when returned to the redirectURL.
func (c *SSOAuthenticator) AuthorizeURL(state string, onlineAccess bool, scopes []string) string {
	var url string

	// Generate the URL
	if onlineAccess == true {
		url = c.oauthConfig.AuthCodeURL(state, oauth2.AccessTypeOnline, oauth2.SetAuthURLParam("scope", strings.Join(scopes, " ")))
	} else {
		url = c.oauthConfig.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.SetAuthURLParam("scope", strings.Join(scopes, " ")))
	}

	return url
}

// TokenExchange exchanges the code returned to the redirectURL with
// the CREST server to an access token. A caching client must be passed.
// This client MUST cache per CCP guidelines or face banning.
func (c *SSOAuthenticator) TokenExchange(code string) (*CRESTToken, error) {
	tok, err := c.oauthConfig.Exchange(createContext(c.httpClient), code)
	if err != nil {
		return nil, err
	}
	return (*CRESTToken)(tok), nil
}

// TokenSource creates a refreshable token that can be passed to ESI functions
func (c *SSOAuthenticator) TokenSource(token *CRESTToken) (CRESTTokenSource, error) {
	return (CRESTTokenSource)(c.oauthConfig.TokenSource(createContext(c.httpClient), (*oauth2.Token)(token))), nil
}

type VerifyResponse struct {
	CharacterID        int32
	CharacterName      string
	ExpiresOn          string
	Scopes             string
	TokenType          string
	CharacterOwnerHash string
}

// Verify the client and collect user information.
func (c *SSOAuthenticator) Verify(auth oauth2.TokenSource) (*VerifyResponse, error) {
	v := &VerifyResponse{}
	_, err := c.doJSON("GET", "https://login.eveonline.com/oauth/verify", nil, v, "application/json;", auth)

	if err != nil {
		return nil, err
	}
	return v, nil
}

// Creates a new http.Request for a public resource.
func (c *SSOAuthenticator) newRequest(method, urlStr string, body interface{}, mediaType string) (*http.Request, error) {
	rel, err := url.Parse(urlStr)
	if err != nil {
		return nil, err
	}

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

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

	return req, nil
}

// Calls a resource from the public CREST
func (c *SSOAuthenticator) doJSON(method, urlStr string, body interface{}, v interface{}, mediaType string, auth oauth2.TokenSource) (*http.Response, error) {

	req, err := c.newRequest(method, urlStr, body, mediaType)
	if err != nil {
		return nil, err
	}

	if auth != nil {
		// We were able to grab an oauth2 token from the context
		var latestToken *oauth2.Token
		if latestToken, err = auth.Token(); err != nil {
			return nil, err
		}
		latestToken.SetAuthHeader(req)
	}

	res, err := c.executeRequest(req)
	if err != nil {
		return nil, err
	}

	defer res.Body.Close()
	buf, err := ioutil.ReadAll(res.Body)
	if err != nil {
		return nil, err
	}

	if res.StatusCode != http.StatusOK {
		return nil, errors.New(string(buf))
	}
	if err := json.Unmarshal([]byte(buf), v); err != nil {
		return nil, err
	}

	return res, nil
}

// Executes a request generated with newRequest
func (c *SSOAuthenticator) executeRequest(req *http.Request) (*http.Response, error) {
	res, err := c.httpClient.Do(req)

	if err != nil {
		return nil, err
	}
	if res.StatusCode == http.StatusOK ||
		res.StatusCode == http.StatusCreated {
		return res, nil
	} else {
		return res, errors.New(res.Status)
	}

}

// Add custom clients to the context.
func createContext(httpClient *http.Client) context.Context {
	parent := oauth2.NoContext
	ctx := context.WithValue(parent, oauth2.HTTPClient, httpClient)
	return ctx
}

// TokenToJSON helper function to convert a token to a storable format.
func TokenToJSON(token *CRESTToken) (string, error) {
	if d, err := json.Marshal(token); err != nil {
		return "", err
	} else {
		return string(d), nil
	}
}

// TokenFromJSON helper function to convert stored JSON to a token.
func TokenFromJSON(jsonStr string) (*CRESTToken, error) {
	var token CRESTToken
	if err := json.Unmarshal([]byte(jsonStr), &token); err != nil {
		return nil, err
	}
	return &token, nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"log"
	"os"
	"os/exec"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/edsrzf/mmap-go"
	"github.com/mibk/syd/core"
	"github.com/mibk/syd/pkg/undo"
	"github.com/mibk/syd/ui"
	"github.com/mibk/syd/ui/term"
	"github.com/mibk/syd/vi"
	"github.com/mibk/syd/view"
)

var (
	win      = &term.UI{}
	filename = ""
)

func main() {
	log.SetPrefix("syd: ")
	log.SetFlags(0)
	if err := win.Init(); err != nil {
		log.Fatalln("initializing ui:", err)
	}
	defer win.Close()

	var b []byte
	if len(os.Args) > 1 {
		filename = os.Args[1]
		m, err := readFile(filename)
		if err != nil {
			panic(err)
		}
		defer m.Unmap()
		b = []byte(m)
	}
	buf := undo.NewBuffer(b)

	e := &Editor{
		events:     make(chan ui.Event),
		vi:         vi.NewParser(),
		activeView: view.New(win, core.NewBuffer(buf)),
	}
	setMappings(e)
	go e.RouteEvents()
	e.Main()
}

func readFile(filename string) (mmap.MMap, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}

	m, err := mmap.Map(f, 0, 0)
	if err != nil {
		return nil, err
	}
	return m, nil
}

const (
	ModeNormal = iota
	ModeInsert
)

type Editor struct {
	events     chan ui.Event
	vi         *vi.Parser
	shouldQuit bool

	activeView *view.View
	mode       int
}

func (e *Editor) RouteEvents() {
	for ev := range ui.Events {
		if keyPress, ok := ev.(ui.KeyPress); ok && e.mode == ModeNormal {
			e.vi.Decode(keyPress)
			continue
		}
		e.events <- ev
	}
}

func parseKeys(cmd string) []ui.KeyPress {
	events := make([]ui.KeyPress, len(cmd))
	for i, r := range []rune(cmd) {
		events[i] = ui.KeyPress{Key: r}
	}
	return events
}

func (e *Editor) AddOperator(cmd []ui.KeyPress, fn func(*view.View, int)) {
	e.vi.AddOperator(cmd, func(n int) { fn(e.activeView, n) }, false)
}

func (e *Editor) AddStringOperator(cmd string, fn func(*view.View, int)) {
	e.AddOperator(parseKeys(cmd), fn)
}

func (e *Editor) AddMotion(cmd []ui.KeyPress, fn func(*view.View, int)) {
	e.vi.AddMotion(cmd, func(n int) { fn(e.activeView, n) })
}

func (e *Editor) AddStringMotion(cmd string, fn func(*view.View, int)) {
	e.AddMotion(parseKeys(cmd), fn)
}

func (e *Editor) Main() {
	var (
		lastQ     int64 = -1
		timestamp time.Time
	)
	for !e.shouldQuit {
		e.activeView.Render()
		select {
		case action := <-e.vi.Actions:
			action()
		case ev := <-e.events:
			switch ev := ev.(type) {
			case ui.KeyPress:
				if ev.Key == ui.KeyEscape {
					e.mode = ModeNormal
					continue
				}
				handleKeyPress(e.activeView, ev)
			case ui.MouseBtnPress:
				switch ev.Button {
				case ui.MouseButton1:
					p := e.activeView.Frame().CharsUntilXY(ev.X, ev.Y)
					q := e.activeView.Origin() + int64(p)
					if time.Since(timestamp) < 300*time.Millisecond {
						e.activeView.Select(dblclick(e.activeView, q))
						e.activeView.Frame().SetWantCol(ui.ColQ0)
						lastQ = -1
						continue
					}
					e.activeView.Select(q, q)
					e.activeView.Frame().SetWantCol(ui.ColQ0)
					lastQ = q
					timestamp = time.Now()
				case ui.MouseButton2:
					// This is just ugly proof of concept.
					p := e.activeView.Frame().CharsUntilXY(ev.X, ev.Y)
					q := e.activeView.Origin() + int64(p)
					q0, q1 := dblclick(e.activeView, q)
					var cmd []rune
					for i := q0; i < q1; i++ {
						cmd = append(cmd, e.activeView.ReadRuneAt(i))
					}
					e.Execute(string(cmd))
				case ui.MouseWheelUp:
					scrollUp(e.activeView, 3)
				case ui.MouseWheelDown:
					scrollDown(e.activeView, 3)
				}
			case ui.MouseBtnRelease:
				lastQ = -1
			case ui.MouseMove:
				if lastQ < 0 {
					continue
				}
				p := e.activeView.Frame().CharsUntilXY(ev.X, ev.Y)
				q0, q1 := lastQ, e.activeView.Origin()+int64(p)
				if q1 < q0 {
					q0, q1 = q1, q0
				}
				e.activeView.Select(q0, q1)
			}
		}
	}
}

func (e *Editor) Execute(command string) {
	switch command {
	case "Put":
		if filename != "" {
			if err := saveFile(filename, e.activeView); err != nil {
				panic(err)
			}
		}
	case "Undo":
		e.activeView.Undo()
	case "Redo":
		e.activeView.Redo()
	default:
		v := e.activeView
		var selected []rune
		q0, q1 := v.Selected()
		for p := q0; p < q1; p++ {
			r := v.ReadRuneAt(p)
			selected = append(selected, r)
		}
		var buf bytes.Buffer
		rd := strings.NewReader(string(selected))
		cmd := exec.Command(command)
		cmd.Stdin = rd
		cmd.Stdout = &buf
		// TODO: Redirect stderr somewhere.
		if err := cmd.Run(); err != nil {
			panic(err)
		}
		s := buf.String()
		v.Insert(s)
		v.Select(q0, q0+int64(utf8.RuneCountInString(s)))
	}
}

func saveFile(filename string, v *view.View) error {
	// TODO: Read bytes directly from the undo.Buffer.
	f, err := os.Create(filename + "~")
	if err != nil {
		return err
	}

	var buf [64]byte
	var i int

	for p := int64(0); ; p++ {
		r := v.ReadRuneAt(p)
		if r == view.EOF || len(buf[i:]) < utf8.UTFMax {
			if _, err := f.Write(buf[:i]); err != nil {
				return err
			}
			i = 0
		}
		if r == view.EOF {
			break
		}
		i += utf8.EncodeRune(buf[i:], r)
	}
	f.Close()

	return os.Rename(filename+"~", filename)
}
<commit_msg>Add Exit command<commit_after>package main

import (
	"bytes"
	"log"
	"os"
	"os/exec"
	"strings"
	"time"
	"unicode/utf8"

	"github.com/edsrzf/mmap-go"
	"github.com/mibk/syd/core"
	"github.com/mibk/syd/pkg/undo"
	"github.com/mibk/syd/ui"
	"github.com/mibk/syd/ui/term"
	"github.com/mibk/syd/vi"
	"github.com/mibk/syd/view"
)

var (
	win      = &term.UI{}
	filename = ""
)

func main() {
	log.SetPrefix("syd: ")
	log.SetFlags(0)
	if err := win.Init(); err != nil {
		log.Fatalln("initializing ui:", err)
	}
	defer win.Close()

	var b []byte
	if len(os.Args) > 1 {
		filename = os.Args[1]
		m, err := readFile(filename)
		if err != nil {
			panic(err)
		}
		defer m.Unmap()
		b = []byte(m)
	}
	buf := undo.NewBuffer(b)

	e := &Editor{
		events:     make(chan ui.Event),
		vi:         vi.NewParser(),
		activeView: view.New(win, core.NewBuffer(buf)),
	}
	setMappings(e)
	go e.RouteEvents()
	e.Main()
}

func readFile(filename string) (mmap.MMap, error) {
	f, err := os.Open(filename)
	if err != nil {
		return nil, err
	}

	m, err := mmap.Map(f, 0, 0)
	if err != nil {
		return nil, err
	}
	return m, nil
}

const (
	ModeNormal = iota
	ModeInsert
)

type Editor struct {
	events     chan ui.Event
	vi         *vi.Parser
	shouldQuit bool

	activeView *view.View
	mode       int
}

func (e *Editor) RouteEvents() {
	for ev := range ui.Events {
		if keyPress, ok := ev.(ui.KeyPress); ok && e.mode == ModeNormal {
			e.vi.Decode(keyPress)
			continue
		}
		e.events <- ev
	}
}

func parseKeys(cmd string) []ui.KeyPress {
	events := make([]ui.KeyPress, len(cmd))
	for i, r := range []rune(cmd) {
		events[i] = ui.KeyPress{Key: r}
	}
	return events
}

func (e *Editor) AddOperator(cmd []ui.KeyPress, fn func(*view.View, int)) {
	e.vi.AddOperator(cmd, func(n int) { fn(e.activeView, n) }, false)
}

func (e *Editor) AddStringOperator(cmd string, fn func(*view.View, int)) {
	e.AddOperator(parseKeys(cmd), fn)
}

func (e *Editor) AddMotion(cmd []ui.KeyPress, fn func(*view.View, int)) {
	e.vi.AddMotion(cmd, func(n int) { fn(e.activeView, n) })
}

func (e *Editor) AddStringMotion(cmd string, fn func(*view.View, int)) {
	e.AddMotion(parseKeys(cmd), fn)
}

func (e *Editor) Main() {
	var (
		lastQ     int64 = -1
		timestamp time.Time
	)
	for !e.shouldQuit {
		e.activeView.Render()
		select {
		case action := <-e.vi.Actions:
			action()
		case ev := <-e.events:
			switch ev := ev.(type) {
			case ui.KeyPress:
				if ev.Key == ui.KeyEscape {
					e.mode = ModeNormal
					continue
				}
				handleKeyPress(e.activeView, ev)
			case ui.MouseBtnPress:
				switch ev.Button {
				case ui.MouseButton1:
					p := e.activeView.Frame().CharsUntilXY(ev.X, ev.Y)
					q := e.activeView.Origin() + int64(p)
					if time.Since(timestamp) < 300*time.Millisecond {
						e.activeView.Select(dblclick(e.activeView, q))
						e.activeView.Frame().SetWantCol(ui.ColQ0)
						lastQ = -1
						continue
					}
					e.activeView.Select(q, q)
					e.activeView.Frame().SetWantCol(ui.ColQ0)
					lastQ = q
					timestamp = time.Now()
				case ui.MouseButton2:
					// This is just ugly proof of concept.
					p := e.activeView.Frame().CharsUntilXY(ev.X, ev.Y)
					q := e.activeView.Origin() + int64(p)
					q0, q1 := dblclick(e.activeView, q)
					var cmd []rune
					for i := q0; i < q1; i++ {
						cmd = append(cmd, e.activeView.ReadRuneAt(i))
					}
					e.Execute(string(cmd))
				case ui.MouseWheelUp:
					scrollUp(e.activeView, 3)
				case ui.MouseWheelDown:
					scrollDown(e.activeView, 3)
				}
			case ui.MouseBtnRelease:
				lastQ = -1
			case ui.MouseMove:
				if lastQ < 0 {
					continue
				}
				p := e.activeView.Frame().CharsUntilXY(ev.X, ev.Y)
				q0, q1 := lastQ, e.activeView.Origin()+int64(p)
				if q1 < q0 {
					q0, q1 = q1, q0
				}
				e.activeView.Select(q0, q1)
			}
		}
	}
}

func (e *Editor) Execute(command string) {
	switch command {
	case "Exit":
		e.shouldQuit = true
	case "Put":
		if filename != "" {
			if err := saveFile(filename, e.activeView); err != nil {
				panic(err)
			}
		}
	case "Undo":
		e.activeView.Undo()
	case "Redo":
		e.activeView.Redo()
	default:
		v := e.activeView
		var selected []rune
		q0, q1 := v.Selected()
		for p := q0; p < q1; p++ {
			r := v.ReadRuneAt(p)
			selected = append(selected, r)
		}
		var buf bytes.Buffer
		rd := strings.NewReader(string(selected))
		cmd := exec.Command(command)
		cmd.Stdin = rd
		cmd.Stdout = &buf
		// TODO: Redirect stderr somewhere.
		if err := cmd.Run(); err != nil {
			panic(err)
		}
		s := buf.String()
		v.Insert(s)
		v.Select(q0, q0+int64(utf8.RuneCountInString(s)))
	}
}

func saveFile(filename string, v *view.View) error {
	// TODO: Read bytes directly from the undo.Buffer.
	f, err := os.Create(filename + "~")
	if err != nil {
		return err
	}

	var buf [64]byte
	var i int

	for p := int64(0); ; p++ {
		r := v.ReadRuneAt(p)
		if r == view.EOF || len(buf[i:]) < utf8.UTFMax {
			if _, err := f.Write(buf[:i]); err != nil {
				return err
			}
			i = 0
		}
		if r == view.EOF {
			break
		}
		i += utf8.EncodeRune(buf[i:], r)
	}
	f.Close()

	return os.Rename(filename+"~", filename)
}
<|endoftext|>


<commit_before>package main

import (
	"strings"
	"sync/atomic"
	"unsafe"

	r "github.com/dancannon/gorethink"
	"github.com/jaracil/ei"
)

func (nc *NexusConn) handleSysReq(req *JsonRpcReq) {
	switch req.Method {
	case "sys.ping":
		req.Result("pong")
	case "sys.watchdog":
		wdt := ei.N(req.Params).Int64Z()
		if wdt < 10 {
			wdt = 10
		}
		atomic.StoreInt64(&nc.wdog, wdt)
		req.Result(ei.M{"ok": true, "watchdog": wdt})
	case "sys.login":
		user, err := ei.N(req.Params).M("user").String()
		if err != nil {
			req.Error(ErrInvalidParams, "user", nil)
			return
		}
		pass, err := ei.N(req.Params).M("pass").String()
		if err != nil {
			req.Error(ErrInvalidParams, "pass", nil)
			return
		}
		var suser string
		split := strings.Split(user, ">")
		switch len(split) {
		case 1:
		case 2:
			if len(split[0]) > 0 && len(split[1]) > 0 {
				user = split[0]
				suser = split[1]
			} else {
				req.Error(ErrInvalidParams, "", nil)
				return
			}
		default:
			req.Error(ErrInvalidParams, "", nil)
			return
		}
		ud := &UserData{}
		cur, err := r.Table("users").Get(strings.ToLower(user)).Run(db)
		if err != nil {
			req.Error(ErrInternal, "", nil)
			return
		}
		defer cur.Close()
		err = cur.One(ud)
		if err != nil {
			if err == r.ErrEmptyResult {
				req.Error(ErrPermissionDenied, "", nil)
				return
			}
			req.Error(ErrInternal, "", nil)
			return
		}
		dk, err := HashPass(pass, ud.Salt)
		if err != nil {
			req.Error(ErrInternal, "", nil)
			return
		}
		if ud.Pass != dk {
			req.Error(ErrPermissionDenied, "", nil)
			return
		}
		atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&nc.user)), unsafe.Pointer(ud))

		if suser != "" {
			tags := nc.getTags(suser)
			if !(ei.N(tags).M("@admin").BoolZ()) {
				req.Error(ErrPermissionDenied, "", nil)
				return
			}
			sud := &UserData{}
			scur, err := r.Table("users").Get(strings.ToLower(suser)).Run(db)
			if err != nil {
				req.Error(ErrInternal, "", nil)
				return
			}
			defer scur.Close()
			err = scur.One(sud)
			if err != nil {
				if err == r.ErrEmptyResult {
					req.Error(ErrPermissionDenied, "", nil)
					return
				}
				req.Error(ErrInternal, "", nil)
				return
			}
			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&nc.user)), unsafe.Pointer(sud))
		}
		req.Result(ei.M{"ok": true, "user": nc.user.User})
	case "sys.nodes":
		tags := nc.getTags("")
		if !(ei.N(tags).M("@admin").BoolZ()) {
			req.Error(ErrPermissionDenied, "", nil)
			return
		}

		cur, err := r.Table("nodes").Pluck("id", "clients", "load").Run(db)
		if err != nil {
			req.Error(ErrInternal, "", nil)
			return
		}
		var all []interface{}
		cur.All(&all)
		req.Result(all)
	case "sys.sessions":
		prefix := ei.N(req.Params).M("prefix").StringZ()

		tags := nc.getTags(prefix)
		if !(ei.N(tags).M("@session.list").BoolZ() || ei.N(tags).M("@admin").BoolZ()) {
			req.Error(ErrPermissionDenied, "", nil)
			return
		}
		cur, err := r.Table("sessions").
			Between(prefix, prefix+"\uffff", r.BetweenOpts{Index: "users"}).
			Group("user").
			Count().
			Ungroup().
			Map(func(row r.Term) interface{} {
				return ei.M{"user": row.Field("group"), "sessions": row.Field("reduction")}
			}).Run(db)
		if err != nil {
			req.Error(ErrInternal, err.Error(), nil)
			return
		}
		var all []interface{}
		cur.All(&all)
		req.Result(all)

	default:
		req.Error(ErrMethodNotFound, "", nil)
	}
}
<commit_msg>Append more session info<commit_after>package main

import (
	"strings"
	"sync/atomic"
	"unsafe"

	r "github.com/dancannon/gorethink"
	"github.com/jaracil/ei"
)

func (nc *NexusConn) handleSysReq(req *JsonRpcReq) {
	switch req.Method {
	case "sys.ping":
		req.Result("pong")
	case "sys.watchdog":
		wdt := ei.N(req.Params).Int64Z()
		if wdt < 10 {
			wdt = 10
		}
		atomic.StoreInt64(&nc.wdog, wdt)
		req.Result(ei.M{"ok": true, "watchdog": wdt})
	case "sys.login":
		user, err := ei.N(req.Params).M("user").String()
		if err != nil {
			req.Error(ErrInvalidParams, "user", nil)
			return
		}
		pass, err := ei.N(req.Params).M("pass").String()
		if err != nil {
			req.Error(ErrInvalidParams, "pass", nil)
			return
		}
		var suser string
		split := strings.Split(user, ">")
		switch len(split) {
		case 1:
		case 2:
			if len(split[0]) > 0 && len(split[1]) > 0 {
				user = split[0]
				suser = split[1]
			} else {
				req.Error(ErrInvalidParams, "", nil)
				return
			}
		default:
			req.Error(ErrInvalidParams, "", nil)
			return
		}
		ud := &UserData{}
		cur, err := r.Table("users").Get(strings.ToLower(user)).Run(db)
		if err != nil {
			req.Error(ErrInternal, "", nil)
			return
		}
		defer cur.Close()
		err = cur.One(ud)
		if err != nil {
			if err == r.ErrEmptyResult {
				req.Error(ErrPermissionDenied, "", nil)
				return
			}
			req.Error(ErrInternal, "", nil)
			return
		}
		dk, err := HashPass(pass, ud.Salt)
		if err != nil {
			req.Error(ErrInternal, "", nil)
			return
		}
		if ud.Pass != dk {
			req.Error(ErrPermissionDenied, "", nil)
			return
		}
		atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&nc.user)), unsafe.Pointer(ud))

		if suser != "" {
			tags := nc.getTags(suser)
			if !(ei.N(tags).M("@admin").BoolZ()) {
				req.Error(ErrPermissionDenied, "", nil)
				return
			}
			sud := &UserData{}
			scur, err := r.Table("users").Get(strings.ToLower(suser)).Run(db)
			if err != nil {
				req.Error(ErrInternal, "", nil)
				return
			}
			defer scur.Close()
			err = scur.One(sud)
			if err != nil {
				if err == r.ErrEmptyResult {
					req.Error(ErrPermissionDenied, "", nil)
					return
				}
				req.Error(ErrInternal, "", nil)
				return
			}
			atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&nc.user)), unsafe.Pointer(sud))
		}
		req.Result(ei.M{"ok": true, "user": nc.user.User})
	case "sys.nodes":
		tags := nc.getTags("")
		if !(ei.N(tags).M("@admin").BoolZ()) {
			req.Error(ErrPermissionDenied, "", nil)
			return
		}

		cur, err := r.Table("nodes").Pluck("id", "clients", "load").Run(db)
		if err != nil {
			req.Error(ErrInternal, "", nil)
			return
		}
		var all []interface{}
		cur.All(&all)
		req.Result(all)
	case "sys.sessions":
		prefix := ei.N(req.Params).M("prefix").StringZ()

		tags := nc.getTags(prefix)
		if !(ei.N(tags).M("@session.list").BoolZ() || ei.N(tags).M("@admin").BoolZ()) {
			req.Error(ErrPermissionDenied, "", nil)
			return
		}
		cur, err := r.Table("sessions").
			Between(prefix, prefix+"\uffff", r.BetweenOpts{Index: "users"}).
			Group("user").
			Pluck("id", "nodeId", "remoteAddress", "creationTime").
			Ungroup().
			Map(func(row r.Term) interface{} {
				return ei.M{"user": row.Field("group"), "sessions": row.Field("reduction"), "n": row.Field("reduction").Count()}
			}).Run(db)
		if err != nil {
			req.Error(ErrInternal, err.Error(), nil)
			return
		}
		var all []interface{}
		cur.All(&all)
		req.Result(all)

	default:
		req.Error(ErrMethodNotFound, "", nil)
	}
}
<|endoftext|>


<commit_before>package main

// suidhelper should be installed setuid root. Having done this, it will
// run the provided command as the specified user identity.
// suidhelper deliberately attempts to be as simple as possible to
// simplify reviewing it for security concerns.

import (
	"flag"
	"os"

	"veyron.io/veyron/veyron/services/mgmt/suidhelper/impl"
)

func main() {
	flag.Parse()
	if err := impl.Run(os.Environ()); err != nil {
		flag.Usage()
	}
}
<commit_msg>veyron/services/mgmt/suidhelper: print the error that comes back from Run<commit_after>package main

// suidhelper should be installed setuid root. Having done this, it will
// run the provided command as the specified user identity.
// suidhelper deliberately attempts to be as simple as possible to
// simplify reviewing it for security concerns.

import (
	"flag"
	"fmt"
	"os"

	"veyron.io/veyron/veyron/services/mgmt/suidhelper/impl"
)

func main() {
	flag.Parse()
	if err := impl.Run(os.Environ()); err != nil {
		fmt.Fprintf(os.Stderr, "Failed with:", err)
		// TODO(rjkroege): We should really only print the usage message
		// if the error is related to interpreting flags.
		flag.Usage()
	}
}
<|endoftext|>