<commit_before>package config

import (
	"github.com/bosssauce/ponzu/content"
	"github.com/bosssauce/ponzu/management/editor"
)

//Config represents the confirgurable options of the system
type Config struct {
	content.Item
	editor editor.Editor

	Name            string   `json:"name"`
	Domain          string   `json:"domain"`
	AdminEmail      string   `json:"admin_email"`
	ClientSecret    string   `json:"client_secret"`
	Etag            string   `json:"etag"`
	CacheInvalidate []string `json:"cache"`
}

// ContentName partially implements editor.Editable
func (c *Config) ContentName() string { return c.Name }

// Editor partially implements editor.Editable
func (c *Config) Editor() *editor.Editor { return &c.editor }

// MarshalEditor writes a buffer of html to edit a Post and partially implements editor.Editable
func (c *Config) MarshalEditor() ([]byte, error) {
	view, err := editor.Form(c,
		editor.Field{
			View: editor.Input("Name", c, map[string]string{
				"label":       "Site Name",
				"placeholder": "Add a name to this site (internal use only)",
			}),
		},
		editor.Field{
			View: editor.Input("Domain", c, map[string]string{
				"label":       "Domain Name (required for SSL certificate)",
				"placeholder": "e.g. www.example.com or example.com",
			}),
		},
		editor.Field{
			View: editor.Input("AdminEmail", c, map[string]string{
				"label": "Adminstrator Email (will be notified of internal system information)",
			}),
		},
		editor.Field{
			View: editor.Input("ClientSecret", c, map[string]string{
				"label":    "Client Secret (used to validate requests, DO NOT SHARE)",
				"disabled": "true",
			}),
		},
		editor.Field{
			View: editor.Input("ClientSecret", c, map[string]string{
				"type": "hidden",
			}),
		},
		editor.Field{
			View: editor.Input("Etag", c, map[string]string{
				"label":    "Etag Header (used for static asset cache)",
				"disabled": "true",
			}),
		},
		editor.Field{
			View: editor.Input("Etag", c, map[string]string{
				"type": "hidden",
			}),
		},
		editor.Field{
			View: editor.Checkbox("CacheInvalidate", c, map[string]string{
				"label": "Invalidate cache on save",
			}, map[string]string{
				"Invalidate": "cache",
			}),
		},
	)
	if err != nil {
		return nil, err
	}

	open := []byte(`<div class="card"><form action="/admin/configure" method="post">`)
	close := []byte(`</form></div>`)
	script := []byte(`
	<script>
		$(function() {
			// hide default fields & labels unecessary for the config
			var fields = $('.default-fields');
			fields.css('position', 'relative');
			fields.find('input:not([type=submit])').remove();
			fields.find('label').remove();
			fields.find('button').css({
				position: 'absolute',
				top: '-10px',
				right: '0px'
			});

			var contentOnly = $('.content-only.__ponzu');
			contentOnly.hide();
			contentOnly.find('input, textarea, select').attr('name', '');

			// adjust layout of td so save button is in same location as usual
			fields.find('td').css('float', 'right');

			// stop some fixed config settings from being modified
			fields.find('input[name=client_secret]').attr('name', '');
		});
	</script>
	`)

	view = append(open, view...)
	view = append(view, close...)
	view = append(view, script...)

	return view, nil
}
<commit_msg>fixing k/v for Checkbox input on cache invalidation in config<commit_after>package config

import (
	"github.com/bosssauce/ponzu/content"
	"github.com/bosssauce/ponzu/management/editor"
)

//Config represents the confirgurable options of the system
type Config struct {
	content.Item
	editor editor.Editor

	Name            string   `json:"name"`
	Domain          string   `json:"domain"`
	AdminEmail      string   `json:"admin_email"`
	ClientSecret    string   `json:"client_secret"`
	Etag            string   `json:"etag"`
	CacheInvalidate []string `json:"cache"`
}

// ContentName partially implements editor.Editable
func (c *Config) ContentName() string { return c.Name }

// Editor partially implements editor.Editable
func (c *Config) Editor() *editor.Editor { return &c.editor }

// MarshalEditor writes a buffer of html to edit a Post and partially implements editor.Editable
func (c *Config) MarshalEditor() ([]byte, error) {
	view, err := editor.Form(c,
		editor.Field{
			View: editor.Input("Name", c, map[string]string{
				"label":       "Site Name",
				"placeholder": "Add a name to this site (internal use only)",
			}),
		},
		editor.Field{
			View: editor.Input("Domain", c, map[string]string{
				"label":       "Domain Name (required for SSL certificate)",
				"placeholder": "e.g. www.example.com or example.com",
			}),
		},
		editor.Field{
			View: editor.Input("AdminEmail", c, map[string]string{
				"label": "Adminstrator Email (will be notified of internal system information)",
			}),
		},
		editor.Field{
			View: editor.Input("ClientSecret", c, map[string]string{
				"label":    "Client Secret (used to validate requests, DO NOT SHARE)",
				"disabled": "true",
			}),
		},
		editor.Field{
			View: editor.Input("ClientSecret", c, map[string]string{
				"type": "hidden",
			}),
		},
		editor.Field{
			View: editor.Input("Etag", c, map[string]string{
				"label":    "Etag Header (used for static asset cache)",
				"disabled": "true",
			}),
		},
		editor.Field{
			View: editor.Input("Etag", c, map[string]string{
				"type": "hidden",
			}),
		},
		editor.Field{
			View: editor.Checkbox("CacheInvalidate", c, map[string]string{
				"label": "Invalidate cache on save",
			}, map[string]string{
				"invalidate": "Invalidate Cache",
			}),
		},
	)
	if err != nil {
		return nil, err
	}

	open := []byte(`<div class="card"><form action="/admin/configure" method="post">`)
	close := []byte(`</form></div>`)
	script := []byte(`
	<script>
		$(function() {
			// hide default fields & labels unecessary for the config
			var fields = $('.default-fields');
			fields.css('position', 'relative');
			fields.find('input:not([type=submit])').remove();
			fields.find('label').remove();
			fields.find('button').css({
				position: 'absolute',
				top: '-10px',
				right: '0px'
			});

			var contentOnly = $('.content-only.__ponzu');
			contentOnly.hide();
			contentOnly.find('input, textarea, select').attr('name', '');

			// adjust layout of td so save button is in same location as usual
			fields.find('td').css('float', 'right');

			// stop some fixed config settings from being modified
			fields.find('input[name=client_secret]').attr('name', '');
		});
	</script>
	`)

	view = append(open, view...)
	view = append(view, close...)
	view = append(view, script...)

	return view, nil
}
<|endoftext|>


<commit_before>package appui

import (
	"fmt"
	"strconv"
	"time"

	units "github.com/docker/go-units"
	termui "github.com/gizak/termui"
	"github.com/moncho/dry/docker"
	"github.com/moncho/dry/ui"
	drytermui "github.com/moncho/dry/ui/termui"
)

var inactiveRowColor = termui.Attribute(ui.Color244)

//ContainerStatsRow is a Grid row showing runtime information about a container
type ContainerStatsRow struct {
	container *docker.Container
	Name      *drytermui.ParColumn
	ID        *drytermui.ParColumn
	CPU       *drytermui.GaugeColumn
	Memory    *drytermui.GaugeColumn
	Net       *drytermui.ParColumn
	Block     *drytermui.ParColumn
	Pids      *drytermui.ParColumn
	Uptime    *drytermui.ParColumn

	X, Y    int
	Width   int
	Height  int
	columns []termui.GridBufferer
}

//NewContainerStatsRow creats a new ContainerStatsRow widget
func NewContainerStatsRow(container *docker.Container) *ContainerStatsRow {
	cf := docker.NewContainerFormatter(container, true)
	row := &ContainerStatsRow{
		container: container,
		Name:      drytermui.NewThemedParColumn(DryTheme, cf.Names()),
		ID:        drytermui.NewThemedParColumn(DryTheme, cf.ID()),
		CPU:       drytermui.NewThemedGaugeColumn(DryTheme),
		Memory:    drytermui.NewThemedGaugeColumn(DryTheme),
		Net:       drytermui.NewThemedParColumn(DryTheme, "-"),
		Block:     drytermui.NewThemedParColumn(DryTheme, "-"),
		Pids:      drytermui.NewThemedParColumn(DryTheme, "-"),
		Uptime:    drytermui.NewThemedParColumn(DryTheme, container.Status),
		Height:    1,
	}
	//Columns are rendered following the slice order
	row.columns = []termui.GridBufferer{
		row.ID,
		row.Name,
		row.CPU,
		row.Memory,
		row.Net,
		row.Block,
		row.Pids,
		row.Uptime,
	}
	if !docker.IsContainerRunning(container) {
		row.markAsNotRunning()
	}
	return row

}

//NewSelfUpdatedContainerStatsRow creates a ContainerStatsRow that updates
//itself on stats message sent on the given channel
func NewSelfUpdatedContainerStatsRow(s *docker.StatsChannel) *ContainerStatsRow {
	c := s.Container
	row := NewContainerStatsRow(c)

	if docker.IsContainerRunning(c) {
		go func() {
			for stat := range s.Stats {
				row.Update(c, stat)
			}
			row.markAsNotRunning()
		}()
	}
	return row
}

//Highlighted marks this rows as being highlighted
func (row *ContainerStatsRow) Highlighted() {
	row.ID.TextBgColor = termui.Attribute(DryTheme.CurrentMatch)
}

//NotHighlighted marks this rows as being not highlighted
func (row *ContainerStatsRow) NotHighlighted() {
	row.ID.TextBgColor = termui.Attribute(DryTheme.Bg)
}

//Reset resets row content
func (row *ContainerStatsRow) Reset() {
	row.CPU.Reset()
	row.Memory.Reset()
	row.Net.Reset()
	row.Pids.Reset()
	row.Block.Reset()
	row.Uptime.Reset()
}

//GetHeight returns this ContainerStatsRow heigth
func (row *ContainerStatsRow) GetHeight() int {
	return row.Height
}

//SetX sets the x position of this ContainerStatsRow
func (row *ContainerStatsRow) SetX(x int) {
	row.X = x
}

//SetY sets the y position of this ContainerStatsRow
func (row *ContainerStatsRow) SetY(y int) {
	if y == row.Y {
		return
	}
	for _, col := range row.columns {
		col.SetY(y)
	}
	row.Y = y
}

//SetWidth sets the width of this ContainerStatsRow
func (row *ContainerStatsRow) SetWidth(width int) {
	if width == row.Width {
		return
	}
	row.Width = width
	x := row.X
	rw := calcItemWidth(width, len(row.columns)-1)
	for _, col := range row.columns {
		col.SetX(x)
		if col != row.ID {
			col.SetWidth(rw)
			x += rw + columnSpacing
		} else {
			col.SetWidth(containerColumnWidth)
			x += containerColumnWidth + columnSpacing
		}
	}
}

//Buffer returns this ContainerStatsRow data as a termui.Buffer
func (row *ContainerStatsRow) Buffer() termui.Buffer {
	buf := termui.NewBuffer()

	buf.Merge(row.ID.Buffer())
	buf.Merge(row.Name.Buffer())
	buf.Merge(row.CPU.Buffer())
	buf.Merge(row.Memory.Buffer())
	buf.Merge(row.Net.Buffer())
	buf.Merge(row.Block.Buffer())
	buf.Merge(row.Pids.Buffer())
	buf.Merge(row.Uptime.Buffer())

	return buf
}

//Update updates the content of this row with the given stats
func (row *ContainerStatsRow) Update(container *docker.Container, stat *docker.Stats) {
	row.setNet(stat.NetworkRx, stat.NetworkTx)
	row.setCPU(stat.CPUPercentage)
	row.setMem(stat.Memory, stat.MemoryLimit, stat.MemoryPercentage)
	row.setBlockIO(stat.BlockRead, stat.BlockWrite)
	row.setPids(stat.PidsCurrent)
	row.setUptime(container.ContainerJSON.State.StartedAt)
}

func (row *ContainerStatsRow) setNet(rx float64, tx float64) {
	row.Net.Text = fmt.Sprintf("%s / %s", units.BytesSize(rx), units.BytesSize(tx))
}

func (row *ContainerStatsRow) setBlockIO(read float64, write float64) {
	row.Block.Text = fmt.Sprintf("%s / %s", units.BytesSize(read), units.BytesSize(write))
}
func (row *ContainerStatsRow) setPids(pids uint64) {
	row.Pids.Text = strconv.Itoa(int(pids))
}

func (row *ContainerStatsRow) setCPU(val float64) {
	row.CPU.Label = fmt.Sprintf("%.2f%%", val)
	cpu := int(val)
	if cpu < 5 {
		cpu = 5
	} else if cpu > 100 {
		cpu = 100
	}
	row.CPU.Percent = cpu
	row.CPU.BarColor = percentileToColor(cpu)
}

