<commit_before>package store

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/wantedly/developers-account-mapper/models"
)

const (
	accountMapTable = "DevelopersAccountMap"
)

type DynamoDB struct {
	db *dynamodb.DynamoDB
}

func NewDynamoDB() *DynamoDB {
	db := dynamodb.New(session.New(&aws.Config{}))

	return &DynamoDB{
		db: db,
	}
}

func (d *DynamoDB) ListUsers() ([]*models.User, error) {
	resp, err := d.db.Scan(&dynamodb.ScanInput{
		TableName: aws.String(accountMapTable),
	})
	if err != nil {
		return nil, err
	}

	var users []*models.User

	for _, item := range resp.Items {
		users = append(users, models.NewUser(*item["LoginName"].S, *item["GitHubUSername"].S))
	}

	return users, nil
}

func (d *DynamoDB) AddUser(user *models.User) (error) {
	_, err := d.db.PutItem(&dynamodb.PutItemInput{
		TableName: aws.String(accountMapTable),
		Item: map[string]*dynamodb.AttributeValue{
			"LoginName": {
				S: aws.String(user.LoginName),
			},
			"GitHubUsername": {
				S: aws.String(user.GitHubUsername),
			},
		},
	})
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>Fix key name<commit_after>package store

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/wantedly/developers-account-mapper/models"
)

const (
	accountMapTable = "DevelopersAccountMap"
)

type DynamoDB struct {
	db *dynamodb.DynamoDB
}

func NewDynamoDB() *DynamoDB {
	db := dynamodb.New(session.New(&aws.Config{}))

	return &DynamoDB{
		db: db,
	}
}

func (d *DynamoDB) ListUsers() ([]*models.User, error) {
	resp, err := d.db.Scan(&dynamodb.ScanInput{
		TableName: aws.String(accountMapTable),
	})
	if err != nil {
		return nil, err
	}

	var users []*models.User

	for _, item := range resp.Items {
		users = append(users, models.NewUser(*item["LoginName"].S, *item["GitHubUsername"].S))
	}

	return users, nil
}

func (d *DynamoDB) AddUser(user *models.User) (error) {
	_, err := d.db.PutItem(&dynamodb.PutItemInput{
		TableName: aws.String(accountMapTable),
		Item: map[string]*dynamodb.AttributeValue{
			"LoginName": {
				S: aws.String(user.LoginName),
			},
			"GitHubUsername": {
				S: aws.String(user.GitHubUsername),
			},
		},
	})
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package ora

/*
#include <oci.h>
#include "version.h"
*/
import "C"
import (
	"sync"
	"unsafe"
)

type arrHlp struct {
	sync.Mutex
	curlen     C.ub4
	nullInds   []C.sb2
	alen       []C.ACTUAL_LENGTH_TYPE
	rcode      []C.ub2
	allocated  []bool
	isAssocArr bool
}

type ociDef struct {
	sync.Mutex
	ocidef *C.OCIDefine
	rset   *Rset
	arrHlp
}

func (d *ociDef) defineByPos(position int, valuep unsafe.Pointer, valueSize int, dty int) error {
	d.Lock()
	defer d.Unlock()
	d.ensureFetchLength(d.rset.stmt.Cfg().FetchLen())
	// If you omit the rlenp parameter of OCIDefineByPos(), returned values are blank-padded to the buffer length, and NULLs are returned as a string of blank characters. If rlenp is included, returned values are not blank-padded. Instead, their actual lengths are returned in the rlenp parameter.
	if r := C.OCIDEFINEBYPOS(
		d.rset.ocistmt,    //OCIStmt     *stmtp,
		&d.ocidef,         //OCIDefine   **defnpp,
		d.rset.env.ocierr, //OCIError    *errhp,
		C.ub4(position),   //ub4         position,
		valuep,            //void        *valuep,
		C.LENGTH_TYPE(valueSize),       //sb8         value_sz,
		C.ub2(dty),                     //ub2         dty,
		unsafe.Pointer(&d.nullInds[0]), //void        *indp,
		&d.alen[0],                     //ub4         *rlenp,
		&d.rcode[0],                    //ub2         *rcodep,
		C.OCI_DEFAULT,                  //ub4         mode );
	); r == C.OCI_ERROR {
		return d.rset.stmt.ses.srv.env.ociError()
	}
	if r := C.OCIDefineArrayOfStruct(
		d.ocidef,          //OCIDefine *defnp
		d.rset.env.ocierr, //OCIError *errhp,
		C.ub4(valueSize),  //ub4 pvskip,
		2,                 //ub4 indskip,
		C.ACTUAL_LENGTH_LENGTH, //ub4 rlskip,
		2, //ub4 rcskip
	); r == C.OCI_ERROR {
		return d.rset.env.ociError()
	}
	return nil
}

var (
	sb2Pool  = sync.Pool{New: func() interface{} { z := []C.sb2{}; return &z }}
	ub2Pool  = sync.Pool{New: func() interface{} { z := []C.ub2{}; return &z }}
	alenPool = sync.Pool{New: func() interface{} { z := []C.ACTUAL_LENGTH_TYPE{}; return &z }}
)

func (d *arrHlp) ensureAllocatedLength(length int) {
	d.Lock()
	defer d.Unlock()
	if cap(d.allocated) < length {
		d.allocated = make([]bool, length)
		return
	}
	d.allocated = d.allocated[:length]
	for i := range d.allocated {
		d.allocated[i] = false
	}
}

func (a *arrHlp) ensureFetchLength(length int) {
	if length <= 0 || length >= MaxFetchLen {
		length = MaxFetchLen
	}
	a.Lock()
	defer a.Unlock()
	if cap(a.nullInds) >= length {
		a.nullInds = a.nullInds[:length]
	} else {
		if a.nullInds = *(sb2Pool.Get().(*[]C.sb2)); cap(a.nullInds) < length {
			a.nullInds = make([]C.sb2, length)
		} else {
			a.nullInds = a.nullInds[:length]
		}
	}
	if cap(a.alen) >= length {
		a.alen = a.alen[:length]
	} else {
		if a.alen = *(alenPool.Get().(*[]C.ACTUAL_LENGTH_TYPE)); cap(a.alen) < length {
			a.alen = make([]C.ACTUAL_LENGTH_TYPE, length)
		} else {
			a.alen = a.alen[:length]
		}
	}
	if cap(a.rcode) >= length {
		a.rcode = a.rcode[:length]
	} else {
		if a.rcode = *(ub2Pool.Get().(*[]C.ub2)); cap(a.rcode) < length {
			a.rcode = make([]C.ub2, length)
		} else {
			a.rcode = a.rcode[:length]
		}
	}
}

// ensureBindArrLength calculates the needed length and capacity,
// and sets up the helper arrays for binding PL/SQL Table.
//
// Returns whether and element is needed to be appended to the value slice.
func (a *arrHlp) ensureBindArrLength(
	length, capacity *int,
	isAssocArray bool,
) (iterations uint32, curlenp *C.ub4, needsAppend bool) {
	a.Lock()
	defer a.Unlock()
	a.curlen = C.ub4(*length) // the real length, not L!
	if isAssocArray {
		// for PL/SQL associative arrays
		curlenp = &a.curlen
		iterations = 1
		a.isAssocArr = true
		if *length == 0 {
			*length = 1
			if *capacity == 0 {
				needsAppend = true
				*capacity = 1
			}
		}
	} else {
		curlenp = nil
		iterations = uint32(*length)
		a.isAssocArr = false
	}
	L, C := *length, *capacity
	if cap(a.nullInds) >= C {
		a.nullInds = (a.nullInds)[:L]
	} else {
		if a.nullInds = *(sb2Pool.Get().(*[]C.sb2)); cap(a.nullInds) < C {
			a.nullInds = make([]C.sb2, L, C)
		} else {
			a.nullInds = (a.nullInds)[:L]
		}
	}
	if cap(a.alen) >= C {
		a.alen = a.alen[:L]
	} else {
		if a.alen = *(alenPool.Get().(*[]C.ACTUAL_LENGTH_TYPE)); cap(a.alen) < C {
			a.alen = make([]C.ACTUAL_LENGTH_TYPE, L, C)
		} else {
			a.alen = a.alen[:L]
		}
	}
	if cap(a.rcode) >= C {
		a.rcode = a.rcode[:L]
	} else {
		if a.rcode = *(ub2Pool.Get().(*[]C.ub2)); cap(a.rcode) < C {
			a.rcode = make([]C.ub2, L, C)
		} else {
			a.rcode = a.rcode[:L]
		}
	}
	return iterations, curlenp, needsAppend
}

// IsAssocArr returns true if the bind uses PL/SQL Table.
func (a *arrHlp) IsAssocArr() bool {
	a.Lock()
	defer a.Unlock()
	return a.isAssocArr
}

// close nils the slices, except when this is a PL/SQL Table.
//
// The reason for this is that for PL/SQL Tables, after exe returns,
// the bound slices can be reused; otherwise, they are still in use for
// the subsequent iterations!
func (a *arrHlp) close() error {
	a.Lock()
	defer a.Unlock()
	if a == nil {
		return nil
	}
	if a.isAssocArr {
		return nil
	}
	if a.nullInds != nil {
		sb2Pool.Put(&a.nullInds)
		a.nullInds = nil
	}
	if a.alen != nil {
		alenPool.Put(&a.alen)
		a.alen = nil
	}
	if a.rcode != nil {
		ub2Pool.Put(&a.rcode)
		a.rcode = nil
	}
	if a.allocated != nil {
		a.allocated = nil
	}
	return nil
}

func getMaxarrLen(C int, isAssocArray bool) C.ub4 {
	if !isAssocArray {
		return 0
	}
	return C.ub4(C)
}
<commit_msg>Revert "add locks to arrHlp, but this is not enough for #244"<commit_after>package ora

/*
#include <oci.h>
#include "version.h"
*/
import "C"
import (
	"sync"
	"unsafe"
)

type arrHlp struct {
	sync.Mutex
	curlen     C.ub4
	nullInds   []C.sb2
	alen       []C.ACTUAL_LENGTH_TYPE
	rcode      []C.ub2
	allocated  []bool
	isAssocArr bool
}

type ociDef struct {
	ocidef *C.OCIDefine
	rset   *Rset
	arrHlp
}

func (d *ociDef) defineByPos(position int, valuep unsafe.Pointer, valueSize int, dty int) error {
	d.ensureFetchLength(d.rset.stmt.Cfg().FetchLen())
	// If you omit the rlenp parameter of OCIDefineByPos(), returned values are blank-padded to the buffer length, and NULLs are returned as a string of blank characters. If rlenp is included, returned values are not blank-padded. Instead, their actual lengths are returned in the rlenp parameter.
	if r := C.OCIDEFINEBYPOS(
		d.rset.ocistmt,    //OCIStmt     *stmtp,
		&d.ocidef,         //OCIDefine   **defnpp,
		d.rset.env.ocierr, //OCIError    *errhp,
		C.ub4(position),   //ub4         position,
		valuep,            //void        *valuep,
		C.LENGTH_TYPE(valueSize),       //sb8         value_sz,
		C.ub2(dty),                     //ub2         dty,
		unsafe.Pointer(&d.nullInds[0]), //void        *indp,
		&d.alen[0],                     //ub4         *rlenp,
		&d.rcode[0],                    //ub2         *rcodep,
		C.OCI_DEFAULT,                  //ub4         mode );
	); r == C.OCI_ERROR {
		return d.rset.stmt.ses.srv.env.ociError()
	}
	if r := C.OCIDefineArrayOfStruct(
		d.ocidef,          //OCIDefine *defnp
		d.rset.env.ocierr, //OCIError *errhp,
		C.ub4(valueSize),  //ub4 pvskip,
		2,                 //ub4 indskip,
		C.ACTUAL_LENGTH_LENGTH, //ub4 rlskip,
		2, //ub4 rcskip
	); r == C.OCI_ERROR {
		return d.rset.env.ociError()
	}
	return nil
}

var (
	sb2Pool  = sync.Pool{New: func() interface{} { z := []C.sb2{}; return &z }}
	ub2Pool  = sync.Pool{New: func() interface{} { z := []C.ub2{}; return &z }}
	alenPool = sync.Pool{New: func() interface{} { z := []C.ACTUAL_LENGTH_TYPE{}; return &z }}
)

func (d *arrHlp) ensureAllocatedLength(length int) {
	if cap(d.allocated) < length {
		d.allocated = make([]bool, length)
		return
	}
	d.allocated = d.allocated[:length]
	for i := range d.allocated {
		d.allocated[i] = false
	}
}

func (a *arrHlp) ensureFetchLength(length int) {
	if length <= 0 || length >= MaxFetchLen {
		length = MaxFetchLen
	}
	if cap(a.nullInds) >= length {
		a.nullInds = a.nullInds[:length]
	} else {
		if a.nullInds = *(sb2Pool.Get().(*[]C.sb2)); cap(a.nullInds) < length {
			a.nullInds = make([]C.sb2, length)
		} else {
			a.nullInds = a.nullInds[:length]
		}
	}
	if cap(a.alen) >= length {
		a.alen = a.alen[:length]
	} else {
		if a.alen = *(alenPool.Get().(*[]C.ACTUAL_LENGTH_TYPE)); cap(a.alen) < length {
			a.alen = make([]C.ACTUAL_LENGTH_TYPE, length)
		} else {
			a.alen = a.alen[:length]
		}
	}
	if cap(a.rcode) >= length {
		a.rcode = a.rcode[:length]
	} else {
		if a.rcode = *(ub2Pool.Get().(*[]C.ub2)); cap(a.rcode) < length {
			a.rcode = make([]C.ub2, length)
		} else {
			a.rcode = a.rcode[:length]
		}
	}
}

// ensureBindArrLength calculates the needed length and capacity,
// and sets up the helper arrays for binding PL/SQL Table.
//
// Returns whether and element is needed to be appended to the value slice.
func (a *arrHlp) ensureBindArrLength(
	length, capacity *int,
	isAssocArray bool,
) (iterations uint32, curlenp *C.ub4, needsAppend bool) {
	a.curlen = C.ub4(*length) // the real length, not L!
	if isAssocArray {
		// for PL/SQL associative arrays
		curlenp = &a.curlen
		iterations = 1
		a.isAssocArr = true
		if *length == 0 {
			*length = 1
			if *capacity == 0 {
				needsAppend = true
				*capacity = 1
			}
		}
	} else {
		curlenp = nil
		iterations = uint32(*length)
		a.isAssocArr = false
	}
	L, C := *length, *capacity
	if cap(a.nullInds) >= C {
		a.nullInds = (a.nullInds)[:L]
	} else {
		if a.nullInds = *(sb2Pool.Get().(*[]C.sb2)); cap(a.nullInds) < C {
			a.nullInds = make([]C.sb2, L, C)
		} else {
			a.nullInds = (a.nullInds)[:L]
		}
	}
	if cap(a.alen) >= C {
		a.alen = a.alen[:L]
	} else {
		if a.alen = *(alenPool.Get().(*[]C.ACTUAL_LENGTH_TYPE)); cap(a.alen) < C {
			a.alen = make([]C.ACTUAL_LENGTH_TYPE, L, C)
		} else {
			a.alen = a.alen[:L]
		}
	}
	if cap(a.rcode) >= C {
		a.rcode = a.rcode[:L]
	} else {
		if a.rcode = *(ub2Pool.Get().(*[]C.ub2)); cap(a.rcode) < C {
			a.rcode = make([]C.ub2, L, C)
		} else {
			a.rcode = a.rcode[:L]
		}
	}
	return iterations, curlenp, needsAppend
}

// IsAssocArr returns true if the bind uses PL/SQL Table.
func (a arrHlp) IsAssocArr() bool {
	return a.isAssocArr
}

// close nils the slices, except when this is a PL/SQL Table.
//
// The reason for this is that for PL/SQL Tables, after exe returns,
// the bound slices can be reused; otherwise, they are still in use for
// the subsequent iterations!
func (a *arrHlp) close() error {
	if a == nil {
		return nil
	}
	if a.isAssocArr {
		return nil
	}
	if a.nullInds != nil {
		sb2Pool.Put(&a.nullInds)
		a.nullInds = nil
	}
	if a.alen != nil {
		alenPool.Put(&a.alen)
		a.alen = nil
	}
	if a.rcode != nil {
		ub2Pool.Put(&a.rcode)
		a.rcode = nil
	}
	if a.allocated != nil {
		a.allocated = nil
	}
	return nil
}

func getMaxarrLen(C int, isAssocArray bool) C.ub4 {
	if !isAssocArray {
		return 0
	}
	return C.ub4(C)
}
<|endoftext|>


<commit_before>package fit_test

import (
	"bytes"
	"compress/gzip"
	"fmt"
	"go/format"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strconv"

	"github.com/cespare/xxhash"
	"github.com/kortschak/utter"
	"github.com/tormoder/fit"
)

func fitFingerprint(fit *fit.File) uint64 {
	h := xxhash.New()
	utter.Fdump(h, fit)
	return h.Sum64()
}

func fitUtterDump(fit *fit.File, path string, compressed bool) error {
	f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0644)
	if err != nil {
		return err
	}
	var w io.WriteCloser
	if compressed {
		w = gzip.NewWriter(f)
	} else {
		w = f
	}

	utter.Fdump(w, fit)

	if !compressed {
		return f.Close()
	}

	err = w.Close()
	if err != nil {
		_ = f.Close()
		return err
	}
	return f.Close()
}

