<commit_before>package models

import (
	"errors"
	"fmt"
	"socialapi/request"
	"time"

	"github.com/koding/bongo"
)

// todo Scope function for this struct
// in order not to fetch passive accounts
type ChannelParticipant struct {
	// unique identifier of the channel
	Id int64 `json:"id,string"`

	// Id of the channel
	ChannelId int64 `json:"channelId,string"       sql:"NOT NULL"`

	// Id of the account
	AccountId int64 `json:"accountId,string"       sql:"NOT NULL"`

	// Status of the participant in the channel
	StatusConstant string `json:"statusConstant"   sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// holds troll, unsafe, etc
	MetaBits MetaBits `json:"metaBits"`

	// date of the user's last access to regarding channel
	LastSeenAt time.Time `json:"lastSeenAt"        sql:"NOT NULL"`

	// Creation date of the channel channel participant
	CreatedAt time.Time `json:"createdAt"          sql:"NOT NULL"`

	// Modification date of the channel participant's status
	UpdatedAt time.Time `json:"updatedAt"          sql:"NOT NULL"`
}

// here is why i did this not-so-good constants
// https://code.google.com/p/go/issues/detail?id=359
const (
	ChannelParticipant_STATUS_ACTIVE              = "active"
	ChannelParticipant_STATUS_LEFT                = "left"
	ChannelParticipant_STATUS_REQUEST_PENDING     = "requestpending"
	ChannelParticipant_Added_To_Channel_Event     = "added_to_channel"
	ChannelParticipant_Removed_From_Channel_Event = "removed_from_channel"
)

func NewChannelParticipant() *ChannelParticipant {
	return &ChannelParticipant{}
}

func (c ChannelParticipant) GetId() int64 {
	return c.Id
}

func (c ChannelParticipant) TableName() string {
	return "api.channel_participant"
}

func (c *ChannelParticipant) BeforeCreate() error {
	c.LastSeenAt = time.Now().UTC()

	return c.MarkIfExempt()
}

func (c *ChannelParticipant) BeforeUpdate() error {
	c.LastSeenAt = time.Now().UTC()

	return c.MarkIfExempt()
}

func (c *ChannelParticipant) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelParticipant) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c ChannelParticipant) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelParticipant) Create() error {
	if c.ChannelId == 0 {
		return fmt.Errorf("Channel Id is not set %d", c.ChannelId)
	}

	if c.AccountId == 0 {
		return fmt.Errorf("AccountId is not set %d", c.AccountId)
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
	}

	// if err is nil
	// it means we already have that channel
	err := c.One(bongo.NewQS(selector))
	if err == nil {
		c.StatusConstant = ChannelParticipant_STATUS_ACTIVE
		if err := c.Update(); err != nil {
			return err
		}

		if err := bongo.B.PublishEvent(
			ChannelParticipant_Added_To_Channel_Event, c,
		); err != nil {
			// log here
		}

		return nil
	}

	if err != bongo.RecordNotFound {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelParticipant) CreateRaw() error {
	insertSql := "INSERT INTO " +
		c.TableName() +
		` ("channel_id","account_id", "status_constant", "last_seen_at","created_at", "updated_at") ` +
		"VALUES ($1,$2,$3,$4,$5,$6) " +
		"RETURNING ID"

	return bongo.B.DB.CommonDB().
		QueryRow(insertSql, c.ChannelId, c.AccountId, c.StatusConstant, c.LastSeenAt, c.CreatedAt, c.UpdatedAt).
		Scan(&c.Id)
}

func (c *ChannelParticipant) Update() error {
	return bongo.B.Update(c)
}

func (c *ChannelParticipant) ById(id int64) error {
	return bongo.B.ById(c, id)
}

func (c *ChannelParticipant) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func (c *ChannelParticipant) Count(where ...interface{}) (int, error) {
	return bongo.B.Count(c, where...)
}

func (c *ChannelParticipant) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(c, data, q)
}

func (c *ChannelParticipant) FetchParticipant() error {
	if c.ChannelId == 0 {
		return errors.New("ChannelId is not set")
	}

	if c.AccountId == 0 {
		return errors.New("AccountId is not set")
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
		// "status_constant":     ChannelParticipant_STATUS_ACTIVE,
	}

	err := c.One(bongo.NewQS(selector))
	if err != nil {
		return err
	}

	return nil
}

func (c *ChannelParticipant) FetchUnreadCount() (int, error) {
	cml := NewChannelMessageList()
	return cml.UnreadCount(c)
}

func (c *ChannelParticipant) Delete() error {
	selector := bongo.Partial{
		"account_id": c.AccountId,
		"channel_id": c.ChannelId,
	}

	if err := c.One(bongo.NewQS(selector)); err != nil {
		return err
	}

	if err := bongo.B.UpdatePartial(c,
		bongo.Partial{
			"status_constant": ChannelParticipant_STATUS_LEFT,
		},
	); err != nil {
		return err
	}

	if err := bongo.B.PublishEvent(
		ChannelParticipant_Removed_From_Channel_Event, c,
	); err != nil {
		// log here
	}

	return nil

}

func (c *ChannelParticipant) List(q *request.Query) ([]ChannelParticipant, error) {
	var participants []ChannelParticipant

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
	}

	// add filter for troll content
	query.AddScope(RemoveTrollContent(c, q.ShowExempt))

	err := bongo.B.Some(c, &participants, query)
	if err != nil {
		return nil, err
	}

	return participants, nil
}

func (c *ChannelParticipant) ListAccountIds(limit int) ([]int64, error) {
	var participants []int64

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
		Pluck:      "account_id",
		Pagination: *bongo.NewPagination(limit, 0),
	}

	err := bongo.B.Some(c, &participants, query)
	if err != nil {
		return nil, err
	}

	return participants, nil
}

func (c *ChannelParticipant) FetchParticipatedChannelIds(a *Account, q *request.Query) ([]int64, error) {
	if a.Id == 0 {
		return nil, errors.New("Account.Id is not set")
	}

	channelIds := make([]int64, 0)

	// var results []ChannelParticipant
	query := bongo.B.DB.
		Model(c).
		Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and api.channel.type_constant = ? and  api.channel_participant.status_constant = ?", a.Id, q.Type, ChannelParticipant_STATUS_ACTIVE)

	// add exempt clause if needed
	if !q.ShowExempt {
		query = query.Where("api.channel.meta_bits = ?", Safe)
	}

	rows, err := query.Limit(q.Limit).
		Offset(q.Skip).
		Rows()

	defer rows.Close()
	if err != nil {
		return channelIds, err
	}

	if rows == nil {
		return nil, nil
	}

	var channelId int64
	for rows.Next() {
		rows.Scan(&channelId)
		channelIds = append(channelIds, channelId)
	}

	return channelIds, nil
}

func (c *ChannelParticipant) FetchParticipantCount() (int, error) {
	if c.ChannelId == 0 {
		return 0, errors.New("channel Id is not set")
	}

	return c.Count("channel_id = ?", c.ChannelId)
}

func (c *ChannelParticipant) IsParticipant(accountId int64) (bool, error) {
	if c.ChannelId == 0 {
		return false, errors.New("channel Id is not set")
	}

	selector := map[string]interface{}{
		"channel_id":      c.ChannelId,
		"account_id":      accountId,
		"status_constant": ChannelParticipant_STATUS_ACTIVE,
	}

	err := c.One(bongo.NewQS(selector))
	if err == nil {
		return true, nil
	}

	if err == bongo.RecordNotFound {
		return false, nil
	}

	return false, err
}

func (c *ChannelParticipant) MarkIfExempt() error {
	isExempt, err := c.isExempt()
	if err != nil {
		return err
	}

	if isExempt {
		c.MetaBits.MarkTroll()
	}

	return nil
}

func (c *ChannelParticipant) isExempt() (bool, error) {
	// return early if channel is already exempt
	if c.MetaBits.IsTroll() {
		return true, nil
	}

	accountId, err := c.getAccountId()
	if err != nil {
		return false, err
	}

	account, err := ResetAccountCache(accountId)
	if err != nil {
		return false, err
	}

	if account.IsTroll {
		return true, nil
	}

	return false, nil
}

func (c *ChannelParticipant) getAccountId() (int64, error) {
	if c.AccountId != 0 {
		return c.AccountId, nil
	}

	if c.Id == 0 {
		return 0, fmt.Errorf("couldnt find accountId from content %+v", c)
	}

	cp := NewChannelParticipant()
	if err := cp.ById(c.Id); err != nil {
		return 0, err
	}

	return cp.AccountId, nil
}
<commit_msg>Social: added todo<commit_after>package models

import (
	"errors"
	"fmt"
	"socialapi/request"
	"time"

	"github.com/koding/bongo"
)

// todo Scope function for this struct
// in order not to fetch passive accounts
type ChannelParticipant struct {
	// unique identifier of the channel
	Id int64 `json:"id,string"`

	// Id of the channel
	ChannelId int64 `json:"channelId,string"       sql:"NOT NULL"`

	// Id of the account
	AccountId int64 `json:"accountId,string"       sql:"NOT NULL"`

	// Status of the participant in the channel
	StatusConstant string `json:"statusConstant"   sql:"NOT NULL;TYPE:VARCHAR(100);"`

	// holds troll, unsafe, etc
	MetaBits MetaBits `json:"metaBits"`

	// date of the user's last access to regarding channel
	LastSeenAt time.Time `json:"lastSeenAt"        sql:"NOT NULL"`

	// Creation date of the channel channel participant
	CreatedAt time.Time `json:"createdAt"          sql:"NOT NULL"`

	// Modification date of the channel participant's status
	UpdatedAt time.Time `json:"updatedAt"          sql:"NOT NULL"`
}

// here is why i did this not-so-good constants
// https://code.google.com/p/go/issues/detail?id=359
const (
	ChannelParticipant_STATUS_ACTIVE              = "active"
	ChannelParticipant_STATUS_LEFT                = "left"
	ChannelParticipant_STATUS_REQUEST_PENDING     = "requestpending"
	ChannelParticipant_Added_To_Channel_Event     = "added_to_channel"
	ChannelParticipant_Removed_From_Channel_Event = "removed_from_channel"
)

func NewChannelParticipant() *ChannelParticipant {
	return &ChannelParticipant{}
}

func (c ChannelParticipant) GetId() int64 {
	return c.Id
}

func (c ChannelParticipant) TableName() string {
	return "api.channel_participant"
}

func (c *ChannelParticipant) BeforeCreate() error {
	c.LastSeenAt = time.Now().UTC()

	return c.MarkIfExempt()
}

func (c *ChannelParticipant) BeforeUpdate() error {
	c.LastSeenAt = time.Now().UTC()

	return c.MarkIfExempt()
}

func (c *ChannelParticipant) AfterCreate() {
	bongo.B.AfterCreate(c)
}

func (c *ChannelParticipant) AfterUpdate() {
	bongo.B.AfterUpdate(c)
}

func (c ChannelParticipant) AfterDelete() {
	bongo.B.AfterDelete(c)
}

func (c *ChannelParticipant) Create() error {
	if c.ChannelId == 0 {
		return fmt.Errorf("Channel Id is not set %d", c.ChannelId)
	}

	if c.AccountId == 0 {
		return fmt.Errorf("AccountId is not set %d", c.AccountId)
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
	}

	// if err is nil
	// it means we already have that channel
	err := c.One(bongo.NewQS(selector))
	if err == nil {
		c.StatusConstant = ChannelParticipant_STATUS_ACTIVE
		if err := c.Update(); err != nil {
			return err
		}

		if err := bongo.B.PublishEvent(
			ChannelParticipant_Added_To_Channel_Event, c,
		); err != nil {
			// log here
		}

		return nil
	}

	if err != bongo.RecordNotFound {
		return err
	}

	return bongo.B.Create(c)
}

func (c *ChannelParticipant) CreateRaw() error {
	insertSql := "INSERT INTO " +
		c.TableName() +
		` ("channel_id","account_id", "status_constant", "last_seen_at","created_at", "updated_at") ` +
		"VALUES ($1,$2,$3,$4,$5,$6) " +
		"RETURNING ID"

	return bongo.B.DB.CommonDB().
		QueryRow(insertSql, c.ChannelId, c.AccountId, c.StatusConstant, c.LastSeenAt, c.CreatedAt, c.UpdatedAt).
		Scan(&c.Id)
}

func (c *ChannelParticipant) Update() error {
	return bongo.B.Update(c)
}

func (c *ChannelParticipant) ById(id int64) error {
	return bongo.B.ById(c, id)
}

func (c *ChannelParticipant) One(q *bongo.Query) error {
	return bongo.B.One(c, c, q)
}

func (c *ChannelParticipant) Count(where ...interface{}) (int, error) {
	return bongo.B.Count(c, where...)
}

func (c *ChannelParticipant) Some(data interface{}, q *bongo.Query) error {
	return bongo.B.Some(c, data, q)
}

func (c *ChannelParticipant) FetchParticipant() error {
	if c.ChannelId == 0 {
		return errors.New("ChannelId is not set")
	}

	if c.AccountId == 0 {
		return errors.New("AccountId is not set")
	}

	selector := map[string]interface{}{
		"channel_id": c.ChannelId,
		"account_id": c.AccountId,
		// "status_constant":     ChannelParticipant_STATUS_ACTIVE,
	}

	err := c.One(bongo.NewQS(selector))
	if err != nil {
		return err
	}

	return nil
}

func (c *ChannelParticipant) FetchUnreadCount() (int, error) {
	cml := NewChannelMessageList()
	return cml.UnreadCount(c)
}

func (c *ChannelParticipant) Delete() error {
	selector := bongo.Partial{
		"account_id": c.AccountId,
		"channel_id": c.ChannelId,
	}

	if err := c.One(bongo.NewQS(selector)); err != nil {
		return err
	}

	if err := bongo.B.UpdatePartial(c,
		bongo.Partial{
			"status_constant": ChannelParticipant_STATUS_LEFT,
		},
	); err != nil {
		return err
	}

	if err := bongo.B.PublishEvent(
		ChannelParticipant_Removed_From_Channel_Event, c,
	); err != nil {
		// log here
	}

	return nil

}

func (c *ChannelParticipant) List(q *request.Query) ([]ChannelParticipant, error) {
	var participants []ChannelParticipant

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
	}

	// add filter for troll content
	query.AddScope(RemoveTrollContent(c, q.ShowExempt))

	err := bongo.B.Some(c, &participants, query)
	if err != nil {
		return nil, err
	}

	return participants, nil
}

func (c *ChannelParticipant) ListAccountIds(limit int) ([]int64, error) {
	var participants []int64

	if c.ChannelId == 0 {
		return participants, errors.New("ChannelId is not set")
	}

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"channel_id":      c.ChannelId,
			"status_constant": ChannelParticipant_STATUS_ACTIVE,
		},
		Pluck:      "account_id",
		Pagination: *bongo.NewPagination(limit, 0),
	}

	err := bongo.B.Some(c, &participants, query)
	if err != nil {
		return nil, err
	}

	return participants, nil
}

func (c *ChannelParticipant) FetchParticipatedChannelIds(a *Account, q *request.Query) ([]int64, error) {
	if a.Id == 0 {
		return nil, errors.New("Account.Id is not set")
	}

	channelIds := make([]int64, 0)

	// var results []ChannelParticipant
	query := bongo.B.DB.
		Model(c).
		Table(c.TableName()).
		Select("api.channel_participant.channel_id").
		Joins("left join api.channel on api.channel_participant.channel_id = api.channel.id").
		Where("api.channel_participant.account_id = ? and api.channel.type_constant = ? and  api.channel_participant.status_constant = ?", a.Id, q.Type, ChannelParticipant_STATUS_ACTIVE)

	// add exempt clause if needed
	if !q.ShowExempt {
		query = query.Where("api.channel.meta_bits = ?", Safe)
	}

	rows, err := query.Limit(q.Limit).
		Offset(q.Skip).
		Rows()

	defer rows.Close()
	if err != nil {
		return channelIds, err
	}

	if rows == nil {
		return nil, nil
	}

	var channelId int64
	for rows.Next() {
		rows.Scan(&channelId)
		channelIds = append(channelIds, channelId)
	}

	return channelIds, nil
}

func (c *ChannelParticipant) FetchParticipantCount() (int, error) {
	if c.ChannelId == 0 {
		return 0, errors.New("channel Id is not set")
	}

	return c.Count("channel_id = ?", c.ChannelId)
}

func (c *ChannelParticipant) IsParticipant(accountId int64) (bool, error) {
	if c.ChannelId == 0 {
		return false, errors.New("channel Id is not set")
	}

	selector := map[string]interface{}{
		"channel_id":      c.ChannelId,
		"account_id":      accountId,
		"status_constant": ChannelParticipant_STATUS_ACTIVE,
	}

	err := c.One(bongo.NewQS(selector))
	if err == nil {
		return true, nil
	}

	if err == bongo.RecordNotFound {
		return false, nil
	}

	return false, err
}

// Put them all behind an interface
// channels, messages, lists, participants, etc
func (c *ChannelParticipant) MarkIfExempt() error {
	isExempt, err := c.isExempt()
	if err != nil {
		return err
	}

	if isExempt {
		c.MetaBits.MarkTroll()
	}

	return nil
}

func (c *ChannelParticipant) isExempt() (bool, error) {
	// return early if channel is already exempt
	if c.MetaBits.IsTroll() {
		return true, nil
	}

	accountId, err := c.getAccountId()
	if err != nil {
		return false, err
	}

	account, err := ResetAccountCache(accountId)
	if err != nil {
		return false, err
	}

	if account == nil {
		return false, fmt.Errorf("account is nil, accountId:%d", accountId)
	}

	if account.IsTroll {
		return true, nil
	}

	return false, nil
}

func (c *ChannelParticipant) getAccountId() (int64, error) {
	if c.AccountId != 0 {
		return c.AccountId, nil
	}

	if c.Id == 0 {
		return 0, fmt.Errorf("couldnt find accountId from content %+v", c)
	}

	cp := NewChannelParticipant()
	if err := cp.ById(c.Id); err != nil {
		return 0, err
	}

	return cp.AccountId, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package vtgate

import (
	"context"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/stretchr/testify/require"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/test/endtoend/cluster"
)

// TestCheckConstraint test check constraints on CREATE TABLE
// This feature is supported from MySQL 8.0.16 and MariaDB 10.2.1.
func TestCheckConstraint(t *testing.T) {
	// Skipping as tests are run against MySQL 5.7
	t.Skip()

	conn, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	query := `CREATE TABLE t7 (CHECK (c1 <> c2), c1 INT CHECK (c1 > 10), c2 INT CONSTRAINT c2_positive CHECK (c2 > 0), c3 INT CHECK (c3 < 100), CONSTRAINT c1_nonzero CHECK (c1 <> 0), CHECK (c1 > c3));`
	exec(t, conn, query)

	checkQuery := `SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 't7';`
	expected := `[[VARCHAR("t7_chk_1")] [VARCHAR("t7_chk_2")] [VARCHAR("c2_positive")] [VARCHAR("t7_chk_3")] [VARCHAR("c1_nonzero")] [VARCHAR("t7_chk_4")]]`

	assertMatches(t, conn, checkQuery, expected)

	cleanup := `DROP TABLE t7`
	exec(t, conn, cleanup)
}

func TestDbNameOverride(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.Nil(t, err)
	defer conn.Close()
	qr, err := conn.ExecuteFetch("SELECT distinct database() FROM information_schema.tables WHERE table_schema = database()", 1000, true)

	require.Nil(t, err)
	assert.Equal(t, 1, len(qr.Rows), "did not get enough rows back")
	assert.Equal(t, "vt_ks", qr.Rows[0][0].ToString())
}

func TestInformationSchemaQuery(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	assertSingleRowIsReturned(t, conn, "table_schema = 'ks'", "vt_ks")
	assertSingleRowIsReturned(t, conn, "table_schema = 'vt_ks'", "vt_ks")
	assertResultIsEmpty(t, conn, "table_schema = 'NONE'")
	assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema'", "performance_schema")
	assertResultIsEmpty(t, conn, "table_schema = 'PERFORMANCE_SCHEMA'")
	assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema' and table_name = 'users'", "performance_schema")
	assertResultIsEmpty(t, conn, "table_schema = 'performance_schema' and table_name = 'foo'")
}

func assertResultIsEmpty(t *testing.T, conn *mysql.Conn, pre string) {
	t.Run(pre, func(t *testing.T) {
		qr, err := conn.ExecuteFetch("SELECT distinct table_schema FROM information_schema.tables WHERE "+pre, 1000, true)
		require.NoError(t, err)
		assert.Empty(t, qr.Rows)
	})
}

func assertSingleRowIsReturned(t *testing.T, conn *mysql.Conn, predicate string, expectedKs string) {
	t.Run(predicate, func(t *testing.T) {
		qr, err := conn.ExecuteFetch("SELECT distinct table_schema FROM information_schema.tables WHERE "+predicate, 1000, true)
		require.NoError(t, err)
		assert.Equal(t, 1, len(qr.Rows), "did not get enough rows back")
		assert.Equal(t, expectedKs, qr.Rows[0][0].ToString())
	})
}

func TestInformationSchemaWithSubquery(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	result := exec(t, conn, "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = (SELECT SCHEMA()) AND TABLE_NAME = 'not_exists'")
	assert.Empty(t, result.Rows)
}

func TestInformationSchemaQueryGetsRoutedToTheRightTableAndKeyspace(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	_ = exec(t, conn, "SELECT * FROM t1000") // test that the routed table is available to us
	result := exec(t, conn, "SELECT * FROM information_schema.tables WHERE table_schema = database() and table_name='t1000'")
	assert.NotEmpty(t, result.Rows)
}

func TestFKConstraintUsingInformationSchema(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	query := "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = 't7_fk' and rc.constraint_schema = database() and rc.table_name = 't7_fk'"
	assertMatches(t, conn, query, `[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") VARCHAR("CASCADE") VARCHAR("SET NULL")]]`)
}

func TestConnectWithSystemSchema(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	for _, dbname := range []string{"information_schema", "mysql", "performance_schema", "sys"} {
		connParams := vtParams
		connParams.DbName = dbname
		conn, err := mysql.Connect(ctx, &connParams)
		require.NoError(t, err)
		exec(t, conn, `select @@max_allowed_packet from dual`)
		conn.Close()
	}
}

func TestUseSystemSchema(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()
	for _, dbname := range []string{"information_schema", "mysql", "performance_schema", "sys"} {
		exec(t, conn, fmt.Sprintf("use %s", dbname))
		exec(t, conn, `select @@max_allowed_packet from dual`)
	}
}

func TestSystemSchemaQueryWithoutQualifier(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	queryWithQualifier := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+
		"from information_schema.tables t "+
		"join information_schema.columns c "+
		"on c.table_schema = t.table_schema and c.table_name = t.table_name "+
		"where t.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName)
	qr1 := exec(t, conn, queryWithQualifier)

	queryWithoutQualifier := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+
		"from tables t "+
		"join columns c "+
		"on c.table_schema = t.table_schema and c.table_name = t.table_name "+
		"where t.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName)
	exec(t, conn, "use information_schema")
	qr2 := exec(t, conn, queryWithoutQualifier)
	require.Equal(t, qr1, qr2)

	connParams := vtParams
	connParams.DbName = "information_schema"
	conn2, err := mysql.Connect(ctx, &connParams)
	require.NoError(t, err)
	defer conn2.Close()

	qr3 := exec(t, conn2, queryWithoutQualifier)
	require.Equal(t, qr2, qr3)
}

func TestMultipleSchemaPredicates(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	query := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+
		"from information_schema.tables t "+
		"join information_schema.columns c "+
		"on c.table_schema = t.table_schema and c.table_name = t.table_name "+
		"where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName, KeyspaceName, KeyspaceName)
	qr1 := exec(t, conn, query)
	require.EqualValues(t, 4, len(qr1.Fields))

	// test a query with two keyspace names
	query = fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+
		"from information_schema.tables t "+
		"join information_schema.columns c "+
		"on c.table_schema = t.table_schema and c.table_name = t.table_name "+
		"where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName, "a")
	_, err = conn.ExecuteFetch(query, 1000, true)
	require.Error(t, err)
	require.Contains(t, err.Error(), "specifying two different database in the query is not supported")
}
<commit_msg>fixup! Update error string in test assertion to match upstream 10.0.2<commit_after>/*
Copyright 2020 The Vitess Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package vtgate

import (
	"context"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/stretchr/testify/require"

	"vitess.io/vitess/go/mysql"
	"vitess.io/vitess/go/test/endtoend/cluster"
)

// TestCheckConstraint test check constraints on CREATE TABLE
// This feature is supported from MySQL 8.0.16 and MariaDB 10.2.1.
func TestCheckConstraint(t *testing.T) {
	// Skipping as tests are run against MySQL 5.7
	t.Skip()

	conn, err := mysql.Connect(context.Background(), &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	query := `CREATE TABLE t7 (CHECK (c1 <> c2), c1 INT CHECK (c1 > 10), c2 INT CONSTRAINT c2_positive CHECK (c2 > 0), c3 INT CHECK (c3 < 100), CONSTRAINT c1_nonzero CHECK (c1 <> 0), CHECK (c1 > c3));`
	exec(t, conn, query)

	checkQuery := `SELECT CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE TABLE_NAME = 't7';`
	expected := `[[VARCHAR("t7_chk_1")] [VARCHAR("t7_chk_2")] [VARCHAR("c2_positive")] [VARCHAR("t7_chk_3")] [VARCHAR("c1_nonzero")] [VARCHAR("t7_chk_4")]]`

	assertMatches(t, conn, checkQuery, expected)

	cleanup := `DROP TABLE t7`
	exec(t, conn, cleanup)
}

func TestDbNameOverride(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.Nil(t, err)
	defer conn.Close()
	qr, err := conn.ExecuteFetch("SELECT distinct database() FROM information_schema.tables WHERE table_schema = database()", 1000, true)

	require.Nil(t, err)
	assert.Equal(t, 1, len(qr.Rows), "did not get enough rows back")
	assert.Equal(t, "vt_ks", qr.Rows[0][0].ToString())
}

func TestInformationSchemaQuery(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	assertSingleRowIsReturned(t, conn, "table_schema = 'ks'", "vt_ks")
	assertSingleRowIsReturned(t, conn, "table_schema = 'vt_ks'", "vt_ks")
	assertResultIsEmpty(t, conn, "table_schema = 'NONE'")
	assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema'", "performance_schema")
	assertResultIsEmpty(t, conn, "table_schema = 'PERFORMANCE_SCHEMA'")
	assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema' and table_name = 'users'", "performance_schema")
	assertResultIsEmpty(t, conn, "table_schema = 'performance_schema' and table_name = 'foo'")
}

func assertResultIsEmpty(t *testing.T, conn *mysql.Conn, pre string) {
	t.Run(pre, func(t *testing.T) {
		qr, err := conn.ExecuteFetch("SELECT distinct table_schema FROM information_schema.tables WHERE "+pre, 1000, true)
		require.NoError(t, err)
		assert.Empty(t, qr.Rows)
	})
}

func assertSingleRowIsReturned(t *testing.T, conn *mysql.Conn, predicate string, expectedKs string) {
	t.Run(predicate, func(t *testing.T) {
		qr, err := conn.ExecuteFetch("SELECT distinct table_schema FROM information_schema.tables WHERE "+predicate, 1000, true)
		require.NoError(t, err)
		assert.Equal(t, 1, len(qr.Rows), "did not get enough rows back")
		assert.Equal(t, expectedKs, qr.Rows[0][0].ToString())
	})
}

func TestInformationSchemaWithSubquery(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	result := exec(t, conn, "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = (SELECT SCHEMA()) AND TABLE_NAME = 'not_exists'")
	assert.Empty(t, result.Rows)
}

func TestInformationSchemaQueryGetsRoutedToTheRightTableAndKeyspace(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	_ = exec(t, conn, "SELECT * FROM t1000") // test that the routed table is available to us
	result := exec(t, conn, "SELECT * FROM information_schema.tables WHERE table_schema = database() and table_name='t1000'")
	assert.NotEmpty(t, result.Rows)
}

func TestFKConstraintUsingInformationSchema(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	query := "select fk.referenced_table_name as to_table, fk.referenced_column_name as primary_key, fk.column_name as `column`, fk.constraint_name as name, rc.update_rule as on_update, rc.delete_rule as on_delete from information_schema.referential_constraints as rc join information_schema.key_column_usage as fk using (constraint_schema, constraint_name) where fk.referenced_column_name is not null and fk.table_schema = database() and fk.table_name = 't7_fk' and rc.constraint_schema = database() and rc.table_name = 't7_fk'"
	assertMatches(t, conn, query, `[[VARCHAR("t7_xxhash") VARCHAR("uid") VARCHAR("t7_uid") VARCHAR("t7_fk_ibfk_1") VARCHAR("CASCADE") VARCHAR("SET NULL")]]`)
}

func TestConnectWithSystemSchema(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	for _, dbname := range []string{"information_schema", "mysql", "performance_schema", "sys"} {
		connParams := vtParams
		connParams.DbName = dbname
		conn, err := mysql.Connect(ctx, &connParams)
		require.NoError(t, err)
		exec(t, conn, `select @@max_allowed_packet from dual`)
		conn.Close()
	}
}

func TestUseSystemSchema(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()
	for _, dbname := range []string{"information_schema", "mysql", "performance_schema", "sys"} {
		exec(t, conn, fmt.Sprintf("use %s", dbname))
		exec(t, conn, `select @@max_allowed_packet from dual`)
	}
}

func TestSystemSchemaQueryWithoutQualifier(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	queryWithQualifier := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+
		"from information_schema.tables t "+
		"join information_schema.columns c "+
		"on c.table_schema = t.table_schema and c.table_name = t.table_name "+
		"where t.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName)
	qr1 := exec(t, conn, queryWithQualifier)

	queryWithoutQualifier := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+
		"from tables t "+
		"join columns c "+
		"on c.table_schema = t.table_schema and c.table_name = t.table_name "+
		"where t.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName)
	exec(t, conn, "use information_schema")
	qr2 := exec(t, conn, queryWithoutQualifier)
	require.Equal(t, qr1, qr2)

	connParams := vtParams
	connParams.DbName = "information_schema"
	conn2, err := mysql.Connect(ctx, &connParams)
	require.NoError(t, err)
	defer conn2.Close()

	qr3 := exec(t, conn2, queryWithoutQualifier)
	require.Equal(t, qr2, qr3)
}

func TestMultipleSchemaPredicates(t *testing.T) {
	defer cluster.PanicHandler(t)
	ctx := context.Background()
	conn, err := mysql.Connect(ctx, &vtParams)
	require.NoError(t, err)
	defer conn.Close()

	query := fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+
		"from information_schema.tables t "+
		"join information_schema.columns c "+
		"on c.table_schema = t.table_schema and c.table_name = t.table_name "+
		"where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName, KeyspaceName, KeyspaceName)
	qr1 := exec(t, conn, query)
	require.EqualValues(t, 4, len(qr1.Fields))

	// test a query with two keyspace names
	query = fmt.Sprintf("select t.table_schema,t.table_name,c.column_name,c.column_type "+
		"from information_schema.tables t "+
		"join information_schema.columns c "+
		"on c.table_schema = t.table_schema and c.table_name = t.table_name "+
		"where t.table_schema = '%s' and c.table_schema = '%s' and c.table_schema = '%s'", KeyspaceName, KeyspaceName, "a")
	_, err = conn.ExecuteFetch(query, 1000, true)
	require.Error(t, err)
	require.Contains(t, err.Error(), "two predicates for specifying the database are not supported")
}
<|endoftext|>


<commit_before>package forge

import (
	"github.com/docker/docker/api/types/container"
	docker "github.com/docker/docker/client"

	"github.com/sclevine/forge/engine"
)

const dockerfile = `
FROM {{.Stack}}

RUN \
  apt-get update && \
  apt-get -y install sshpass && \
  apt-get clean

RUN \
  curl -L "https://storage.googleapis.com/golang/go1.9.1.linux-amd64.tar.gz" | tar -C /usr/local -xz && \
  git -C /tmp clone --single-branch https://github.com/cloudfoundry/diego-release && \
  cd /tmp/diego-release && \
  git checkout "v1.29.0" && \
  git submodule update --init --recursive \
    src/code.cloudfoundry.org/archiver \
    src/code.cloudfoundry.org/buildpackapplifecycle \
    src/code.cloudfoundry.org/bytefmt \
    src/code.cloudfoundry.org/cacheddownloader \
    src/code.cloudfoundry.org/lager \
    src/code.cloudfoundry.org/systemcerts \
    src/github.com/cloudfoundry-incubator/credhub-cli \
    src/gopkg.in/yaml.v2 && \
  export PATH=/usr/local/go/bin:$PATH && \
  export GOPATH=/tmp/diego-release && \
  go build -o /tmp/lifecycle/launcher code.cloudfoundry.org/buildpackapplifecycle/launcher && \
  go build -o /tmp/lifecycle/builder code.cloudfoundry.org/buildpackapplifecycle/builder && \
  rm -rf /tmp/diego-release /usr/local/go

USER vcap

RUN mkdir -p /tmp/app /tmp/cache /home/vcap/tmp /tmp/buildpacks

{{range .Buildpacks}}
RUN curl -L -o /tmp/buildpack.zip "{{.URL}}" && unzip /tmp/buildpack.zip -d /tmp/buildpacks/{{.MD5}} && rm /tmp/buildpack.zip
{{end}}
`

type dockerEngine struct {
	Docker *docker.Client
	Exit   <-chan struct{}
}

func (d *dockerEngine) NewContainer(name string, config *container.Config, hostConfig *container.HostConfig) (Container, error) {
	contr, err := engine.NewContainer(d.Docker, name, config, hostConfig)
	if err != nil {
		return nil, err
	}
	contr.Exit = d.Exit
	return contr, nil
}
<commit_msg>Bump Diego version<commit_after>package forge

import (
	"github.com/docker/docker/api/types/container"
	docker "github.com/docker/docker/client"

	"github.com/sclevine/forge/engine"
)

const dockerfile = `
FROM {{.Stack}}

RUN \
  apt-get update && \
  apt-get -y install sshpass && \
  apt-get clean

RUN \
  curl -L "https://storage.googleapis.com/golang/go1.9.1.linux-amd64.tar.gz" | tar -C /usr/local -xz && \
  git -C /tmp clone --single-branch https://github.com/cloudfoundry/diego-release && \
  cd /tmp/diego-release && \
  git checkout "v1.29.1" && \
  git submodule update --init --recursive \
    src/code.cloudfoundry.org/archiver \
    src/code.cloudfoundry.org/buildpackapplifecycle \
    src/code.cloudfoundry.org/bytefmt \
    src/code.cloudfoundry.org/cacheddownloader \
    src/code.cloudfoundry.org/lager \
    src/code.cloudfoundry.org/systemcerts \
    src/github.com/cloudfoundry-incubator/credhub-cli \
    src/gopkg.in/yaml.v2 && \
  export PATH=/usr/local/go/bin:$PATH && \
  export GOPATH=/tmp/diego-release && \
  go build -o /tmp/lifecycle/launcher code.cloudfoundry.org/buildpackapplifecycle/launcher && \
  go build -o /tmp/lifecycle/builder code.cloudfoundry.org/buildpackapplifecycle/builder && \
  rm -rf /tmp/diego-release /usr/local/go

USER vcap

RUN mkdir -p /tmp/app /tmp/cache /home/vcap/tmp /tmp/buildpacks

{{range .Buildpacks}}
RUN curl -L -o /tmp/buildpack.zip "{{.URL}}" && unzip /tmp/buildpack.zip -d /tmp/buildpacks/{{.MD5}} && rm /tmp/buildpack.zip
{{end}}
`

type dockerEngine struct {
	Docker *docker.Client
	Exit   <-chan struct{}
}

func (d *dockerEngine) NewContainer(name string, config *container.Config, hostConfig *container.HostConfig) (Container, error) {
	contr, err := engine.NewContainer(d.Docker, name, config, hostConfig)
	if err != nil {
		return nil, err
	}
	contr.Exit = d.Exit
	return contr, nil
}
<|endoftext|>


<commit_before>// program to check if you actually get better odds by changing doors if shown one to be empty
// backstory: the popular riddle goes as that at a game show you're shown three doors, behind one
// there's an expensive gift - the others are empty. once you select a door, the host opens one of the
// remaining doors and shows that it's empty, and gives you a chance to revise your choice -
// do you stick with your original selection or do you swap?

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	totalRuns := 0.0 // number of total selections
	totalWins := 0.0 // number of total wins by contestant
	change := false  // flag denoting whether contestant changes selection upon empty door reveal or not

	// run through some number of game shows
	for i := 0; i < 10000; i++ {
		totalRuns++

		// initialize three doors with a gift behind one
		doors := []int{0, 0, 0} // doors are slice indexes 0, 1, and 2 - gift will be changed to 1
		doors[rand.Intn(3)] = 1 // gift placed behind random door

		// contestant selects a door
		contestantChoice := rand.Intn(3)

		// host demonstrates the empty door from the remaining ones
		empty := demoEmptyDoor(doors, contestantChoice)

		// change or not
		contestantChoice = changeOrKeep(contestantChoice, empty, change)

		// outcome
		if doors[contestantChoice] == 1 {
			totalWins++
		}
	}

	// calculate odds / output results
	odds := (totalWins * 100) / totalRuns
	fmt.Printf("Change: %v\nRuns: %.0f\nWins: %.0f\nOdds: %.2f%%\n", change, totalRuns, totalWins, odds)
}

// given contestant's choice, shown empty door, and a flag denoting to change selection or not, return a selection
// (changed if flag set)
func changeOrKeep(choice int, empty int, change bool) int {
	if !change {
		return choice
	}

	for i := 0; i < 3; i++ {
		if i == choice || i == empty {
			continue
		}

		return i
	}

	// dummy int return at end of function to make compiler happy
	return 10
}

// given the selection the contestant made and the knowledge of what's behind each door,
// the host opens an empty door from the remaining two
func demoEmptyDoor(doors []int, choice int) int {
	for i := 0; i < 3; i++ {
		if i == choice {
			continue
		}

		if doors[i] == 0 {
			return i
		}
	}

	// dummy int return at end of function to make compiler happy
	return 10
}
<commit_msg>comment + go fmt<commit_after>// program to check if you actually get better odds by changing doors if shown one to be empty
// backstory: the popular riddle goes as that at a game show you're shown three doors, behind one
// there's an expensive gift - the others are empty. once you select a door, the host opens one of the
// remaining doors and shows that it's empty, and gives you a chance to revise your choice -
// do you stick with your original selection or do you swap?

package main

import (
	"fmt"
	"math/rand"
)

func main() {
	totalRuns := 0.0 // number of total selections (float values to calculate %.2f precise odds later - Go keeps int division int)
	totalWins := 0.0 // number of total wins by contestant
	change := false  // flag denoting whether contestant changes selection upon empty door reveal or not

	// run through some number of game shows
	for i := 0; i < 10000; i++ {
		totalRuns++

		// initialize three doors with a gift behind one
		doors := []int{0, 0, 0} // doors are slice indexes 0, 1, and 2 - gift will be changed to 1
		doors[rand.Intn(3)] = 1 // gift placed behind random door

		// contestant selects a door
		contestantChoice := rand.Intn(3)

		// host demonstrates the empty door from the remaining ones
		empty := demoEmptyDoor(doors, contestantChoice)

		// change or not
		contestantChoice = changeOrKeep(contestantChoice, empty, change)

		// outcome
		if doors[contestantChoice] == 1 {
			totalWins++
		}
	}

	// calculate odds / output results
	odds := (totalWins * 100) / totalRuns
	fmt.Printf("Change: %v\nRuns: %.0f\nWins: %.0f\nOdds: %.2f%%\n", change, totalRuns, totalWins, odds)
}

// given contestant's choice, shown empty door, and a flag denoting to change selection or not, return a selection
// (changed if flag set)
func changeOrKeep(choice int, empty int, change bool) int {
	if !change {
		return choice
	}

	for i := 0; i < 3; i++ {
		if i == choice || i == empty {
			continue
		}

		return i
	}

	// dummy int return at end of function to make compiler happy
	return 10
}

// given the selection the contestant made and the knowledge of what's behind each door,
// the host opens an empty door from the remaining two
func demoEmptyDoor(doors []int, choice int) int {
	for i := 0; i < 3; i++ {
		if i == choice {
			continue
		}

		if doors[i] == 0 {
			return i
		}
	}

	// dummy int return at end of function to make compiler happy
	return 10
}
<|endoftext|>


<commit_before>// +build linux

/*
Copyright 2018 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package none

import (
	"fmt"
	"os/exec"
	"os/user"

	"github.com/docker/machine/libmachine/drivers"
	"k8s.io/minikube/pkg/drivers/none"
	"k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/driver"
	"k8s.io/minikube/pkg/minikube/localpath"
	"k8s.io/minikube/pkg/minikube/registry"
)

func init() {
	if err := registry.Register(registry.DriverDef{
		Name:     driver.None,
		Config:   configure,
		Init:     func() drivers.Driver { return none.NewDriver(none.Config{}) },
		Status:   status,
		Priority: registry.Discouraged, // requires root
	}); err != nil {
		panic(fmt.Sprintf("register failed: %v", err))
	}
}

func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
	return none.NewDriver(none.Config{
		MachineName:      driver.MachineName(cc, n),
		StorePath:        localpath.MiniPath(),
		ContainerRuntime: cc.KubernetesConfig.ContainerRuntime,
	}), nil
}

func status() registry.State {
	_, err := exec.LookPath("iptables")
	if err != nil {
		return registry.State{Error: err, Fix: "iptables must be installed", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
	}

	/* if _, err := exec.LookPath("systemctl"); err != nil {
		return registry.State{Error: err, Fix: "Use a systemd based Linux distribution", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
	}*/

	if _, err := exec.LookPath("docker"); err != nil {
		return registry.State{Error: err, Installed: false, Fix: "Install docker", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
	}

	u, err := user.Current()
	if err != nil {
		return registry.State{Error: err, Healthy: false, Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
	}

	if u.Uid != "0" {
		return registry.State{Error: fmt.Errorf("the 'none' driver must be run as the root user"), Healthy: false, Fix: "For non-root usage, try the newer 'docker' driver", Installed: true}
	}

	return registry.State{Installed: true, Healthy: true}
}
<commit_msg>Remove obsolete comment<commit_after>// +build linux

/*
Copyright 2018 The Kubernetes Authors All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

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

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

package none

import (
	"fmt"
	"os/exec"
	"os/user"

	"github.com/docker/machine/libmachine/drivers"
	"k8s.io/minikube/pkg/drivers/none"
	"k8s.io/minikube/pkg/minikube/config"
	"k8s.io/minikube/pkg/minikube/driver"
	"k8s.io/minikube/pkg/minikube/localpath"
	"k8s.io/minikube/pkg/minikube/registry"
)

func init() {
	if err := registry.Register(registry.DriverDef{
		Name:     driver.None,
		Config:   configure,
		Init:     func() drivers.Driver { return none.NewDriver(none.Config{}) },
		Status:   status,
		Priority: registry.Discouraged, // requires root
	}); err != nil {
		panic(fmt.Sprintf("register failed: %v", err))
	}
}

func configure(cc config.ClusterConfig, n config.Node) (interface{}, error) {
	return none.NewDriver(none.Config{
		MachineName:      driver.MachineName(cc, n),
		StorePath:        localpath.MiniPath(),
		ContainerRuntime: cc.KubernetesConfig.ContainerRuntime,
	}), nil
}

func status() registry.State {
	_, err := exec.LookPath("iptables")
	if err != nil {
		return registry.State{Error: err, Fix: "iptables must be installed", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
	}

	if _, err := exec.LookPath("docker"); err != nil {
		return registry.State{Error: err, Installed: false, Fix: "Install docker", Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
	}

	u, err := user.Current()
	if err != nil {
		return registry.State{Error: err, Healthy: false, Doc: "https://minikube.sigs.k8s.io/docs/reference/drivers/none/"}
	}

	if u.Uid != "0" {
		return registry.State{Error: fmt.Errorf("the 'none' driver must be run as the root user"), Healthy: false, Fix: "For non-root usage, try the newer 'docker' driver", Installed: true}
	}

	return registry.State{Installed: true, Healthy: true}
}
<|endoftext|>


<commit_before>package asana

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"reflect"
	"testing"
)

var (
	client *Client
	mux    *http.ServeMux
	server *httptest.Server
)

func setup() {
	client = NewClient(nil)
	mux = http.NewServeMux()
	server = httptest.NewServer(mux)
	url, _ := url.Parse(server.URL)
	client.BaseURL = url
}

func teardown() {
	server.Close()
}

func TestNewClient(t *testing.T) {
	c := NewClient(nil)

	if c.BaseURL.String() != defaultBaseURL {
		t.Errorf("NewClient BaseURL = %v, want %v", c.BaseURL.String(), defaultBaseURL)
	}
	if c.UserAgent != userAgent {
		t.Errorf("NewClient UserAgent = %v, want %v", c.UserAgent, userAgent)
	}
}

func TestNewError(t *testing.T) {
	err := Error{Phrase: "P", Message: "M"}
	if err.Error() != "M - P" {
		t.Errorf("Invalid Error message: %v", err.Error())
	}
}

func TestListWorkspaces(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/workspaces", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"name":"Organization 1"},
			{"id":2,"name":"Organization 2"}
		]}`)
	})

	workspaces, err := client.ListWorkspaces()
	if err != nil {
		t.Errorf("ListWorkspaces returned error: %v", err)
	}

	want := []Workspace{
		{ID: 1, Name: "Organization 1"},
		{ID: 2, Name: "Organization 2"},
	}

	if !reflect.DeepEqual(workspaces, want) {
		t.Errorf("ListWorkspaces returned %+v, want %+v", workspaces, want)
	}
}

func TestListUsers(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"email":"test1@asana.com"},
			{"id":2,"email":"test2@asana.com"}
		]}`)
	})

	users, err := client.ListUsers(nil)
	if err != nil {
		t.Errorf("ListUsers returned error: %v", err)
	}

	want := []User{
		{ID: 1, Email: "test1@asana.com"},
		{ID: 2, Email: "test2@asana.com"},
	}

	if !reflect.DeepEqual(users, want) {
		t.Errorf("ListUsers returned %+v, want %+v", users, want)
	}
}

func TestListProjects(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/projects", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"name":"Project 1"},
			{"id":2,"name":"Project 2"}
		]}`)
	})

	projects, err := client.ListProjects(nil)
	if err != nil {
		t.Errorf("ListProjects returned error: %v", err)
	}

	want := []Project{
		{ID: 1, Name: "Project 1"},
		{ID: 2, Name: "Project 2"},
	}

	if !reflect.DeepEqual(projects, want) {
		t.Errorf("ListProjects returned %+v, want %+v", projects, want)
	}
}

func TestListTasks(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/tasks", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"name":"Task 1"},
			{"id":2,"name":"Task 2"}
		]}`)
	})

	tasks, err := client.ListTasks(nil)
	if err != nil {
		t.Errorf("ListTasks returned error: %v", err)
	}

	want := []Task{
		{ID: 1, Name: "Task 1"},
		{ID: 2, Name: "Task 2"},
	}

	if !reflect.DeepEqual(tasks, want) {
		t.Errorf("ListTasks returned %+v, want %+v", tasks, want)
	}
}

func TestUpdateTask(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/tasks/1", func(w http.ResponseWriter, r *http.Request) {
		// TODO: Verify method, headers, etc.
		// TODO: Verify that this handler is hit exactly once.
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			t.Fatalf("error reading request body: %v", err)
		}
		want := `{"data":{"notes":"updated notes"}}`
		if !reflect.DeepEqual(string(b), want) {
			t.Errorf("handler received request body %+v, want %+v", string(b), want)
		}

		fmt.Fprint(w, `{"data":{"id":1,"notes":"updated notes"}}`)
	})

	// TODO: Add this to package API, like go-github, maybe? Think about it first.
	//
	// String is a helper routine that allocates a new string value
	// to store v and returns a pointer to it.
	String := func(v string) *string { return &v }

	task, err := client.UpdateTask(1, TaskUpdate{Notes: String("updated notes")}, nil)
	if err != nil {
		t.Errorf("UpdateTask returned error: %v", err)
	}

	want := Task{ID: 1, Notes: "updated notes"}
	if !reflect.DeepEqual(task, want) {
		t.Errorf("UpdateTask returned %+v, want %+v", task, want)
	}
}

func TestListTags(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/tags", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"name":"Tag 1"},
			{"id":2,"name":"Tag 2"}
		]}`)
	})

	tags, err := client.ListTags(nil)
	if err != nil {
		t.Errorf("ListTags returned error: %v", err)
	}

	want := []Tag{
		{ID: 1, Name: "Tag 1"},
		{ID: 2, Name: "Tag 2"},
	}

	if !reflect.DeepEqual(tags, want) {
		t.Errorf("ListTags returned %+v, want %+v", tags, want)
	}
}
<commit_msg>Test method, headers, number of times handler called.<commit_after>package asana

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"net/url"
	"reflect"
	"testing"
)

var (
	client *Client
	mux    *http.ServeMux
	server *httptest.Server
)

func setup() {
	client = NewClient(nil)
	mux = http.NewServeMux()
	server = httptest.NewServer(mux)
	url, _ := url.Parse(server.URL)
	client.BaseURL = url
}

func teardown() {
	server.Close()
}

func TestNewClient(t *testing.T) {
	c := NewClient(nil)

	if c.BaseURL.String() != defaultBaseURL {
		t.Errorf("NewClient BaseURL = %v, want %v", c.BaseURL.String(), defaultBaseURL)
	}
	if c.UserAgent != userAgent {
		t.Errorf("NewClient UserAgent = %v, want %v", c.UserAgent, userAgent)
	}
}

func TestNewError(t *testing.T) {
	err := Error{Phrase: "P", Message: "M"}
	if err.Error() != "M - P" {
		t.Errorf("Invalid Error message: %v", err.Error())
	}
}

func TestListWorkspaces(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/workspaces", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"name":"Organization 1"},
			{"id":2,"name":"Organization 2"}
		]}`)
	})

	workspaces, err := client.ListWorkspaces()
	if err != nil {
		t.Errorf("ListWorkspaces returned error: %v", err)
	}

	want := []Workspace{
		{ID: 1, Name: "Organization 1"},
		{ID: 2, Name: "Organization 2"},
	}

	if !reflect.DeepEqual(workspaces, want) {
		t.Errorf("ListWorkspaces returned %+v, want %+v", workspaces, want)
	}
}

func TestListUsers(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/users", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"email":"test1@asana.com"},
			{"id":2,"email":"test2@asana.com"}
		]}`)
	})

	users, err := client.ListUsers(nil)
	if err != nil {
		t.Errorf("ListUsers returned error: %v", err)
	}

	want := []User{
		{ID: 1, Email: "test1@asana.com"},
		{ID: 2, Email: "test2@asana.com"},
	}

	if !reflect.DeepEqual(users, want) {
		t.Errorf("ListUsers returned %+v, want %+v", users, want)
	}
}

func TestListProjects(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/projects", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"name":"Project 1"},
			{"id":2,"name":"Project 2"}
		]}`)
	})

	projects, err := client.ListProjects(nil)
	if err != nil {
		t.Errorf("ListProjects returned error: %v", err)
	}

	want := []Project{
		{ID: 1, Name: "Project 1"},
		{ID: 2, Name: "Project 2"},
	}

	if !reflect.DeepEqual(projects, want) {
		t.Errorf("ListProjects returned %+v, want %+v", projects, want)
	}
}

func TestListTasks(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/tasks", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"name":"Task 1"},
			{"id":2,"name":"Task 2"}
		]}`)
	})

	tasks, err := client.ListTasks(nil)
	if err != nil {
		t.Errorf("ListTasks returned error: %v", err)
	}

	want := []Task{
		{ID: 1, Name: "Task 1"},
		{ID: 2, Name: "Task 2"},
	}

	if !reflect.DeepEqual(tasks, want) {
		t.Errorf("ListTasks returned %+v, want %+v", tasks, want)
	}
}

func TestUpdateTask(t *testing.T) {
	setup()
	defer teardown()

	var called int
	defer func() { testCalled(t, called, 1) }()
	mux.HandleFunc("/tasks/1", func(w http.ResponseWriter, r *http.Request) {
		called++
		testMethod(t, r, "PUT")
		b, err := ioutil.ReadAll(r.Body)
		if err != nil {
			t.Fatalf("error reading request body: %v", err)
		}
		want := `{"data":{"notes":"updated notes"}}`
		if !reflect.DeepEqual(string(b), want) {
			t.Errorf("handler received request body %+v, want %+v", string(b), want)
		}

		fmt.Fprint(w, `{"data":{"id":1,"notes":"updated notes"}}`)
	})

	// TODO: Add this to package API, like go-github, maybe? Think about it first.
	//
	// String is a helper routine that allocates a new string value
	// to store v and returns a pointer to it.
	String := func(v string) *string { return &v }

	task, err := client.UpdateTask(1, TaskUpdate{Notes: String("updated notes")}, nil)
	if err != nil {
		t.Errorf("UpdateTask returned error: %v", err)
	}

	want := Task{ID: 1, Notes: "updated notes"}
	if !reflect.DeepEqual(task, want) {
		t.Errorf("UpdateTask returned %+v, want %+v", task, want)
	}
}

func TestListTags(t *testing.T) {
	setup()
	defer teardown()

	mux.HandleFunc("/tags", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, `{"data":[
			{"id":1,"name":"Tag 1"},
			{"id":2,"name":"Tag 2"}
		]}`)
	})

	tags, err := client.ListTags(nil)
	if err != nil {
		t.Errorf("ListTags returned error: %v", err)
	}

	want := []Tag{
		{ID: 1, Name: "Tag 1"},
		{ID: 2, Name: "Tag 2"},
	}

	if !reflect.DeepEqual(tags, want) {
		t.Errorf("ListTags returned %+v, want %+v", tags, want)
	}
}

func testMethod(t *testing.T, r *http.Request, want string) {
	if got := r.Method; got != want {
		t.Errorf("Request method: %v, want %v", got, want)
	}
}

func testHeader(t *testing.T, r *http.Request, header string, want string) {
	if got := r.Header.Get(header); got != want {
		t.Errorf("Header.Get(%q) returned %q, want %q", header, got, want)
	}
}

func testCalled(t *testing.T, called int, want int) {
	if got := called; got != want {
		t.Errorf("handler was called %v times, but expected to be called %v times", got, want)
	}
}
<|endoftext|>


<commit_before>package arn

// GetUser ...
func GetUser(id string) (*User, error) {
	obj, err := DB.Get("User", id)
	return obj.(*User), err
}

// GetUserByNick ...
func GetUserByNick(nick string) (*User, error) {
	return GetUserFromTable("NickToUser", nick)
}

// GetUserByEmail ...
func GetUserByEmail(email string) (*User, error) {
	return GetUserFromTable("EmailToUser", email)
}

// GetUserFromTable queries a table for the record with the given ID
// and returns the user that is referenced by record["userId"].
func GetUserFromTable(table string, id string) (*User, error) {
	rec, err := DB.GetMap(table, id)

	if err != nil {
		return nil, err
	}

	return GetUser(rec["userId"].(string))
}

// AllUsers returns a stream of all users.
func AllUsers() (chan *User, error) {
	channel := make(chan *User)
	err := DB.Scan("User", channel)
	return channel, err
}

// FilterUsers filters all users by a custom function.
func FilterUsers(filter func(*User) bool) ([]*User, error) {
	var filtered []*User

	channel, err := AllUsers()

	if err != nil {
		return filtered, err
	}

	for obj := range channel {
		if filter(obj) {
			filtered = append(filtered, obj)
		}
	}

	return filtered, nil
}
<commit_msg>Added SortByLastSeen<commit_after>package arn

import "sort"

// GetUser ...
func GetUser(id string) (*User, error) {
	obj, err := DB.Get("User", id)
	return obj.(*User), err
}

// GetUserByNick ...
func GetUserByNick(nick string) (*User, error) {
	return GetUserFromTable("NickToUser", nick)
}

// GetUserByEmail ...
func GetUserByEmail(email string) (*User, error) {
	return GetUserFromTable("EmailToUser", email)
}

// GetUserFromTable queries a table for the record with the given ID
// and returns the user that is referenced by record["userId"].
func GetUserFromTable(table string, id string) (*User, error) {
	rec, err := DB.GetMap(table, id)

	if err != nil {
		return nil, err
	}

	return GetUser(rec["userId"].(string))
}

// AllUsers returns a stream of all users.
func AllUsers() (chan *User, error) {
	channel := make(chan *User)
	err := DB.Scan("User", channel)
	return channel, err
}

// FilterUsers filters all users by a custom function.
func FilterUsers(filter func(*User) bool) ([]*User, error) {
	var filtered []*User

	channel, err := AllUsers()

	if err != nil {
		return filtered, err
	}

	for obj := range channel {
		if filter(obj) {
			filtered = append(filtered, obj)
		}
	}

	return filtered, nil
}

// SortUserByLastSeen sorts a list of users by their last seen date.
func SortByLastSeen(users []*User) []*User {

	sort.Slice(users, func(i, j int) bool {
		return users[i].LastSeen > users[j].LastSeen
	})

	return users
}
<|endoftext|>


<commit_before>package assets

import (
	"fmt"
	"html/template"
	"regexp"
	"strconv"
)

var (
	conditionalRe = regexp.MustCompile("(?i:^!?ie((?:l|g)te?)?(\\d+)?$)")
)

type Condition int

const (
	ConditionNone Condition = iota
	ConditionIf
	ConditionIfNot
	ConditionIfEqual
	ConditionIfLessThan
	ConditionIfLessThanOrEqual
	ConditionIfGreaterThan
	ConditionIfGreaterThanOrEqual
)

var conditions = map[Condition]string{
	ConditionIfEqual:              "",
	ConditionIfLessThan:           "lt",
	ConditionIfLessThanOrEqual:    "lte",
	ConditionIfGreaterThan:        "gt",
	ConditionIfGreaterThanOrEqual: "gte",
}

func ParseCondition(val string) (Condition, int, error) {
	if val == "" {
		return ConditionNone, 0, nil
	}
	if conditionalRe.MatchString(val) {
		m := conditionalRe.FindStringSubmatch(val)
		var version int
		var err error
		if len(m) == 3 {
			if v := m[len(m)-1]; v != "" {
				version, err = strconv.Atoi(m[len(m)-1])
				if err != nil {
					return ConditionNone, 0, err
				}
			}
			var cond Condition
			switch m[1] {
			case "lt":
				cond = ConditionIfLessThan
			case "lte":
				cond = ConditionIfLessThanOrEqual
			case "gt":
				cond = ConditionIfGreaterThan
			case "gte":
				cond = ConditionIfGreaterThanOrEqual
			case "":
				cond = ConditionIfEqual
			default:
				return ConditionNone, 0, fmt.Errorf("Invalid condition %q", val)
			}
			return cond, version, nil
		}
	}
	return ConditionNone, 0, fmt.Errorf("Invalid condition %q", val)
}

func Conditional(cond Condition, version int, html string) template.HTML {
	var conditional string
	var cmp string
	var vers string
	switch cond {
	case ConditionNone:
		conditional = html
	case ConditionIfNot:
		conditional = fmt.Sprintf("<!--[if !IE]> -->%s<!-- <![endif]-->", html)
	default:
		cmp = conditions[cond]
		vers = strconv.Itoa(version)
		fallthrough
	case ConditionIf:
		conditional = fmt.Sprintf("<!--[if %s IE %s]>%s<![endif]-->", cmp, vers, html)
	}
	return template.HTML(conditional)
}
<commit_msg>Fix if=ie conditional<commit_after>package assets

import (
	"fmt"
	"html/template"
	"regexp"
	"strconv"
)

var (
	conditionalRe = regexp.MustCompile("(?i:^!?ie((?:l|g)te?)?(\\d+)?$)")
)

type Condition int

const (
	ConditionNone Condition = iota
	ConditionIf
	ConditionIfNot
	ConditionIfEqual
	ConditionIfLessThan
	ConditionIfLessThanOrEqual
	ConditionIfGreaterThan
	ConditionIfGreaterThanOrEqual
)

var conditions = map[Condition]string{
	ConditionIfEqual:              "",
	ConditionIfLessThan:           "lt ",
	ConditionIfLessThanOrEqual:    "lte ",
	ConditionIfGreaterThan:        "gt ",
	ConditionIfGreaterThanOrEqual: "gte ",
}

func ParseCondition(val string) (Condition, int, error) {
	if val == "" {
		return ConditionNone, 0, nil
	}
	if conditionalRe.MatchString(val) {
		m := conditionalRe.FindStringSubmatch(val)
		var version int
		var err error
		if len(m) == 3 {
			if v := m[len(m)-1]; v != "" {
				version, err = strconv.Atoi(m[len(m)-1])
				if err != nil {
					return ConditionNone, 0, err
				}
			}
			var cond Condition
			switch m[1] {
			case "lt":
				cond = ConditionIfLessThan
			case "lte":
				cond = ConditionIfLessThanOrEqual
			case "gt":
				cond = ConditionIfGreaterThan
			case "gte":
				cond = ConditionIfGreaterThanOrEqual
			case "":
				cond = ConditionIfEqual
			default:
				return ConditionNone, 0, fmt.Errorf("Invalid condition %q", val)
			}
			return cond, version, nil
		}
	}
	return ConditionNone, 0, fmt.Errorf("Invalid condition %q", val)
}

func Conditional(cond Condition, version int, html string) template.HTML {
	var conditional string
	var cmp string
	var vers string
	switch cond {
	case ConditionNone:
		conditional = html
	case ConditionIfNot:
		conditional = fmt.Sprintf("<!--[if !IE]> -->%s<!-- <![endif]-->", html)
	default:
		cmp = conditions[cond]
		if version != 0 {
			vers = fmt.Sprintf(" %d", version)
		}
		fallthrough
	case ConditionIf:
		conditional = fmt.Sprintf("<!--[if %sIE%s]>%s<![endif]-->", cmp, vers, html)
	}
	return template.HTML(conditional)
}
<|endoftext|>


<commit_before>package neural

import "math"

// Activator calculates neuron activation and it's derivative from given potential
type Activator interface {
	Activation(dst, potentials []float64)
	Derivative(dst, potentials []float64)
}

// NewLinearActivator creates Activator that applies linear function to given potential
// Actication: a*potential + 0
// Derivative: a
func NewLinearActivator(a float64) Activator {
	return &linearActication{a}
}

type linearActication struct {
	a float64
}

func (l *linearActication) Activation(dst, potentials []float64) {
	for i, potential := range potentials {
		dst[i] = l.a * potential
	}
}

func (l *linearActication) Derivative(dst, potentials []float64) {
	for i := range potentials {
		dst[i] = l.a
	}
}

// NewSigmoidActivator creates Activator that applies linear function to given potential
// Actication: a*potential + 0
// Derivative: a
func NewSigmoidActivator() Activator {
	return &sigmoidActivator{}
}

type sigmoidActivator struct{}

func (s *sigmoidActivator) Activation(dst, potentials []float64) {
	for i, potential := range potentials {
		dst[i] = 1.0 / (1.0 + math.Exp(-potential))
	}
}

func (s *sigmoidActivator) Derivative(dst, potentials []float64) {
	s.Activation(dst, potentials)
	for i, activation := range dst {
		dst[i] = activation * (1 - activation)
	}
}

// NewStepFunction creates Activator that returns 0 or 1 only
// Actication: 1 if potential >= 0 else 0
// Derivative: 0 (is that correct?)
func NewStepFunction() Activator {
	return &stepActicator{}
}

type stepActicator struct{}

func (s *stepActicator) Activation(dst, potentials []float64) {
	for i, potential := range potentials {
		if potential >= 0 {
			dst[i] = 1
		} else {
			dst[i] = 0
		}
	}
}

func (s *stepActicator) Derivative(dst, potentials []float64) {
	for i := range potentials {
		dst[i] = 1
	}
}

func NewSoftmaxFunction() Activator {
	return &softmaxActicator{}
}

type softmaxActicator struct{}

func (s *softmaxActicator) Activation(dst, potentials []float64) {
	var sum float64

	for i, potential := range potentials {
		dst[i] = math.Exp(potential)
		sum += dst[i]
	}

	for i, dstVal := range dst {
		dst[i] = dstVal / sum
	}
}

func (s *softmaxActicator) Derivative(dst, potentials []float64) {
	panic("Derivative of Softmax should not be used in ANN")
}
<commit_msg>Docs for softmax activation function<commit_after>package neural

import "math"

// Activator calculates neuron activation and it's derivative from given potential
type Activator interface {
	Activation(dst, potentials []float64)
	Derivative(dst, potentials []float64)
}

// NewLinearActivator creates Activator that applies linear function to given potential
// Actication: a*potential + 0
// Derivative: a
func NewLinearActivator(a float64) Activator {
	return &linearActication{a}
}

type linearActication struct {
	a float64
}

func (l *linearActication) Activation(dst, potentials []float64) {
	for i, potential := range potentials {
		dst[i] = l.a * potential
	}
}

func (l *linearActication) Derivative(dst, potentials []float64) {
	for i := range potentials {
		dst[i] = l.a
	}
}

// NewSigmoidActivator creates Activator that applies linear function to given potential
// Actication: a*potential + 0
// Derivative: a
func NewSigmoidActivator() Activator {
	return &sigmoidActivator{}
}

type sigmoidActivator struct{}

func (s *sigmoidActivator) Activation(dst, potentials []float64) {
	for i, potential := range potentials {
		dst[i] = 1.0 / (1.0 + math.Exp(-potential))
	}
}

func (s *sigmoidActivator) Derivative(dst, potentials []float64) {
	s.Activation(dst, potentials)
	for i, activation := range dst {
		dst[i] = activation * (1 - activation)
	}
}

// NewStepFunction creates Activator that returns 0 or 1 only
// Actication: 1 if potential >= 0 else 0
// Derivative: 0 (is that correct?)
func NewStepFunction() Activator {
	return &stepActicator{}
}

type stepActicator struct{}

func (s *stepActicator) Activation(dst, potentials []float64) {
	for i, potential := range potentials {
		if potential >= 0 {
			dst[i] = 1
		} else {
			dst[i] = 0
		}
	}
}

func (s *stepActicator) Derivative(dst, potentials []float64) {
	for i := range potentials {
		dst[i] = 1
	}
}

// NewSoftmaxFunction creates Activator that scales responses in layer from 0 to 1
// Sum of responses in layer are equal 1, so it can be interpret as probability
// This activator should be used in last layer with Log Likelihood
// Derivative is not implemented as it should not be needed. If used it will panic
func NewSoftmaxFunction() Activator {
	return &softmaxActicator{}
}

type softmaxActicator struct{}

func (s *softmaxActicator) Activation(dst, potentials []float64) {
	var sum float64

	for i, potential := range potentials {
		dst[i] = math.Exp(potential)
		sum += dst[i]
	}

	for i, dstVal := range dst {
		dst[i] = dstVal / sum
	}
}

func (s *softmaxActicator) Derivative(dst, potentials []float64) {
	panic("Derivative of Softmax should not be used in ANN")
}
<|endoftext|>


<commit_before>// Package bh provides some helper classes for convenience of using github.com/boltdb/bolt package.
// All wrapper classes will use their friend wrapper classes whenever possible.
// All returned errors are with call stackes using github.com/golangplus/errors.
package bh

import (
	"io"
	"os"

	"github.com/golangplus/bytes"
	"github.com/golangplus/errors"

	"github.com/boltdb/bolt"
)

// A wrapper to *bolt.DB.
type DB struct {
	*bolt.DB
}

// A wrapper to *bolt.Tx.
type Tx struct {
	*bolt.Tx
}

// A wrapper to *bolt.Bucket.
type Bucket struct {
	*bolt.Bucket
}

// A wrapper to *bolt.Cursor.
type Cursor struct {
	*bolt.Cursor
}

// Open creates and opens a database at the given path. If the file does
// not exist then it will be created automatically. Passing in nil options
// will cause Bolt to open the database with the default options.
func Open(path string, mode os.FileMode, options *bolt.Options) (DB, error) {
	db, err := bolt.Open(path, mode, options)
	return DB{db}, errorsp.WithStacks(err)
}

// Batch wraps bolt.DB.Batch.
func (db DB) Batch(f func(Tx) error) error {
	return errorsp.WithStacks(db.DB.Batch(func(tx *bolt.Tx) error {
		return errorsp.WithStacks(f(Tx{tx}))
	}))
}

// Begin wraps bolt.DB.Begin.
func (db DB) Begin(writable bool) (Tx, error) {
	tx, err := db.DB.Begin(writable)
	return Tx{tx}, errorsp.WithStacks(err)
}

// Close releases all database resources. All transactions must be closed
// before closing the database.
func (db DB) Close() error {
	return errorsp.WithStacks(db.DB.Close())
}

// Sync wraps bolt.DB.Sync.
func (db DB) Sync() error {
	return errorsp.WithStacks(db.DB.Sync())
}

// Update wraps bolt.DB.Update.
func (db DB) Update(f func(Tx) error) error {
	return errorsp.WithStacks(db.DB.Update(func(tx *bolt.Tx) error {
		return errorsp.WithStacks(f(Tx{tx}))
	}))
}

// View wraps bolt.DB.View.
func (db DB) View(f func(Tx) error) error {
	return errorsp.WithStacks(db.DB.View(func(tx *bolt.Tx) error {
		return errorsp.WithStacks(f(Tx{tx}))
	}))
}

func (tx Tx) Bucket(folders [][]byte, f func(Bucket) error) error {
	b := tx.Tx.Bucket(folders[0])
	if b == nil {
		return nil
	}
	if len(folders) == 1 {
		return errorsp.WithStacks(f(Bucket{b}))
	}
	return Bucket{b}.OpenBucket(folders[1:], f)
}

// Commit writes all changes to disk and updates the meta page. Returns an
// error if a disk write error occurs, or if Commit is called on a
// read-only transaction.
func (tx Tx) Commit() error {
	return errorsp.WithStacks(tx.Tx.Commit())
}

// CopyFile copies the entire database to file at the given path. A reader
// transaction is maintained during the copy so it is safe to continue
// using the database while a copy is in progress.
func (tx Tx) CopyFile(path string, mode os.FileMode) error {
	return errorsp.WithStacks(tx.Tx.CopyFile(path, mode))
}

// CreateBucketIfNotExists creates a new bucket if it doesn't already
// exist. Returns an error if the bucket name is blank, or if the bucket
// name is too long. The bucket instance is only valid for the lifetime of
// the transaction.
func (tx Tx) CreateBucketIfNotExists(folders [][]byte) (Bucket, error) {
	b, err := tx.Tx.CreateBucketIfNotExists(folders[0])
	if err != nil {
		return Bucket{}, nil
	}
	if len(folders) == 1 {
		return Bucket{b}, nil
	}
	return Bucket{b}.CreateBucketIfNotExists(folders[1:])
}

func (tx Tx) Cursor(folders [][]byte, f func(Cursor) error) error {
	if len(folders) == 0 {
		return errorsp.WithStacks(f(Cursor{tx.Tx.Cursor()}))
	}
	return tx.Bucket(folders, func(b Bucket) error {
		return errorsp.WithStacks(f(b.Cursor()))
	})
}

// DB returns a reference to the database that created the transaction.
func (tx Tx) DB() DB {
	return DB{tx.Tx.DB()}
}

// Delete deletes a key.
func (tx Tx) Delete(k [][]byte) error {
	if len(k) == 1 {
		return errorsp.WithStacks(tx.Tx.DeleteBucket(k[0]))
	}
	return tx.Bucket(k[:len(k)-1], func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.Delete(k[len(k)-1]))
	})
}

// ForEach iterates over all key values of a folder.
func (tx Tx) ForEach(folders [][]byte, f func(Bucket, bytesp.Slice, bytesp.Slice) error) error {
	return tx.Bucket(folders, func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.ForEach(func(k, v []byte) error {
			return errorsp.WithStacks(f(b, bytesp.Slice(k), bytesp.Slice(v)))
		}))
	})
}

// Rollback closes the transaction and ignores all previous updates.
// Read-only transactions must be rolled back and not committed.
func (tx Tx) Rollback() error {
	return errorsp.WithStacks(tx.Tx.Rollback())
}

// WriteTo writes the entire database to a writer. If err == nil then
// exactly tx.Size() bytes will be written into the writer.
func (tx *Tx) WriteTo(w io.Writer) (int64, error) {
	n, err := tx.Tx.WriteTo(w)
	return n, errorsp.WithStacks(err)
}

// Put sets the value for a key in the transaction.
// If the key exist then its previous value will be overwritten.
// Supplied value must remain valid for the life of the transaction.
// Returns an error if the bucket was created from a read-only transaction,
// if the key is blank, if the key is too large, or if the value is too
// large.
func (tx Tx) Put(k [][]byte, v []byte) error {
	b, err := tx.CreateBucketIfNotExists(k[:len(k)-1])
	if err != nil {
		return err
	}
	return errorsp.WithStacks(b.Bucket.Put(k[len(k)-1], v))
}

// Value tries to get a value from the transaction. If the key does not
// exist, the f is not called and nil is return.
func (tx Tx) Value(k [][]byte, f func(v bytesp.Slice) error) error {
	return tx.Bucket(k[:len(k)-1], func(b Bucket) error {
		v := b.Bucket.Get(k[len(k)-1])
		if v == nil {
			return nil
		}
		return errorsp.WithStacks(f(bytesp.Slice(v)))
	})
}

// Bucket retrieves a nested bucket by name. Returns nil if the bucket
// does not exist. The bucket instance is only valid for the lifetime of
// the transaction.
func (b Bucket) OpenBucket(folders [][]byte, f func(Bucket) error) error {
	bb := b.Bucket
	for _, fld := range folders {
		bb = bb.Bucket(fld)
		if bb == nil {
			return nil
		}
	}
	return errorsp.WithStacks(f(Bucket{bb}))
}

// CreateBucketIfNotExists creates a new bucket if it doesn't already
// exist and returns a reference to it. Returns an error if the bucket
// name is blank, or if the bucket name is too long. The bucket instance
// is only valid for the lifetime of the transaction.
func (b Bucket) CreateBucketIfNotExists(folders [][]byte) (Bucket, error) {
	bb := b.Bucket
	for _, fld := range folders {
		var err error
		if bb, err = bb.CreateBucketIfNotExists(fld); err != nil {
			return Bucket{}, errorsp.WithStacks(err)
		}
	}
	return Bucket{bb}, nil
}

// Cursor creates a cursor associated with the bucket. The cursor is only
// valid as long as the transaction is open. Do not use a cursor after the
// transaction is closed.
func (b Bucket) Cursor() Cursor {
	return Cursor{b.Bucket.Cursor()}
}

// Delete removes a key from the bucket. If the key does not exist then
// nothing is done and a nil error is returned. Returns an error if the
// bucket was created from a read-only transaction.
func (b Bucket) Delete(k [][]byte) error {
	return b.OpenBucket(k[:len(k)-1], func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.Delete(k[len(k)-1]))
	})
}

// ForEach executes a function for each key/value pair in a bucket. If the
// provided function returns an error then the iteration is stopped and
// the error is returned to the caller. The provided function must not
// modify the bucket; this will result in undefined behavior.
func (b Bucket) ForEach(folders [][]byte, f func(k, v bytesp.Slice) error) error {
	return b.OpenBucket(folders, func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.ForEach(func(k, v []byte) error {
			return errorsp.WithStacks(f(bytesp.Slice(k), bytesp.Slice(k)))
		}))
	})
}

// Get retrieves the value for a key in the bucket. f is not called if
// the key does not exist or if the key is a nested bucket.
func (b Bucket) Value(k [][]byte, f func(bytesp.Slice) error) error {
	return b.OpenBucket(k[:len(k)-1], func(b Bucket) error {
		if v := b.Bucket.Get(k[len(k)-1]); v != nil {
			return errorsp.WithStacks(f(bytesp.Slice(v)))
		}
		return nil
	})
}

// NextSequence returns an autoincrementing integer for the bucket.
func (b Bucket) NextSequence() (uint64, error) {
	s, err := b.Bucket.NextSequence()
	return s, errorsp.WithStacks(err)
}

// Put sets the value for a key in the bucket. If the key exist then its
// previous value will be overwritten. Supplied value must remain valid
// for the life of the transaction. Returns an error if the bucket was
// created from a read-only transaction, if the key is blank, if the key
// is too large, or if the value is too large.
func (b Bucket) Put(k [][]byte, v []byte) error {
	return b.OpenBucket(k[:len(k)-1], func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.Put(k[len(k)-1], v))
	})
}

// Tx returns the tx of the bucket.
func (b Bucket) Tx() Tx {
	return Tx{b.Bucket.Tx()}
}

// Bucket returns the bucket that this cursor was created from.
func (c Cursor) Bucket() Bucket {
	return Bucket{c.Cursor.Bucket()}
}

// Delete removes the current key/value under the cursor from the bucket.
// Delete fails if current key/value is a bucket or if the transaction is
// not writable.
func (c Cursor) Delete() error {
	return errorsp.WithStacks(c.Cursor.Delete())
}
<commit_msg>Add Tx.Update<commit_after>// Package bh provides some helper classes for convenience of using github.com/boltdb/bolt package.
// All wrapper classes will use their friend wrapper classes whenever possible.
// All returned errors are with call stackes using github.com/golangplus/errors.
package bh

import (
	"io"
	"os"

	"github.com/golangplus/bytes"
	"github.com/golangplus/errors"

	"github.com/boltdb/bolt"
)

// A wrapper to *bolt.DB.
type DB struct {
	*bolt.DB
}

// A wrapper to *bolt.Tx.
type Tx struct {
	*bolt.Tx
}

// A wrapper to *bolt.Bucket.
type Bucket struct {
	*bolt.Bucket
}

// A wrapper to *bolt.Cursor.
type Cursor struct {
	*bolt.Cursor
}

// Open creates and opens a database at the given path. If the file does
// not exist then it will be created automatically. Passing in nil options
// will cause Bolt to open the database with the default options.
func Open(path string, mode os.FileMode, options *bolt.Options) (DB, error) {
	db, err := bolt.Open(path, mode, options)
	return DB{db}, errorsp.WithStacks(err)
}

// Batch wraps bolt.DB.Batch.
func (db DB) Batch(f func(Tx) error) error {
	return errorsp.WithStacks(db.DB.Batch(func(tx *bolt.Tx) error {
		return errorsp.WithStacks(f(Tx{tx}))
	}))
}

// Begin wraps bolt.DB.Begin.
func (db DB) Begin(writable bool) (Tx, error) {
	tx, err := db.DB.Begin(writable)
	return Tx{tx}, errorsp.WithStacks(err)
}

// Close releases all database resources. All transactions must be closed
// before closing the database.
func (db DB) Close() error {
	return errorsp.WithStacks(db.DB.Close())
}

// Sync wraps bolt.DB.Sync.
func (db DB) Sync() error {
	return errorsp.WithStacks(db.DB.Sync())
}

// Update wraps bolt.DB.Update.
func (db DB) Update(f func(Tx) error) error {
	return errorsp.WithStacks(db.DB.Update(func(tx *bolt.Tx) error {
		return errorsp.WithStacks(f(Tx{tx}))
	}))
}

// View wraps bolt.DB.View.
func (db DB) View(f func(Tx) error) error {
	return errorsp.WithStacks(db.DB.View(func(tx *bolt.Tx) error {
		return errorsp.WithStacks(f(Tx{tx}))
	}))
}

func (tx Tx) Bucket(folders [][]byte, f func(Bucket) error) error {
	b := tx.Tx.Bucket(folders[0])
	if b == nil {
		return nil
	}
	if len(folders) == 1 {
		return errorsp.WithStacks(f(Bucket{b}))
	}
	return Bucket{b}.OpenBucket(folders[1:], f)
}

// Commit writes all changes to disk and updates the meta page. Returns an
// error if a disk write error occurs, or if Commit is called on a
// read-only transaction.
func (tx Tx) Commit() error {
	return errorsp.WithStacks(tx.Tx.Commit())
}

// CopyFile copies the entire database to file at the given path. A reader
// transaction is maintained during the copy so it is safe to continue
// using the database while a copy is in progress.
func (tx Tx) CopyFile(path string, mode os.FileMode) error {
	return errorsp.WithStacks(tx.Tx.CopyFile(path, mode))
}

// CreateBucketIfNotExists creates a new bucket if it doesn't already
// exist. Returns an error if the bucket name is blank, or if the bucket
// name is too long. The bucket instance is only valid for the lifetime of
// the transaction.
func (tx Tx) CreateBucketIfNotExists(folders [][]byte) (Bucket, error) {
	b, err := tx.Tx.CreateBucketIfNotExists(folders[0])
	if err != nil {
		return Bucket{}, nil
	}
	if len(folders) == 1 {
		return Bucket{b}, nil
	}
	return Bucket{b}.CreateBucketIfNotExists(folders[1:])
}

func (tx Tx) Cursor(folders [][]byte, f func(Cursor) error) error {
	if len(folders) == 0 {
		return errorsp.WithStacks(f(Cursor{tx.Tx.Cursor()}))
	}
	return tx.Bucket(folders, func(b Bucket) error {
		return errorsp.WithStacks(f(b.Cursor()))
	})
}

// DB returns a reference to the database that created the transaction.
func (tx Tx) DB() DB {
	return DB{tx.Tx.DB()}
}

// Delete deletes a key.
func (tx Tx) Delete(k [][]byte) error {
	if len(k) == 1 {
		return errorsp.WithStacks(tx.Tx.DeleteBucket(k[0]))
	}
	return tx.Bucket(k[:len(k)-1], func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.Delete(k[len(k)-1]))
	})
}

// ForEach iterates over all key values of a folder.
func (tx Tx) ForEach(folders [][]byte, f func(Bucket, bytesp.Slice, bytesp.Slice) error) error {
	return tx.Bucket(folders, func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.ForEach(func(k, v []byte) error {
			return errorsp.WithStacks(f(b, bytesp.Slice(k), bytesp.Slice(v)))
		}))
	})
}

// Rollback closes the transaction and ignores all previous updates.
// Read-only transactions must be rolled back and not committed.
func (tx Tx) Rollback() error {
	return errorsp.WithStacks(tx.Tx.Rollback())
}

// WriteTo writes the entire database to a writer. If err == nil then
// exactly tx.Size() bytes will be written into the writer.
func (tx *Tx) WriteTo(w io.Writer) (int64, error) {
	n, err := tx.Tx.WriteTo(w)
	return n, errorsp.WithStacks(err)
}

// Put sets the value for a key in the transaction.
// If the key exist then its previous value will be overwritten.
// Supplied value must remain valid for the life of the transaction.
// Returns an error if the bucket was created from a read-only transaction,
// if the key is blank, if the key is too large, or if the value is too
// large.
func (tx Tx) Put(k [][]byte, v []byte) error {
	b, err := tx.CreateBucketIfNotExists(k[:len(k)-1])
	if err != nil {
		return err
	}
	return errorsp.WithStacks(b.Bucket.Put(k[len(k)-1], v))
}

// Value tries to get a value from the transaction. If the key does not
// exist, the f is not called and nil is return.
func (tx Tx) Value(k [][]byte, f func(v bytesp.Slice) error) error {
	return tx.Bucket(k[:len(k)-1], func(b Bucket) error {
		v := b.Bucket.Get(k[len(k)-1])
		if v == nil {
			return nil
		}
		return errorsp.WithStacks(f(bytesp.Slice(v)))
	})
}

// Updates fetches the current value and updates to a new value. If a nil
// value is returned by f, the item is deleted.
func (tx Tx) Update(k [][]byte, f func(bytesp.Slice) (bytesp.Slice, error)) error {
	b, err := tx.CreateBucketIfNotExists(k[:len(k)-1])
	if err != nil {
		return err
	}
	v, err := f(b.Bucket.Get(k[len(k)-1]))
	if err != nil {
		return errorsp.WithStacks(err)
	}
	if v == nil {
		return errorsp.WithStacks(b.Bucket.Delete(k[len(k)-1]))
	}
	return errorsp.WithStacks(b.Bucket.Put(k[len(k)-1], v))
}

// Bucket retrieves a nested bucket by name. Returns nil if the bucket
// does not exist. The bucket instance is only valid for the lifetime of
// the transaction.
func (b Bucket) OpenBucket(folders [][]byte, f func(Bucket) error) error {
	bb := b.Bucket
	for _, fld := range folders {
		bb = bb.Bucket(fld)
		if bb == nil {
			return nil
		}
	}
	return errorsp.WithStacks(f(Bucket{bb}))
}

// CreateBucketIfNotExists creates a new bucket if it doesn't already
// exist and returns a reference to it. Returns an error if the bucket
// name is blank, or if the bucket name is too long. The bucket instance
// is only valid for the lifetime of the transaction.
func (b Bucket) CreateBucketIfNotExists(folders [][]byte) (Bucket, error) {
	bb := b.Bucket
	for _, fld := range folders {
		var err error
		if bb, err = bb.CreateBucketIfNotExists(fld); err != nil {
			return Bucket{}, errorsp.WithStacks(err)
		}
	}
	return Bucket{bb}, nil
}

// Cursor creates a cursor associated with the bucket. The cursor is only
// valid as long as the transaction is open. Do not use a cursor after the
// transaction is closed.
func (b Bucket) Cursor() Cursor {
	return Cursor{b.Bucket.Cursor()}
}

// Delete removes a key from the bucket. If the key does not exist then
// nothing is done and a nil error is returned. Returns an error if the
// bucket was created from a read-only transaction.
func (b Bucket) Delete(k [][]byte) error {
	return b.OpenBucket(k[:len(k)-1], func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.Delete(k[len(k)-1]))
	})
}

// ForEach executes a function for each key/value pair in a bucket. If the
// provided function returns an error then the iteration is stopped and
// the error is returned to the caller. The provided function must not
// modify the bucket; this will result in undefined behavior.
func (b Bucket) ForEach(folders [][]byte, f func(k, v bytesp.Slice) error) error {
	return b.OpenBucket(folders, func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.ForEach(func(k, v []byte) error {
			return errorsp.WithStacks(f(bytesp.Slice(k), bytesp.Slice(k)))
		}))
	})
}

// Get retrieves the value for a key in the bucket. f is not called if
// the key does not exist or if the key is a nested bucket.
func (b Bucket) Value(k [][]byte, f func(bytesp.Slice) error) error {
	return b.OpenBucket(k[:len(k)-1], func(b Bucket) error {
		if v := b.Bucket.Get(k[len(k)-1]); v != nil {
			return errorsp.WithStacks(f(bytesp.Slice(v)))
		}
		return nil
	})
}

// NextSequence returns an autoincrementing integer for the bucket.
func (b Bucket) NextSequence() (uint64, error) {
	s, err := b.Bucket.NextSequence()
	return s, errorsp.WithStacks(err)
}

// Put sets the value for a key in the bucket. If the key exist then its
// previous value will be overwritten. Supplied value must remain valid
// for the life of the transaction. Returns an error if the bucket was
// created from a read-only transaction, if the key is blank, if the key
// is too large, or if the value is too large.
func (b Bucket) Put(k [][]byte, v []byte) error {
	return b.OpenBucket(k[:len(k)-1], func(b Bucket) error {
		return errorsp.WithStacks(b.Bucket.Put(k[len(k)-1], v))
	})
}

// Tx returns the tx of the bucket.
func (b Bucket) Tx() Tx {
	return Tx{b.Bucket.Tx()}
}

// Bucket returns the bucket that this cursor was created from.
func (c Cursor) Bucket() Bucket {
	return Bucket{c.Cursor.Bucket()}
}

// Delete removes the current key/value under the cursor from the bucket.
// Delete fails if current key/value is a bucket or if the transaction is
// not writable.
func (c Cursor) Delete() error {
	return errorsp.WithStacks(c.Cursor.Delete())
}
<|endoftext|>


<commit_before>package main

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

	// TODO: import your plugins
	// _ "github.com/my_github_user/my_plugin_repo/plugins/inputs/mypluginname"

	"github.com/influxdata/telegraf/plugins/common/shim"
)

var pollInterval = flag.Duration("poll_interval", 1*time.Second, "how often to send metrics")
var pollIntervalDisabled = flag.Bool("poll_interval_disabled", false, "set to true to disable polling. You want to use this when you are sending metrics on your own schedule")
var configFile = flag.String("config", "", "path to the config file for this plugin")
var err error

// This is designed to be simple; Just change the import above and you're good.
//
// However, if you want to do all your config in code, you can like so:
//
// // initialize your plugin with any settngs you want
// myInput := &mypluginname.MyPlugin{
// 	DefaultSettingHere: 3,
// }
//
// shim := shim.New()
//
// shim.AddInput(myInput)
//
// // now the shim.Run() call as below.
//
func main() {
	// parse command line options
	flag.Parse()
	if *pollIntervalDisabled {
		*pollInterval = shim.PollIntervalDisabled
	}

	// create the shim. This is what will run your plugins.
	shim := shim.New()

	// If no config is specified, all imported plugins are loaded.
	// otherwise follow what the config asks for.
	// Check for settings from a config toml file,
	// (or just use whatever plugins were imported above)
	err = shim.LoadConfig(configFile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err loading input: %s\n", err)
		os.Exit(1)
	}

	// run the input plugin(s) until stdin closes or we receive a termination signal
	if err := shim.Run(*pollInterval); err != nil {
		fmt.Fprintf(os.Stderr, "Err: %s\n", err)
		os.Exit(1)
	}
}
<commit_msg>clarify docs around shim plugin loading<commit_after>package main

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

	// TODO: import your plugins
	// _ "github.com/my_github_user/my_plugin_repo/plugins/inputs/mypluginname"

	"github.com/influxdata/telegraf/plugins/common/shim"
)

var pollInterval = flag.Duration("poll_interval", 1*time.Second, "how often to send metrics")
var pollIntervalDisabled = flag.Bool("poll_interval_disabled", false, "set to true to disable polling. You want to use this when you are sending metrics on your own schedule")
var configFile = flag.String("config", "", "path to the config file for this plugin")
var err error

// This is designed to be simple; Just change the import above and you're good.
//
// However, if you want to do all your config in code, you can like so:
//
// // initialize your plugin with any settngs you want
// myInput := &mypluginname.MyPlugin{
// 	DefaultSettingHere: 3,
// }
//
// shim := shim.New()
//
// shim.AddInput(myInput)
//
// // now the shim.Run() call as below. Note the shim is only intended to run a single plugin.
//
func main() {
	// parse command line options
	flag.Parse()
	if *pollIntervalDisabled {
		*pollInterval = shim.PollIntervalDisabled
	}

	// create the shim. This is what will run your plugins.
	shim := shim.New()

	// If no config is specified, all imported plugins are loaded.
	// otherwise follow what the config asks for.
	// Check for settings from a config toml file,
	// (or just use whatever plugins were imported above)
	err = shim.LoadConfig(configFile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Err loading input: %s\n", err)
		os.Exit(1)
	}

	// run a single plugin until stdin closes or we receive a termination signal
	if err := shim.Run(*pollInterval); err != nil {
		fmt.Fprintf(os.Stderr, "Err: %s\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/dokku/dokku/plugins/config"
	columnize "github.com/ryanuber/columnize"
)

const (
	helpHeader = `Usage: dokku config [<app>|--global]

Display all global or app-specific config vars

Additional commands:`

	helpContent = `
    config (<app>|--global), Pretty-print an app or global environment
    config:get (<app>|--global) KEY, Display a global or app-specific config value
    config:set (<app>|--global) [--encoded] [--no-restart] KEY1=VALUE1 [KEY2=VALUE2 ...], Set one or more config vars
    config:unset (<app>|--global) KEY1 [KEY2 ...], Unset one or more config vars
    config:export (<app>|--global) [--envfile], Export a global or app environment
    config:keys (<app>|--global) [--merged], Show keys set in environment
    config:bundle (<app>|--global) [--merged], Bundle environment into tarfile
`
)

func main() {
	flag.Usage = usage
	flag.Parse()

	cmd := flag.Arg(0)
	switch cmd {
	case "config", "config:show":
		args := flag.NewFlagSet("config:show", flag.ExitOnError)
		global := args.Bool("global", false, "--global: use the global environment")
		shell := args.Bool("shell", false, "--shell: in a single-line for usage in command-line utilities [deprecated]")
		export := args.Bool("export", false, "--export: print the env as eval-compatible exports [deprecated]")
		merged := args.Bool("merged", false, "--merged: display the app's envionment merged with the global environment")
		args.Parse(os.Args[2:])
		config.CommandShow(args.Args(), *global, *shell, *export, *merged)
	case "help":
		fmt.Print(helpContent)
	case "config:help":
		usage()
	default:
		dokkuNotImplementExitCode, err := strconv.Atoi(os.Getenv("DOKKU_NOT_IMPLEMENTED_EXIT"))
		if err != nil {
			fmt.Println("failed to retrieve DOKKU_NOT_IMPLEMENTED_EXIT environment variable")
			dokkuNotImplementExitCode = 10
		}
		os.Exit(dokkuNotImplementExitCode)
	}
}

func usage() {
	config := columnize.DefaultConfig()
	config.Delim = ","
	config.Prefix = "    "
	config.Empty = ""
	content := strings.Split(helpContent, "\n")[1:]
	fmt.Println(helpHeader)
	fmt.Println(columnize.Format(content, config))
}
<commit_msg>Fix typo<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/dokku/dokku/plugins/config"
	columnize "github.com/ryanuber/columnize"
)

const (
	helpHeader = `Usage: dokku config [<app>|--global]

Display all global or app-specific config vars

Additional commands:`

	helpContent = `
    config (<app>|--global), Pretty-print an app or global environment
    config:get (<app>|--global) KEY, Display a global or app-specific config value
    config:set (<app>|--global) [--encoded] [--no-restart] KEY1=VALUE1 [KEY2=VALUE2 ...], Set one or more config vars
    config:unset (<app>|--global) KEY1 [KEY2 ...], Unset one or more config vars
    config:export (<app>|--global) [--envfile], Export a global or app environment
    config:keys (<app>|--global) [--merged], Show keys set in environment
    config:bundle (<app>|--global) [--merged], Bundle environment into tarfile
`
)

func main() {
	flag.Usage = usage
	flag.Parse()

	cmd := flag.Arg(0)
	switch cmd {
	case "config", "config:show":
		args := flag.NewFlagSet("config:show", flag.ExitOnError)
		global := args.Bool("global", false, "--global: use the global environment")
		shell := args.Bool("shell", false, "--shell: in a single-line for usage in command-line utilities [deprecated]")
		export := args.Bool("export", false, "--export: print the env as eval-compatible exports [deprecated]")
		merged := args.Bool("merged", false, "--merged: display the app's environment merged with the global environment")
		args.Parse(os.Args[2:])
		config.CommandShow(args.Args(), *global, *shell, *export, *merged)
	case "help":
		fmt.Print(helpContent)
	case "config:help":
		usage()
	default:
		dokkuNotImplementExitCode, err := strconv.Atoi(os.Getenv("DOKKU_NOT_IMPLEMENTED_EXIT"))
		if err != nil {
			fmt.Println("failed to retrieve DOKKU_NOT_IMPLEMENTED_EXIT environment variable")
			dokkuNotImplementExitCode = 10
		}
		os.Exit(dokkuNotImplementExitCode)
	}
}

func usage() {
	config := columnize.DefaultConfig()
	config.Delim = ","
	config.Prefix = "    "
	config.Empty = ""
	content := strings.Split(helpContent, "\n")[1:]
	fmt.Println(helpHeader)
	fmt.Println(columnize.Format(content, config))
}
<|endoftext|>