func (row *ContainerStatsRow) setMem(val float64, limit float64, percent float64) {
	row.Memory.Label = fmt.Sprintf("%s / %s", units.BytesSize(val), units.BytesSize(limit))
	mem := int(percent)
	if mem < 5 {
		mem = 5
	} else if mem > 100 {
		mem = 100
	}
	row.Memory.Percent = mem
	row.Memory.BarColor = percentileToColor(mem)
}

func (row *ContainerStatsRow) setUptime(startedAt string) {
	if startTime, err := time.Parse(time.RFC3339, startedAt); err == nil {
		row.Uptime.Text = units.HumanDuration(time.Now().UTC().Sub(startTime))
	} else {
		row.Uptime.Text = ""
	}
}

//markAsNotRunning
func (row *ContainerStatsRow) markAsNotRunning() {

	row.Name.TextFgColor = inactiveRowColor
	row.ID.TextFgColor = inactiveRowColor
	row.CPU.PercentColor = inactiveRowColor
	row.CPU.Percent = 0
	row.CPU.Label = "-"
	row.Memory.PercentColor = inactiveRowColor
	row.Memory.Percent = 0
	row.Memory.Label = "-"
	row.Net.TextFgColor = inactiveRowColor
	row.Net.Text = "-"
	row.Block.TextFgColor = inactiveRowColor
	row.Block.Text = "-"
	row.Pids.Text = "0"
	row.Pids.TextFgColor = inactiveRowColor
	row.Uptime.Text = "-"
	row.Pids.TextFgColor = inactiveRowColor

}

func percentileToColor(n int) termui.Attribute {
	c := ui.Color23
	if n > 90 {
		c = ui.Color161
	} else if n > 60 {
		c = ui.Color131
	}
	return termui.Attribute(c)
}
<commit_msg>Minor<commit_after>package appui

import (
	"fmt"
	"strconv"
	"time"

	units "github.com/docker/go-units"
	termui "github.com/gizak/termui"
	"github.com/moncho/dry/docker"
	"github.com/moncho/dry/ui"
	drytermui "github.com/moncho/dry/ui/termui"
)

var inactiveRowColor = termui.Attribute(ui.Color244)

//ContainerStatsRow is a Grid row showing runtime information about a container
type ContainerStatsRow struct {
	container *docker.Container
	Name      *drytermui.ParColumn
	ID        *drytermui.ParColumn
	CPU       *drytermui.GaugeColumn
	Memory    *drytermui.GaugeColumn
	Net       *drytermui.ParColumn
	Block     *drytermui.ParColumn
	Pids      *drytermui.ParColumn
	Uptime    *drytermui.ParColumn

	X, Y    int
	Width   int
	Height  int
	columns []termui.GridBufferer
}

//NewContainerStatsRow creats a new ContainerStatsRow widget
func NewContainerStatsRow(container *docker.Container) *ContainerStatsRow {
	cf := docker.NewContainerFormatter(container, true)
	row := &ContainerStatsRow{
		container: container,
		Name:      drytermui.NewThemedParColumn(DryTheme, cf.Names()),
		ID:        drytermui.NewThemedParColumn(DryTheme, cf.ID()),
		CPU:       drytermui.NewThemedGaugeColumn(DryTheme),
		Memory:    drytermui.NewThemedGaugeColumn(DryTheme),
		Net:       drytermui.NewThemedParColumn(DryTheme, "-"),
		Block:     drytermui.NewThemedParColumn(DryTheme, "-"),
		Pids:      drytermui.NewThemedParColumn(DryTheme, "-"),
		Uptime:    drytermui.NewThemedParColumn(DryTheme, container.Status),
		Height:    1,
	}
	//Columns are rendered following the slice order
	row.columns = []termui.GridBufferer{
		row.ID,
		row.Name,
		row.CPU,
		row.Memory,
		row.Net,
		row.Block,
		row.Pids,
		row.Uptime,
	}
	if !docker.IsContainerRunning(container) {
		row.markAsNotRunning()
	} else {
		row.NotHighlighted()
	}
	return row

}

//NewSelfUpdatedContainerStatsRow creates a ContainerStatsRow that updates
//itself on stats message sent on the given channel
func NewSelfUpdatedContainerStatsRow(s *docker.StatsChannel) *ContainerStatsRow {
	c := s.Container
	row := NewContainerStatsRow(c)

	if docker.IsContainerRunning(c) {
		go func() {
			for stat := range s.Stats {
				row.Update(c, stat)
			}
			row.markAsNotRunning()
		}()
	}
	return row
}

//Highlighted marks this rows as being highlighted
func (row *ContainerStatsRow) Highlighted() {
	row.changeTextColor(termui.Attribute(DryTheme.SelectedListItem))
}

//NotHighlighted marks this rows as being not highlighted
func (row *ContainerStatsRow) NotHighlighted() {
	row.changeTextColor(termui.Attribute(DryTheme.ListItem))
}

func (row *ContainerStatsRow) changeTextColor(color termui.Attribute) {
	row.Name.TextFgColor = color
	row.ID.TextFgColor = color
	row.CPU.PercentColor = color
	row.Memory.PercentColor = color
	row.Net.TextFgColor = color
	row.Block.TextFgColor = color
	row.Pids.TextFgColor = color
	row.Uptime.TextFgColor = color
}

//Reset resets row content
func (row *ContainerStatsRow) Reset() {
	row.CPU.Reset()
	row.Memory.Reset()
	row.Net.Reset()
	row.Pids.Reset()
	row.Block.Reset()
	row.Uptime.Reset()
}

//GetHeight returns this ContainerStatsRow heigth
func (row *ContainerStatsRow) GetHeight() int {
	return row.Height
}

//SetX sets the x position of this ContainerStatsRow
func (row *ContainerStatsRow) SetX(x int) {
	row.X = x
}

//SetY sets the y position of this ContainerStatsRow
func (row *ContainerStatsRow) SetY(y int) {
	if y == row.Y {
		return
	}
	for _, col := range row.columns {
		col.SetY(y)
	}
	row.Y = y
}

//SetWidth sets the width of this ContainerStatsRow
func (row *ContainerStatsRow) SetWidth(width int) {
	if width == row.Width {
		return
	}
	row.Width = width
	x := row.X
	rw := calcItemWidth(width, len(row.columns)-1)
	for _, col := range row.columns {
		col.SetX(x)
		if col != row.ID {
			col.SetWidth(rw)
			x += rw + defaultColumnSpacing
		} else {
			col.SetWidth(containerColumnWidth)
			x += containerColumnWidth + defaultColumnSpacing
		}
	}
}

//Buffer returns this ContainerStatsRow data as a termui.Buffer
func (row *ContainerStatsRow) Buffer() termui.Buffer {
	buf := termui.NewBuffer()

	buf.Merge(row.ID.Buffer())
	buf.Merge(row.Name.Buffer())
	buf.Merge(row.CPU.Buffer())
	buf.Merge(row.Memory.Buffer())
	buf.Merge(row.Net.Buffer())
	buf.Merge(row.Block.Buffer())
	buf.Merge(row.Pids.Buffer())
	buf.Merge(row.Uptime.Buffer())

	return buf
}

//Update updates the content of this row with the given stats
func (row *ContainerStatsRow) Update(container *docker.Container, stat *docker.Stats) {
	row.setNet(stat.NetworkRx, stat.NetworkTx)
	row.setCPU(stat.CPUPercentage)
	row.setMem(stat.Memory, stat.MemoryLimit, stat.MemoryPercentage)
	row.setBlockIO(stat.BlockRead, stat.BlockWrite)
	row.setPids(stat.PidsCurrent)
	row.setUptime(container.ContainerJSON.State.StartedAt)
}

func (row *ContainerStatsRow) setNet(rx float64, tx float64) {
	row.Net.Text = fmt.Sprintf("%s / %s", units.BytesSize(rx), units.BytesSize(tx))
}

func (row *ContainerStatsRow) setBlockIO(read float64, write float64) {
	row.Block.Text = fmt.Sprintf("%s / %s", units.BytesSize(read), units.BytesSize(write))
}
func (row *ContainerStatsRow) setPids(pids uint64) {
	row.Pids.Text = strconv.Itoa(int(pids))
}

func (row *ContainerStatsRow) setCPU(val float64) {
	row.CPU.Label = fmt.Sprintf("%.2f%%", val)
	cpu := int(val)
	if cpu < 5 {
		cpu = 5
	} else if cpu > 100 {
		cpu = 100
	}
	row.CPU.Percent = cpu
	row.CPU.BarColor = percentileToColor(cpu)
}

func (row *ContainerStatsRow) setMem(val float64, limit float64, percent float64) {
	row.Memory.Label = fmt.Sprintf("%s / %s", units.BytesSize(val), units.BytesSize(limit))
	mem := int(percent)
	if mem < 5 {
		mem = 5
	} else if mem > 100 {
		mem = 100
	}
	row.Memory.Percent = mem
	row.Memory.BarColor = percentileToColor(mem)
}

func (row *ContainerStatsRow) setUptime(startedAt string) {
	if startTime, err := time.Parse(time.RFC3339, startedAt); err == nil {
		row.Uptime.Text = units.HumanDuration(time.Now().UTC().Sub(startTime))
	} else {
		row.Uptime.Text = ""
	}
}

//markAsNotRunning
func (row *ContainerStatsRow) markAsNotRunning() {

	row.Name.TextFgColor = inactiveRowColor
	row.ID.TextFgColor = inactiveRowColor
	row.CPU.PercentColor = inactiveRowColor
	row.CPU.Percent = 0
	row.CPU.Label = "-"
	row.Memory.PercentColor = inactiveRowColor
	row.Memory.Percent = 0
	row.Memory.Label = "-"
	row.Net.TextFgColor = inactiveRowColor
	row.Net.Text = "-"
	row.Block.TextFgColor = inactiveRowColor
	row.Block.Text = "-"
	row.Pids.Text = "0"
	row.Pids.TextFgColor = inactiveRowColor
	row.Uptime.Text = "-"
	row.Pids.TextFgColor = inactiveRowColor

}

func percentileToColor(n int) termui.Attribute {
	c := ui.Color23
	if n > 90 {
		c = ui.Color161
	} else if n > 60 {
		c = ui.Color131
	}
	return termui.Attribute(c)
}
<|endoftext|>


<commit_before><commit_msg>Added connect.go<commit_after><|endoftext|>


<commit_before>package modelhelper

import (
	"koding/db/models"
	"koding/db/mongodb"
	"labix.org/v2/mgo"
)

func GetAllRelationships(selector Selector) ([]models.Relationship, error) {
	relationships := make([]models.Relationship, 0)

	query := func(c *mgo.Collection) error {
		return c.Find(selector).Sort("timestamp").All(&relationships)
	}

	err := mongodb.Run("relationships", query)

	return relationships, err
}

func GetSomeRelationships(selector Selector, limit int) ([]models.Relationship, error) {
	relationships := make([]models.Relationship, 0)

	query := func(c *mgo.Collection) error {
		return c.Find(selector).Limit(limit).All(&relationships)
	}

	err := mongodb.Run("relationships", query)

	return relationships, err
}

func GetRelationship(selector Selector) (models.Relationship, error) {
	relationship := models.Relationship{}

	query := func(c *mgo.Collection) error {
		return c.Find(selector).One(&relationship)
	}

	err := mongodb.Run("relationships", query)

	return relationship, err

}

func DeleteRelationship(selector Selector) error {
	query := func(c *mgo.Collection) error {
		return c.Remove(selector)
	}

	return mongodb.Run("relationships", query)
}

func AddRelationship(r *models.Relationship) error {
	query := func(c *mgo.Collection) error {
		return c.Insert(r)
	}

	return mongodb.Run("relationships", query)
}
<commit_msg>Moderation: DeleteRelationship calls c.RemoveAll insted of .Remove<commit_after>package modelhelper

import (
	"koding/db/models"
	"koding/db/mongodb"
	"labix.org/v2/mgo"
)

func GetAllRelationships(selector Selector) ([]models.Relationship, error) {
	relationships := make([]models.Relationship, 0)

	query := func(c *mgo.Collection) error {
		return c.Find(selector).Sort("timestamp").All(&relationships)
	}

	err := mongodb.Run("relationships", query)

	return relationships, err
}

func GetSomeRelationships(selector Selector, limit int) ([]models.Relationship, error) {
	relationships := make([]models.Relationship, 0)

	query := func(c *mgo.Collection) error {
		return c.Find(selector).Limit(limit).All(&relationships)
	}

	err := mongodb.Run("relationships", query)

	return relationships, err
}