// testingDecodeOpts is a convenience type to simplify code generation for
// reader_files_test.go.
type testingDecodeOpts int

const (
	tdoNone testingDecodeOpts = iota
	tdoAllWithDiscardLogger
	tdoStderrLogger
)

func (tdo testingDecodeOpts) opts() []fit.DecodeOption {
	return tdoOpts[tdo]
}

var tdoOpts = [...][]fit.DecodeOption{
	nil,
	{
		fit.WithUnknownFields(),
		fit.WithUnknownMessages(),
		fit.WithLogger(discardLogger()), // For test coverage.
	},
	{
		fit.WithStdLogger(), // For debugging.
	},
}

func (tdo testingDecodeOpts) String() string {
	return tdoString[tdo]
}

var tdoString = [...]string{
	"tdoNone",
	"tdoAllWithDiscardLogger",
	"tdoStderrLogger",
}

func discardLogger() *log.Logger {
	return log.New(ioutil.Discard, "", 0)
}

func regenerateDecodeTestTable() error {
	const header = `// Generated by reader_util_test.go.
// Only edit to bootstrap new entries or change existing entries.

package fit_test

var decodeTestFiles = [...]struct {
	folder      string
	name        string
	wantErr     bool
	fingerprint uint64
	compress    bool
	dopts       testingDecodeOpts
}{
`

	g := new(gen)
	g.WriteString(header)
	for _, dto := range decodeTestFiles {
		g.openField()
		g.writeStringQField(dto.folder)
		g.writeStringQField(dto.name)
		g.writeBoolField(dto.wantErr)
		g.writeUintField(dto.fingerprint)
		g.writeBoolField(dto.compress)
		g.writeStringField(dto.dopts.String())
		g.closeField()
	}

	g.WriteString("}\n")

	preFormat := g.Bytes()
	src, err := format.Source(preFormat)
	if err != nil {
		return fmt.Errorf("format.Source: %v on\n%s", err, preFormat)
	}

	return ioutil.WriteFile("reader_files_test.go", src, 0644)
}

type gen struct {
	bytes.Buffer
}

func (g *gen) openField() {
	g.WriteString("{\n")
}

func (g *gen) closeField() {
	g.WriteString("},\n")
}

func (g *gen) writeStringField(s string) {
	g.WriteString(s)
	g.WriteString(",\n")
}

func (g *gen) writeStringQField(s string) {
	g.WriteString(strconv.Quote(s))
	g.WriteString(",\n")
}

func (g *gen) writeBoolField(b bool) {
	g.WriteString(strconv.FormatBool(b))
	g.WriteString(",\n")
}

func (g *gen) writeUintField(u uint64) {
	g.WriteString(strconv.FormatUint(u, 10))
	g.WriteString(",\n")
}
<commit_msg>reader_util_test: Truncate file when dumping<commit_after>package fit_test

import (
	"bytes"
	"compress/gzip"
	"fmt"
	"go/format"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strconv"

	"github.com/cespare/xxhash"
	"github.com/kortschak/utter"
	"github.com/tormoder/fit"
)

func fitFingerprint(fit *fit.File) uint64 {
	h := xxhash.New()
	utter.Fdump(h, fit)
	return h.Sum64()
}

func fitUtterDump(fit *fit.File, path string, compressed bool) error {
	f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	var w io.WriteCloser
	if compressed {
		w = gzip.NewWriter(f)
	} else {
		w = f
	}

	utter.Fdump(w, fit)

	if !compressed {
		return f.Close()
	}

	err = w.Close()
	if err != nil {
		_ = f.Close()
		return err
	}
	return f.Close()
}

// testingDecodeOpts is a convenience type to simplify code generation for
// reader_files_test.go.
type testingDecodeOpts int

const (
	tdoNone testingDecodeOpts = iota
	tdoAllWithDiscardLogger
	tdoStderrLogger
)

func (tdo testingDecodeOpts) opts() []fit.DecodeOption {
	return tdoOpts[tdo]
}

var tdoOpts = [...][]fit.DecodeOption{
	nil,
	{
		fit.WithUnknownFields(),
		fit.WithUnknownMessages(),
		fit.WithLogger(discardLogger()), // For test coverage.
	},
	{
		fit.WithStdLogger(), // For debugging.
	},
}

func (tdo testingDecodeOpts) String() string {
	return tdoString[tdo]
}

var tdoString = [...]string{
	"tdoNone",
	"tdoAllWithDiscardLogger",
	"tdoStderrLogger",
}

func discardLogger() *log.Logger {
	return log.New(ioutil.Discard, "", 0)
}

func regenerateDecodeTestTable() error {
	const header = `// Generated by reader_util_test.go.
// Only edit to bootstrap new entries or change existing entries.

package fit_test

var decodeTestFiles = [...]struct {
	folder      string
	name        string
	wantErr     bool
	fingerprint uint64
	compress    bool
	dopts       testingDecodeOpts
}{
`

	g := new(gen)
	g.WriteString(header)
	for _, dto := range decodeTestFiles {
		g.openField()
		g.writeStringQField(dto.folder)
		g.writeStringQField(dto.name)
		g.writeBoolField(dto.wantErr)
		g.writeUintField(dto.fingerprint)
		g.writeBoolField(dto.compress)
		g.writeStringField(dto.dopts.String())
		g.closeField()
	}

	g.WriteString("}\n")

	preFormat := g.Bytes()
	src, err := format.Source(preFormat)
	if err != nil {
		return fmt.Errorf("format.Source: %v on\n%s", err, preFormat)
	}

	return ioutil.WriteFile("reader_files_test.go", src, 0644)
}

type gen struct {
	bytes.Buffer
}

func (g *gen) openField() {
	g.WriteString("{\n")
}

func (g *gen) closeField() {
	g.WriteString("},\n")
}

func (g *gen) writeStringField(s string) {
	g.WriteString(s)
	g.WriteString(",\n")
}

func (g *gen) writeStringQField(s string) {
	g.WriteString(strconv.Quote(s))
	g.WriteString(",\n")
}

func (g *gen) writeBoolField(b bool) {
	g.WriteString(strconv.FormatBool(b))
	g.WriteString(",\n")
}

func (g *gen) writeUintField(u uint64) {
	g.WriteString(strconv.FormatUint(u, 10))
	g.WriteString(",\n")
}
<|endoftext|>