func GetRelationship(selector Selector) (models.Relationship, error) {
	relationship := models.Relationship{}

	query := func(c *mgo.Collection) error {
		return c.Find(selector).One(&relationship)
	}

	err := mongodb.Run("relationships", query)

	return relationship, err
}

func DeleteRelationship(selector Selector) error {
	query := func(c *mgo.Collection) error {
		_, err := c.RemoveAll(selector)
		return err
	}

	return mongodb.Run("relationships", query)
}

func AddRelationship(r *models.Relationship) error {
	query := insertQuery(r)

	return mongodb.Run("relationships", query)
}
<|endoftext|>


<commit_before>package exporter

import (
	"socialapi/config"
	"socialapi/workers/countly/api"
	"socialapi/workers/countly/client"

	mgo "gopkg.in/mgo.v2"

	"github.com/koding/eventexporter"
	"github.com/koding/logging"
	"github.com/koding/runner"
)

// CountlyExporter exports events to countly..
type CountlyExporter struct {
	client      *client.Client
	log         logging.Logger
	globalOwner string
	groupCache  *groupCache
	disabled    bool // if countly integration is disabled.
	fixApps     bool // if we should create non existing apps.
}

// NewCountlyExporter creates exporter for countly.
func NewCountlyExporter(cfg *config.Config) *CountlyExporter {
	logger := runner.MustGetLogger().New("countly-exporter")
	return &CountlyExporter{
		client: client.New(
			cfg.Countly.APIKey,
			client.SetBaseURL(cfg.Countly.Host),
			client.SetLogger(logger),
		),
		log:         logger,
		globalOwner: cfg.Countly.AppOwner,
		groupCache:  newGroupCache(),
		disabled:    cfg.Countly.Disabled,
		fixApps:     cfg.Countly.FixApps,
	}
}

// Send publishes the events to countly.
func (c *CountlyExporter) Send(event *eventexporter.Event) error {
	c.log.Debug("got event %+v", event)
	if c.disabled {
		return nil
	}

	slug := getGroupName(event)
	if slug == "" {
		c.log.Debug("skipping event, does not have group %+v", event)
		return nil
	}

	group, err := c.groupCache.BySlug(slug)
	if err != nil {
		if err == mgo.ErrNotFound {
			return nil
		}
		return err
	}

	if !group.HasCountly() {
		if !c.fixApps {
			return nil
		}

		res, err := api.NewCountlyAPI(config.MustGet()).CreateCountlyApp(slug)
		if err != nil {
			return err
		}
		// we persist in API call but here we have the old group, so update it
		group.Countly.AppKey = res.AppKey
		group.Countly.AppID = res.AppID
		group.Countly.APIKey = res.APIKey
	}

	events := []client.Event{client.Event{
		Key:          event.Name,
		Count:        1,
		Segmentation: event.Properties,
	}}
	return c.client.WriteEvent(group.Countly.AppKey, group.Id.Hex(), events)
}

// Close closes the exporter.
func (c *CountlyExporter) Close() error {
	return nil
}

func getGroupName(event *eventexporter.Event) string {
	if len(event.Properties) == 0 {
		return ""
	}

	if name, ok := event.Properties["groupName"]; ok {
		return name.(string)
	}

	if name, ok := event.Properties["group"]; ok {
		return name.(string)
	}

	return ""
}
<commit_msg>socialapi/countly: simplfy definition<commit_after>package exporter

import (
	"socialapi/config"
	"socialapi/workers/countly/api"
	"socialapi/workers/countly/client"

	mgo "gopkg.in/mgo.v2"

	"github.com/koding/eventexporter"
	"github.com/koding/logging"
	"github.com/koding/runner"
)

// CountlyExporter exports events to countly..
type CountlyExporter struct {
	client      *client.Client
	log         logging.Logger
	globalOwner string
	groupCache  *groupCache
	disabled    bool // if countly integration is disabled.
	fixApps     bool // if we should create non existing apps.
}

// NewCountlyExporter creates exporter for countly.
func NewCountlyExporter(cfg *config.Config) *CountlyExporter {
	logger := runner.MustGetLogger().New("countly-exporter")
	return &CountlyExporter{
		client: client.New(
			cfg.Countly.APIKey,
			client.SetBaseURL(cfg.Countly.Host),
			client.SetLogger(logger),
		),
		log:         logger,
		globalOwner: cfg.Countly.AppOwner,
		groupCache:  newGroupCache(),
		disabled:    cfg.Countly.Disabled,
		fixApps:     cfg.Countly.FixApps,
	}
}

// Send publishes the events to countly.
func (c *CountlyExporter) Send(event *eventexporter.Event) error {
	c.log.Debug("got event %+v", event)
	if c.disabled {
		return nil
	}

	slug := getGroupName(event)
	if slug == "" {
		c.log.Debug("skipping event, does not have group %+v", event)
		return nil
	}

	group, err := c.groupCache.BySlug(slug)
	if err != nil {
		if err == mgo.ErrNotFound {
			return nil
		}
		return err
	}

	if !group.HasCountly() {
		if !c.fixApps {
			return nil
		}

		res, err := api.NewCountlyAPI(config.MustGet()).CreateCountlyApp(slug)
		if err != nil {
			return err
		}
		// we persist in API call but here we have the old group, so update it
		group.Countly.AppKey = res.AppKey
		group.Countly.AppID = res.AppID
		group.Countly.APIKey = res.APIKey
	}

	events := []client.Event{{
		Key:          event.Name,
		Count:        1,
		Segmentation: event.Properties,
	}}
	return c.client.WriteEvent(group.Countly.AppKey, group.Id.Hex(), events)
}

// Close closes the exporter.
func (c *CountlyExporter) Close() error {
	return nil
}

func getGroupName(event *eventexporter.Event) string {
	if len(event.Properties) == 0 {
		return ""
	}

	if name, ok := event.Properties["groupName"]; ok {
		return name.(string)
	}

	if name, ok := event.Properties["group"]; ok {
		return name.(string)
	}

	return ""
}
<|endoftext|>


<commit_before>package exporter

import (
	"socialapi/config"
	"socialapi/workers/countly/api"
	"socialapi/workers/countly/client"

	mgo "gopkg.in/mgo.v2"

	"github.com/koding/eventexporter"
	"github.com/koding/logging"
	"github.com/koding/runner"
)

// CountlyExporter exports events to countly..
type CountlyExporter struct {
	client      *client.Client
	log         logging.Logger
	globalOwner string
	groupCache  *groupCache
	disabled    bool // if countly integration is disabled.
	fixApps     bool // if we should create non existing apps.
}

// NewCountlyExporter creates exporter for countly.
func NewCountlyExporter(cfg *config.Config) *CountlyExporter {
	logger := runner.MustGetLogger().New("countly-exporter")
	return &CountlyExporter{
		client: client.New(
			cfg.Countly.APIKey,
			client.SetBaseURL(cfg.Countly.Host),
			client.SetLogger(logger),
		),
		log:         logger,
		globalOwner: cfg.Countly.AppOwner,
		groupCache:  newGroupCache(),
		disabled:    cfg.Countly.Disabled,
		fixApps:     cfg.Countly.FixApps,
	}
}

// Send publishes the events to countly.
func (c *CountlyExporter) Send(event *eventexporter.Event) error {
	c.log.Debug("got event %+v", event)
	if c.disabled {
		return nil
	}

	slug := getGroupName(event)
	if slug == "" {
		c.log.Debug("skipping event, does not have group %+v", event)
		return nil
	}

	group, err := c.groupCache.BySlug(slug)
	if err != nil {
		if err == mgo.ErrNotFound {
			return nil
		}
		return err
	}

	if !group.HasCountly() {
		if !c.fixApps {
			return nil
		}

		res, err := api.NewCountlyAPI(config.MustGet()).CreateCountlyApp(slug)
		if err != nil {
			return err
		}
		// we persist in API call but here we have the old group, so update it
		group.Countly.AppKey = res.AppKey
		group.Countly.AppID = res.AppID
		group.Countly.APIKey = res.APIKey
	}

	events := []client.Event{{
		Key:          event.Name,
		Count:        1,
		Segmentation: event.Properties,
	}}
	return c.client.WriteEvent(group.Countly.AppKey, group.Id.Hex(), events)
}

// Close closes the exporter.
func (c *CountlyExporter) Close() error {
	return nil
}

func getGroupName(event *eventexporter.Event) string {
	if len(event.Properties) == 0 {
		return ""
	}

	if name, ok := event.Properties["groupName"]; ok {
		return name.(string)
	}

	if name, ok := event.Properties["group"]; ok {
		return name.(string)
	}

	return ""
}
<commit_msg>socialapi/countly: fix possible panic case<commit_after>package exporter

import (
	"socialapi/config"
	"socialapi/workers/countly/api"
	"socialapi/workers/countly/client"

	mgo "gopkg.in/mgo.v2"

	"github.com/koding/eventexporter"
	"github.com/koding/logging"
	"github.com/koding/runner"
)

// CountlyExporter exports events to countly..
type CountlyExporter struct {
	client      *client.Client
	log         logging.Logger
	globalOwner string
	groupCache  *groupCache
	disabled    bool // if countly integration is disabled.
	fixApps     bool // if we should create non existing apps.
}

// NewCountlyExporter creates exporter for countly.
func NewCountlyExporter(cfg *config.Config) *CountlyExporter {
	logger := runner.MustGetLogger().New("countly-exporter")
	return &CountlyExporter{
		client: client.New(
			cfg.Countly.APIKey,
			client.SetBaseURL(cfg.Countly.Host),
			client.SetLogger(logger),
		),
		log:         logger,
		globalOwner: cfg.Countly.AppOwner,
		groupCache:  newGroupCache(),
		disabled:    cfg.Countly.Disabled,
		fixApps:     cfg.Countly.FixApps,
	}
}

// Send publishes the events to countly.
func (c *CountlyExporter) Send(event *eventexporter.Event) error {
	c.log.Debug("got event %+v", event)
	if c.disabled {
		return nil
	}

	slug := getGroupName(event)
	if slug == "" {
		c.log.Debug("skipping event, does not have group %+v", event)
		return nil
	}

	group, err := c.groupCache.BySlug(slug)
	if err != nil {
		if err == mgo.ErrNotFound {
			return nil
		}
		return err
	}

	if !group.HasCountly() {
		if !c.fixApps {
			return nil
		}

		res, err := api.NewCountlyAPI(config.MustGet()).CreateCountlyApp(slug)
		if err != nil {
			return err
		}
		// we persist in API call but here we have the old group, so update it
		group.Countly.AppKey = res.AppKey
		group.Countly.AppID = res.AppID
		group.Countly.APIKey = res.APIKey
	}

	events := []client.Event{{
		Key:          event.Name,
		Count:        1,
		Segmentation: event.Properties,
	}}
	return c.client.WriteEvent(group.Countly.AppKey, group.Id.Hex(), events)
}

// Close closes the exporter.
func (c *CountlyExporter) Close() error {
	return nil
}

func getGroupName(event *eventexporter.Event) string {
	if len(event.Properties) == 0 {
		return ""
	}

	if name, ok := event.Properties["groupName"].(string); ok {
		return name
	}

	if name, ok := event.Properties["group"].(string); ok {
		return name
	}

	return ""
}
<|endoftext|>


<commit_before>package main

import (
	"os"

	"github.com/Xe/x/version"
	_ "github.com/joho/godotenv/autoload"
)

func main() {
	version.Run(os.Getenv("GO_VERSION"))
}
<commit_msg>version/ko: be smarter<commit_after>package main

import (
	"log"
	"os"
	"runtime"

	"github.com/Xe/x/version"
	_ "github.com/joho/godotenv/autoload"
)

func main() {
	ver := os.Getenv("GO_VERSION")

	if ver == "" {
		log.Printf("ko: No GO_VERSION specified (wanted GO_VERSION=%[1]s) specified, assuming %[1]s", runtime.Version())
	}

	ver = "go" + ver

	version.Run(ver)
}
<|endoftext|>


<commit_before>package version

// Version is the version of the build.
const Version = "0.1.13-dev"
<commit_msg>bump to v0.1.13<commit_after>package version

// Version is the version of the build.
const Version = "0.1.13"
<|endoftext|>


<commit_before>// Copyright (c) 2014-2017 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package version

// ensure that git has a tag: "vX.Y" corresponding to major and minor
const (
	Major   = "3"
	Minor   = "29"
	Version = Major + "." + Minor
)
<commit_msg>[version] version 3.30<commit_after>// Copyright (c) 2014-2017 Bitmark Inc.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package version

// ensure that git has a tag: "vX.Y" corresponding to major and minor
const (
	Major   = "3"
	Minor   = "30"
	Version = Major + "." + Minor
)
<|endoftext|>


<commit_before>/*----------------------------------------------------------------
 *  Copyright (c) ThoughtWorks, Inc.
 *  Licensed under the Apache License, Version 2.0
 *  See LICENSE in the project root for license information.
 *----------------------------------------------------------------*/

package version

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

// CurrentGaugeVersion represents the current version of Gauge
var CurrentGaugeVersion = &Version{1, 0, 9}

// BuildMetadata represents build information of current release (e.g, nightly build information)
var BuildMetadata = ""
var CommitHash = ""

type Version struct {
	Major int
	Minor int
	Patch int
}

type VersionSupport struct {
	Minimum string
	Maximum string
}

func ParseVersion(versionText string) (*Version, error) {
	splits := strings.Split(versionText, ".")
	if len(splits) != 3 {
		return nil, fmt.Errorf("incorrect version format. version should be in the form 1.5.7")
	}
	Major, err := strconv.Atoi(splits[0])
	if err != nil {
		return nil, VersionError("major", splits[0], err)
	}
	Minor, err := strconv.Atoi(splits[1])
	if err != nil {
		return nil, VersionError("minor", splits[1], err)
	}
	Patch, err := strconv.Atoi(splits[2])
	if err != nil {
		return nil, VersionError("patch", splits[2], err)
	}

	return &Version{Major, Minor, Patch}, nil
}

func VersionError(level, text string, err error) error {
	return fmt.Errorf("error parsing %s version %s to integer. %s", level, text, err.Error())
}

func (Version *Version) IsBetween(lower, greater *Version) bool {
	return Version.IsGreaterThanEqualTo(lower) && Version.IsLesserThanEqualTo(greater)
}

func (Version *Version) IsLesserThan(version1 *Version) bool {
	return CompareVersions(Version, version1, LesserThanFunc)
}

func (Version *Version) IsGreaterThan(version1 *Version) bool {
	return CompareVersions(Version, version1, GreaterThanFunc)
}

func (Version *Version) IsLesserThanEqualTo(version1 *Version) bool {
	return Version.IsLesserThan(version1) || Version.IsEqualTo(version1)
}

func (Version *Version) IsGreaterThanEqualTo(version1 *Version) bool {
	return Version.IsGreaterThan(version1) || Version.IsEqualTo(version1)
}

func (Version *Version) IsEqualTo(version1 *Version) bool {
	return IsEqual(Version.Major, version1.Major) && IsEqual(Version.Minor, version1.Minor) && IsEqual(Version.Patch, version1.Patch)
}

func CompareVersions(first, second *Version, compareFunc func(int, int) bool) bool {
	if compareFunc(first.Major, second.Major) {
		return true
	} else if IsEqual(first.Major, second.Major) {
		if compareFunc(first.Minor, second.Minor) {
			return true
		} else if IsEqual(first.Minor, second.Minor) {
			return compareFunc(first.Patch, second.Patch)
		}
	}
	return false
}

func LesserThanFunc(first, second int) bool {
	return first < second
}

func GreaterThanFunc(first, second int) bool {
	return first > second
}

func IsEqual(first, second int) bool {
	return first == second
}

func (Version *Version) String() string {
	return fmt.Sprintf("%d.%d.%d", Version.Major, Version.Minor, Version.Patch)
}

// FullVersion returns the CurrentGaugeVersion including build metadata.
func FullVersion() string {
	var metadata string
	if BuildMetadata != "" {
		metadata = fmt.Sprintf(".%s", BuildMetadata)
	}
	return fmt.Sprintf("%s%s", CurrentGaugeVersion.String(), metadata)
}

type byDecreasingVersion []*Version

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

func GetLatestVersion(versions []*Version) *Version {
	sort.Sort(byDecreasingVersion(versions))
	return versions[0]
}

func CheckCompatibility(currentVersion *Version, versionSupport *VersionSupport) error {
	minSupportVersion, err := ParseVersion(versionSupport.Minimum)
	if err != nil {
		return fmt.Errorf("invalid minimum support version %s. : %s. ", versionSupport.Minimum, err.Error())
	}
	if versionSupport.Maximum != "" {
		maxSupportVersion, err := ParseVersion(versionSupport.Maximum)
		if err != nil {
			return fmt.Errorf("invalid maximum support version %s. : %s. ", versionSupport.Maximum, err.Error())
		}
		if currentVersion.IsBetween(minSupportVersion, maxSupportVersion) {
			return nil
		}
		return fmt.Errorf("version %s is not between %s and %s", currentVersion, minSupportVersion, maxSupportVersion)
	}

	if minSupportVersion.IsLesserThanEqualTo(currentVersion) {
		return nil
	}
	return fmt.Errorf("incompatible version. Minimum support version %s is higher than current version %s", minSupportVersion, currentVersion)
}
<commit_msg>bump up to v1.1.0 <commit_after>/*----------------------------------------------------------------
 *  Copyright (c) ThoughtWorks, Inc.
 *  Licensed under the Apache License, Version 2.0
 *  See LICENSE in the project root for license information.
 *----------------------------------------------------------------*/

package version

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
)

// CurrentGaugeVersion represents the current version of Gauge
var CurrentGaugeVersion = &Version{1, 1, 0}

// BuildMetadata represents build information of current release (e.g, nightly build information)
var BuildMetadata = ""
var CommitHash = ""

type Version struct {
	Major int
	Minor int
	Patch int
}

type VersionSupport struct {
	Minimum string
	Maximum string
}

func ParseVersion(versionText string) (*Version, error) {
	splits := strings.Split(versionText, ".")
	if len(splits) != 3 {
		return nil, fmt.Errorf("incorrect version format. version should be in the form 1.5.7")
	}
	Major, err := strconv.Atoi(splits[0])
	if err != nil {
		return nil, VersionError("major", splits[0], err)
	}
	Minor, err := strconv.Atoi(splits[1])
	if err != nil {
		return nil, VersionError("minor", splits[1], err)
	}
	Patch, err := strconv.Atoi(splits[2])
	if err != nil {
		return nil, VersionError("patch", splits[2], err)
	}

	return &Version{Major, Minor, Patch}, nil
}

func VersionError(level, text string, err error) error {
	return fmt.Errorf("error parsing %s version %s to integer. %s", level, text, err.Error())
}

func (Version *Version) IsBetween(lower, greater *Version) bool {
	return Version.IsGreaterThanEqualTo(lower) && Version.IsLesserThanEqualTo(greater)
}

func (Version *Version) IsLesserThan(version1 *Version) bool {
	return CompareVersions(Version, version1, LesserThanFunc)
}

func (Version *Version) IsGreaterThan(version1 *Version) bool {
	return CompareVersions(Version, version1, GreaterThanFunc)
}

func (Version *Version) IsLesserThanEqualTo(version1 *Version) bool {
	return Version.IsLesserThan(version1) || Version.IsEqualTo(version1)
}

func (Version *Version) IsGreaterThanEqualTo(version1 *Version) bool {
	return Version.IsGreaterThan(version1) || Version.IsEqualTo(version1)
}

func (Version *Version) IsEqualTo(version1 *Version) bool {
	return IsEqual(Version.Major, version1.Major) && IsEqual(Version.Minor, version1.Minor) && IsEqual(Version.Patch, version1.Patch)
}

func CompareVersions(first, second *Version, compareFunc func(int, int) bool) bool {
	if compareFunc(first.Major, second.Major) {
		return true
	} else if IsEqual(first.Major, second.Major) {
		if compareFunc(first.Minor, second.Minor) {
			return true
		} else if IsEqual(first.Minor, second.Minor) {
			return compareFunc(first.Patch, second.Patch)
		}
	}
	return false
}

func LesserThanFunc(first, second int) bool {
	return first < second
}

func GreaterThanFunc(first, second int) bool {
	return first > second
}

func IsEqual(first, second int) bool {
	return first == second
}

func (Version *Version) String() string {
	return fmt.Sprintf("%d.%d.%d", Version.Major, Version.Minor, Version.Patch)
}

// FullVersion returns the CurrentGaugeVersion including build metadata.
func FullVersion() string {
	var metadata string
	if BuildMetadata != "" {
		metadata = fmt.Sprintf(".%s", BuildMetadata)
	}
	return fmt.Sprintf("%s%s", CurrentGaugeVersion.String(), metadata)
}

type byDecreasingVersion []*Version

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

func GetLatestVersion(versions []*Version) *Version {
	sort.Sort(byDecreasingVersion(versions))
	return versions[0]
}

func CheckCompatibility(currentVersion *Version, versionSupport *VersionSupport) error {
	minSupportVersion, err := ParseVersion(versionSupport.Minimum)
	if err != nil {
		return fmt.Errorf("invalid minimum support version %s. : %s. ", versionSupport.Minimum, err.Error())
	}
	if versionSupport.Maximum != "" {
		maxSupportVersion, err := ParseVersion(versionSupport.Maximum)
		if err != nil {
			return fmt.Errorf("invalid maximum support version %s. : %s. ", versionSupport.Maximum, err.Error())
		}
		if currentVersion.IsBetween(minSupportVersion, maxSupportVersion) {
			return nil
		}
		return fmt.Errorf("version %s is not between %s and %s", currentVersion, minSupportVersion, maxSupportVersion)
	}

	if minSupportVersion.IsLesserThanEqualTo(currentVersion) {
		return nil
	}
	return fmt.Errorf("incompatible version. Minimum support version %s is higher than current version %s", minSupportVersion, currentVersion)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/go-kit/kit/log/term"
	metrics "github.com/rcrowley/go-metrics"

	tmtypes "github.com/tendermint/tendermint/types"
	"github.com/tendermint/tmlibs/log"
	"github.com/tendermint/tools/tm-monitor/monitor"
)

var version = "0.1.0"

var logger = log.NewNopLogger()

type statistics struct {
	BlockTimeSample    metrics.Histogram
	TxThroughputSample metrics.Histogram
	BlockLatency       metrics.Histogram
}