<commit_before>// Copyright 2013 The go-logger Authors. All rights reserved.
// This code is MIT licensed. See the LICENSE file for more info.

package log

import (
	"bytes"
	"fmt"
	"io"
	"math/rand"
	"os"
	"path/filepath"
	"testing"
	"runtime"
	"time"
)

func TestStream(t *testing.T) {
	var buf bytes.Buffer
	logr := New(LEVEL_CRITICAL, os.Stdout, &buf)
	logr.Streams[1] = &buf
	if out := logr.Streams[1]; out != &buf {
		t.Errorf("Stream = %p, want %p", out, &buf)
	}
}

func TestMultiStreams(t *testing.T) {
	rand.Seed(time.Now().UnixNano())
	fPath := filepath.Join(os.TempDir(), fmt.Sprint("go_test_",
		rand.Int()))
	file, err := os.Create(fPath)
	if err != nil {
		t.Error("Create(%q) = %v; want: nil", fPath, err)
	}
	defer file.Close()
	var buf bytes.Buffer
	eLen := 55
	logr := New(LEVEL_DEBUG, file, &buf)
	logr.Debugln("Testing debug output!")
	b := make([]byte, eLen)
	n, err := file.ReadAt(b, 0)
	if n != eLen || err != nil {
		t.Errorf("Read(%d) = %d, %v; want: %d, nil", eLen, n, err,
			eLen)
	}
	if buf.Len() != eLen {
		t.Errorf("buf.Len() = %d; want: %d", buf.Len(), eLen)
	}
}

func TestLongFileFlag(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LlongFileName)

	Debugln("Test long file flag")

	_, file, _, _ := runtime.Caller(0)

	expect := fmt.Sprintf("[DEBUG] %s: Test long file flag\n", file)

	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestShortFileFlag(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LshortFileName)

	Debugln("Test short file flag")

	_, file, _, _ := runtime.Caller(0)

	short := file
	for i := len(file) - 1; i > 0; i-- {
		if file[i] == '/' {
			short = file[i+1:]
			break
		}
	}
	file = short

	expect := fmt.Sprintf("[DEBUG] %s: Test short file flag\n", file)

	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

var (
	boldPrefix  = AnsiEscape(ANSI_BOLD, "TEST>", ANSI_OFF)
	colorPrefix = AnsiEscape(ANSI_BOLD, ANSI_RED, "TEST>", ANSI_OFF)
	date        = "Mon 20060102 15:04:05"
)

var outputTests = []struct {
	template   string
	prefix     string
	level      level
	dateFormat string
	flags      int
	text       string
	want       string
	wantErr    bool
}{

	// The %s format specifier is the placeholder for the date.
	{logFmt, boldPrefix, LEVEL_ALL, date, LstdFlags, "test number 1",
		"%s \x1b[1mTEST>\x1b[0m test number 1", false},

	{logFmt, colorPrefix, LEVEL_ALL, date, LstdFlags, "test number 2",
		"%s \x1b[1m\x1b[31mTEST>\x1b[0m test number 2", false},

	// Test output with coloring turned off
	{logFmt, AnsiEscape(ANSI_BOLD, "::", ANSI_OFF), LEVEL_ALL, date, Ldate,
		"test number 3", "%s :: test number 3", false},

	{logFmt, defaultPrefixColor, LEVEL_DEBUG, time.RubyDate, LstdFlags,
		"test number 4",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[37m[DEBUG]\x1b[0m test number 4",
		false},

	{logFmt, defaultPrefixColor, LEVEL_INFO, time.RubyDate, LstdFlags,
		"test number 5",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[32m[INFO]\x1b[0m test number 5",
		false},

	{logFmt, defaultPrefixColor, LEVEL_WARNING, time.RubyDate, LstdFlags,
		"test number 6",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[33m[WARNING]\x1b[0m test number 6",
		false},

	{logFmt, defaultPrefixColor, LEVEL_ERROR, time.RubyDate, LstdFlags,
		"test number 7",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[35m[ERROR]\x1b[0m test number 7",
		false},

	{logFmt, defaultPrefixColor, LEVEL_CRITICAL, time.RubyDate, LstdFlags,
		"test number 8",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[31m[CRITICAL]\x1b[0m test number 8",
		false},

	// Test date format
	{logFmt, defaultPrefixColor, LEVEL_ALL, "Mon 20060102 15:04:05",
		Ldate, "test number 9",
		"%s :: test number 9", false},
}

func TestOutput(t *testing.T) {
	for i, k := range outputTests {
		var buf bytes.Buffer
		logr := New(LEVEL_DEBUG, &buf)
		logr.Prefix = k.prefix
		logr.DateFormat = k.dateFormat
		logr.Flags = k.flags
		logr.Level = k.level
		d := time.Now().Format(logr.DateFormat)
		n, err := logr.Fprint(k.level, 1, k.text, &buf)
		if n != buf.Len() {
			t.Error("Error: ", io.ErrShortWrite)
		}
		want := fmt.Sprintf(k.want, d)
		if buf.String() != want || err != nil && !k.wantErr {
			t.Errorf("Print test %d failed, \ngot:  %q\nwant: "+
				"%q", i+1, buf.String(), want)
			continue
		}
	}
}

func TestLevel(t *testing.T) {
	var buf bytes.Buffer
	logr := New(LEVEL_CRITICAL, &buf)
	logr.Debug("This level should produce no output")
	if buf.Len() != 0 {
		t.Errorf("Debug() produced output at LEVEL_CRITICAL logging level")
	}
	logr.Level = LEVEL_DEBUG
	logr.Debug("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the LEVEL_DEBUG logging level")
	}
	buf.Reset()
	logr.Level = LEVEL_CRITICAL
	logr.Println("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the ALL logging level")
	}
	buf.Reset()
	logr.Level = LEVEL_ALL
	logr.Debug("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the ALL logging level")
	}
}

func TestPrefixNewline(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)

	Debug("\n\nThis line should be padded with newlines.\n\n")

	expect := "\n\n[DEBUG] This line should be padded with newlines.\n\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n%q\nGot:\n%q\n", expect, buf.String())
	}
}

func TestFlagsLdate(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)

	Debugln("This output should not have a date.")

	expect := "[DEBUG] This output should not have a date.\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestFlagsLfunctionName(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LfunctionName)

	Debugln("This output should have a function name.")

	expect := "[DEBUG] TestFlagsLfunctionName: This output should have a function name.\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestFlagsNoLansiWithNewlinePadding(t *testing.T) {
	var buf bytes.Buffer
	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)
	Debug("\n\nThis output should be padded with newlines and not colored.\n\n")
	expect := "\n\n[DEBUG] This output should be padded with newlines and not colored.\n\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}
<commit_msg>logger_test.go: Add TestFlagsLfunctionNameWithFileName<commit_after>// Copyright 2013 The go-logger Authors. All rights reserved.
// This code is MIT licensed. See the LICENSE file for more info.

package log

import (
	"bytes"
	"fmt"
	"io"
	"math/rand"
	"os"
	"path/filepath"
	"testing"
	"runtime"
	"time"
)

func TestStream(t *testing.T) {
	var buf bytes.Buffer
	logr := New(LEVEL_CRITICAL, os.Stdout, &buf)
	logr.Streams[1] = &buf
	if out := logr.Streams[1]; out != &buf {
		t.Errorf("Stream = %p, want %p", out, &buf)
	}
}

func TestMultiStreams(t *testing.T) {
	rand.Seed(time.Now().UnixNano())
	fPath := filepath.Join(os.TempDir(), fmt.Sprint("go_test_",
		rand.Int()))
	file, err := os.Create(fPath)
	if err != nil {
		t.Error("Create(%q) = %v; want: nil", fPath, err)
	}
	defer file.Close()
	var buf bytes.Buffer
	eLen := 55
	logr := New(LEVEL_DEBUG, file, &buf)
	logr.Debugln("Testing debug output!")
	b := make([]byte, eLen)
	n, err := file.ReadAt(b, 0)
	if n != eLen || err != nil {
		t.Errorf("Read(%d) = %d, %v; want: %d, nil", eLen, n, err,
			eLen)
	}
	if buf.Len() != eLen {
		t.Errorf("buf.Len() = %d; want: %d", buf.Len(), eLen)
	}
}

func TestLongFileFlag(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LlongFileName)

	Debugln("Test long file flag")

	_, file, _, _ := runtime.Caller(0)

	expect := fmt.Sprintf("[DEBUG] %s: Test long file flag\n", file)

	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestShortFileFlag(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LshortFileName)

	Debugln("Test short file flag")

	_, file, _, _ := runtime.Caller(0)

	short := file
	for i := len(file) - 1; i > 0; i-- {
		if file[i] == '/' {
			short = file[i+1:]
			break
		}
	}
	file = short

	expect := fmt.Sprintf("[DEBUG] %s: Test short file flag\n", file)

	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

var (
	boldPrefix  = AnsiEscape(ANSI_BOLD, "TEST>", ANSI_OFF)
	colorPrefix = AnsiEscape(ANSI_BOLD, ANSI_RED, "TEST>", ANSI_OFF)
	date        = "Mon 20060102 15:04:05"
)

var outputTests = []struct {
	template   string
	prefix     string
	level      level
	dateFormat string
	flags      int
	text       string
	want       string
	wantErr    bool
}{

	// The %s format specifier is the placeholder for the date.
	{logFmt, boldPrefix, LEVEL_ALL, date, LstdFlags, "test number 1",
		"%s \x1b[1mTEST>\x1b[0m test number 1", false},

	{logFmt, colorPrefix, LEVEL_ALL, date, LstdFlags, "test number 2",
		"%s \x1b[1m\x1b[31mTEST>\x1b[0m test number 2", false},

	// Test output with coloring turned off
	{logFmt, AnsiEscape(ANSI_BOLD, "::", ANSI_OFF), LEVEL_ALL, date, Ldate,
		"test number 3", "%s :: test number 3", false},

	{logFmt, defaultPrefixColor, LEVEL_DEBUG, time.RubyDate, LstdFlags,
		"test number 4",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[37m[DEBUG]\x1b[0m test number 4",
		false},

	{logFmt, defaultPrefixColor, LEVEL_INFO, time.RubyDate, LstdFlags,
		"test number 5",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[32m[INFO]\x1b[0m test number 5",
		false},

	{logFmt, defaultPrefixColor, LEVEL_WARNING, time.RubyDate, LstdFlags,
		"test number 6",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[33m[WARNING]\x1b[0m test number 6",
		false},

	{logFmt, defaultPrefixColor, LEVEL_ERROR, time.RubyDate, LstdFlags,
		"test number 7",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[35m[ERROR]\x1b[0m test number 7",
		false},

	{logFmt, defaultPrefixColor, LEVEL_CRITICAL, time.RubyDate, LstdFlags,
		"test number 8",
		"%s \x1b[1m\x1b[32m::\x1b[0m \x1b[1m\x1b[31m[CRITICAL]\x1b[0m test number 8",
		false},

	// Test date format
	{logFmt, defaultPrefixColor, LEVEL_ALL, "Mon 20060102 15:04:05",
		Ldate, "test number 9",
		"%s :: test number 9", false},
}

func TestOutput(t *testing.T) {
	for i, k := range outputTests {
		var buf bytes.Buffer
		logr := New(LEVEL_DEBUG, &buf)
		logr.Prefix = k.prefix
		logr.DateFormat = k.dateFormat
		logr.Flags = k.flags
		logr.Level = k.level
		d := time.Now().Format(logr.DateFormat)
		n, err := logr.Fprint(k.level, 1, k.text, &buf)
		if n != buf.Len() {
			t.Error("Error: ", io.ErrShortWrite)
		}
		want := fmt.Sprintf(k.want, d)
		if buf.String() != want || err != nil && !k.wantErr {
			t.Errorf("Print test %d failed, \ngot:  %q\nwant: "+
				"%q", i+1, buf.String(), want)
			continue
		}
	}
}

func TestLevel(t *testing.T) {
	var buf bytes.Buffer
	logr := New(LEVEL_CRITICAL, &buf)
	logr.Debug("This level should produce no output")
	if buf.Len() != 0 {
		t.Errorf("Debug() produced output at LEVEL_CRITICAL logging level")
	}
	logr.Level = LEVEL_DEBUG
	logr.Debug("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the LEVEL_DEBUG logging level")
	}
	buf.Reset()
	logr.Level = LEVEL_CRITICAL
	logr.Println("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the ALL logging level")
	}
	buf.Reset()
	logr.Level = LEVEL_ALL
	logr.Debug("This level should produce output")
	if buf.Len() == 0 {
		t.Errorf("Debug() did not produce output at the ALL logging level")
	}
}

func TestPrefixNewline(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)

	Debug("\n\nThis line should be padded with newlines.\n\n")

	expect := "\n\n[DEBUG] This line should be padded with newlines.\n\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n%q\nGot:\n%q\n", expect, buf.String())
	}
}

func TestFlagsLdate(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)

	Debugln("This output should not have a date.")

	expect := "[DEBUG] This output should not have a date.\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestFlagsLfunctionName(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LfunctionName)

	Debugln("This output should have a function name.")

	expect := "[DEBUG] TestFlagsLfunctionName: This output should have a function name.\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestFlagsLfunctionNameWithFileName(t *testing.T) {
	var buf bytes.Buffer

	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix | LfunctionName | LshortFileName)

	Debug("This output should have a file name and a function name.")

	expect := "[DEBUG] logger_test.go: TestFlagsLfunctionNameWithFileName"+
		": This output should have a file name and a function name."
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}

func TestFlagsNoLansiWithNewlinePadding(t *testing.T) {
	var buf bytes.Buffer
	SetStreams(&buf)
	SetLevel(LEVEL_DEBUG)
	SetFlags(LnoPrefix)
	Debug("\n\nThis output should be padded with newlines and not colored.\n\n")
	expect := "\n\n[DEBUG] This output should be padded with newlines and not colored.\n\n"
	if buf.String() != expect {
		t.Errorf("\nExpect:\n\t%q\nGot:\n\t%q\n", expect, buf.String())
	}
}
<|endoftext|>


<commit_before>package bitrise

import (
	"errors"
	"fmt"
	"runtime"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise/configs"
	"github.com/bitrise-io/bitrise/toolkits"
	"github.com/bitrise-io/bitrise/version"
	"github.com/bitrise-io/go-utils/colorstring"
)

const (
	minEnvmanVersion  = "1.1.3"
	minStepmanVersion = "0.9.30"
)

// PluginDependency ..
type PluginDependency struct {
	Source     string
	MinVersion string
}

// PluginDependencyMap ...
var PluginDependencyMap = map[string]PluginDependency{
	"init": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-init.git",
		MinVersion: "0.9.2",
	},
	"step": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-step.git",
		MinVersion: "0.9.1",
	},
	"workflow-editor": PluginDependency{
		Source:     "https://github.com/bitrise-io/bitrise-workflow-editor.git",
		MinVersion: "0.9.9",
	},
	"analytics": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-analytics.git",
		MinVersion: "0.9.9",
	},
}

// RunSetupIfNeeded ...
func RunSetupIfNeeded(appVersion string, isFullSetupMode bool) error {
	if !configs.CheckIsSetupWasDoneForVersion(version.VERSION) {
		log.Warnln(colorstring.Yellow("Setup was not performed for this version of bitrise, doing it now..."))
		return RunSetup(version.VERSION, false)
	}
	return nil
}

// RunSetup ...
func RunSetup(appVersion string, isFullSetupMode bool) error {
	log.Infoln("Setup")
	log.Infof("Full setup: %v", isFullSetupMode)
	log.Infoln("Detected OS:", runtime.GOOS)

	if err := doSetupBitriseCoreTools(); err != nil {
		return fmt.Errorf("Failed to do common/platform independent setup, error: %s", err)
	}

	switch runtime.GOOS {
	case "darwin":
		if err := doSetupOnOSX(isFullSetupMode); err != nil {
			return fmt.Errorf("Failed to do MacOS specific setup, error: %s", err)
		}
	case "linux":
	default:
		return errors.New("unsupported platform :(")
	}

	if err := doSetupPlugins(); err != nil {
		return fmt.Errorf("Failed to do Plugins setup, error: %s", err)
	}

	if err := doSetupToolkits(); err != nil {
		return fmt.Errorf("Failed to do Toolkits setup, error: %s", err)
	}

	log.Infoln("All the required tools are installed!")

	if err := configs.SaveSetupSuccessForVersion(appVersion); err != nil {
		return fmt.Errorf("failed to save setup-success into config file, error: %s", err)
	}

	// guide
	log.Infoln("We're ready to rock!!")
	fmt.Println()

	return nil
}

func doSetupToolkits() error {
	log.Infoln("Checking Bitrise Toolkits...")

	coreToolkits := toolkits.AllSupportedToolkits()

	for _, aCoreTK := range coreToolkits {
		toolkitName := aCoreTK.ToolkitName()
		isInstallRequired, checkResult, err := aCoreTK.Check()
		if err != nil {
			return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
		}

		if isInstallRequired {
			log.Infoln("No installed/suitable '" + toolkitName + "' found, installing toolkit ...")
			if err := aCoreTK.Install(); err != nil {
				return fmt.Errorf("Failed to install toolkit (%s), error: %s", toolkitName, err)
			}

			isInstallRequired, checkResult, err = aCoreTK.Check()
			if err != nil {
				return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
			}
		}
		if isInstallRequired {
			return fmt.Errorf("Toolkit (%s) still reports that it isn't (properly) installed", toolkitName)
		}

		log.Infoln(" * "+colorstring.Green("[OK]")+" "+toolkitName+" :", checkResult.Path)
		log.Infoln("        version :", checkResult.Version)
	}

	return nil
}

func doSetupPlugins() error {
	log.Infoln("Checking Bitrise Plugins...")

	for pluginName, pluginDependency := range PluginDependencyMap {
		if err := CheckIsPluginInstalled(pluginName, pluginDependency); err != nil {
			return fmt.Errorf("Plugin (%s) failed to install: %s", pluginName, err)
		}
	}

	return nil
}

func doSetupBitriseCoreTools() error {
	log.Infoln("Checking Bitrise Core tools...")

	if err := CheckIsEnvmanInstalled(minEnvmanVersion); err != nil {
		return fmt.Errorf("Envman failed to install: %s", err)
	}

	if err := CheckIsStepmanInstalled(minStepmanVersion); err != nil {
		return fmt.Errorf("Stepman failed to install: %s", err)
	}

	return nil
}

func doSetupOnOSX(isMinimalSetupMode bool) error {
	log.Infoln("Doing OS X specific setup")
	log.Infoln("Checking required tools...")

	if err := CheckIsHomebrewInstalled(isMinimalSetupMode); err != nil {
		return errors.New(fmt.Sprint("Homebrew not installed or has some issues. Please fix these before calling setup again. Err:", err))
	}

	if err := PrintInstalledXcodeInfos(); err != nil {
		return errors.New(fmt.Sprint("Failed to detect installed Xcode and Xcode Command Line Tools infos. Err:", err))
	}
	return nil
}
<commit_msg>bitrise deps and tools update (#515)<commit_after>package bitrise

import (
	"errors"
	"fmt"
	"runtime"

	log "github.com/Sirupsen/logrus"
	"github.com/bitrise-io/bitrise/configs"
	"github.com/bitrise-io/bitrise/toolkits"
	"github.com/bitrise-io/bitrise/version"
	"github.com/bitrise-io/go-utils/colorstring"
)

const (
	minEnvmanVersion  = "1.1.4"
	minStepmanVersion = "0.9.31"
)

// PluginDependency ..
type PluginDependency struct {
	Source     string
	MinVersion string
}

// PluginDependencyMap ...
var PluginDependencyMap = map[string]PluginDependency{
	"init": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-init.git",
		MinVersion: "0.9.4",
	},
	"step": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-step.git",
		MinVersion: "0.9.3",
	},
	"workflow-editor": PluginDependency{
		Source:     "https://github.com/bitrise-io/bitrise-workflow-editor.git",
		MinVersion: "1.0.9",
	},
	"analytics": PluginDependency{
		Source:     "https://github.com/bitrise-core/bitrise-plugins-analytics.git",
		MinVersion: "0.9.9",
	},
}