func main() {
	var duration, txsRate, connections int
	var verbose bool

	flag.IntVar(&connections, "c", 1, "Connections to keep open per endpoint")
	flag.IntVar(&duration, "T", 10, "Exit after the specified amount of time in seconds")
	flag.IntVar(&txsRate, "r", 1000, "Txs per second to send in a connection")
	flag.BoolVar(&verbose, "v", false, "Verbose output")

	flag.Usage = func() {
		fmt.Println(`Tendermint blockchain benchmarking tool.

Usage:
	tm-bench [-c 1] [-T 10] [-r 1000] [endpoints]

Examples:
	tm-bench localhost:46657`)
		fmt.Println("Flags:")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	if verbose {
		// Color errors red
		colorFn := func(keyvals ...interface{}) term.FgBgColor {
			for i := 1; i < len(keyvals); i += 2 {
				if _, ok := keyvals[i].(error); ok {
					return term.FgBgColor{Fg: term.White, Bg: term.Red}
				}
			}
			return term.FgBgColor{}
		}
		logger = log.NewTMLoggerWithColorFn(log.NewSyncWriter(os.Stdout), colorFn)
	}

	fmt.Printf("Running %ds test @ %s\n", duration, flag.Arg(0))

	endpoints := strings.Split(flag.Arg(0), ",")

	blockCh := make(chan tmtypes.Header, 100)
	blockLatencyCh := make(chan float64, 100)

	nodes := startNodes(endpoints, blockCh, blockLatencyCh)

	transacters := startTransacters(endpoints, connections, txsRate)

	stats := &statistics{
		BlockTimeSample:    metrics.NewHistogram(metrics.NewUniformSample(1000)),
		TxThroughputSample: metrics.NewHistogram(metrics.NewUniformSample(1000)),
		BlockLatency:       metrics.NewHistogram(metrics.NewUniformSample(1000)),
	}

	lastBlockHeight := -1

	durationTimer := time.After(time.Duration(duration) * time.Second)
	ticker := time.NewTicker(1 * time.Second)
	var blocks, txs int
	for {
		select {
		case b := <-blockCh:
			if lastBlockHeight < b.Height {
				blocks++
				txs += b.NumTxs
				lastBlockHeight = b.Height
			}
		case l := <-blockLatencyCh:
			stats.BlockLatency.Update(int64(l))
		case <-ticker.C:
			stats.BlockTimeSample.Update(int64(blocks))
			stats.TxThroughputSample.Update(int64(txs))
			blocks = 0
			txs = 0
		case <-durationTimer:
			for _, t := range transacters {
				t.Stop()
			}

			printStatistics(stats)

			for _, n := range nodes {
				n.Stop()
			}
			return
		}
	}
}

func startNodes(endpoints []string, blockCh chan<- tmtypes.Header, blockLatencyCh chan<- float64) []*monitor.Node {
	nodes := make([]*monitor.Node, len(endpoints))

	for i, e := range endpoints {
		n := monitor.NewNode(e)
		n.SetLogger(logger.With("node", e))
		n.SendBlocksTo(blockCh)
		n.SendBlockLatenciesTo(blockLatencyCh)
		if err := n.Start(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		nodes[i] = n
	}

	return nodes
}

func startTransacters(endpoints []string, connections int, txsRate int) []*transacter {
	transacters := make([]*transacter, len(endpoints))

	for i, e := range endpoints {
		t := newTransacter(e, connections, txsRate)
		t.SetLogger(logger)
		if err := t.Start(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		transacters[i] = t
	}

	return transacters
}

func printStatistics(stats *statistics) {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 5, ' ', 0)
	fmt.Fprintln(w, "Stats\tAvg\tStdev\tMax\t")
	fmt.Fprintln(w, fmt.Sprintf("Block latency\t%.2fms\t%.2fms\t%dms\t",
		stats.BlockLatency.Mean()/1000000.0,
		stats.BlockLatency.StdDev()/1000000.0,
		stats.BlockLatency.Max()/1000000))
	fmt.Fprintln(w, fmt.Sprintf("Blocks/sec\t%.3f\t%.3f\t%d\t",
		stats.BlockTimeSample.Mean(),
		stats.BlockTimeSample.StdDev(),
		stats.BlockTimeSample.Max()))
	fmt.Fprintln(w, fmt.Sprintf("Txs/sec\t%.0f\t%.0f\t%d\t",
		stats.TxThroughputSample.Mean(),
		stats.TxThroughputSample.StdDev(),
		stats.TxThroughputSample.Max()))
	w.Flush()
}
<commit_msg>[tm-bench] bump version to 0.2.0<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/go-kit/kit/log/term"
	metrics "github.com/rcrowley/go-metrics"

	tmtypes "github.com/tendermint/tendermint/types"
	"github.com/tendermint/tmlibs/log"
	"github.com/tendermint/tools/tm-monitor/monitor"
)

var version = "0.2.0"

var logger = log.NewNopLogger()

type statistics struct {
	BlockTimeSample    metrics.Histogram
	TxThroughputSample metrics.Histogram
	BlockLatency       metrics.Histogram
}

func main() {
	var duration, txsRate, connections int
	var verbose bool

	flag.IntVar(&connections, "c", 1, "Connections to keep open per endpoint")
	flag.IntVar(&duration, "T", 10, "Exit after the specified amount of time in seconds")
	flag.IntVar(&txsRate, "r", 1000, "Txs per second to send in a connection")
	flag.BoolVar(&verbose, "v", false, "Verbose output")

	flag.Usage = func() {
		fmt.Println(`Tendermint blockchain benchmarking tool.

Usage:
	tm-bench [-c 1] [-T 10] [-r 1000] [endpoints]

Examples:
	tm-bench localhost:46657`)
		fmt.Println("Flags:")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	if verbose {
		// Color errors red
		colorFn := func(keyvals ...interface{}) term.FgBgColor {
			for i := 1; i < len(keyvals); i += 2 {
				if _, ok := keyvals[i].(error); ok {
					return term.FgBgColor{Fg: term.White, Bg: term.Red}
				}
			}
			return term.FgBgColor{}
		}
		logger = log.NewTMLoggerWithColorFn(log.NewSyncWriter(os.Stdout), colorFn)
	}

	fmt.Printf("Running %ds test @ %s\n", duration, flag.Arg(0))

	endpoints := strings.Split(flag.Arg(0), ",")

	blockCh := make(chan tmtypes.Header, 100)
	blockLatencyCh := make(chan float64, 100)

	nodes := startNodes(endpoints, blockCh, blockLatencyCh)

	transacters := startTransacters(endpoints, connections, txsRate)

	stats := &statistics{
		BlockTimeSample:    metrics.NewHistogram(metrics.NewUniformSample(1000)),
		TxThroughputSample: metrics.NewHistogram(metrics.NewUniformSample(1000)),
		BlockLatency:       metrics.NewHistogram(metrics.NewUniformSample(1000)),
	}

	lastBlockHeight := -1

	durationTimer := time.After(time.Duration(duration) * time.Second)
	ticker := time.NewTicker(1 * time.Second)
	var blocks, txs int
	for {
		select {
		case b := <-blockCh:
			if lastBlockHeight < b.Height {
				blocks++
				txs += b.NumTxs
				lastBlockHeight = b.Height
			}
		case l := <-blockLatencyCh:
			stats.BlockLatency.Update(int64(l))
		case <-ticker.C:
			stats.BlockTimeSample.Update(int64(blocks))
			stats.TxThroughputSample.Update(int64(txs))
			blocks = 0
			txs = 0
		case <-durationTimer:
			for _, t := range transacters {
				t.Stop()
			}

			printStatistics(stats)

			for _, n := range nodes {
				n.Stop()
			}
			return
		}
	}
}

func startNodes(endpoints []string, blockCh chan<- tmtypes.Header, blockLatencyCh chan<- float64) []*monitor.Node {
	nodes := make([]*monitor.Node, len(endpoints))

	for i, e := range endpoints {
		n := monitor.NewNode(e)
		n.SetLogger(logger.With("node", e))
		n.SendBlocksTo(blockCh)
		n.SendBlockLatenciesTo(blockLatencyCh)
		if err := n.Start(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		nodes[i] = n
	}

	return nodes
}

func startTransacters(endpoints []string, connections int, txsRate int) []*transacter {
	transacters := make([]*transacter, len(endpoints))

	for i, e := range endpoints {
		t := newTransacter(e, connections, txsRate)
		t.SetLogger(logger)
		if err := t.Start(); err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		transacters[i] = t
	}

	return transacters
}

func printStatistics(stats *statistics) {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 5, ' ', 0)
	fmt.Fprintln(w, "Stats\tAvg\tStdev\tMax\t")
	fmt.Fprintln(w, fmt.Sprintf("Block latency\t%.2fms\t%.2fms\t%dms\t",
		stats.BlockLatency.Mean()/1000000.0,
		stats.BlockLatency.StdDev()/1000000.0,
		stats.BlockLatency.Max()/1000000))
	fmt.Fprintln(w, fmt.Sprintf("Blocks/sec\t%.3f\t%.3f\t%d\t",
		stats.BlockTimeSample.Mean(),
		stats.BlockTimeSample.StdDev(),
		stats.BlockTimeSample.Max()))
	fmt.Fprintln(w, fmt.Sprintf("Txs/sec\t%.0f\t%.0f\t%d\t",
		stats.TxThroughputSample.Mean(),
		stats.TxThroughputSample.StdDev(),
		stats.TxThroughputSample.Max()))
	w.Flush()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/tendermint/tools/tm-monitor/monitor"
)

var version = "0.1.0.pre"

func main() {
	var listenAddr string
	var duration, txsRate int

	flag.StringVar(&listenAddr, "listen-addr", "tcp://0.0.0.0:46670", "HTTP and Websocket server listen address")
	flag.IntVar(&duration, "T", 10, "Exit after the specified amount of time in seconds")
	flag.IntVar(&txsRate, "r", 1000, "Txs per second to send in a connection")

	flag.Usage = func() {
		fmt.Println(`Tendermint bench.

Usage:
	tm-bench [-listen-addr="tcp://0.0.0.0:46670"] [-T 10] [-r 1000] [endpoints]

Examples:
	tm-bench localhost:46657`)
		fmt.Println("Flags:")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	fmt.Printf("Running %ds test @ %s\n", duration, flag.Arg(0))

	m := startMonitor(flag.Arg(0))

	endpoints := strings.Split(flag.Arg(0), ",")
	transacters := make([]*transacter, len(endpoints))
	for i, e := range endpoints {
		t := newTransacter(e, txsRate)
		if err := t.Start(); err != nil {
			panic(err)
		}
		transacters[i] = t
	}

	select {
	case <-time.After(time.Duration(duration) * time.Second):
		for _, t := range transacters {
			t.Stop()
		}
		collectAndPrintResults(m)
		m.Stop()
	}
}

func startMonitor(endpoints string) *monitor.Monitor {
	m := monitor.NewMonitor()

	for _, e := range strings.Split(endpoints, ",") {
		if err := m.Monitor(monitor.NewNode(e)); err != nil {
			panic(err)
		}
	}

	if err := m.Start(); err != nil {
		panic(err)
	}

	return m
}

func collectAndPrintResults(m *monitor.Monitor) {
	n := m.Network
	fmt.Println("===")
	fmt.Printf("Avg block time: %.3f ms\n", n.AvgBlockTime)
	fmt.Printf("Avg tx throughput: %.0f per sec\n", n.AvgTxThroughput)
	fmt.Printf("Avg block latency: %.3f ms\n", n.AvgBlockLatency)
	fmt.Println("===")
}
<commit_msg>more accurate statistics<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"text/tabwriter"
	"time"

	metrics "github.com/rcrowley/go-metrics"
	tmtypes "github.com/tendermint/tendermint/types"
	"github.com/tendermint/tools/tm-monitor/monitor"
)

var version = "0.1.0.pre"

type statistics struct {
	BlockTimeSample    metrics.Histogram
	TxThroughputSample metrics.Histogram
	BlockLatency       metrics.Histogram
}

func main() {
	var listenAddr string
	var duration, txsRate int

	flag.StringVar(&listenAddr, "listen-addr", "tcp://0.0.0.0:46670", "HTTP and Websocket server listen address")
	flag.IntVar(&duration, "T", 10, "Exit after the specified amount of time in seconds")
	flag.IntVar(&txsRate, "r", 1000, "Txs per second to send in a connection")

	flag.Usage = func() {
		fmt.Println(`Tendermint bench.

Usage:
	tm-bench [-listen-addr="tcp://0.0.0.0:46670"] [-T 10] [-r 1000] [endpoints]

Examples:
	tm-bench localhost:46657`)
		fmt.Println("Flags:")
		flag.PrintDefaults()
	}

	flag.Parse()

	if flag.NArg() == 0 {
		flag.Usage()
		os.Exit(1)
	}

	fmt.Printf("Running %ds test @ %s\n", duration, flag.Arg(0))

	endpoints := strings.Split(flag.Arg(0), ",")

	blockCh := make(chan tmtypes.Header, 100)
	blockLatencyCh := make(chan float64, 100)

	nodes := startNodes(endpoints, blockCh, blockLatencyCh)

	transacters := startTransacters(endpoints, txsRate)

	stats := &statistics{
		BlockTimeSample:    metrics.NewHistogram(metrics.NewUniformSample(1000)),
		TxThroughputSample: metrics.NewHistogram(metrics.NewUniformSample(1000)),
		BlockLatency:       metrics.NewHistogram(metrics.NewUniformSample(1000)),
	}

	lastBlockHeight := -1

	durationTimer := time.After(time.Duration(duration) * time.Second)
	ticker := time.NewTicker(1 * time.Second)
	var blocks, txs int
	for {
		select {
		case b := <-blockCh:
			if lastBlockHeight < b.Height {
				blocks++
				txs += b.NumTxs
				lastBlockHeight = b.Height
			}
		case l := <-blockLatencyCh:
			stats.BlockLatency.Update(int64(l))
		case <-ticker.C:
			stats.BlockTimeSample.Update(int64(blocks))
			stats.TxThroughputSample.Update(int64(txs))
			blocks = 0
			txs = 0
		case <-durationTimer:
			for _, t := range transacters {
				t.Stop()
			}

			printStatistics(stats)

			for _, n := range nodes {
				n.Stop()
			}
			return
		}
	}
}

func startNodes(endpoints []string, blockCh chan<- tmtypes.Header, blockLatencyCh chan<- float64) []*monitor.Node {
	nodes := make([]*monitor.Node, len(endpoints))

	for i, e := range endpoints {
		n := monitor.NewNode(e)
		n.SendBlocksTo(blockCh)
		n.SendBlockLatenciesTo(blockLatencyCh)
		if err := n.Start(); err != nil {
			panic(err)
		}
		nodes[i] = n
	}

	return nodes
}

func startTransacters(endpoints []string, txsRate int) []*transacter {
	transacters := make([]*transacter, len(endpoints))

	for i, e := range endpoints {
		t := newTransacter(e, txsRate)
		if err := t.Start(); err != nil {
			panic(err)
		}
		transacters[i] = t
	}

	return transacters
}

func printStatistics(stats *statistics) {
	w := tabwriter.NewWriter(os.Stdout, 0, 0, 5, ' ', 0)
	fmt.Fprintln(w, "Stats\tAvg\tStdev\tMax\t")
	fmt.Fprintln(w, fmt.Sprintf("Block latency\t%.2fms\t%.2fms\t%dms\t",
		stats.BlockLatency.Mean()/1000000.0,
		stats.BlockLatency.StdDev()/1000000.0,
		stats.BlockLatency.Max()/1000000))
	fmt.Fprintln(w, fmt.Sprintf("Blocks/sec\t%.3f\t%.3f\t%d\t",
		stats.BlockTimeSample.Mean(),
		stats.BlockTimeSample.StdDev(),
		stats.BlockTimeSample.Max()))
	fmt.Fprintln(w, fmt.Sprintf("Txs/sec\t%.0f\t%.0f\t%d\t",
		stats.TxThroughputSample.Mean(),
		stats.TxThroughputSample.StdDev(),
		stats.TxThroughputSample.Max()))
	w.Flush()
}
<|endoftext|>


<commit_before>// gitbot project gitbot.go
package gitbot

import (
	"encoding/json"
	"fmt"
	"github.com/aarondl/gitio"
	"github.com/aarondl/ultimateq/data"
	"log"
	"net/http"
	"strings"
)

var (
	Endpoint *data.DataEndpoint
	Channel  string
)

const (
	MSG1 = "[%s] %s pushed %v commits to %s %s"
	MSG2 = "[%s/%s] %s: %s: %s"
)

type Commit struct {
	Added     []string
	Modified  []string
	Removed   []string
	Author    *Person
	Committer *Person
	Distinct  bool
	Id        string
	Message   string
	Timestamp string //Might be able to use time here
	Url       string
}

func (c Commit) User() string {
	if c.Committer == nil || c.Committer.Username == "" {
		return "\x02Unknown\x02"
	}
	return c.Committer.Username
}

func (c Commit) ShortId() string {
	if c.Id == "" {
		return "\x02Unknown\x02"
	}
	if len(c.Id) < 7 {
		return c.Id
	}
	return c.Id[:7]
}

func (c Commit) Msg() string {
	if c.Message == "" {
		return "No message"
	}
	return c.Message
}

type Person struct {
	Email    string
	Name     string
	Username string
}

type Repository struct {
	Created_at    uint64
	Description   string
	Fork          bool
	Forks         uint
	Has_downloads bool
	Has_issues    bool
	Has_wiki      bool
	Homepage      string
	Id            uint
	Language      string
	Master_branch string
	Name          string
	Open_issues   uint
	Owner         *Person
	Private       bool
	Pushed_at     uint64
	Size          uint
	Stargazers    uint
	Url           string
	Watchers      uint
}

type Payload struct {
	Before      string
	After       string
	Ref         string
	Compare     string
	Created     bool
	Deleted     bool
	Forced      bool
	Commits     []*Commit
	Head_commit *Commit
	Pusher      *Person //may not have Username, beware
	Repository  *Repository
}

func (pl Payload) Branch() string {
	refs := strings.Split(pl.Ref, "/")
	return refs[len(refs)-1]
}

func (pl Payload) Name() string {
	if pl.Repository == nil || pl.Repository.Name == "" {
		return "\x02Unknown\x02"
	}
	return pl.Repository.Name
}

func (pl Payload) NumCommits() int {
	if pl.Commits == nil {
		return 0
	}
	return len(pl.Commits)
}

func (pl Payload) PusherName() string {
	if pl.Pusher == nil || pl.Pusher.Name == "" {
		return "\x02Unknown\x02"
	}
	return pl.Pusher.Name
}

func alertChan(pl Payload) {
	name := pl.Name()
	num := pl.NumCommits()
	who := pl.PusherName()
	branch := pl.Branch()
	comp, err := gitio.Shorten(pl.Compare)
	if err != nil {
		comp = pl.Compare
	}

	msg := fmt.Sprintf(MSG1, name, who, num, branch, comp)
	Endpoint.Privmsg(Channel, msg)

	var c *Commit
	for i := 0; i < num; i++ {
		c = pl.Commits[i]
		msg = fmt.Sprintf(MSG2, name, branch, c.ShortId(), c.User(), c.Message)
		Endpoint.Privmsg(Channel, msg)
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	payload := r.FormValue("payload")
	var Pl Payload
	err := json.Unmarshal([]byte(payload), &Pl)
	if err != nil {
		log.Println(err)
		return
	}
	alertChan(Pl)
}

//Start the http listener
func Listen(port, channel string, endpoint *data.DataEndpoint) (err error) {
	Channel = channel
	Endpoint = endpoint
	http.HandleFunc("/", handler)
	err = http.ListenAndServe(":"+port, nil)
	return
}
<commit_msg>forgot to use c.Msg()<commit_after>// gitbot project gitbot.go
package gitbot

import (
	"encoding/json"
	"fmt"
	"github.com/aarondl/gitio"
	"github.com/aarondl/ultimateq/data"
	"log"
	"net/http"
	"strings"
)

var (
	Endpoint *data.DataEndpoint
	Channel  string
)

const (
	MSG1 = "[%s] %s pushed %v commits to %s %s"
	MSG2 = "[%s/%s] %s: %s: %s"
)

type Commit struct {
	Added     []string
	Modified  []string
	Removed   []string
	Author    *Person
	Committer *Person
	Distinct  bool
	Id        string
	Message   string
	Timestamp string //Might be able to use time here
	Url       string
}

func (c Commit) User() string {
	if c.Committer == nil || c.Committer.Username == "" {
		return "\x02Unknown\x02"
	}
	return c.Committer.Username
}

func (c Commit) ShortId() string {
	if c.Id == "" {
		return "\x02Unknown\x02"
	}
	if len(c.Id) < 7 {
		return c.Id
	}
	return c.Id[:7]
}

func (c Commit) Msg() string {
	if c.Message == "" {
		return "No message"
	}
	return c.Message
}

type Person struct {
	Email    string
	Name     string
	Username string
}

type Repository struct {
	Created_at    uint64
	Description   string
	Fork          bool
	Forks         uint
	Has_downloads bool
	Has_issues    bool
	Has_wiki      bool
	Homepage      string
	Id            uint
	Language      string
	Master_branch string
	Name          string
	Open_issues   uint
	Owner         *Person
	Private       bool
	Pushed_at     uint64
	Size          uint
	Stargazers    uint
	Url           string
	Watchers      uint
}

type Payload struct {
	Before      string
	After       string
	Ref         string
	Compare     string
	Created     bool
	Deleted     bool
	Forced      bool
	Commits     []*Commit
	Head_commit *Commit
	Pusher      *Person //may not have Username, beware
	Repository  *Repository
}

func (pl Payload) Branch() string {
	refs := strings.Split(pl.Ref, "/")
	return refs[len(refs)-1]
}

func (pl Payload) Name() string {
	if pl.Repository == nil || pl.Repository.Name == "" {
		return "\x02Unknown\x02"
	}
	return pl.Repository.Name
}

func (pl Payload) NumCommits() int {
	if pl.Commits == nil {
		return 0
	}
	return len(pl.Commits)
}

func (pl Payload) PusherName() string {
	if pl.Pusher == nil || pl.Pusher.Name == "" {
		return "\x02Unknown\x02"
	}
	return pl.Pusher.Name
}

func alertChan(pl Payload) {
	name := pl.Name()
	num := pl.NumCommits()
	who := pl.PusherName()
	branch := pl.Branch()
	comp, err := gitio.Shorten(pl.Compare)
	if err != nil {
		comp = pl.Compare
	}

	msg := fmt.Sprintf(MSG1, name, who, num, branch, comp)
	Endpoint.Privmsg(Channel, msg)

	var c *Commit
	for i := 0; i < num; i++ {
		c = pl.Commits[i]
		msg = fmt.Sprintf(MSG2, name, branch, c.ShortId(), c.User(), c.Msg())
		Endpoint.Privmsg(Channel, msg)
	}
}

func handler(w http.ResponseWriter, r *http.Request) {
	payload := r.FormValue("payload")
	var Pl Payload
	err := json.Unmarshal([]byte(payload), &Pl)
	if err != nil {
		log.Println(err)
		return
	}
	alertChan(Pl)
}

//Start the http listener
func Listen(port, channel string, endpoint *data.DataEndpoint) (err error) {
	Channel = channel
	Endpoint = endpoint
	http.HandleFunc("/", handler)
	err = http.ListenAndServe(":"+port, nil)
	return
}
<|endoftext|>


<commit_before>package reviewdog

import (
	"fmt"
	"os/exec"

	"github.com/google/go-github/github"
	"golang.org/x/sync/errgroup"
)

var _ = github.ScopeAdminOrg

var _ CommentService = &GitHubPullRequest{}
var _ DiffService = &GitHubPullRequest{}

// `path` to `position`(Lnum for new file) to comment `body`s
type postedcomments map[string]map[int][]string

// IsPosted returns true if a given comment has been posted in GitHub already,
// otherwise returns false. It sees comments with same path, same position,
// and same body as same comments.
func (p postedcomments) IsPosted(c *Comment) bool {
	if _, ok := p[c.Path]; !ok {
		return false
	}
	bodys, ok := p[c.Path][c.LnumDiff]
	if !ok {
		return false
	}
	for _, body := range bodys {
		if body == commentBody(c) {
			return true
		}
	}
	return false
}

// GitHubPullRequest is a comment and diff service for GitHub PullRequest.
//
// API:
//	https://developer.github.com/v3/pulls/comments/#create-a-comment
// 	POST /repos/:owner/:repo/pulls/:number/comments
type GitHubPullRequest struct {
	postComments []*Comment

	cli   *github.Client
	owner string
	repo  string
	pr    int
	sha   string

	postedcs postedcomments
}

// NewGitHubPullReqest returns a new GitHubPullRequest service.
func NewGitHubPullReqest(cli *github.Client, owner, repo string, pr int, sha string) *GitHubPullRequest {
	return &GitHubPullRequest{
		cli:   cli,
		owner: owner,
		repo:  repo,
		pr:    pr,
		sha:   sha,
	}
}

// Post accepts a comment and holds it. Flash method actually posts comments to
// GitHub in parallel.
func (g *GitHubPullRequest) Post(c *Comment) error {
	g.postComments = append(g.postComments, c)
	return nil
}

const bodyPrefix = `<sub>reported by [reviewdog](https://github.com/haya14busa/reviewdog) :dog:</sub>`

func commentBody(c *Comment) string {
	tool := ""
	if c.ToolName != "" {
		tool = fmt.Sprintf("**[%s]** ", c.ToolName)
	}
	return tool + bodyPrefix + "\n" + c.Body
}

// Flash posts comments which has not been posted yet.
func (g *GitHubPullRequest) Flash() error {
	if err := g.setPostedComment(); err != nil {
		return err
	}
	var eg errgroup.Group
	for _, c := range g.postComments {
		comment := c
		if g.postedcs.IsPosted(comment) {
			continue
		}
		eg.Go(func() error {
			body := commentBody(comment)
			prcomment := &github.PullRequestComment{
				CommitID: &g.sha,
				Body:     &body,
				Path:     &comment.Path,
				Position: &comment.LnumDiff,
			}
			_, _, err := g.cli.PullRequests.CreateComment(g.owner, g.repo, g.pr, prcomment)
			return err
		})
	}
	return eg.Wait()
}

func (g *GitHubPullRequest) setPostedComment() error {
	g.postedcs = make(postedcomments)
	cs, err := g.comment()
	if err != nil {
		return err
	}
	for _, c := range cs {
		if c.Position == nil || c.Path == nil || c.Body == nil {
			// skip resolved comments. Or comments which do not have "path" nor
			// "body".
			continue
		}
		path := *c.Path
		pos := *c.Position
		body := *c.Body
		if _, ok := g.postedcs[path]; !ok {
			g.postedcs[path] = make(map[int][]string)
		}
		if _, ok := g.postedcs[path][pos]; !ok {
			g.postedcs[path][pos] = make([]string, 0)
		}
		g.postedcs[path][pos] = append(g.postedcs[path][pos], body)
	}
	return nil
}

// Diff returns a diff of PullRequest. It runs `git diff` locally instead of
// diff_url of GitHub Pull Request because diff of diff_url is not suited for
// comment API in a sense that diff of diff_url is equivalent to
// `git diff --no-renames`, we want diff which is equivalent to
// `git diff --find-renames`.
func (g *GitHubPullRequest) Diff() ([]byte, error) {
	pr, _, err := g.cli.PullRequests.Get(g.owner, g.repo, g.pr)
	if err != nil {
		return nil, err
	}
	return exec.Command("git", "diff", "--find-renames", *pr.Base.SHA, g.sha).Output()
}

// Strip returns 1 as a strip of git diff.
func (g *GitHubPullRequest) Strip() int {
	return 1
}

func (g *GitHubPullRequest) comment() ([]*github.PullRequestComment, error) {
	comments, _, err := g.cli.PullRequests.ListComments(g.owner, g.repo, g.pr, nil)
	if err != nil {
		return nil, err
	}
	return comments, nil
}
<commit_msg>github: implement GitHub PullRequest Create Review API<commit_after>package reviewdog

import (
	"fmt"
	"os/exec"

	"github.com/google/go-github/github"
	"golang.org/x/sync/errgroup"
)

var _ = github.ScopeAdminOrg

var _ CommentService = &GitHubPullRequest{}
var _ DiffService = &GitHubPullRequest{}

// `path` to `position`(Lnum for new file) to comment `body`s
type postedcomments map[string]map[int][]string

// IsPosted returns true if a given comment has been posted in GitHub already,
// otherwise returns false. It sees comments with same path, same position,
// and same body as same comments.
func (p postedcomments) IsPosted(c *Comment) bool {
	if _, ok := p[c.Path]; !ok {
		return false
	}
	bodys, ok := p[c.Path][c.LnumDiff]
	if !ok {
		return false
	}
	for _, body := range bodys {
		if body == commentBody(c) {
			return true
		}
	}
	return false
}

// GitHubPullRequest is a comment and diff service for GitHub PullRequest.
//
// API:
//	https://developer.github.com/v3/pulls/comments/#create-a-comment
// 	POST /repos/:owner/:repo/pulls/:number/comments
type GitHubPullRequest struct {
	postComments []*Comment

	cli   *github.Client
	owner string
	repo  string
	pr    int
	sha   string

	postedcs postedcomments
}

// NewGitHubPullReqest returns a new GitHubPullRequest service.
func NewGitHubPullReqest(cli *github.Client, owner, repo string, pr int, sha string) *GitHubPullRequest {
	return &GitHubPullRequest{
		cli:   cli,
		owner: owner,
		repo:  repo,
		pr:    pr,
		sha:   sha,
	}
}

// Post accepts a comment and holds it. Flash method actually posts comments to
// GitHub in parallel.
func (g *GitHubPullRequest) Post(c *Comment) error {
	g.postComments = append(g.postComments, c)
	return nil
}

const bodyPrefix = `<sub>reported by [reviewdog](https://github.com/haya14busa/reviewdog) :dog:</sub>`

func commentBody(c *Comment) string {
	tool := ""
	if c.ToolName != "" {
		tool = fmt.Sprintf("**[%s]** ", c.ToolName)
	}
	return tool + bodyPrefix + "\n" + c.Body
}

// Flash posts comments which has not been posted yet.
func (g *GitHubPullRequest) Flash() error {
	if err := g.setPostedComment(); err != nil {
		return err
	}
	var eg errgroup.Group
	for _, c := range g.postComments {
		comment := c
		if g.postedcs.IsPosted(comment) {
			continue
		}
		eg.Go(func() error {
			body := commentBody(comment)
			prcomment := &github.PullRequestComment{
				CommitID: &g.sha,
				Body:     &body,
				Path:     &comment.Path,
				Position: &comment.LnumDiff,
			}
			_, _, err := g.cli.PullRequests.CreateComment(g.owner, g.repo, g.pr, prcomment)
			return err
		})
	}
	return eg.Wait()
}

func (g *GitHubPullRequest) setPostedComment() error {
	g.postedcs = make(postedcomments)
	cs, err := g.comment()
	if err != nil {
		return err
	}
	for _, c := range cs {
		if c.Position == nil || c.Path == nil || c.Body == nil {
			// skip resolved comments. Or comments which do not have "path" nor
			// "body".
			continue
		}
		path := *c.Path
		pos := *c.Position
		body := *c.Body
		if _, ok := g.postedcs[path]; !ok {
			g.postedcs[path] = make(map[int][]string)
		}
		if _, ok := g.postedcs[path][pos]; !ok {
			g.postedcs[path][pos] = make([]string, 0)
		}
		g.postedcs[path][pos] = append(g.postedcs[path][pos], body)
	}
	return nil
}

// Diff returns a diff of PullRequest. It runs `git diff` locally instead of
// diff_url of GitHub Pull Request because diff of diff_url is not suited for
// comment API in a sense that diff of diff_url is equivalent to
// `git diff --no-renames`, we want diff which is equivalent to
// `git diff --find-renames`.
func (g *GitHubPullRequest) Diff() ([]byte, error) {
	pr, _, err := g.cli.PullRequests.Get(g.owner, g.repo, g.pr)
	if err != nil {
		return nil, err
	}
	return exec.Command("git", "diff", "--find-renames", *pr.Base.SHA, g.sha).Output()
}

// Strip returns 1 as a strip of git diff.
func (g *GitHubPullRequest) Strip() int {
	return 1
}

func (g *GitHubPullRequest) comment() ([]*github.PullRequestComment, error) {
	comments, _, err := g.cli.PullRequests.ListComments(g.owner, g.repo, g.pr, nil)
	if err != nil {
		return nil, err
	}
	return comments, nil
}

// ---
// GitHub PullRequest Review API Implementation
// ref: https://github.com/google/go-github/issues/495

const (
	mediaTypePullRequestReview = "application/vnd.github.black-cat-preview+json"
)

type Review struct {
	Body     *string          `json:"body,omitempty"`
	Event    *string          `json:"event,omitempty"`
	Comments []*ReviewComment `json:"comments,omitempty"`
}

type ReviewComment struct {
	Path     *string `json:"path,omitempty"`
	Position *int    `json:"position,omitempty"`
	Body     *string `json:"body,omitempty"`
}

// CreateReview creates a new review comment on the specified pull request.
//
// GitHub API docs: https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review
func (g *GitHubPullRequest) CreateReview(owner, repo string, number int, review *Review) (*github.PullRequestReview, *github.Response, error) {
	u := fmt.Sprintf("repos/%v/%v/pulls/%d/reviews", owner, repo, number)

	req, err := g.cli.NewRequest("POST", u, review)
	if err != nil {
		return nil, nil, err
	}

	req.Header.Set("Accept", mediaTypePullRequestReview)

	r := new(github.PullRequestReview)
	resp, err := g.cli.Do(req, r)
	if err != nil {
		return nil, resp, err
	}
	return r, resp, err
}
<|endoftext|>


<commit_before>package arduino

import (
	"github.com/distributed/sers"
	"log"
)

func SetColor(color string) (err error) {
	s, err := sers.Open("COM6")
	if err != nil {
		log.Printf("Error connecting to Arduino: %v", err)
		return
	}
	n, err := s.Write([]byte(color))
	if err != nil {
		log.Printf("Error setting LED to green: %v", err)
	}
	log.Printf("Bytes written: %d", n)
	s.Close()
	return
}
<commit_msg>removed arduino logging<commit_after>package arduino

import (
	"github.com/distributed/sers"
	"log"
)

func SetColor(color string) (err error) {
	s, err := sers.Open("COM6")
	if err != nil {
		log.Printf("Error connecting to Arduino: %v", err)
		return
	}
	_, err := s.Write([]byte(color))
	if err != nil {
		log.Printf("Error setting LED to green: %v", err)
	}
	s.Close()
	return
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"

	"code.cloudfoundry.org/lager"

	"github.com/apihub/apihub"
	"github.com/gorilla/mux"
)

func (s *ApihubServer) addService(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("add-service")
	log.Debug("start")
	defer log.Debug("end")

	var spec apihub.ServiceSpec
	if err := json.NewDecoder(r.Body).Decode(&spec); err != nil {
		log.Error("failed-to-parse-spec", err)
		s.handleError(rw, errors.New("Failed to parse request."))
		return
	}

	if spec.Handle == "" || len(spec.Backends) == 0 {
		s.handleError(rw, errors.New("Handle and Backend cannot be empty."))
		return
	}
	if err := s.storage.AddService(spec); err != nil {
		log.Error("failed-to-store-service", err)
		s.handleError(rw, fmt.Errorf("failed to add service: '%s'", err))
		return
	}

	if !spec.Disabled {
		if err := s.servicePublisher.Publish(log, apihub.SERVICES_PREFIX, spec); err != nil {
			log.Error("failed-to-publish-service", err)
			// If it fails to clean up the state it's ok to just log that
			if cleanErr := s.storage.RemoveService(spec.Handle); cleanErr != nil {
				log.Error("failed-to-remove-service", cleanErr)
			}

			s.handleError(rw, fmt.Errorf("failed to publish service: '%s'", err))
			return
		}
	}

	log.Info("service-added", lager.Data{"serviceSpec": spec})
	s.writeResponse(rw, response{
		StatusCode: http.StatusCreated,
		Body:       spec,
	})
}

func (s *ApihubServer) listServices(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("list-services")
	log.Debug("start")
	defer log.Debug("end")

	services, err := s.storage.Services()
	if err != nil {
		log.Error("failed-to-list-services", err)
		s.handleError(rw, errors.New("Failed to retrieve service list."))
		return
	}

	collection := Collection(services, len(services))

	log.Debug("services-found", lager.Data{"services": services})
	s.writeResponse(rw, response{
		StatusCode: http.StatusOK,
		Body:       collection,
	})
}

func (s *ApihubServer) removeService(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("remove-service")
	log.Debug("start")
	defer log.Debug("end")

	handle := mux.Vars(r)["handle"]

	_, err := s.storage.FindServiceByHandle(handle)
	if err != nil {
		log.Error("failed-to-find-service", err, lager.Data{"handle": handle})
		s.handleError(rw, errors.New("Handle not found."))
		return
	}

	err = s.storage.RemoveService(handle)
	if err != nil {
		log.Error("failed-to-remove-service", err)
		s.handleError(rw, errors.New("Failed to remove service."))
		return
	}

	if err := s.servicePublisher.Unpublish(log, apihub.SERVICES_PREFIX, handle); err != nil {
		log.Error("failed-to-unpublish-service", err)
	}

	s.writeResponse(rw, response{
		StatusCode: http.StatusNoContent,
	})
}

func (s *ApihubServer) findService(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("find-service")
	log.Debug("start")
	defer log.Debug("end")

	handle := mux.Vars(r)["handle"]

	service, err := s.storage.FindServiceByHandle(handle)
	if err != nil {
		log.Error("failed-to-find-service", err, lager.Data{"handle": handle})
		s.handleError(rw, errors.New("Failed to find service."))
		return
	}

	s.writeResponse(rw, response{
		StatusCode: http.StatusOK,
		Body:       service,
	})
}

func (s *ApihubServer) updateService(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("update-service")
	log.Debug("start")
	defer log.Debug("end")

	handle := mux.Vars(r)["handle"]

	service, err := s.storage.FindServiceByHandle(handle)
	if err != nil {
		log.Error("failed-to-find-service", err, lager.Data{"handle": handle})
		s.handleError(rw, errors.New("Failed to find service."))
		return
	}

	if err := json.NewDecoder(r.Body).Decode(&service); err != nil {
		log.Error("failed-to-parse-spec", err)
		s.handleError(rw, errors.New("Failed to parse request."))
		return
	}

	service.Handle = handle
	if err := s.storage.UpdateService(service); err != nil {
		log.Error("failed-to-store-service", err)
		s.handleError(rw, errors.New("Failed to update service."))
		return
	}

	if service.Disabled {
		if err := s.servicePublisher.Unpublish(log, apihub.SERVICES_PREFIX, service.Handle); err != nil {
			log.Error("failed-to-unpublish-service", err)
			return
		}
		log.Info("service-unpublished")
	} else {
		if err := s.servicePublisher.Publish(log, apihub.SERVICES_PREFIX, service); err != nil {
			log.Error("failed-to-publish-service", err)
			return
		}
		log.Info("service-published")
	}

	log.Info("service-updated", lager.Data{"serviceSpec": service})
	s.writeResponse(rw, response{
		StatusCode: http.StatusOK,
		Body:       service,
	})
}
<commit_msg>Update log messages<commit_after>package api

import (
	"encoding/json"
	"errors"
	"fmt"
	"net/http"

	"code.cloudfoundry.org/lager"

	"github.com/apihub/apihub"
	"github.com/gorilla/mux"
)

func (s *ApihubServer) addService(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("add-service")
	log.Debug("start")
	defer log.Debug("end")

	var spec apihub.ServiceSpec
	if err := json.NewDecoder(r.Body).Decode(&spec); err != nil {
		log.Error("failed-to-parse-spec", err)
		s.handleError(rw, errors.New("Failed to parse request."))
		return
	}

	if spec.Handle == "" || len(spec.Backends) == 0 {
		s.handleError(rw, errors.New("Handle and Backend cannot be empty."))
		return
	}
	if err := s.storage.AddService(spec); err != nil {
		log.Error("failed-to-store-service", err)
		s.handleError(rw, fmt.Errorf("failed to add service: '%s'", err))
		return
	}

	if !spec.Disabled {
		if err := s.servicePublisher.Publish(log, apihub.SERVICES_PREFIX, spec); err != nil {
			log.Error("failed-to-publish-service", err)
			if cleanErr := s.storage.RemoveService(spec.Handle); cleanErr != nil {
				log.Error("failed-to-remove-service", cleanErr)
			}

			s.handleError(rw, fmt.Errorf("failed to publish service: '%s'", err))
			return
		}
	}

	log.Info("service-added", lager.Data{"service": spec})
	s.writeResponse(rw, response{
		StatusCode: http.StatusCreated,
		Body:       spec,
	})
}

func (s *ApihubServer) listServices(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("list-services")
	log.Debug("start")
	defer log.Debug("end")

	services, err := s.storage.Services()
	if err != nil {
		log.Error("failed-to-list-services", err)
		s.handleError(rw, errors.New("Failed to retrieve service list."))
		return
	}

	collection := Collection(services, len(services))

	log.Debug("services-found", lager.Data{"services": services})
	s.writeResponse(rw, response{
		StatusCode: http.StatusOK,
		Body:       collection,
	})
}

func (s *ApihubServer) removeService(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("remove-service")
	log.Debug("start")
	defer log.Debug("end")

	handle := mux.Vars(r)["handle"]

	_, err := s.storage.FindServiceByHandle(handle)
	if err != nil {
		log.Error("failed-to-find-service", err, lager.Data{"handle": handle})
		s.handleError(rw, errors.New("Handle not found."))
		return
	}

	err = s.storage.RemoveService(handle)
	if err != nil {
		log.Error("failed-to-remove-service", err)
		s.handleError(rw, errors.New("Failed to remove service."))
		return
	}

	if err := s.servicePublisher.Unpublish(log, apihub.SERVICES_PREFIX, handle); err != nil {
		log.Error("failed-to-unpublish-service", err)
	}

	log.Info("service-removed", lager.Data{"handle": handle})
	s.writeResponse(rw, response{
		StatusCode: http.StatusNoContent,
	})
}

func (s *ApihubServer) findService(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("find-service")
	log.Debug("start")
	defer log.Debug("end")

	handle := mux.Vars(r)["handle"]

	service, err := s.storage.FindServiceByHandle(handle)
	if err != nil {
		log.Error("failed-to-find-service", err, lager.Data{"handle": handle})
		s.handleError(rw, errors.New("Failed to find service."))
		return
	}

	log.Debug("service-found", lager.Data{"service": service})
	s.writeResponse(rw, response{
		StatusCode: http.StatusOK,
		Body:       service,
	})
}

func (s *ApihubServer) updateService(rw http.ResponseWriter, r *http.Request) {
	log := s.logger.Session("update-service")
	log.Debug("start")
	defer log.Debug("end")

	handle := mux.Vars(r)["handle"]

	service, err := s.storage.FindServiceByHandle(handle)
	if err != nil {
		log.Error("failed-to-find-service", err, lager.Data{"handle": handle})
		s.handleError(rw, errors.New("Failed to find service."))
		return
	}

	if err := json.NewDecoder(r.Body).Decode(&service); err != nil {
		log.Error("failed-to-parse-spec", err)
		s.handleError(rw, errors.New("Failed to parse request."))
		return
	}

	service.Handle = handle
	if err := s.storage.UpdateService(service); err != nil {
		log.Error("failed-to-store-service", err)
		s.handleError(rw, errors.New("Failed to update service."))
		return
	}

	if service.Disabled {
		if err := s.servicePublisher.Unpublish(log, apihub.SERVICES_PREFIX, service.Handle); err != nil {
			log.Error("failed-to-unpublish-service", err)
		}
	} else {
		if err := s.servicePublisher.Publish(log, apihub.SERVICES_PREFIX, service); err != nil {
			log.Error("failed-to-publish-service", err)
		}
	}

	log.Info("service-updated", lager.Data{"service": service})
	s.writeResponse(rw, response{
		StatusCode: http.StatusOK,
		Body:       service,
	})
}
<|endoftext|>


<commit_before>package api

import (
	"sync"
	"time"

	"golang.org/x/net/context"

	"chain/api/asset"
	"chain/api/issuer"
	"chain/api/txbuilder"
	"chain/database/pg"
	"chain/errors"
	"chain/fedchain/bc"
	"chain/metrics"
	"chain/net/http/reqid"
	"chain/net/trace/span"
)

// POST /v3/assets/:assetID/issue
func issueAsset(ctx context.Context, assetIDStr string, reqDests []*Destination) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)
	if err := assetAuthz(ctx, assetIDStr); err != nil {
		return nil, err
	}

	var assetID bc.AssetID
	err := assetID.UnmarshalText([]byte(assetIDStr))
	if err != nil {
		return nil, errors.WithDetailf(ErrBadBuildRequest, "invalid asset id %q", assetIDStr)
	}

	// Where asset_ids are not specified in destinations - and even
	// where they are - use the one passed in above.
	for _, dest := range reqDests {
		dest.AssetID = &assetID
	}

	dests := make([]*txbuilder.Destination, 0, len(reqDests))
	for _, reqDest := range reqDests {
		parsed, err := reqDest.parse(ctx)
		if err != nil {
			return nil, err
		}
		dests = append(dests, parsed)
	}

	template, err := issuer.Issue(ctx, assetID, dests)
	if err != nil {
		return nil, err
	}

	ret := map[string]interface{}{"template": template}
	return ret, nil
}

func buildSingle(ctx context.Context, req *BuildRequest) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)
	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		return nil, err
	}
	defer dbtx.Rollback(ctx)

	prevTx, sources, destinations, err := req.parse(ctx)
	if err != nil {
		return nil, err
	}

	tpl, err := txbuilder.Build(ctx, prevTx, sources, destinations, req.Metadata, req.ResTime)
	if err != nil {
		return nil, err
	}

	err = dbtx.Commit(ctx)
	if err != nil {
		return nil, err
	}

	return map[string]interface{}{"template": tpl}, nil
}