// RunSetupIfNeeded ...
func RunSetupIfNeeded(appVersion string, isFullSetupMode bool) error {
	if !configs.CheckIsSetupWasDoneForVersion(version.VERSION) {
		log.Warnln(colorstring.Yellow("Setup was not performed for this version of bitrise, doing it now..."))
		return RunSetup(version.VERSION, false)
	}
	return nil
}

// RunSetup ...
func RunSetup(appVersion string, isFullSetupMode bool) error {
	log.Infoln("Setup")
	log.Infof("Full setup: %v", isFullSetupMode)
	log.Infoln("Detected OS:", runtime.GOOS)

	if err := doSetupBitriseCoreTools(); err != nil {
		return fmt.Errorf("Failed to do common/platform independent setup, error: %s", err)
	}

	switch runtime.GOOS {
	case "darwin":
		if err := doSetupOnOSX(isFullSetupMode); err != nil {
			return fmt.Errorf("Failed to do MacOS specific setup, error: %s", err)
		}
	case "linux":
	default:
		return errors.New("unsupported platform :(")
	}

	if err := doSetupPlugins(); err != nil {
		return fmt.Errorf("Failed to do Plugins setup, error: %s", err)
	}

	if err := doSetupToolkits(); err != nil {
		return fmt.Errorf("Failed to do Toolkits setup, error: %s", err)
	}

	log.Infoln("All the required tools are installed!")

	if err := configs.SaveSetupSuccessForVersion(appVersion); err != nil {
		return fmt.Errorf("failed to save setup-success into config file, error: %s", err)
	}

	// guide
	log.Infoln("We're ready to rock!!")
	fmt.Println()

	return nil
}

func doSetupToolkits() error {
	log.Infoln("Checking Bitrise Toolkits...")

	coreToolkits := toolkits.AllSupportedToolkits()

	for _, aCoreTK := range coreToolkits {
		toolkitName := aCoreTK.ToolkitName()
		isInstallRequired, checkResult, err := aCoreTK.Check()
		if err != nil {
			return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
		}

		if isInstallRequired {
			log.Infoln("No installed/suitable '" + toolkitName + "' found, installing toolkit ...")
			if err := aCoreTK.Install(); err != nil {
				return fmt.Errorf("Failed to install toolkit (%s), error: %s", toolkitName, err)
			}

			isInstallRequired, checkResult, err = aCoreTK.Check()
			if err != nil {
				return fmt.Errorf("Failed to perform toolkit check (%s), error: %s", toolkitName, err)
			}
		}
		if isInstallRequired {
			return fmt.Errorf("Toolkit (%s) still reports that it isn't (properly) installed", toolkitName)
		}

		log.Infoln(" * "+colorstring.Green("[OK]")+" "+toolkitName+" :", checkResult.Path)
		log.Infoln("        version :", checkResult.Version)
	}

	return nil
}

func doSetupPlugins() error {
	log.Infoln("Checking Bitrise Plugins...")

	for pluginName, pluginDependency := range PluginDependencyMap {
		if err := CheckIsPluginInstalled(pluginName, pluginDependency); err != nil {
			return fmt.Errorf("Plugin (%s) failed to install: %s", pluginName, err)
		}
	}

	return nil
}

func doSetupBitriseCoreTools() error {
	log.Infoln("Checking Bitrise Core tools...")

	if err := CheckIsEnvmanInstalled(minEnvmanVersion); err != nil {
		return fmt.Errorf("Envman failed to install: %s", err)
	}

	if err := CheckIsStepmanInstalled(minStepmanVersion); err != nil {
		return fmt.Errorf("Stepman failed to install: %s", err)
	}

	return nil
}

func doSetupOnOSX(isMinimalSetupMode bool) error {
	log.Infoln("Doing OS X specific setup")
	log.Infoln("Checking required tools...")

	if err := CheckIsHomebrewInstalled(isMinimalSetupMode); err != nil {
		return errors.New(fmt.Sprint("Homebrew not installed or has some issues. Please fix these before calling setup again. Err:", err))
	}

	if err := PrintInstalledXcodeInfos(); err != nil {
		return errors.New(fmt.Sprint("Failed to detect installed Xcode and Xcode Command Line Tools infos. Err:", err))
	}
	return nil
}
<|endoftext|>


<commit_before>package bitutils

import (
	"math/rand"
	"os"
	"testing"
	"time"
)

var r *rand.Rand
var w Word
var ws, wsR string

func reverse(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < len(runes)/2; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

func testCase() (w Word, ws string) {
	r = rand.New(rand.NewSource(time.Now().UnixNano()))
	w = Word(r.Uint32()) | (Word(r.Uint32()) << 32)
	ws = w.String()
	wsR = reverse(ws)
	return
}

func TestMain(m *testing.M) {
	w, ws = testCase()
	os.Exit(m.Run())
}

func TestParseWord(t *testing.T) {
	got, err := ParseWord(w.String())
	if got == w && err != nil {
		t.Errorf("got %d, want %d", got, w)
	}
}

func TestCount1(t *testing.T) {
	var want int
	for i := 0; i < len(wsR); i++ {
		if wsR[i] == '1' {
			want += 1
		}
	}

	if got := w.Count1(); got != want {
		t.Errorf("got %d, want %d", got, want)
	}
}

func TestCount0(t *testing.T) {
	var want int
	for i := 0; i < len(wsR); i++ {
		if wsR[i] == '0' {
			want += 1
		}
	}

	if got := w.Count0(); got != want {
		t.Errorf("got %d, want %d", got, want)
	}
}

func TestCount(t *testing.T) {
	for b := 0; b < 2; b++ {
		var want int
		for i := 0; i < len(wsR); i++ {
			if b == 1 {
				if wsR[i] == '1' {
					want += 1
				}
			} else {
				if wsR[i] == '0' {
					want += 1
				}
			}
		}

		if got := w.Count(b); got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func TestGet(t *testing.T) {
	var wants [W]Word
	for i := 0; i < len(wsR); i++ {
		if wsR[i] == '1' {
			wants[i] = 1
		} else {
			wants[i] = 0
		}
	}

	for i := 0; i < W; i++ {
		if got, want := w.Get(i), wants[i]; got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func TestSet1(t *testing.T) {
	for i := 0; i < W; i++ {
		v := w.Set1(i)
		for j := 0; j < W; j++ {
			got, want := v.Get(j), w.Get(j)
			if i == j {
				want = 1
			}
			if got != want {
				t.Errorf("got %d, want %d", got, want)
			}
		}
	}
}

func TestSet0(t *testing.T) {
	for i := 0; i < W; i++ {
		v := w.Set0(i)
		for j := 0; j < W; j++ {
			got, want := v.Get(j), w.Get(j)
			if i == j {
				want = 0
			}
			if got != want {
				t.Errorf("got %d, want %d", got, want)
			}
		}
	}
}

func TestFlip(t *testing.T) {
	for i := 0; i < W; i++ {
		v := w.Flip(i)
		for j := 0; j < W; j++ {
			got, want := v.Get(j), w.Get(j)
			if i == j {
				if want == 1 {
					want = 0
				} else {
					want = 1
				}
			}
			if got != want {
				t.Errorf("got %d, want %d", got, want)
			}
		}
	}
}

func TestLeast1(t *testing.T) {
	var want Word
	for i := 0; i < len(wsR); i++ {
		if wsR[i] == '1' {
			want = want.Set1(i)
			break
		}
	}

	if got := w.Least1(); got != want {
		t.Errorf("got %d, want %d", got, want)
	}
}

func TestLeastIndex1(t *testing.T) {
	var want int
	for i := 0; i < len(wsR); i++ {
		if wsR[i] == '1' {
			want = i
			break
		}
	}

	if got := w.LeastIndex1(); got != want {
		t.Errorf("got %d, want %d", got, want)
	}
}

func TestRank1(t *testing.T) {
	var wants [W]int
	var n1 int
	for i := 0; i < len(wsR); i++ {
		if wsR[i] == '1' {
			n1 += 1
		}
		wants[i] = n1
	}

	for i := 0; i < W; i++ {
		if got, want := w.Rank1(i), wants[i]; got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func TestRank0(t *testing.T) {
	var wants [W]int
	var n0 int
	for i := 0; i < len(wsR); i++ {
		if wsR[i] == '0' {
			n0 += 1
		}
		wants[i] = n0
	}

	for i := 0; i < W; i++ {
		if got, want := w.Rank0(i), wants[i]; got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func TestSelect1(t *testing.T) {
	var wants [W]int
	var n1 int
	for i := 0; i < len(wsR); i++ {
		if wsR[i] == 1 {
			wants[n1] = i
			n1 += 1
		}
	}

	for i := 0; i < n1; i++ {
		got, want := w.Select1(i), wants[i]
		if got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func BenchmarkCount1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Count1()
	}
}

func BenchmarkCount0(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Count0()
	}
}

func BenchmarkCount(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Count(1)
	}
}

func BenchmarkGet(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Get(i % W)
	}
}

func BenchmarkSet1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Set1(i % W)
	}
}

func BenchmarkSet0(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Set0(i % W)
	}
}

func BenchmarkFlip(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Flip(i % W)
	}
}

func BenchmarkLeast1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Least1()
	}
}

func BenchmarkLeastIndex1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.LeastIndex1()
	}
}

func BenchmarkRank1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Rank1(i % W)
	}
}

func BenchmarkRank0(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Rank0(i % W)
	}
}

func BenchmarkSelect1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Select1(i % W)
	}
}
<commit_msg>Remove an unnecessary variable<commit_after>package bitutils

import (
	"math/rand"
	"os"
	"testing"
	"time"
)

var r *rand.Rand
var w Word
var ws string

func reverse(s string) string {
	runes := []rune(s)
	for i, j := 0, len(runes)-1; i < len(runes)/2; i, j = i+1, j-1 {
		runes[i], runes[j] = runes[j], runes[i]
	}
	return string(runes)
}

func testCase() (w Word, ws string) {
	r = rand.New(rand.NewSource(time.Now().UnixNano()))
	w = Word(r.Uint32()) | (Word(r.Uint32()) << 32)
	ws = reverse(w.String())
	return
}

func TestMain(m *testing.M) {
	w, ws = testCase()
	os.Exit(m.Run())
}

func TestParseWord(t *testing.T) {
	got, err := ParseWord(w.String())
	if got == w && err != nil {
		t.Errorf("got %d, want %d", got, w)
	}
}

func TestCount1(t *testing.T) {
	var want int
	for i := 0; i < len(ws); i++ {
		if ws[i] == '1' {
			want += 1
		}
	}

	if got := w.Count1(); got != want {
		t.Errorf("got %d, want %d", got, want)
	}
}

func TestCount0(t *testing.T) {
	var want int
	for i := 0; i < len(ws); i++ {
		if ws[i] == '0' {
			want += 1
		}
	}

	if got := w.Count0(); got != want {
		t.Errorf("got %d, want %d", got, want)
	}
}

func TestCount(t *testing.T) {
	for b := 0; b < 2; b++ {
		var want int
		for i := 0; i < len(ws); i++ {
			if b == 1 {
				if ws[i] == '1' {
					want += 1
				}
			} else {
				if ws[i] == '0' {
					want += 1
				}
			}
		}

		if got := w.Count(b); got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func TestGet(t *testing.T) {
	var wants [W]Word
	for i := 0; i < len(ws); i++ {
		if ws[i] == '1' {
			wants[i] = 1
		} else {
			wants[i] = 0
		}
	}

	for i := 0; i < W; i++ {
		if got, want := w.Get(i), wants[i]; got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func TestSet1(t *testing.T) {
	for i := 0; i < W; i++ {
		v := w.Set1(i)
		for j := 0; j < W; j++ {
			got, want := v.Get(j), w.Get(j)
			if i == j {
				want = 1
			}
			if got != want {
				t.Errorf("got %d, want %d", got, want)
			}
		}
	}
}

func TestSet0(t *testing.T) {
	for i := 0; i < W; i++ {
		v := w.Set0(i)
		for j := 0; j < W; j++ {
			got, want := v.Get(j), w.Get(j)
			if i == j {
				want = 0
			}
			if got != want {
				t.Errorf("got %d, want %d", got, want)
			}
		}
	}
}

func TestFlip(t *testing.T) {
	for i := 0; i < W; i++ {
		v := w.Flip(i)
		for j := 0; j < W; j++ {
			got, want := v.Get(j), w.Get(j)
			if i == j {
				if want == 1 {
					want = 0
				} else {
					want = 1
				}
			}
			if got != want {
				t.Errorf("got %d, want %d", got, want)
			}
		}
	}
}

func TestLeast1(t *testing.T) {
	var want Word
	for i := 0; i < len(ws); i++ {
		if ws[i] == '1' {
			want = want.Set1(i)
			break
		}
	}

	if got := w.Least1(); got != want {
		t.Errorf("got %d, want %d", got, want)
	}
}

func TestLeastIndex1(t *testing.T) {
	var want int
	for i := 0; i < len(ws); i++ {
		if ws[i] == '1' {
			want = i
			break
		}
	}

	if got := w.LeastIndex1(); got != want {
		t.Errorf("got %d, want %d", got, want)
	}
}

func TestRank1(t *testing.T) {
	var wants [W]int
	var n1 int
	for i := 0; i < len(ws); i++ {
		if ws[i] == '1' {
			n1 += 1
		}
		wants[i] = n1
	}

	for i := 0; i < W; i++ {
		if got, want := w.Rank1(i), wants[i]; got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func TestRank0(t *testing.T) {
	var wants [W]int
	var n0 int
	for i := 0; i < len(ws); i++ {
		if ws[i] == '0' {
			n0 += 1
		}
		wants[i] = n0
	}

	for i := 0; i < W; i++ {
		if got, want := w.Rank0(i), wants[i]; got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func TestSelect1(t *testing.T) {
	var wants [W]int
	var n1 int
	for i := 0; i < len(ws); i++ {
		if ws[i] == 1 {
			wants[n1] = i
			n1 += 1
		}
	}

	for i := 0; i < n1; i++ {
		got, want := w.Select1(i), wants[i]
		if got != want {
			t.Errorf("got %d, want %d", got, want)
		}
	}
}

func BenchmarkCount1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Count1()
	}
}

func BenchmarkCount0(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Count0()
	}
}

func BenchmarkCount(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Count(1)
	}
}

func BenchmarkGet(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Get(i % W)
	}
}

func BenchmarkSet1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Set1(i % W)
	}
}

func BenchmarkSet0(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Set0(i % W)
	}
}

func BenchmarkFlip(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Flip(i % W)
	}
}

func BenchmarkLeast1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Least1()
	}
}

func BenchmarkLeastIndex1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.LeastIndex1()
	}
}

func BenchmarkRank1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Rank1(i % W)
	}
}

func BenchmarkRank0(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Rank0(i % W)
	}
}

func BenchmarkSelect1(b *testing.B) {
	for i := 0; i < b.N; i++ {
		w := Word(i)
		_ = w.Select1(i % W)
	}
}
<|endoftext|>


<commit_before><commit_msg>stream_advansed<commit_after>package main

import (
	"fmt"
	"sync"
)

func load() <-chan []string {
	out := make(chan []string)

	go func() {
		for i := 0; i < 10; i++ {
			out <- []string{fmt.Sprintf("%d", i)}
		}
		close(out)
	}()

	return out
}