// POST /v3/transact/build
// Idempotent
func build(ctx context.Context, buildReqs []*BuildRequest) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	if err := buildAuthz(ctx, buildReqs...); err != nil {
		return nil, err
	}

	responses := make([]interface{}, len(buildReqs))
	var wg sync.WaitGroup
	wg.Add(len(responses))

	for i := 0; i < len(responses); i++ {
		go func(i int) {
			defer wg.Done()
			resp, err := buildSingle(reqid.NewSubContext(ctx, reqid.New()), buildReqs[i])
			if err != nil {
				logHTTPError(ctx, err)
				responses[i], _ = errInfo(err)
			} else {
				responses[i] = resp
			}
		}(i)
	}

	wg.Wait()
	return responses, nil
}

// POST /v3/manager-nodes/transact/finalize
// Idempotent
func submitSingle(ctx context.Context, tpl *Template) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	parsed, err := tpl.parse(ctx)
	if err != nil {
		return nil, err
	}

	tx, err := asset.FinalizeTx(ctx, parsed)
	if err != nil {
		return nil, err
	}

	ret := map[string]interface{}{
		"transaction_id":  tx.Hash.String(),
		"raw_transaction": tx,
	}
	return ret, nil
}

// TODO(bobg): allow caller to specify reservation by (encrypted) id?
// POST /v3/assets/cancel-reservation
// Idempotent
func cancelReservation(ctx context.Context, x struct{ Transaction bc.Tx }) error {
	var outpoints []bc.Outpoint
	for _, input := range x.Transaction.Inputs {
		outpoints = append(outpoints, input.Previous)
	}
	return asset.CancelReservations(ctx, outpoints)
}