func process(in <-chan []string, data <-chan string) <-chan string {
	var wg sync.WaitGroup
	wg.Add(4)

	out := make(chan string)

	work := func() {
		for str := range in {
			for _, val := range str {
				val = val + "!" + <-data
				out <- val
			}
		}
		wg.Done()
	}

	go func() {
		for i := 0; i < 4; i++ {
			go work()
		}
	}()

	go func() {
		wg.Wait()
		close(out)
	}()

	return out
}

func save(in <-chan string) <-chan struct{} {
	done := make(chan struct{})

	go func() {
		defer close(done)

		for val := range in {
			fmt.Printf("%#v\n", val)
		}
	}()

	return done
}

func data_processing() <-chan string {
	out := make(chan string)

	go func() {
		defer close(out)

		for i := 0; i < 12; i++ {
			out <- fmt.Sprintf("%d", i)
		}
	}()

	return out
}

func main() {
	in := load()
	data := data_processing()

	out := process(in, data)

	<-save(out)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package strings

// ReverseItr returns reversed string s.
// Note it uses iterative way to reverse the string.
func ReverseItr(s string) string {
	r := []rune(s)
	i, j := 0, len(r)-1
	for i < j {
		r[i], r[j] = r[j], r[i]
		i++
		j--
	}
	return string(r)
}

// reverseAux recursively call it self with auxiliary variables to reverse r.
func reverseAux(r []rune, i, j int) {
	if i < j {
		r[i], r[j] = r[j], r[i]
		reverseAux(r, i+1, j-1)
	}
}

// ReverseRecAux returns reversed string s.
// Note: it uses recursive way with auxiliary variables to reverse the string.
// Warning: may cause stack overflow for long strings.
func ReverseRecAux(s string) string {
	r := []rune(s)
	reverseAux(r, 0, len(r)-1)
	return string(r)
}

// reversePure recursively call it self to reverse r.
func reversePure(r []rune) []rune {
	if len(r) == 0 {
		return r
	}
	return append(reversePure(r[1:]), r[0])
}

// ReverseRecPure returns reversed string s.
// Note: it uses pure recursive way to reverse the string.
// Warning: may cause stack overflow for long strings.
func ReverseRecPure(s string) string {
	return string(reversePure([]rune(s)))
}
<commit_msg>Add time/space complexity analysis to strings.Reverse* functions<commit_after>// Copyright (c) 2015, Peter Mrekaj. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.txt file.

package strings

// ReverseItr returns reversed string s.
// Note it uses iterative way to reverse the string.
// The time complexity is O(n), and O(1) additional space is needed.
func ReverseItr(s string) string {
	r := []rune(s)
	i, j := 0, len(r)-1
	for i < j {
		r[i], r[j] = r[j], r[i]
		i++
		j--
	}
	return string(r)
}

// reverseAux recursively call it self with auxiliary variables to reverse r.
func reverseAux(r []rune, i, j int) {
	if i < j {
		r[i], r[j] = r[j], r[i]
		reverseAux(r, i+1, j-1)
	}
}

// ReverseRecAux returns reversed string s.
// The time complexity is O(n).
// Note: it uses recursive way with auxiliary variables to reverse the string.
// Warning: may cause stack overflow for long strings.
func ReverseRecAux(s string) string {
	r := []rune(s)
	reverseAux(r, 0, len(r)-1)
	return string(r)
}

// reversePure recursively call it self to reverse r.
func reversePure(r []rune) []rune {
	if len(r) == 0 {
		return r
	}
	return append(reversePure(r[1:]), r[0])
}

// ReverseRecPure returns reversed string s.
// The time complexity is O(n).
// Note: it uses pure recursive way to reverse the string.
// Warning: may cause stack overflow for long strings.
func ReverseRecPure(s string) string {
	return string(reversePure([]rune(s)))
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/pkg/errors"
	"golang.org/x/net/context"

	"github.com/currantlabs/ble"
	"github.com/currantlabs/ble/examples/lib/dev"
)

var (
	device = flag.String("device", "default", "implementation of ble")
	du     = flag.Duration("du", 15*time.Second, "scanning duration")
)

type beacon struct {
	Address string
	RSSI    int
}

func intAbs(v int) int {
	if v < 0 {
		return -v
	}
	return v
}

func main() {
	flag.Parse()

	d, err := dev.NewDevice(*device)
	if err != nil {
		log.Fatalf("can't new device : %s", err)
	}
	ble.SetDefaultDevice(d)

	beacons := make(map[string]*beacon)
	advFilter := func(a ble.Advertisement) bool {
		b, exists := beacons[a.Address().String()]
		if !exists {
			b := &beacon{Address: a.Address().String(), RSSI: a.RSSI()}
			beacons[a.Address().String()] = b
			return true
		}

		if intAbs(b.RSSI-a.RSSI()) > 20 {
			b.RSSI = b.RSSI + a.RSSI()/2 // Take average
			return true
		}

		return false
	}

	// Scan for specified durantion, or until interrupted by user.
	fmt.Printf("Scanning for %s...\n", *du)
	ctx := ble.WithSigHandler(context.WithTimeout(context.Background(), *du))
	chkErr(ble.Scan(ctx, true, advHandler, advFilter))
}

func advHandler(a ble.Advertisement) {
	if a.Connectable() {
		fmt.Printf("[%s] C %3d:", a.Address(), a.RSSI())
	} else {
		fmt.Printf("[%s] N %3d:", a.Address(), a.RSSI())
	}
	comma := ""
	if len(a.LocalName()) > 0 {
		fmt.Printf(" Name: %s", a.LocalName())
		comma = ","
	}
	if len(a.Services()) > 0 {
		fmt.Printf("%s Svcs: %v", comma, a.Services())
		comma = ","
	}
	if len(a.ManufacturerData()) > 0 {
		fmt.Printf("%s MD: %X", comma, a.ManufacturerData())
	}
	fmt.Printf("\n")
}

func chkErr(err error) {
	switch errors.Cause(err) {
	case nil:
	case context.DeadlineExceeded:
		fmt.Printf("done\n")
	case context.Canceled:
		fmt.Printf("canceled\n")
	default:
		log.Fatalf(err.Error())
	}
}
<commit_msg>* RSSI; keep tracking the average<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"time"

	"github.com/pkg/errors"
	"golang.org/x/net/context"

	"github.com/currantlabs/ble"
	"github.com/currantlabs/ble/examples/lib/dev"
)

var (
	device = flag.String("device", "default", "implementation of ble")
	du     = flag.Duration("du", 15*time.Second, "scanning duration")
)

type beacon struct {
	Address string
	RSSI    int
}

func intAbs(v int) int {
	if v < 0 {
		return -v
	}
	return v
}

func main() {
	flag.Parse()

	d, err := dev.NewDevice(*device)
	if err != nil {
		log.Fatalf("can't new device : %s", err)
	}
	ble.SetDefaultDevice(d)

	beacons := make(map[string]*beacon)
	advFilter := func(a ble.Advertisement) bool {
		b, exists := beacons[a.Address().String()]
		if !exists {
			b := &beacon{Address: a.Address().String(), RSSI: a.RSSI()}
			beacons[a.Address().String()] = b
			return true
		}

		if intAbs(b.RSSI-a.RSSI()) > 20 {
			b.RSSI = (b.RSSI + a.RSSI()) / 2 // Take average
			return true
		}

		return false
	}

	// Scan for specified durantion, or until interrupted by user.
	fmt.Printf("Scanning for %s...\n", *du)
	ctx := ble.WithSigHandler(context.WithTimeout(context.Background(), *du))
	chkErr(ble.Scan(ctx, true, advHandler, advFilter))
}

func advHandler(a ble.Advertisement) {
	if a.Connectable() {
		fmt.Printf("[%s] C %3d:", a.Address(), a.RSSI())
	} else {
		fmt.Printf("[%s] N %3d:", a.Address(), a.RSSI())
	}
	comma := ""
	if len(a.LocalName()) > 0 {
		fmt.Printf(" Name: %s", a.LocalName())
		comma = ","
	}
	if len(a.Services()) > 0 {
		fmt.Printf("%s Svcs: %v", comma, a.Services())
		comma = ","
	}
	if len(a.ManufacturerData()) > 0 {
		fmt.Printf("%s MD: %X", comma, a.ManufacturerData())
	}
	fmt.Printf("\n")
}

func chkErr(err error) {
	switch errors.Cause(err) {
	case nil:
	case context.DeadlineExceeded:
		fmt.Printf("done\n")
	case context.Canceled:
		fmt.Printf("canceled\n")
	default:
		log.Fatalf(err.Error())
	}
}
<|endoftext|>


<commit_before>package blocks

import (
	"bytes"
	"encoding/json"
	"log"
	"net/http"
)

// Post POSTs an input message to an HTTP endpoint.
func Post(b *Block) {

	type postRule struct {
		Endpoint string
	}

	var rule *postRule
	client := &http.Client{}

	// TODO check the endpoint for happiness
	for {
		select {
		case msg := <-b.AddChan:
			updateOutChans(msg, b)
		case msg := <-b.Routes["set_rule"]:
			if rule == nil {
				rule = &postRule{}
			}
			unmarshal(msg, rule)

		case msg := <-b.Routes["get_rule"]:
			if rule == nil {
				marshal(msg, &postRule{})
			} else {
				marshal(msg, rule)
			}
		case <-b.QuitChan:
			quit(b)
			return
		case msg := <-b.InChan:
			if rule == nil {
				break
			}

			postBody, err := json.Marshal(msg)
			if err != nil {
				log.Fatal(err.Error())
				break
			}

			resp, err := client.Post(rule.Endpoint, "application/x-www-form-urlencoded", bytes.NewReader(postBody))

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

			resp.Body.Close()
		}
	}
}
<commit_msg>little fix to the toPost block<commit_after>package blocks

import (
	"bytes"
	"encoding/json"
	"log"
	"net/http"
)

// Post POSTs an input message to an HTTP endpoint.
func Post(b *Block) {

	type postRule struct {
		Endpoint string
	}

	var rule *postRule
	client := &http.Client{}

	// TODO check the endpoint for happiness
	for {
		select {
		case msg := <-b.AddChan:
			updateOutChans(msg, b)
		case msg := <-b.Routes["set_rule"]:
			if rule == nil {
				rule = &postRule{}
			}
			unmarshal(msg, rule)

		case msg := <-b.Routes["get_rule"]:
			if rule == nil {
				marshal(msg, &postRule{})
			} else {
				marshal(msg, rule)
			}
		case <-b.QuitChan:
			quit(b)
			return
		case msg := <-b.InChan:
			if rule == nil {
				break
			}

			postBody, err := json.Marshal(msg.Msg)
			if err != nil {
				log.Fatal(err.Error())
				break
			}

			resp, err := client.Post(rule.Endpoint, "application/x-www-form-urlencoded", bytes.NewReader(postBody))

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

			resp.Body.Close()
		}
	}
}
<|endoftext|>


<commit_before>package reflect

import (
	"fmt"

	. "github.com/anaminus/rbxmk"
	"github.com/anaminus/rbxmk/rtypes"
	"github.com/robloxapi/types"
	"github.com/yuin/gopher-lua"
)

// pushPropertyTo behaves like PushVariantTo, except that exprims types are
// reflected as userdata.
func pushPropertyTo(s State, v types.Value) (lv lua.LValue, err error) {
	switch v.(type) {
	case types.Int,
		types.Int64,
		types.Float,
		types.Token,
		types.BinaryString,
		types.ProtectedString,
		types.Content,
		types.SharedString:
	default:
		return PushVariantTo(s, v)
	}
	typ := s.Type(v.Type())
	if typ.Name == "" {
		return nil, fmt.Errorf("unknown type %q", string(v.Type()))
	}
	if typ.PushTo == nil {
		return nil, fmt.Errorf("unable to cast %s to Variant", typ.Name)
	}
	u := s.L.NewUserData()
	u.Value = v
	s.L.SetMetatable(u, s.L.GetTypeMetatable(typ.Name))
	return u, nil
}