// POST /v3/transact/submit
// Idempotent
func submit(ctx context.Context, x struct{ Transactions []*Template }) interface{} {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	responses := make([]interface{}, len(x.Transactions))
	var wg sync.WaitGroup
	wg.Add(len(responses))
	for i := range responses {
		go func(i int) {
			resp, err := submitSingle(reqid.NewSubContext(ctx, reqid.New()), x.Transactions[i])
			if err != nil {
				logHTTPError(ctx, err)
				responses[i], _ = errInfo(err)
			} else {
				responses[i] = resp
			}
			wg.Done()
		}(i)
	}

	wg.Wait()
	return responses
}
<commit_msg>api: make build response inputs never return null<commit_after>package api

import (
	"sync"
	"time"

	"golang.org/x/net/context"

	"chain/api/asset"
	"chain/api/issuer"
	"chain/api/txbuilder"
	"chain/database/pg"
	"chain/errors"
	"chain/fedchain/bc"
	"chain/metrics"
	"chain/net/http/reqid"
	"chain/net/trace/span"
)

// POST /v3/assets/:assetID/issue
func issueAsset(ctx context.Context, assetIDStr string, reqDests []*Destination) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)
	if err := assetAuthz(ctx, assetIDStr); err != nil {
		return nil, err
	}

	var assetID bc.AssetID
	err := assetID.UnmarshalText([]byte(assetIDStr))
	if err != nil {
		return nil, errors.WithDetailf(ErrBadBuildRequest, "invalid asset id %q", assetIDStr)
	}

	// Where asset_ids are not specified in destinations - and even
	// where they are - use the one passed in above.
	for _, dest := range reqDests {
		dest.AssetID = &assetID
	}

	dests := make([]*txbuilder.Destination, 0, len(reqDests))
	for _, reqDest := range reqDests {
		parsed, err := reqDest.parse(ctx)
		if err != nil {
			return nil, err
		}
		dests = append(dests, parsed)
	}

	template, err := issuer.Issue(ctx, assetID, dests)
	if err != nil {
		return nil, err
	}

	ret := map[string]interface{}{"template": template}
	return ret, nil
}