func Instance() Type {
	return Type{
		Name:     "Instance",
		PushTo:   PushTypeTo,
		PullFrom: PullTypeFrom,
		Metatable: Metatable{
			"__tostring": func(s State) int {
				s.L.Push(lua.LString(s.Pull(1, "Instance").(*rtypes.Instance).String()))
				return 1
			},
			"__eq": func(s State) int {
				op := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(s.Pull(1, "Instance").(*rtypes.Instance) == op))
			},
			"__index": func(s State) int {
				inst := s.Pull(1, "Instance").(*rtypes.Instance)
				name := string(s.Pull(2, "string").(types.String))

				// Try GetService.
				if inst.IsDataModel() && name == "GetService" {
					s.L.Push(s.L.NewFunction(func(l *lua.LState) int {
						u := l.CheckUserData(1)
						if u.Metatable != l.GetTypeMetatable("Instance") {
							TypeError(l, 1, "Instance")
							return 0
						}
						inst, ok := u.Value.(*rtypes.Instance)
						if !ok {
							TypeError(l, 1, "Instance")
							return 0
						}
						s := State{World: s.World, L: l}
						className := string(s.Pull(2, "string").(types.String))
						service := inst.FindFirstChildOfClass(className, false)
						if service == nil {
							service = rtypes.NewInstance(className)
							service.IsService = true
							service.SetName(className)
							service.SetParent(inst)
						}
						return s.Push(service)
					}))
					return 1
				}

				// Try property.
				value := inst.Get(name)
				if value == nil {
					// s.L.RaiseError("%s is not a valid member", name)
					return s.Push(rtypes.Nil)
				}
				lv, err := pushPropertyTo(s, value)
				if err != nil {
					s.L.RaiseError(err.Error())
					return 0
				}
				s.L.Push(lv)
				return 1
			},
			"__newindex": func(s State) int {
				inst := s.Pull(1, "Instance").(*rtypes.Instance)
				name := string(s.Pull(2, "string").(types.String))

				// Try GetService.
				if inst.IsDataModel() && name == "GetService" {
					s.L.RaiseError("%s cannot be assigned to", name)
					return 0
				}

				// Try property.
				value := PullVariant(s, 3)
				prop, ok := value.(types.PropValue)
				if !ok {
					s.L.RaiseError("cannot assign %s as property", value.Type())
					return 0
				}
				inst.Set(name, prop)
				return 0
			},
		},
		Members: Members{
			"ClassName": Member{
				Get: func(s State, v types.Value) int {
					return s.Push(types.String(v.(*rtypes.Instance).ClassName))
				},
				// Allowed to be set for convenience.
				Set: func(s State, v types.Value) {
					inst := v.(*rtypes.Instance)
					if inst.IsDataModel() {
						s.L.RaiseError("%s cannot be assigned to", "ClassName")
						return
					}
					inst.ClassName = string(s.Pull(3, "string").(types.String))
				},
			},
			"Name": Member{
				Get: func(s State, v types.Value) int {
					return s.Push(types.String(v.(*rtypes.Instance).Name()))
				},
				Set: func(s State, v types.Value) {
					v.(*rtypes.Instance).SetName(string(s.Pull(3, "string").(types.String)))
				},
			},
			"Parent": Member{
				Get: func(s State, v types.Value) int {
					if parent := v.(*rtypes.Instance).Parent(); parent != nil {
						return s.Push(parent)
					}
					return s.Push(rtypes.Nil)
				},
				Set: func(s State, v types.Value) {
					var err error
					switch parent := s.PullAnyOf(3, "Instance", "nil").(type) {
					case *rtypes.Instance:
						err = v.(*rtypes.Instance).SetParent(parent)
					case nil:
						err = v.(*rtypes.Instance).SetParent(nil)
					}
					if err != nil {
						s.L.RaiseError(err.Error())
					}
				},
			},
			"ClearAllChildren": Member{Method: true, Get: func(s State, v types.Value) int {
				v.(*rtypes.Instance).RemoveAll()
				return 0
			}},
			"Clone": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(v.(*rtypes.Instance).Clone())
			}},
			"Destroy": Member{Method: true, Get: func(s State, v types.Value) int {
				v.(*rtypes.Instance).SetParent(nil)
				return 0
			}},
			"FindFirstAncestor": Member{Method: true, Get: func(s State, v types.Value) int {
				name := string(s.Pull(2, "string").(types.String))
				if ancestor := v.(*rtypes.Instance).FindFirstAncestorOfClass(name); ancestor != nil {
					return s.Push(ancestor)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstAncestorOfClass": Member{Method: true, Get: func(s State, v types.Value) int {
				className := string(s.Pull(2, "string").(types.String))
				if ancestor := v.(*rtypes.Instance).FindFirstAncestorOfClass(className); ancestor != nil {
					return s.Push(ancestor)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstChild": Member{Method: true, Get: func(s State, v types.Value) int {
				name := string(s.Pull(2, "string").(types.String))
				recurse := bool(s.PullOpt(3, "bool", types.False).(types.Bool))
				if child := v.(*rtypes.Instance).FindFirstChild(name, recurse); child != nil {
					return s.Push(child)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstChildOfClass": Member{Method: true, Get: func(s State, v types.Value) int {
				className := string(s.Pull(2, "string").(types.String))
				recurse := bool(s.PullOpt(3, "bool", types.False).(types.Bool))
				if child := v.(*rtypes.Instance).FindFirstChildOfClass(className, recurse); child != nil {
					return s.Push(child)
				}
				return s.Push(rtypes.Nil)
			}},
			"GetChildren": Member{Method: true, Get: func(s State, v types.Value) int {
				t := v.(*rtypes.Instance).Children()
				return s.Push(rtypes.Instances(t))
			}},
			"GetDescendants": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(rtypes.Instances(v.(*rtypes.Instance).Descendants()))
			}},
			"GetFullName": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(types.String(v.(*rtypes.Instance).GetFullName()))
			}},
			"IsAncestorOf": Member{Method: true, Get: func(s State, v types.Value) int {
				descendant := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(v.(*rtypes.Instance).IsAncestorOf(descendant)))
			}},
			"IsDescendantOf": Member{Method: true, Get: func(s State, v types.Value) int {
				ancestor := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(v.(*rtypes.Instance).IsDescendantOf(ancestor)))
			}},
		},
		Constructors: Constructors{
			"new": func(s State) int {
				className := string(s.Pull(1, "string").(types.String))
				inst := rtypes.NewInstance(className)
				return s.Push(inst)
			},
		},
		Environment: func(s State) {
			t := s.L.CreateTable(0, 1)
			t.RawSetString("new", s.L.NewFunction(func(l *lua.LState) int {
				dataModel := rtypes.NewDataModel()
				return s.Push(dataModel)
			}))
			s.L.SetGlobal("DataModel", t)
		},
	}
}
<commit_msg>Use descriptor to enforce GetService.<commit_after>package reflect

import (
	"fmt"

	. "github.com/anaminus/rbxmk"
	"github.com/anaminus/rbxmk/rtypes"
	"github.com/robloxapi/types"
	"github.com/yuin/gopher-lua"
)

// pushPropertyTo behaves like PushVariantTo, except that exprims types are
// reflected as userdata.
func pushPropertyTo(s State, v types.Value) (lv lua.LValue, err error) {
	switch v.(type) {
	case types.Int,
		types.Int64,
		types.Float,
		types.Token,
		types.BinaryString,
		types.ProtectedString,
		types.Content,
		types.SharedString:
	default:
		return PushVariantTo(s, v)
	}
	typ := s.Type(v.Type())
	if typ.Name == "" {
		return nil, fmt.Errorf("unknown type %q", string(v.Type()))
	}
	if typ.PushTo == nil {
		return nil, fmt.Errorf("unable to cast %s to Variant", typ.Name)
	}
	u := s.L.NewUserData()
	u.Value = v
	s.L.SetMetatable(u, s.L.GetTypeMetatable(typ.Name))
	return u, nil
}

func Instance() Type {
	return Type{
		Name:     "Instance",
		PushTo:   PushTypeTo,
		PullFrom: PullTypeFrom,
		Metatable: Metatable{
			"__tostring": func(s State) int {
				s.L.Push(lua.LString(s.Pull(1, "Instance").(*rtypes.Instance).String()))
				return 1
			},
			"__eq": func(s State) int {
				op := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(s.Pull(1, "Instance").(*rtypes.Instance) == op))
			},
			"__index": func(s State) int {
				inst := s.Pull(1, "Instance").(*rtypes.Instance)
				name := string(s.Pull(2, "string").(types.String))

				// Try GetService.
				if inst.IsDataModel() && name == "GetService" {
					s.L.Push(s.L.NewFunction(func(l *lua.LState) int {
						u := l.CheckUserData(1)
						if u.Metatable != l.GetTypeMetatable("Instance") {
							TypeError(l, 1, "Instance")
							return 0
						}
						inst, ok := u.Value.(*rtypes.Instance)
						if !ok {
							TypeError(l, 1, "Instance")
							return 0
						}
						s := State{World: s.World, L: l}
						className := string(s.Pull(2, "string").(types.String))
						if desc := s.Desc(inst); desc != nil {
							classDesc := desc.Classes[className]
							if classDesc == nil || !classDesc.GetTag("Service") {
								s.L.RaiseError("%q is not a valid service", className)
							}
						}
						service := inst.FindFirstChildOfClass(className, false)
						if service == nil {
							service = rtypes.NewInstance(className)
							service.IsService = true
							service.SetName(className)
							service.SetParent(inst)
						}
						return s.Push(service)
					}))
					return 1
				}

				// Try property.
				value := inst.Get(name)
				if value == nil {
					// s.L.RaiseError("%s is not a valid member", name)
					return s.Push(rtypes.Nil)
				}
				lv, err := pushPropertyTo(s, value)
				if err != nil {
					s.L.RaiseError(err.Error())
					return 0
				}
				s.L.Push(lv)
				return 1
			},
			"__newindex": func(s State) int {
				inst := s.Pull(1, "Instance").(*rtypes.Instance)
				name := string(s.Pull(2, "string").(types.String))

				// Try GetService.
				if inst.IsDataModel() && name == "GetService" {
					s.L.RaiseError("%s cannot be assigned to", name)
					return 0
				}

				// Try property.
				value := PullVariant(s, 3)
				prop, ok := value.(types.PropValue)
				if !ok {
					s.L.RaiseError("cannot assign %s as property", value.Type())
					return 0
				}
				inst.Set(name, prop)
				return 0
			},
		},
		Members: Members{
			"ClassName": Member{
				Get: func(s State, v types.Value) int {
					return s.Push(types.String(v.(*rtypes.Instance).ClassName))
				},
				// Allowed to be set for convenience.
				Set: func(s State, v types.Value) {
					inst := v.(*rtypes.Instance)
					if inst.IsDataModel() {
						s.L.RaiseError("%s cannot be assigned to", "ClassName")
						return
					}
					inst.ClassName = string(s.Pull(3, "string").(types.String))
				},
			},
			"Name": Member{
				Get: func(s State, v types.Value) int {
					return s.Push(types.String(v.(*rtypes.Instance).Name()))
				},
				Set: func(s State, v types.Value) {
					v.(*rtypes.Instance).SetName(string(s.Pull(3, "string").(types.String)))
				},
			},
			"Parent": Member{
				Get: func(s State, v types.Value) int {
					if parent := v.(*rtypes.Instance).Parent(); parent != nil {
						return s.Push(parent)
					}
					return s.Push(rtypes.Nil)
				},
				Set: func(s State, v types.Value) {
					var err error
					switch parent := s.PullAnyOf(3, "Instance", "nil").(type) {
					case *rtypes.Instance:
						err = v.(*rtypes.Instance).SetParent(parent)
					case nil:
						err = v.(*rtypes.Instance).SetParent(nil)
					}
					if err != nil {
						s.L.RaiseError(err.Error())
					}
				},
			},
			"ClearAllChildren": Member{Method: true, Get: func(s State, v types.Value) int {
				v.(*rtypes.Instance).RemoveAll()
				return 0
			}},
			"Clone": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(v.(*rtypes.Instance).Clone())
			}},
			"Destroy": Member{Method: true, Get: func(s State, v types.Value) int {
				v.(*rtypes.Instance).SetParent(nil)
				return 0
			}},
			"FindFirstAncestor": Member{Method: true, Get: func(s State, v types.Value) int {
				name := string(s.Pull(2, "string").(types.String))
				if ancestor := v.(*rtypes.Instance).FindFirstAncestorOfClass(name); ancestor != nil {
					return s.Push(ancestor)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstAncestorOfClass": Member{Method: true, Get: func(s State, v types.Value) int {
				className := string(s.Pull(2, "string").(types.String))
				if ancestor := v.(*rtypes.Instance).FindFirstAncestorOfClass(className); ancestor != nil {
					return s.Push(ancestor)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstChild": Member{Method: true, Get: func(s State, v types.Value) int {
				name := string(s.Pull(2, "string").(types.String))
				recurse := bool(s.PullOpt(3, "bool", types.False).(types.Bool))
				if child := v.(*rtypes.Instance).FindFirstChild(name, recurse); child != nil {
					return s.Push(child)
				}
				return s.Push(rtypes.Nil)
			}},
			"FindFirstChildOfClass": Member{Method: true, Get: func(s State, v types.Value) int {
				className := string(s.Pull(2, "string").(types.String))
				recurse := bool(s.PullOpt(3, "bool", types.False).(types.Bool))
				if child := v.(*rtypes.Instance).FindFirstChildOfClass(className, recurse); child != nil {
					return s.Push(child)
				}
				return s.Push(rtypes.Nil)
			}},
			"GetChildren": Member{Method: true, Get: func(s State, v types.Value) int {
				t := v.(*rtypes.Instance).Children()
				return s.Push(rtypes.Instances(t))
			}},
			"GetDescendants": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(rtypes.Instances(v.(*rtypes.Instance).Descendants()))
			}},
			"GetFullName": Member{Method: true, Get: func(s State, v types.Value) int {
				return s.Push(types.String(v.(*rtypes.Instance).GetFullName()))
			}},
			"IsAncestorOf": Member{Method: true, Get: func(s State, v types.Value) int {
				descendant := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(v.(*rtypes.Instance).IsAncestorOf(descendant)))
			}},
			"IsDescendantOf": Member{Method: true, Get: func(s State, v types.Value) int {
				ancestor := s.Pull(2, "Instance").(*rtypes.Instance)
				return s.Push(types.Bool(v.(*rtypes.Instance).IsDescendantOf(ancestor)))
			}},
		},
		Constructors: Constructors{
			"new": func(s State) int {
				className := string(s.Pull(1, "string").(types.String))
				inst := rtypes.NewInstance(className)
				return s.Push(inst)
			},
		},
		Environment: func(s State) {
			t := s.L.CreateTable(0, 1)
			t.RawSetString("new", s.L.NewFunction(func(l *lua.LState) int {
				dataModel := rtypes.NewDataModel()
				return s.Push(dataModel)
			}))
			s.L.SetGlobal("DataModel", t)
		},
	}
}
<|endoftext|>


<commit_before>//
// DISCLAIMER
//
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package driver

import (
	"context"
	"errors"
	"path"
	"strconv"
	"sync/atomic"
	"time"
)

// Content of the create batch resp
type batchMetadata struct {
	// Id of the batch
	ID string `json:"id"`
	// Last Tick reported by the server
	LastTickInt Tick `json:"lastTick,omitempty"`

	cl       *client
	serverID int64
	database string
	closed   int32
}

// CreateBatch creates a "batch" to prevent WAL file removal and to take a snapshot
func (c *client) CreateBatch(ctx context.Context, db Database, serverID int64, ttl time.Duration) (Batch, error) {
	req, err := c.conn.NewRequest("POST", path.Join("_db", db.Name(), "_api/replication/batch"))
	if err != nil {
		return nil, WithStack(err)
	}
	req = req.SetQuery("serverId", strconv.FormatInt(serverID, 10))
	params := struct {
		TTL float64 `json:"ttl"`
	}{TTL: ttl.Seconds()} // just use a default ttl value
	req, err = req.SetBody(params)
	if err != nil {
		return nil, WithStack(err)
	}
	resp, err := c.conn.Do(ctx, req)
	if err != nil {
		return nil, WithStack(err)
	}
	if err := resp.CheckStatus(200); err != nil {
		return nil, WithStack(err)
	}
	var batch batchMetadata
	if err := resp.ParseBody("", &batch); err != nil {
		return nil, WithStack(err)
	}
	batch.cl = c
	batch.serverID = serverID
	batch.database = db.Name()
	return &batch, nil
}

// Get the inventory of a server containing all collections (with entire details) of a database.
func (c *client) DatabaseInventory(ctx context.Context, db Database) (DatabaseInventory, error) {
	req, err := c.conn.NewRequest("GET", path.Join("_db", db.Name(), "_api/replication/inventory"))
	if err != nil {
		return DatabaseInventory{}, WithStack(err)
	}
	applyContextSettings(ctx, req)
	resp, err := c.conn.Do(ctx, req)
	if err != nil {
		return DatabaseInventory{}, WithStack(err)
	}
	if err := resp.CheckStatus(200); err != nil {
		return DatabaseInventory{}, WithStack(err)
	}
	var result DatabaseInventory
	if err := resp.ParseBody("", &result); err != nil {
		return DatabaseInventory{}, WithStack(err)
	}
	return result, nil
}

// BatchID reported by the server
func (b batchMetadata) BatchID() string {
	return b.ID
}

// LastTick reported by the server for this batch
func (b batchMetadata) LastTick() Tick {
	return b.LastTickInt
}

// Extend the lifetime of an existing batch on the server
func (b batchMetadata) Extend(ctx context.Context, ttl time.Duration) error {
	if !atomic.CompareAndSwapInt32(&b.closed, 0, 0) {
		return WithStack(errors.New("Batch already closed"))
	}

	req, err := b.cl.conn.NewRequest("PUT", path.Join("_db", b.database, "_api/replication/batch", b.ID))
	if err != nil {
		return WithStack(err)
	}
	req = req.SetQuery("serverId", strconv.FormatInt(b.serverID, 10))
	input := struct {
		TTL int64 `json:"ttl"`
	}{
		TTL: int64(ttl.Seconds()),
	}
	req, err = req.SetBody(input)
	if err != nil {
		return WithStack(err)
	}
	resp, err := b.cl.conn.Do(ctx, req)
	if err != nil {
		return WithStack(err)
	}
	if err := resp.CheckStatus(204); err != nil {
		return WithStack(err)
	}
	return nil
}

// Delete an existing dump batch
func (b *batchMetadata) Delete(ctx context.Context) error {
	if !atomic.CompareAndSwapInt32(&b.closed, 0, 1) {
		return WithStack(errors.New("Batch already closed"))
	}

	req, err := b.cl.conn.NewRequest("DELETE", path.Join("_db", b.database, "_api/replication/batch", b.ID))
	if err != nil {
		return WithStack(err)
	}
	resp, err := b.cl.conn.Do(ctx, req)
	if err != nil {
		return WithStack(err)
	}
	if err := resp.CheckStatus(204); err != nil {
		return WithStack(err)
	}
	return nil
}
<commit_msg>Export batch error to be used by the client<commit_after>//
// DISCLAIMER
//
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
//
// 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.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//

package driver

import (
	"context"
	"errors"
	"path"
	"strconv"
	"sync/atomic"
	"time"
)

// Content of the create batch resp
type batchMetadata struct {
	// Id of the batch
	ID string `json:"id"`
	// Last Tick reported by the server
	LastTickInt Tick `json:"lastTick,omitempty"`

	cl       *client
	serverID int64
	database string
	closed   int32
}

// ErrBatchClosed occurs when there is an attempt closing or prolonging closed batch
var ErrBatchClosed = errors.New("Batch already closed")

// CreateBatch creates a "batch" to prevent WAL file removal and to take a snapshot
func (c *client) CreateBatch(ctx context.Context, db Database, serverID int64, ttl time.Duration) (Batch, error) {
	req, err := c.conn.NewRequest("POST", path.Join("_db", db.Name(), "_api/replication/batch"))
	if err != nil {
		return nil, WithStack(err)
	}
	req = req.SetQuery("serverId", strconv.FormatInt(serverID, 10))
	params := struct {
		TTL float64 `json:"ttl"`
	}{TTL: ttl.Seconds()} // just use a default ttl value
	req, err = req.SetBody(params)
	if err != nil {
		return nil, WithStack(err)
	}
	resp, err := c.conn.Do(ctx, req)
	if err != nil {
		return nil, WithStack(err)
	}
	if err := resp.CheckStatus(200); err != nil {
		return nil, WithStack(err)
	}
	var batch batchMetadata
	if err := resp.ParseBody("", &batch); err != nil {
		return nil, WithStack(err)
	}
	batch.cl = c
	batch.serverID = serverID
	batch.database = db.Name()
	return &batch, nil
}

// Get the inventory of a server containing all collections (with entire details) of a database.
func (c *client) DatabaseInventory(ctx context.Context, db Database) (DatabaseInventory, error) {
	req, err := c.conn.NewRequest("GET", path.Join("_db", db.Name(), "_api/replication/inventory"))
	if err != nil {
		return DatabaseInventory{}, WithStack(err)
	}
	applyContextSettings(ctx, req)
	resp, err := c.conn.Do(ctx, req)
	if err != nil {
		return DatabaseInventory{}, WithStack(err)
	}
	if err := resp.CheckStatus(200); err != nil {
		return DatabaseInventory{}, WithStack(err)
	}
	var result DatabaseInventory
	if err := resp.ParseBody("", &result); err != nil {
		return DatabaseInventory{}, WithStack(err)
	}
	return result, nil
}

// BatchID reported by the server
func (b batchMetadata) BatchID() string {
	return b.ID
}

// LastTick reported by the server for this batch
func (b batchMetadata) LastTick() Tick {
	return b.LastTickInt
}

// Extend the lifetime of an existing batch on the server
func (b batchMetadata) Extend(ctx context.Context, ttl time.Duration) error {
	if !atomic.CompareAndSwapInt32(&b.closed, 0, 0) {
		return WithStack(ErrBatchClosed)
	}

	req, err := b.cl.conn.NewRequest("PUT", path.Join("_db", b.database, "_api/replication/batch", b.ID))
	if err != nil {
		return WithStack(err)
	}
	req = req.SetQuery("serverId", strconv.FormatInt(b.serverID, 10))
	input := struct {
		TTL int64 `json:"ttl"`
	}{
		TTL: int64(ttl.Seconds()),
	}
	req, err = req.SetBody(input)
	if err != nil {
		return WithStack(err)
	}
	resp, err := b.cl.conn.Do(ctx, req)
	if err != nil {
		return WithStack(err)
	}
	if err := resp.CheckStatus(204); err != nil {
		return WithStack(err)
	}
	return nil
}

// Delete an existing dump batch
func (b *batchMetadata) Delete(ctx context.Context) error {
	if !atomic.CompareAndSwapInt32(&b.closed, 0, 1) {
		return WithStack(ErrBatchClosed)
	}

	req, err := b.cl.conn.NewRequest("DELETE", path.Join("_db", b.database, "_api/replication/batch", b.ID))
	if err != nil {
		return WithStack(err)
	}
	resp, err := b.cl.conn.Do(ctx, req)
	if err != nil {
		return WithStack(err)
	}
	if err := resp.CheckStatus(204); err != nil {
		return WithStack(err)
	}
	return nil
}
<|endoftext|>