func buildSingle(ctx context.Context, req *BuildRequest) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)
	dbtx, ctx, err := pg.Begin(ctx)
	if err != nil {
		return nil, err
	}
	defer dbtx.Rollback(ctx)

	prevTx, sources, destinations, err := req.parse(ctx)
	if err != nil {
		return nil, err
	}

	tpl, err := txbuilder.Build(ctx, prevTx, sources, destinations, req.Metadata, req.ResTime)
	if err != nil {
		return nil, err
	}

	err = dbtx.Commit(ctx)
	if err != nil {
		return nil, err
	}

	// ensure null is never returned for inputs
	if tpl.Inputs == nil {
		tpl.Inputs = []*txbuilder.Input{}
	}

	return map[string]interface{}{"template": tpl}, nil
}

// POST /v3/transact/build
// Idempotent
func build(ctx context.Context, buildReqs []*BuildRequest) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	if err := buildAuthz(ctx, buildReqs...); err != nil {
		return nil, err
	}

	responses := make([]interface{}, len(buildReqs))
	var wg sync.WaitGroup
	wg.Add(len(responses))

	for i := 0; i < len(responses); i++ {
		go func(i int) {
			defer wg.Done()
			resp, err := buildSingle(reqid.NewSubContext(ctx, reqid.New()), buildReqs[i])
			if err != nil {
				logHTTPError(ctx, err)
				responses[i], _ = errInfo(err)
			} else {
				responses[i] = resp
			}
		}(i)
	}

	wg.Wait()
	return responses, nil
}

// POST /v3/manager-nodes/transact/finalize
// Idempotent
func submitSingle(ctx context.Context, tpl *Template) (interface{}, error) {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	parsed, err := tpl.parse(ctx)
	if err != nil {
		return nil, err
	}

	tx, err := asset.FinalizeTx(ctx, parsed)
	if err != nil {
		return nil, err
	}

	ret := map[string]interface{}{
		"transaction_id":  tx.Hash.String(),
		"raw_transaction": tx,
	}
	return ret, nil
}

// TODO(bobg): allow caller to specify reservation by (encrypted) id?
// POST /v3/assets/cancel-reservation
// Idempotent
func cancelReservation(ctx context.Context, x struct{ Transaction bc.Tx }) error {
	var outpoints []bc.Outpoint
	for _, input := range x.Transaction.Inputs {
		outpoints = append(outpoints, input.Previous)
	}
	return asset.CancelReservations(ctx, outpoints)
}

// POST /v3/transact/submit
// Idempotent
func submit(ctx context.Context, x struct{ Transactions []*Template }) interface{} {
	defer metrics.RecordElapsed(time.Now())
	ctx = span.NewContext(ctx)
	defer span.Finish(ctx)

	responses := make([]interface{}, len(x.Transactions))
	var wg sync.WaitGroup
	wg.Add(len(responses))
	for i := range responses {
		go func(i int) {
			resp, err := submitSingle(reqid.NewSubContext(ctx, reqid.New()), x.Transactions[i])
			if err != nil {
				logHTTPError(ctx, err)
				responses[i], _ = errInfo(err)
			} else {
				responses[i] = resp
			}
			wg.Done()
		}(i)
	}

	wg.Wait()
	return responses
}
<|endoftext|>