<commit_before>package bitmap

import (
	"reflect"
	"testing"

	"github.com/facebookgo/ensure"
)

// -----------------------------------------------------------------------------

func TestFlatten_singleValue_int(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(int(50))},
	}
	ensure.Subset(t, Flatten(int(50)), subset)
}

func TestFlatten_singleValue_int8(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(int8(50))},
	}
	ensure.Subset(t, Flatten(int8(50)), subset)
}

func TestFlatten_singleValue_int16(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(int16(50))},
	}
	ensure.Subset(t, Flatten(int16(50)), subset)
}

func TestFlatten_singleValue_int32(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(int32(50))},
	}
	ensure.Subset(t, Flatten(int32(50)), subset)
}

func TestFlatten_singleValue_int64(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(int64(50))},
	}
	ensure.Subset(t, Flatten(int64(50)), subset)
}

func TestFlatten_singleValue_uint(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(uint(50))},
	}
	ensure.Subset(t, Flatten(uint(50)), subset)
}

func TestFlatten_singleValue_uint8(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(uint8(50))},
	}
	ensure.Subset(t, Flatten(uint8(50)), subset)
}

func TestFlatten_singleValue_uint16(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(uint16(50))},
	}
	ensure.Subset(t, Flatten(uint16(50)), subset)
}

func TestFlatten_singleValue_uint32(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(uint32(50))},
	}
	ensure.Subset(t, Flatten(uint32(50)), subset)
}

func TestFlatten_singleValue_uint64(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(uint64(50))},
	}
	ensure.Subset(t, Flatten(uint64(50)), subset)
}

func TestFlatten_singleValue_float32(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(float32(50.20))},
	}
	ensure.Subset(t, Flatten(float32(50.20)), subset)
}

func TestFlatten_singleValue_float64(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(float64(50.20))},
	}
	ensure.Subset(t, Flatten(float64(50.20)), subset)
}

func TestFlatten_singleValue_complex64(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(complex64(50))},
	}
	ensure.Subset(t, Flatten(complex64(50)), subset)
}

func TestFlatten_singleValue_complex128(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(complex128(50))},
	}
	ensure.Subset(t, Flatten(complex128(50)), subset)
}

func TestFlatten_singleValue_ptr(t *testing.T) {
	subset := [][]interface{}{
		{reflect.ValueOf(int(50))},
	}

	ensure.Subset(t, Flatten(int(50)), subset)
}

// -----------------------------------------------------------------------------
<commit_msg>add generateSubset<commit_after>package bitmap

import (
	"reflect"
	"testing"

	"github.com/facebookgo/ensure"
)

// -----------------------------------------------------------------------------

// TODO
func generateSubset(iface interface{}) [][]interface{} {
	subset := [][]interface{}{
		{reflect.ValueOf(iface)},
	}
	return subset
}

// -----------------------------------------------------------------------------

func TestFlatten_singleValue_int(t *testing.T) {
	ensure.Subset(t, Flatten(int(50)), generateSubset(int(50)))
}

func TestFlatten_singleValue_int8(t *testing.T) {
	ensure.Subset(t, Flatten(int8(8)), generateSubset(int8(8)))
}

func TestFlatten_singleValue_int16(t *testing.T) {
	ensure.Subset(t, Flatten(int16(16)), generateSubset(int16(16)))
}

func TestFlatten_singleValue_int32(t *testing.T) {
	ensure.Subset(t, Flatten(int32(32)), generateSubset(int32(32)))
}

func TestFlatten_singleValue_int64(t *testing.T) {
	ensure.Subset(t, Flatten(int64(64)), generateSubset(int64(64)))
}

func TestFlatten_singleValue_uint(t *testing.T) {
	ensure.Subset(t, Flatten(uint(50)), generateSubset(uint(50)))
}

func TestFlatten_singleValue_uint8(t *testing.T) {
	ensure.Subset(t, Flatten(uint8(8)), generateSubset(uint8(8)))
}

func TestFlatten_singleValue_uint16(t *testing.T) {
	ensure.Subset(t, Flatten(uint16(16)), generateSubset(uint16(16)))
}

func TestFlatten_singleValue_uint32(t *testing.T) {
	ensure.Subset(t, Flatten(uint32(32)), generateSubset(uint32(32)))
}

func TestFlatten_singleValue_uint64(t *testing.T) {
	ensure.Subset(t, Flatten(uint64(64)), generateSubset(uint64(64)))
}

func TestFlatten_singleValue_float32(t *testing.T) {
	ensure.Subset(t, Flatten(float32(50.32)), generateSubset(float32(50.32)))
}

func TestFlatten_singleValue_float64(t *testing.T) {
	ensure.Subset(t, Flatten(float64(50.64)), generateSubset(float64(50.64)))
}

func TestFlatten_singleValue_complex64(t *testing.T) {
	ensure.Subset(t, Flatten(complex64(64)), generateSubset(complex64(64)))
}

func TestFlatten_singleValue_complex128(t *testing.T) {
	ensure.Subset(t, Flatten(complex128(128)), generateSubset(complex128(128)))
}

func TestFlatten_singleValue_ptr(t *testing.T) {
	ensure.Subset(t, Flatten(int(50)), generateSubset(int(50)))
}

// -----------------------------------------------------------------------------
<|endoftext|>


<commit_before>package clickhouse_test

import (
	"database/sql/driver"
	"reflect"
	"testing"
	"time"

	"github.com/kshvakov/clickhouse"
	"github.com/kshvakov/clickhouse/lib/data"
	"github.com/stretchr/testify/assert"
)

func Test_ColumnarInsert(t *testing.T) {
	const (
		ddl = `
			CREATE TABLE clickhouse_test_columnar_insert (
				uint8  UInt8,
				uint16 UInt16,
				uint32 UInt32,
				uint64 UInt64,
				float32 Float32,
				float64 Float64,
				string  String,
				fString FixedString(2),
				date    Date,
				datetime   DateTime,
				enum8      Enum8 ('a' = 1, 'b' = 2),
				enum16     Enum16('c' = 1, 'd' = 2),
				array      Array(String),
				array2     Array(String),
				arrayArray Array(Array(String))
			) Engine=Memory
		`
		dml = `
			INSERT INTO clickhouse_test_columnar_insert (
				uint8,
				uint16,
				uint32,
				uint64,
				float32,
				float64,
				string,
				fString,
				date,
				datetime,
				enum8,
				enum16,
				array,
				array2,
				arrayArray
			) VALUES (
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?
			)
		`
	)
	if connect, err := clickhouse.OpenDirect("tcp://127.0.0.1:9000?debug=true"); assert.NoError(t, err) {
		{
			connect.Begin()
			stmt, _ := connect.Prepare("DROP TABLE IF EXISTS clickhouse_test_columnar_insert")
			stmt.Exec([]driver.Value{})
			connect.Commit()
		}
		{
			if _, err := connect.Begin(); assert.NoError(t, err) {
				if stmt, err := connect.Prepare(ddl); assert.NoError(t, err) {
					if _, err := stmt.Exec([]driver.Value{}); assert.NoError(t, err) {
						assert.NoError(t, connect.Commit())
					}
				}
			}
		}
		{
			if _, err := connect.Begin(); assert.NoError(t, err) {
				if _, err := connect.Prepare(dml); assert.NoError(t, err) {
					block, err := connect.Block()
					assert.NoError(t, err)
					block.Reserve()
					block.NumRows = 100

					for i := 0; i < 100; i++ {
						block.WriteUInt8(0, uint8(i))
						block.WriteUInt16(1, uint16(i))
						block.WriteUInt32(2, uint32(i))
						block.WriteUInt64(3, uint64(i))

						block.WriteFloat32(4, float32(i))
						block.WriteFloat64(5, float64(i))

						block.WriteString(6, "string")
						block.WriteFixedString(7, []byte("CH"))
						block.WriteDate(8, time.Now())
						block.WriteDateTime(9, time.Now())

						block.WriteUInt8(10, 1)
						block.WriteUInt16(11, 2)
						block.WriteArray(12, []string{"A", "B", "C"})
						block.WriteArrayWithValue(13, stringSliceValue{value: []string{"A", "B", "C"}})
						block.WriteArray(14, [][]string{[]string{"A", "B"}, []string{"CC", "DD", "EE"}})
						if !assert.NoError(t, err) {
							return
						}
					}

					assert.NoError(t, connect.Commit())
				}
			}
		}
	}
}

type stringValue struct {
	value string
}

func (v stringValue) Kind() reflect.Kind {
	return reflect.String
}

func (v stringValue) Len() int {
	panic("string has no length")
}
func (v stringValue) Index(i int) data.Value {
	panic("string has no index")
}

func (v stringValue) Interface() interface{} {
	return v.value
}

type stringSliceValue struct {
	value []string
}

func (v stringSliceValue) Kind() reflect.Kind {
	return reflect.Slice
}

func (v stringSliceValue) Len() int {
	return len(v.value)
}

func (v stringSliceValue) Index(i int) data.Value {
	return stringValue{value: v.value[i]}
}

func (v stringSliceValue) Interface() interface{} {
	return v.value
}
<commit_msg>Update test<commit_after>package clickhouse_test

import (
	"database/sql/driver"
	"reflect"
	"testing"
	"time"

	"github.com/kshvakov/clickhouse"
	"github.com/kshvakov/clickhouse/lib/data"
	"github.com/stretchr/testify/assert"
)

func Test_ColumnarInsert(t *testing.T) {
	const (
		ddl = `
			CREATE TABLE clickhouse_test_columnar_insert (
				uint8  UInt8,
				uint16 UInt16,
				uint32 UInt32,
				uint64 UInt64,
				float32 Float32,
				float64 Float64,
				string  String,
				fString FixedString(2),
				date    Date,
				datetime   DateTime,
				enum8      Enum8 ('a' = 1, 'b' = 2),
				enum16     Enum16('c' = 1, 'd' = 2),
				array      Array(String),
				array2     Array(UInt64),
				arrayArray Array(Array(String))
			) Engine=Memory
		`
		dml = `
			INSERT INTO clickhouse_test_columnar_insert (
				uint8,
				uint16,
				uint32,
				uint64,
				float32,
				float64,
				string,
				fString,
				date,
				datetime,
				enum8,
				enum16,
				array,
				array2,
				arrayArray
			) VALUES (
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?,
				?
			)
		`
	)
	if connect, err := clickhouse.OpenDirect("tcp://127.0.0.1:9000?debug=true"); assert.NoError(t, err) {
		{
			connect.Begin()
			stmt, _ := connect.Prepare("DROP TABLE IF EXISTS clickhouse_test_columnar_insert")
			stmt.Exec([]driver.Value{})
			connect.Commit()
		}
		{
			if _, err := connect.Begin(); assert.NoError(t, err) {
				if stmt, err := connect.Prepare(ddl); assert.NoError(t, err) {
					if _, err := stmt.Exec([]driver.Value{}); assert.NoError(t, err) {
						assert.NoError(t, connect.Commit())
					}
				}
			}
		}
		{
			if _, err := connect.Begin(); assert.NoError(t, err) {
				if _, err := connect.Prepare(dml); assert.NoError(t, err) {
					block, err := connect.Block()
					assert.NoError(t, err)
					block.Reserve()
					block.NumRows = 100

					for i := 0; i < 100; i++ {
						block.WriteUInt8(0, uint8(i))
						block.WriteUInt16(1, uint16(i))
						block.WriteUInt32(2, uint32(i))
						block.WriteUInt64(3, uint64(i))

						block.WriteFloat32(4, float32(i))
						block.WriteFloat64(5, float64(i))

						block.WriteString(6, "string")
						block.WriteFixedString(7, []byte("CH"))
						block.WriteDate(8, time.Now())
						block.WriteDateTime(9, time.Now())

						block.WriteUInt8(10, 1)
						block.WriteUInt16(11, 2)
						block.WriteArray(12, []string{"A", "B", "C"})
						block.WriteArrayWithValue(13, uint64SliceValue{value: []uint64{1, 2, 3}})
						block.WriteArray(14, [][]string{[]string{"A", "B"}, []string{"CC", "DD", "EE"}})
						if !assert.NoError(t, err) {
							return
						}
					}

					assert.NoError(t, connect.Commit())
				}
			}
		}
	}
}

type uint64Value struct {
	value uint64
}

func (v uint64Value) Kind() reflect.Kind {
	return reflect.String
}

func (v uint64Value) Len() int {
	panic("uint64 has no length")
}

func (v uint64Value) Index(i int) data.Value {
	panic("uint64 has no index")
}

func (v uint64Value) Interface() interface{} {
	return v.value
}

type uint64SliceValue struct {
	value []uint64
}

func (v uint64SliceValue) Kind() reflect.Kind {
	return reflect.Slice
}

func (v uint64SliceValue) Len() int {
	return len(v.value)
}

func (v uint64SliceValue) Index(i int) data.Value {
	return uint64Value{value: v.value[i]}
}

func (v uint64SliceValue) Interface() interface{} {
	return v.value
}
<|endoftext|>


<commit_before>package cliedit

// Elvish code for default bindings, assuming the editor ns as the global ns.
const defaultBindingsElv = `
insert:binding = (binding-map [
  &Left=  $move-left~
  &Right= $move-right~

  &Ctrl-Left=  $move-left-word~
  &Ctrl-Right= $move-right-word~
  &Alt-Left=   $move-left-word~
  &Alt-Right=  $move-right-word~
  &Alt-b=      $move-left-word~
  &Alt-f=      $move-right-word~

  &Home= $move-sol~
  &End=  $move-eol~

  &Backspace= $kill-left~
  &Delete=    $kill-right~
  &Ctrl-W=    $kill-left-word~
  &Ctrl-U=    $kill-sol~
  &Ctrl-K=    $kill-eol~

  &Alt-,=  $lastcmd:start~
  &Ctrl-R= $histlist:start~
  &Ctrl-L= $location:start~

  &Ctrl-D=  $commit-eof~
  &Default= $insert:default-handler~
])

listing:binding = (binding-map [
  &Up=        $listing:up~
  &Down=      $listing:down~
  &Tab=       $listing:down-cycle~
  &Shift-Tab= $listing:up-cycle~

  &Ctrl-F=    $listing:toggle-filtering~

  &Alt-Enter= $listing:accept~
  &Enter=     $listing:accept-close~
  &Alt-,=     $listing:accept-close~
  &Ctrl-'['=  $reset-mode~

  &Default=   $listing:default~
])
`

// vi: set et:
<commit_msg>cliedit: Comment out unimplemented functions in default binding.<commit_after>package cliedit

// Elvish code for default bindings, assuming the editor ns as the global ns.
const defaultBindingsElv = `
insert:binding = (binding-map [
  &Left=  $move-left~
  &Right= $move-right~

  &Ctrl-Left=  $move-left-word~
  &Ctrl-Right= $move-right-word~
  &Alt-Left=   $move-left-word~
  &Alt-Right=  $move-right-word~
  &Alt-b=      $move-left-word~
  &Alt-f=      $move-right-word~

  &Home= $move-sol~
  &End=  $move-eol~

  &Backspace= $kill-left~
  &Delete=    $kill-right~
  &Ctrl-W=    $kill-left-word~
  &Ctrl-U=    $kill-sol~
  &Ctrl-K=    $kill-eol~

  &Alt-,=  $lastcmd:start~
  &Ctrl-R= $histlist:start~
  &Ctrl-L= $location:start~

  &Ctrl-D=  $commit-eof~
])

listing:binding = (binding-map [
  &Ctrl-'['= $listing:close~
])
#  &Up=        $listing:up~
#  &Down=      $listing:down~
#  &Tab=       $listing:down-cycle~
#  &Shift-Tab= $listing:up-cycle~
#
#  &Ctrl-F=    $listing:toggle-filtering~
#
#  &Alt-Enter= $listing:accept~
#  &Enter=     $listing:accept-close~
#  &Alt-,=     $listing:accept-close~
#  &Ctrl-'['=  $reset-mode~
#
#  &Default=   $listing:default~
`

// vi: set et:
<|endoftext|>


<commit_before>package client

import (
	"encoding/json"
	"fmt"
	"text/tabwriter"
	"time"

	"github.com/docker/docker/api/types"
	Cli "github.com/docker/docker/cli"
	flag "github.com/docker/docker/pkg/mflag"
	"github.com/docker/docker/pkg/stringid"
	"github.com/docker/docker/pkg/stringutils"
	"github.com/docker/docker/pkg/units"
)

// CmdHistory shows the history of an image.
//
// Usage: docker history [OPTIONS] IMAGE
func (cli *DockerCli) CmdHistory(args ...string) error {
	cmd := Cli.Subcmd("history", []string{"IMAGE"}, "Show the history of an image", true)
	human := cmd.Bool([]string{"H", "-human"}, true, "Print sizes and dates in human readable format")
	quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
	noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
	cmd.Require(flag.Exact, 1)

	cmd.ParseFlags(args, true)

	serverResp, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil)
	if err != nil {
		return err
	}

	defer serverResp.body.Close()

	history := []types.ImageHistory{}
	if err := json.NewDecoder(serverResp.body).Decode(&history); err != nil {
		return err
	}

	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
	if !*quiet {
		fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT")
	}

	for _, entry := range history {
		if *noTrunc {
			fmt.Fprintf(w, entry.ID)
		} else {
			fmt.Fprintf(w, stringid.TruncateID(entry.ID))
		}
		if !*quiet {
			if *human {
				fmt.Fprintf(w, "\t%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))))
			} else {
				fmt.Fprintf(w, "\t%s\t", time.Unix(entry.Created, 0).Format(time.RFC3339))
			}

			if *noTrunc {
				fmt.Fprintf(w, "%s\t", entry.CreatedBy)
			} else {
				fmt.Fprintf(w, "%s\t", stringutils.Truncate(entry.CreatedBy, 45))
			}

			if *human {
				fmt.Fprintf(w, "%s\t", units.HumanSize(float64(entry.Size)))
			} else {
				fmt.Fprintf(w, "%d\t", entry.Size)
			}

			fmt.Fprintf(w, "%s", entry.Comment)
		}
		fmt.Fprintf(w, "\n")
	}
	w.Flush()
	return nil
}
<commit_msg>Format the output of docker history<commit_after>package client

import (
	"encoding/json"
	"fmt"
	"strings"
	"text/tabwriter"
	"time"

	"github.com/docker/docker/api/types"
	Cli "github.com/docker/docker/cli"
	flag "github.com/docker/docker/pkg/mflag"
	"github.com/docker/docker/pkg/stringid"
	"github.com/docker/docker/pkg/stringutils"
	"github.com/docker/docker/pkg/units"
)

// CmdHistory shows the history of an image.
//
// Usage: docker history [OPTIONS] IMAGE
func (cli *DockerCli) CmdHistory(args ...string) error {
	cmd := Cli.Subcmd("history", []string{"IMAGE"}, "Show the history of an image", true)
	human := cmd.Bool([]string{"H", "-human"}, true, "Print sizes and dates in human readable format")
	quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only show numeric IDs")
	noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
	cmd.Require(flag.Exact, 1)

	cmd.ParseFlags(args, true)

	serverResp, err := cli.call("GET", "/images/"+cmd.Arg(0)+"/history", nil, nil)
	if err != nil {
		return err
	}

	defer serverResp.body.Close()

	history := []types.ImageHistory{}
	if err := json.NewDecoder(serverResp.body).Decode(&history); err != nil {
		return err
	}

	w := tabwriter.NewWriter(cli.out, 20, 1, 3, ' ', 0)
	if !*quiet {
		fmt.Fprintln(w, "IMAGE\tCREATED\tCREATED BY\tSIZE\tCOMMENT")
	}

	for _, entry := range history {
		if *noTrunc {
			fmt.Fprintf(w, entry.ID)
		} else {
			fmt.Fprintf(w, stringid.TruncateID(entry.ID))
		}
		if !*quiet {
			if *human {
				fmt.Fprintf(w, "\t%s ago\t", units.HumanDuration(time.Now().UTC().Sub(time.Unix(entry.Created, 0))))
			} else {
				fmt.Fprintf(w, "\t%s\t", time.Unix(entry.Created, 0).Format(time.RFC3339))
			}

			if *noTrunc {
				fmt.Fprintf(w, "%s\t", strings.Replace(entry.CreatedBy, "\t", " ", -1))
			} else {
				fmt.Fprintf(w, "%s\t", stringutils.Truncate(strings.Replace(entry.CreatedBy, "\t", " ", -1), 45))
			}

			if *human {
				fmt.Fprintf(w, "%s\t", units.HumanSize(float64(entry.Size)))
			} else {
				fmt.Fprintf(w, "%d\t", entry.Size)
			}

			fmt.Fprintf(w, "%s", entry.Comment)
		}
		fmt.Fprintf(w, "\n")
	}
	w.Flush()
	return nil
}
<|endoftext|>


<commit_before>// Copyright © 2016 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package jwalterweatherman

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

var (
	TRACE    *log.Logger
	DEBUG    *log.Logger
	INFO     *log.Logger
	WARN     *log.Logger
	ERROR    *log.Logger
	CRITICAL *log.Logger
	FATAL    *log.Logger

	LOG      *log.Logger
	FEEDBACK *Feedback

	defaultNotepad *Notepad
)

func reloadDefaultNotepad() {
	TRACE = defaultNotepad.TRACE
	DEBUG = defaultNotepad.DEBUG
	INFO = defaultNotepad.INFO
	WARN = defaultNotepad.WARN
	ERROR = defaultNotepad.ERROR
	CRITICAL = defaultNotepad.CRITICAL
	FATAL = defaultNotepad.FATAL

	LOG = defaultNotepad.LOG
	FEEDBACK = defaultNotepad.FEEDBACK
}

func init() {
	defaultNotepad = NewNotepad(LevelInfo, LevelTrace, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime)
	reloadDefaultNotepad()
}

// SetLogThreshold set the log threshold for the default notepad. Trace by default.
func SetLogThreshold(threshold Threshold) {
	defaultNotepad.SetLogThreshold(threshold)
	reloadDefaultNotepad()
}

// SetLogOutput set the log output for the default notepad. Discarded by default.
func SetLogOutput(handle io.Writer) {
	defaultNotepad.SetLogOutput(handle)
	reloadDefaultNotepad()
}

// SetStdoutThreshold set the standard output threshold for the default notepad.
// Info by default.
func SetStdoutThreshold(threshold Threshold) {
	defaultNotepad.SetStdoutThreshold(threshold)
	reloadDefaultNotepad()
}

// SetPrefix set the prefix for the default logger. Empty by default.
func SetPrefix(prefix string) {
	defaultNotepad.SetPrefix(prefix)
	reloadDefaultNotepad()
}

// SetFlags set the flags for the default logger. "log.Ldate | log.Ltime" by default.
func SetFlags(flags int) {
	defaultNotepad.SetFlags(flags)
	reloadDefaultNotepad()
}

// Level returns the current global log threshold.
func LogThreshold() Threshold {
	return defaultNotepad.logThreshold
}

// Level returns the current global output threshold.
func StdoutThreshold() Threshold {
	return defaultNotepad.stdoutThreshold
}

// LogCountForLevel returns the number of log invocations for a given threshold.
func LogCountForLevel(l Threshold) uint64 {
	return defaultNotepad.LogCountForLevel(l)
}

// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations
// greater than or equal to a given threshold.
func LogCountForLevelsGreaterThanorEqualTo(threshold Threshold) uint64 {
	return defaultNotepad.LogCountForLevelsGreaterThanorEqualTo(threshold)
}

// ResetLogCounters resets the invocation counters for all levels.
func ResetLogCounters() {
	defaultNotepad.ResetLogCounters()
}
<commit_msg>Set correct default log levels<commit_after>// Copyright © 2016 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package jwalterweatherman

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

var (
	TRACE    *log.Logger
	DEBUG    *log.Logger
	INFO     *log.Logger
	WARN     *log.Logger
	ERROR    *log.Logger
	CRITICAL *log.Logger
	FATAL    *log.Logger

	LOG      *log.Logger
	FEEDBACK *Feedback

	defaultNotepad *Notepad
)

func reloadDefaultNotepad() {
	TRACE = defaultNotepad.TRACE
	DEBUG = defaultNotepad.DEBUG
	INFO = defaultNotepad.INFO
	WARN = defaultNotepad.WARN
	ERROR = defaultNotepad.ERROR
	CRITICAL = defaultNotepad.CRITICAL
	FATAL = defaultNotepad.FATAL

	LOG = defaultNotepad.LOG
	FEEDBACK = defaultNotepad.FEEDBACK
}

func init() {
	defaultNotepad = NewNotepad(LevelError, LevelWarn, os.Stdout, ioutil.Discard, "", log.Ldate|log.Ltime)
	reloadDefaultNotepad()
}

// SetLogThreshold set the log threshold for the default notepad. Trace by default.
func SetLogThreshold(threshold Threshold) {
	defaultNotepad.SetLogThreshold(threshold)
	reloadDefaultNotepad()
}

// SetLogOutput set the log output for the default notepad. Discarded by default.
func SetLogOutput(handle io.Writer) {
	defaultNotepad.SetLogOutput(handle)
	reloadDefaultNotepad()
}

// SetStdoutThreshold set the standard output threshold for the default notepad.
// Info by default.
func SetStdoutThreshold(threshold Threshold) {
	defaultNotepad.SetStdoutThreshold(threshold)
	reloadDefaultNotepad()
}

// SetPrefix set the prefix for the default logger. Empty by default.
func SetPrefix(prefix string) {
	defaultNotepad.SetPrefix(prefix)
	reloadDefaultNotepad()
}

// SetFlags set the flags for the default logger. "log.Ldate | log.Ltime" by default.
func SetFlags(flags int) {
	defaultNotepad.SetFlags(flags)
	reloadDefaultNotepad()
}

// Level returns the current global log threshold.
func LogThreshold() Threshold {
	return defaultNotepad.logThreshold
}

// Level returns the current global output threshold.
func StdoutThreshold() Threshold {
	return defaultNotepad.stdoutThreshold
}

// LogCountForLevel returns the number of log invocations for a given threshold.
func LogCountForLevel(l Threshold) uint64 {
	return defaultNotepad.LogCountForLevel(l)
}

// LogCountForLevelsGreaterThanorEqualTo returns the number of log invocations
// greater than or equal to a given threshold.
func LogCountForLevelsGreaterThanorEqualTo(threshold Threshold) uint64 {
	return defaultNotepad.LogCountForLevelsGreaterThanorEqualTo(threshold)
}

// ResetLogCounters resets the invocation counters for all levels.
func ResetLogCounters() {
	defaultNotepad.ResetLogCounters()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"strconv"

	"github.com/deis/deis/deisctl/backend/fleet"
	"github.com/deis/deis/deisctl/client"
	"github.com/deis/deis/deisctl/utils"

	docopt "github.com/docopt/docopt-go"
)

const (
	// Version of deisctl client
	Version string = "0.13.0-dev"
)

func exit(err error, code int) {
	fmt.Printf("Error: %v\n", err)
	os.Exit(code)
}

func setGlobalFlags(args map[string]interface{}, setTunnel bool) {
	fleet.Flags.Endpoint = args["--endpoint"].(string)
	fleet.Flags.EtcdKeyPrefix = args["--etcd-key-prefix"].(string)
	fleet.Flags.EtcdKeyFile = args["--etcd-keyfile"].(string)
	fleet.Flags.EtcdCertFile = args["--etcd-certfile"].(string)
	fleet.Flags.EtcdCAFile = args["--etcd-cafile"].(string)
	//fleet.Flags.UseAPI = args["--experimental-api"].(bool)
	fleet.Flags.KnownHostsFile = args["--known-hosts-file"].(string)
	fleet.Flags.StrictHostKeyChecking = args["--strict-host-key-checking"].(bool)
	timeout, _ := strconv.ParseFloat(args["--request-timeout"].(string), 64)
	fleet.Flags.RequestTimeout = timeout
	if setTunnel == true {
		tunnel := args["--tunnel"].(string)
		if tunnel != "" {
			fleet.Flags.Tunnel = tunnel
		} else {
			fleet.Flags.Tunnel = os.Getenv("DEISCTL_TUNNEL")
		}
	}
}

func main() {
	deisctlMotd := utils.DeisIfy("Deis Control Utility")
	usage := deisctlMotd + `
Usage:
  deisctl <command> [<target>...] [options]

Commands:
  deisctl install [<service> | platform]
  deisctl uninstall [<service> | platform]
  deisctl list
  deisctl scale [<service>=<num>]
  deisctl start [<service> | platform]
  deisctl stop [<service> | platform]
  deisctl restart [<service> | platform]
  deisctl journal <service>
  deisctl config <component> <get|set> <args>
  deisctl update
  deisctl refresh-units

Example Commands:
  deisctl install platform
  deisctl uninstall builder@1
  deisctl scale router=2
  deisctl start router@2
  deisctl stop router builder
  deisctl status controller
  deisctl journal controller

Options:
  --version                   print version and exit
  --endpoint=<url>            etcd endpoint for fleet [default: http://127.0.0.1:4001]
  --etcd-key-prefix=<path>    keyspace for fleet data in etcd [default: /_coreos.com/fleet/]
  --etcd-keyfile=<path>       etcd key file authentication [default: ]
  --etcd-certfile=<path>      etcd cert file authentication [default: ]
  --etcd-cafile=<path>        etcd CA file authentication [default: ]
  --known-hosts-file=<path>   file used to store remote machine fingerprints [default: ~/.ssh/known_hosts]
  --strict-host-key-checking  verify SSH host keys [default: true]
  --tunnel=<host>             establish an SSH tunnel for communication with fleet and etcd [default: ]
  --request-timeout=<secs>    amount of time to allow a single request before considering it failed. [default: 3.0]
`
	// parse command-line arguments
	args, err := docopt.Parse(usage, nil, true, Version, true)
	if err != nil {
		exit(err, 2)
	}
	command := args["<command>"]
	targets := args["<target>"].([]string)
	setTunnel := true
	// refresh-units doesn't need SSH tunneling
	if command == "refresh-units" {
		setTunnel = false
	}
	setGlobalFlags(args, setTunnel)
	// construct a client
	c, err := client.NewClient("fleet")
	if err != nil {
		exit(err, 1)
	}
	// dispatch the command
	switch command {
	case "list":
		err = c.List()
	case "scale":
		err = c.Scale(targets)
	case "start":
		err = c.Start(targets)
	case "restart":
		err = c.Restart(targets)
	case "stop":
		err = c.Stop(targets)
	case "status":
		err = c.Status(targets)
	case "journal":
		err = c.Journal(targets)
	case "install":
		err = c.Install(targets)
	case "uninstall":
		err = c.Uninstall(targets)
	case "config":
		err = c.Config()
	case "update":
		err = c.Update()
	case "refresh-units":
		err = c.RefreshUnits()
	default:
		fmt.Printf(usage)
		os.Exit(2)
	}
	if err != nil {
		exit(err, 1)
	}
}
<commit_msg>fix(deisctl): bump default etcd timeout to 10s<commit_after>package main

import (
	"fmt"
	"os"
	"strconv"

	"github.com/deis/deis/deisctl/backend/fleet"
	"github.com/deis/deis/deisctl/client"
	"github.com/deis/deis/deisctl/utils"

	docopt "github.com/docopt/docopt-go"
)

const (
	// Version of deisctl client
	Version string = "0.13.0-dev"
)

func exit(err error, code int) {
	fmt.Printf("Error: %v\n", err)
	os.Exit(code)
}

func setGlobalFlags(args map[string]interface{}, setTunnel bool) {
	fleet.Flags.Endpoint = args["--endpoint"].(string)
	fleet.Flags.EtcdKeyPrefix = args["--etcd-key-prefix"].(string)
	fleet.Flags.EtcdKeyFile = args["--etcd-keyfile"].(string)
	fleet.Flags.EtcdCertFile = args["--etcd-certfile"].(string)
	fleet.Flags.EtcdCAFile = args["--etcd-cafile"].(string)
	//fleet.Flags.UseAPI = args["--experimental-api"].(bool)
	fleet.Flags.KnownHostsFile = args["--known-hosts-file"].(string)
	fleet.Flags.StrictHostKeyChecking = args["--strict-host-key-checking"].(bool)
	timeout, _ := strconv.ParseFloat(args["--request-timeout"].(string), 64)
	fleet.Flags.RequestTimeout = timeout
	if setTunnel == true {
		tunnel := args["--tunnel"].(string)
		if tunnel != "" {
			fleet.Flags.Tunnel = tunnel
		} else {
			fleet.Flags.Tunnel = os.Getenv("DEISCTL_TUNNEL")
		}
	}
}

func main() {
	deisctlMotd := utils.DeisIfy("Deis Control Utility")
	usage := deisctlMotd + `
Usage:
  deisctl <command> [<target>...] [options]

Commands:
  deisctl install [<service> | platform]
  deisctl uninstall [<service> | platform]
  deisctl list
  deisctl scale [<service>=<num>]
  deisctl start [<service> | platform]
  deisctl stop [<service> | platform]
  deisctl restart [<service> | platform]
  deisctl journal <service>
  deisctl config <component> <get|set> <args>
  deisctl update
  deisctl refresh-units

Example Commands:
  deisctl install platform
  deisctl uninstall builder@1
  deisctl scale router=2
  deisctl start router@2
  deisctl stop router builder
  deisctl status controller
  deisctl journal controller

Options:
  --version                   print version and exit
  --endpoint=<url>            etcd endpoint for fleet [default: http://127.0.0.1:4001]
  --etcd-key-prefix=<path>    keyspace for fleet data in etcd [default: /_coreos.com/fleet/]
  --etcd-keyfile=<path>       etcd key file authentication [default: ]
  --etcd-certfile=<path>      etcd cert file authentication [default: ]
  --etcd-cafile=<path>        etcd CA file authentication [default: ]
  --known-hosts-file=<path>   file used to store remote machine fingerprints [default: ~/.ssh/known_hosts]
  --strict-host-key-checking  verify SSH host keys [default: true]
  --tunnel=<host>             establish an SSH tunnel for communication with fleet and etcd [default: ]
  --request-timeout=<secs>    amount of time to allow a single request before considering it failed. [default: 10.0]
`
	// parse command-line arguments
	args, err := docopt.Parse(usage, nil, true, Version, true)
	if err != nil {
		exit(err, 2)
	}
	command := args["<command>"]
	targets := args["<target>"].([]string)
	setTunnel := true
	// refresh-units doesn't need SSH tunneling
	if command == "refresh-units" {
		setTunnel = false
	}
	setGlobalFlags(args, setTunnel)
	// construct a client
	c, err := client.NewClient("fleet")
	if err != nil {
		exit(err, 1)
	}
	// dispatch the command
	switch command {
	case "list":
		err = c.List()
	case "scale":
		err = c.Scale(targets)
	case "start":
		err = c.Start(targets)
	case "restart":
		err = c.Restart(targets)
	case "stop":
		err = c.Stop(targets)
	case "status":
		err = c.Status(targets)
	case "journal":
		err = c.Journal(targets)
	case "install":
		err = c.Install(targets)
	case "uninstall":
		err = c.Uninstall(targets)
	case "config":
		err = c.Config()
	case "update":
		err = c.Update()
	case "refresh-units":
		err = c.RefreshUnits()
	default:
		fmt.Printf(usage)
		os.Exit(2)
	}
	if err != nil {
		exit(err, 1)
	}
}
<|endoftext|>


<commit_before>package client_test

import (
	"io"
	"fmt"
	"net"
	"testing"

	"github.com/emersion/go-imap/common"
	"github.com/emersion/go-imap/client"
)

func TestClient_Check(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		err = c.Check()
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "CHECK" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, tag + " OK CHECK completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Close(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState
		c.Mailbox = &common.MailboxStatus{Name: "INBOX"}

		err = c.Close()
		if err != nil {
			return
		}

		if c.State != common.AuthenticatedState {
			return fmt.Errorf("Bad client state: %v", c.State)
		}
		if c.Mailbox != nil {
			return fmt.Errorf("Client selected mailbox is not nil: %v", c.Mailbox)
		}
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "CLOSE" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, tag + " OK CLOSE completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Expunge(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		expunged := make(chan uint32, 4)
		err = c.Expunge(expunged)
		if err != nil {
			return
		}

		expected := []uint32{3, 3, 5, 8}

		i := 0
		for id := range expunged {
			if id != expected[i] {
				return fmt.Errorf("Bad expunged sequence number: got %v instead of %v", id, expected[i])
			}
			i++
		}
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "EXPUNGE" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* 3 EXPUNGE\r\n")
		io.WriteString(c, "* 3 EXPUNGE\r\n")
		io.WriteString(c, "* 5 EXPUNGE\r\n")
		io.WriteString(c, "* 8 EXPUNGE\r\n")
		io.WriteString(c, tag + " OK EXPUNGE completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Search(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		date, _ := common.ParseSearchDate("1-Feb-1994")
		criteria := &common.SearchCriteria{
			Deleted: true,
			From: "Smith",
			Since: date,
			Not: &common.SearchCriteria{To: "Pauline"},
		}

		results, err := c.Search(criteria)
		if err != nil {
			return
		}

		expected := []uint32{2, 84, 882}
		if fmt.Sprint(results) != fmt.Sprint(expected) {
			return fmt.Errorf("Bad results: %v", results)
		}
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "SEARCH CHARSET UTF-8 DELETED FROM Smith NOT (TO Pauline) SINCE 1-Feb-1994" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* SEARCH 2 84 882\r\n")
		io.WriteString(c, tag + " OK SEARCH completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Search_Uid(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		criteria := &common.SearchCriteria{
			Undeleted: true,
		}

		results, err := c.UidSearch(criteria)
		if err != nil {
			return
		}

		expected := []uint32{1, 78, 2010}
		if fmt.Sprint(results) != fmt.Sprint(expected) {
			return fmt.Errorf("Bad results: %v", results)
		}
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "UID SEARCH CHARSET UTF-8 UNDELETED" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* SEARCH 1 78 2010\r\n")
		io.WriteString(c, tag + " OK UID SEARCH completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Fetch(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		seqset, _ := common.NewSeqSet("2:3")
		fields := []string{"UID", "BODY[]"}
		messages := make(chan *common.Message, 2)

		err = c.Fetch(seqset, fields, messages)
		if err != nil {
			return
		}

		msg := <-messages
		body := msg.GetBody("BODY[]").String()
		if msg.Uid != 42 {
			return fmt.Errorf("First message has bad UID: %v", msg.Uid)
		}
		if body != "I love potatoes." {
			return fmt.Errorf("First message has bad body: %v", body)
		}

		msg = <-messages
		body = msg.GetBody("BODY[]").String()
		if msg.Uid != 28 {
			return fmt.Errorf("Second message has bad UID: %v", msg.Uid)
		}
		if body != "Hello World!" {
			return fmt.Errorf("Second message has bad body: %v", body)
		}

		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "FETCH 2:3 (UID BODY[])" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* 2 FETCH (UID 42 BODY[] {16}\r\n")
		io.WriteString(c, "I love potatoes.")
		io.WriteString(c, ")\r\n")

		io.WriteString(c, "* 3 FETCH (UID 28 BODY[] {12}\r\n")
		io.WriteString(c, "Hello World!")
		io.WriteString(c, ")\r\n")

		io.WriteString(c, tag + " OK FETCH completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Store(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		updates := make(chan *common.Message, 1)
		seqset, _ := common.NewSeqSet("2")
		err = c.Store(seqset, "+FLAGS", []interface{}{"\\Seen"}, updates)
		if err != nil {
			return
		}

		msg := <-updates
		if len(msg.Flags) != 1 || msg.Flags[0] != "\\Seen" {
			return fmt.Errorf("Bad message flags: %v", msg.Flags)
		}

		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "STORE 2 +FLAGS (\\Seen)" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* 2 FETCH (FLAGS (\\Seen))\r\n")
		io.WriteString(c, tag + " OK STORE completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Store_Silent(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		seqset, _ := common.NewSeqSet("2:3")
		err = c.Store(seqset, "+FLAGS", []interface{}{"\\Seen"}, nil)
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "STORE 2:3 +FLAGS.SILENT (\\Seen)" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, tag + " OK STORE completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Copy(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		seqset, _ := common.NewSeqSet("2:4")
		err = c.Copy(seqset, "Sent")
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "COPY 2:4 Sent" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, tag + " OK COPY completed\r\n")
	}

	testClient(t, ct, st)
}
<commit_msg>client: adds test for UID FETCH<commit_after>package client_test

import (
	"io"
	"fmt"
	"net"
	"testing"

	"github.com/emersion/go-imap/common"
	"github.com/emersion/go-imap/client"
)

func TestClient_Check(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		err = c.Check()
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "CHECK" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, tag + " OK CHECK completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Close(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState
		c.Mailbox = &common.MailboxStatus{Name: "INBOX"}

		err = c.Close()
		if err != nil {
			return
		}

		if c.State != common.AuthenticatedState {
			return fmt.Errorf("Bad client state: %v", c.State)
		}
		if c.Mailbox != nil {
			return fmt.Errorf("Client selected mailbox is not nil: %v", c.Mailbox)
		}
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "CLOSE" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, tag + " OK CLOSE completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Expunge(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		expunged := make(chan uint32, 4)
		err = c.Expunge(expunged)
		if err != nil {
			return
		}

		expected := []uint32{3, 3, 5, 8}

		i := 0
		for id := range expunged {
			if id != expected[i] {
				return fmt.Errorf("Bad expunged sequence number: got %v instead of %v", id, expected[i])
			}
			i++
		}
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "EXPUNGE" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* 3 EXPUNGE\r\n")
		io.WriteString(c, "* 3 EXPUNGE\r\n")
		io.WriteString(c, "* 5 EXPUNGE\r\n")
		io.WriteString(c, "* 8 EXPUNGE\r\n")
		io.WriteString(c, tag + " OK EXPUNGE completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Search(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		date, _ := common.ParseSearchDate("1-Feb-1994")
		criteria := &common.SearchCriteria{
			Deleted: true,
			From: "Smith",
			Since: date,
			Not: &common.SearchCriteria{To: "Pauline"},
		}

		results, err := c.Search(criteria)
		if err != nil {
			return
		}

		expected := []uint32{2, 84, 882}
		if fmt.Sprint(results) != fmt.Sprint(expected) {
			return fmt.Errorf("Bad results: %v", results)
		}
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "SEARCH CHARSET UTF-8 DELETED FROM Smith NOT (TO Pauline) SINCE 1-Feb-1994" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* SEARCH 2 84 882\r\n")
		io.WriteString(c, tag + " OK SEARCH completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Search_Uid(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		criteria := &common.SearchCriteria{
			Undeleted: true,
		}

		results, err := c.UidSearch(criteria)
		if err != nil {
			return
		}

		expected := []uint32{1, 78, 2010}
		if fmt.Sprint(results) != fmt.Sprint(expected) {
			return fmt.Errorf("Bad results: %v", results)
		}
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "UID SEARCH CHARSET UTF-8 UNDELETED" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* SEARCH 1 78 2010\r\n")
		io.WriteString(c, tag + " OK UID SEARCH completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Fetch(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		seqset, _ := common.NewSeqSet("2:3")
		fields := []string{"UID", "BODY[]"}
		messages := make(chan *common.Message, 2)

		err = c.Fetch(seqset, fields, messages)
		if err != nil {
			return
		}

		msg := <-messages
		body := msg.GetBody("BODY[]").String()
		if msg.SeqNum != 2 {
			return fmt.Errorf("First message has bad sequence number: %v", msg.SeqNum)
		}
		if msg.Uid != 42 {
			return fmt.Errorf("First message has bad UID: %v", msg.Uid)
		}
		if body != "I love potatoes." {
			return fmt.Errorf("First message has bad body: %v", body)
		}

		msg = <-messages
		body = msg.GetBody("BODY[]").String()
		if msg.SeqNum != 3 {
			return fmt.Errorf("First message has bad sequence number: %v", msg.SeqNum)
		}
		if msg.Uid != 28 {
			return fmt.Errorf("Second message has bad UID: %v", msg.Uid)
		}
		if body != "Hello World!" {
			return fmt.Errorf("Second message has bad body: %v", body)
		}

		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "FETCH 2:3 (UID BODY[])" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* 2 FETCH (UID 42 BODY[] {16}\r\n")
		io.WriteString(c, "I love potatoes.")
		io.WriteString(c, ")\r\n")

		io.WriteString(c, "* 3 FETCH (UID 28 BODY[] {12}\r\n")
		io.WriteString(c, "Hello World!")
		io.WriteString(c, ")\r\n")

		io.WriteString(c, tag + " OK FETCH completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Fetch_Uid(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		seqset, _ := common.NewSeqSet("1:867")
		fields := []string{"FLAGS"}
		messages := make(chan *common.Message, 1)

		err = c.UidFetch(seqset, fields, messages)
		if err != nil {
			return
		}

		msg := <-messages
		if msg.SeqNum != 23 {
			return fmt.Errorf("First message has bad sequence number: %v", msg.SeqNum)
		}
		if msg.Uid != 42 {
			return fmt.Errorf("Message has bad UID: %v", msg.Uid)
		}
		if len(msg.Flags) != 1 || msg.Flags[0] != "\\Seen" {
			return fmt.Errorf("Message has bad flags: %v", msg.Flags)
		}

		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "UID FETCH 1:867 (FLAGS)" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* 23 FETCH (UID 42 FLAGS (\\Seen))\r\n")

		io.WriteString(c, tag + " OK UID FETCH completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Store(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		updates := make(chan *common.Message, 1)
		seqset, _ := common.NewSeqSet("2")
		err = c.Store(seqset, "+FLAGS", []interface{}{"\\Seen"}, updates)
		if err != nil {
			return
		}

		msg := <-updates
		if len(msg.Flags) != 1 || msg.Flags[0] != "\\Seen" {
			return fmt.Errorf("Bad message flags: %v", msg.Flags)
		}

		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "STORE 2 +FLAGS (\\Seen)" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, "* 2 FETCH (FLAGS (\\Seen))\r\n")
		io.WriteString(c, tag + " OK STORE completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Store_Silent(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		seqset, _ := common.NewSeqSet("2:3")
		err = c.Store(seqset, "+FLAGS", []interface{}{"\\Seen"}, nil)
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "STORE 2:3 +FLAGS.SILENT (\\Seen)" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, tag + " OK STORE completed\r\n")
	}

	testClient(t, ct, st)
}

func TestClient_Copy(t *testing.T) {
	ct := func(c *client.Client) (err error) {
		c.State = common.SelectedState

		seqset, _ := common.NewSeqSet("2:4")
		err = c.Copy(seqset, "Sent")
		return
	}

	st := func(c net.Conn) {
		scanner := NewCmdScanner(c)

		tag, cmd := scanner.Scan()
		if cmd != "COPY 2:4 Sent" {
			t.Fatal("Bad command:", cmd)
		}

		io.WriteString(c, tag + " OK COPY completed\r\n")
	}

	testClient(t, ct, st)
}
<|endoftext|>


<commit_before>// Package utils - 套件所需的公用工具（總和、平均、序列差、持續天數、
// 民國日期解析、簡單亂數、標準差、簡單 net/http 快取）.
//
package utils

import (
	"math"
	"regexp"
	"strconv"
	"time"
)

// ExchangeMap is simple to check tse or otc.
var ExchangeMap = map[string]bool{"tse": true, "otc": true}

// TaipeiTimeZone is for time.Data() setting.
var TaipeiTimeZone = time.FixedZone("Asia/Taipei", 8*3600)

// TWSE base url.
const (
	TWSEURL     string = "http://mis.tse.com.tw"
	TWSEHOST    string = "http://www.twse.com.tw"
	OTCHOST     string = "http://www.tpex.org.tw"
	OTCCSV      string = "/ch/stock/aftertrading/daily_trading_info/st43_download.php?d=%d/%02d&stkno=%s&r=%%d"           // year, mon, stock, rand
	OTCLISTCSV  string = "/web/stock/aftertrading/otc_quotes_no1430/stk_wn1430_download.php?l=zh-tw&d=%s&se=%s&s=0,asc,0" // date, cate
	TWSECSV     string = "/ch/trading/exchange/STOCK_DAY/STOCK_DAY_print.php?genpage=genpage/Report%d%02d/%d%02d_F3_1_8_%s.php&type=csv&r=%%d"
	TWSELISTCSV string = "/ch/trading/exchange/MI_INDEX/MI_INDEX.php" // year, mon, day, type
	TWSEREAL    string = "/stock/api/getStockInfo.jsp?ex_ch=%s_%s.tw_%s&json=1&delay=0&_=%d"
	QFIISTOP20  string = "/ch/trading/fund/MI_QFIIS_sort_20/MI_QFIIS_sort_20_PD.php?filename=%d%02d%d.php&type=csv"                            // yyyymmdd
	BFI82U      string = "/ch/trading/fund/BFI82U/BFI82U_print.php?begin_date=%d%02d%d&end_date=%d%02d%d&report_type=day&language=ch&save=csv" // yyyymmdd
	T86         string = "/ch/trading/fund/T86/print.php?edition=ch&filename=genpage/%s/%s_2by_issue.dat&type=csv&select2=%s&qdate=%s"
	TWTXXU      string = "/ch/trading/fund/%s/%s.php?download=csv&qdate=%d/%02d/%02d&sorting=by_issue"
)

// RandInt return random int.
func RandInt() int {
	return time.Now().Nanosecond()
}

//func RandInt() int64 {
//	result, _ := rand.Int(rand.Reader, big.NewInt(102400))
//	return result.Int64()
//}

//func RandInt() int64 {
//	r := rand.New(rand.NewSource(time.Now().UnixNano()))
//	return r.Int63n(100000)
//}

var dateReg = regexp.MustCompile(`([\d]{2,})/([\d]{1,2})/([\d]{1,2})`)

// ParseDate is to parse "104/01/13" format.
func ParseDate(strDate string) time.Time {
	p := dateReg.FindStringSubmatch(strDate)
	year, _ := strconv.Atoi(p[1])
	mon, _ := strconv.Atoi(p[2])
	day, _ := strconv.Atoi(p[3])
	return time.Date(year+1911, time.Month(mon), day, 0, 0, 0, 0, TaipeiTimeZone)
}

// SumFloat64 計算總和（float64）
func SumFloat64(data []float64) float64 {
	var result float64
	for _, v := range data {
		result += v
	}
	return result
}

// AvgFloat64 計算平均（float64）
func AvgFloat64(data []float64) float64 {
	return float64(int(SumFloat64(data)*100)/len(data)) / 100
}

// SumUint64 計算總和（uint64）
func SumUint64(data []uint64) uint64 {
	var result uint64
	for _, v := range data {
		result += v
	}
	return result
}

// AvgUint64 計算平均（uint64）
func AvgUint64(data []uint64) uint64 {
	return SumUint64(data) / uint64(len(data))
}

// ThanPastUint64 計算最後一個數值是否為過去幾天最大或最小（uint64）
func ThanPastUint64(data []uint64, days int, max bool) bool {
	var dataFloat64 = make([]float64, days+1)
	for i, v := range data[len(data)-1-days:] {
		dataFloat64[i] = float64(v)
	}
	return thanPast(dataFloat64, max)
}

// ThanPastFloat64 計算最後一個數值是否為過去幾天最大或最小（float64）
func ThanPastFloat64(data []float64, days int, max bool) bool {
	return thanPast(data[len(data)-1-days:], max)
}

func thanPast(data []float64, max bool) bool {
	//var dataFloat64 []float64
	//dataFloat64 = make([]float64, days+1)
	//for i, v := range data[len(data)-1-days : len(data)-1] {
	//	switch v.(type) {
	//	case int64:
	//		dataFloat64[i] = float64(v.(int64))
	//	case float64:
	//		dataFloat64[i] = v.(float64)
	//	}
	//}

	var base = data[len(data)-1]
	var condition func(b float64) bool

	if max {
		condition = func(b float64) bool { return base > b }
	} else {
		condition = func(b float64) bool { return base < b }
	}

	for _, v := range data[:len(data)-1] {
		if condition(v) {
			continue
		} else {
			return false
		}
	}
	return true
}

// ThanSumPastFloat64 計算最後一個數值是否為過去幾天的總和大或小（float64）
func ThanSumPastFloat64(data []float64, days int, max bool) bool {
	return thanSumPast(data[len(data)-1-days:], max)
}

// ThanSumPastUint64 計算最後一個數值是否為過去幾天的總和大或小（uint64）
func ThanSumPastUint64(data []uint64, days int, max bool) bool {
	var dataFloat64 = make([]float64, days+1)
	for i, v := range data[len(data)-1-days:] {
		dataFloat64[i] = float64(v)
	}
	return thanSumPast(dataFloat64, max)
}

func thanSumPast(data []float64, max bool) bool {
	var result = data[len(data)-1] > SumFloat64(data[:len(data)-1])
	if max {
		return result
	}
	return !result
}

// CountCountineFloat64 計算最後一個數值為正或負值的持續天數（float64）
func CountCountineFloat64(data []float64) (int, bool) {
	var condition func(x float64) bool
	if data[len(data)-1] > 0 {
		condition = func(x float64) bool { return x > 0 }
	} else {
		condition = func(x float64) bool { return x < 0 }
	}
	counter := 1
	for i := 1; i <= len(data)-1; i++ {
		if condition(data[len(data)-1-i]) {
			counter++
		} else {
			break
		}
	}
	return counter, data[len(data)-1] > 0
}

// CalDiffFloat64 計算兩序列的差（listA - listB）
func CalDiffFloat64(listA, listB []float64) []float64 {
	var length int
	var result []float64
	if len(listA) <= len(listB) {
		length = len(listA)
	} else {
		length = len(listB)
	}
	result = make([]float64, length)
	for i := 1; i <= length; i++ {
		result[length-i] = listA[len(listA)-i] - listB[len(listB)-i]
	}
	return result
}

// CalDiffInt64 計算兩序列的差（listA - listB）
func CalDiffInt64(listA, listB []int64) []int64 {
	var length int
	var result []int64
	if len(listA) <= len(listB) {
		length = len(listA)
	} else {
		length = len(listB)
	}
	result = make([]int64, length)
	for i := 1; i <= length; i++ {
		result[length-i] = listA[len(listA)-i] - listB[len(listB)-i]
	}
	return result
}

// CalLHPower 計算兩序列與終點的比例
func CalLHPower(final, low, high []float64) []float64 {
	var result []float64
	result = make([]float64, len(final))
	for i, _ := range result {
		result[i] = (final[i] - low[i]) / (high[i] - low[i])
	}
	return result
}

// SDUint64 計算標準差
func SDUint64(list []uint64) float64 {
	var data = make([]float64, len(list))
	for i := 0; i < len(list); i++ {
		data[i] = float64(list[i])
	}
	return SD(data)
}

// SD 計算標準差
func SD(list []float64) float64 {
	var avg = AvgFloat64(list)
	var data = make([]float64, len(list))
	for i := 0; i < len(data); i++ {
		data[i] = list[i] - avg
		data[i] *= data[i]
	}
	return math.Sqrt(AvgFloat64(data))
}

// DeltaFloat64 計算數列間距差
func DeltaFloat64(data []float64) []float64 {
	var result = make([]float64, len(data)-1)
	for i := 0; i < (len(data) - 1); i++ {
		result[i] = data[i+1] - data[i]
	}
	return result
}

// DeltaInt64 計算數列間距差
func DeltaInt64(data []int64) []int64 {
	var result = make([]int64, len(data)-1)
	for i := 0; i < (len(data) - 1); i++ {
		result[i] = data[i+1] - data[i]
	}
	return result
}
<commit_msg>Tiny changed.<commit_after>// Package utils - 套件所需的公用工具（總和、平均、序列差、持續天數、
// 民國日期解析、簡單亂數、標準差、簡單 net/http 快取）.
//
package utils

import (
	"math"
	"regexp"
	"strconv"
	"time"
)

// ExchangeMap is simple to check tse or otc.
var ExchangeMap = map[string]bool{"tse": true, "otc": true}

// TaipeiTimeZone is for time.Data() setting.
var TaipeiTimeZone = time.FixedZone("Asia/Taipei", 8*3600)

// TWSE base url.
const (
	TWSEURL     string = "http://mis.tse.com.tw"
	TWSEHOST    string = "http://www.twse.com.tw"
	OTCHOST     string = "http://www.tpex.org.tw"
	OTCCSV      string = "/ch/stock/aftertrading/daily_trading_info/st43_download.php?d=%d/%02d&stkno=%s&r=%%d"           // year, mon, stock, rand
	OTCLISTCSV  string = "/web/stock/aftertrading/otc_quotes_no1430/stk_wn1430_download.php?l=zh-tw&d=%s&se=%s&s=0,asc,0" // date, cate
	TWSECSV     string = "/ch/trading/exchange/STOCK_DAY/STOCK_DAY_print.php?genpage=genpage/Report%d%02d/%d%02d_F3_1_8_%s.php&type=csv&r=%%d"
	TWSELISTCSV string = "/ch/trading/exchange/MI_INDEX/MI_INDEX.php" // year, mon, day, type
	TWSEREAL    string = "/stock/api/getStockInfo.jsp?ex_ch=%s_%s.tw_%s&json=1&delay=0&_=%d"
	QFIISTOP20  string = "/ch/trading/fund/MI_QFIIS_sort_20/MI_QFIIS_sort_20_PD.php?filename=%d%02d%d.php&type=csv"                            // yyyymmdd
	BFI82U      string = "/ch/trading/fund/BFI82U/BFI82U_print.php?begin_date=%d%02d%d&end_date=%d%02d%d&report_type=day&language=ch&save=csv" // yyyymmdd
	T86         string = "/ch/trading/fund/T86/print.php?edition=ch&filename=genpage/%s/%s_2by_issue.dat&type=csv&select2=%s&qdate=%s"
	TWTXXU      string = "/ch/trading/fund/%s/%s.php?download=csv&qdate=%d/%02d/%02d&sorting=by_issue"
)

// RandInt return random int.
func RandInt() int {
	return time.Now().Nanosecond()
}

//func RandInt() int64 {
//	result, _ := rand.Int(rand.Reader, big.NewInt(102400))
//	return result.Int64()
//}

//func RandInt() int64 {
//	r := rand.New(rand.NewSource(time.Now().UnixNano()))
//	return r.Int63n(100000)
//}

var dateReg = regexp.MustCompile(`([\d]{2,})/([\d]{1,2})/([\d]{1,2})`)

// ParseDate is to parse "104/01/13" format.
func ParseDate(strDate string) time.Time {
	p := dateReg.FindStringSubmatch(strDate)
	year, _ := strconv.Atoi(p[1])
	mon, _ := strconv.Atoi(p[2])
	day, _ := strconv.Atoi(p[3])
	return time.Date(year+1911, time.Month(mon), day, 0, 0, 0, 0, TaipeiTimeZone)
}

// SumFloat64 計算總和（float64）
func SumFloat64(data []float64) float64 {
	var result float64
	for _, v := range data {
		result += v
	}
	return result
}

// AvgFloat64 計算平均（float64）
func AvgFloat64(data []float64) float64 {
	return float64(int(SumFloat64(data)*100)/len(data)) / 100
}

// SumUint64 計算總和（uint64）
func SumUint64(data []uint64) uint64 {
	var result uint64
	for _, v := range data {
		result += v
	}
	return result
}

// AvgUint64 計算平均（uint64）
func AvgUint64(data []uint64) uint64 {
	return SumUint64(data) / uint64(len(data))
}

// ThanPastUint64 計算最後一個數值是否為過去幾天最大或最小（uint64）
func ThanPastUint64(data []uint64, days int, max bool) bool {
	var dataFloat64 = make([]float64, days+1)
	for i, v := range data[len(data)-1-days:] {
		dataFloat64[i] = float64(v)
	}
	return thanPast(dataFloat64, max)
}

// ThanPastFloat64 計算最後一個數值是否為過去幾天最大或最小（float64）
func ThanPastFloat64(data []float64, days int, max bool) bool {
	return thanPast(data[len(data)-1-days:], max)
}

func thanPast(data []float64, max bool) bool {
	//var dataFloat64 []float64
	//dataFloat64 = make([]float64, days+1)
	//for i, v := range data[len(data)-1-days : len(data)-1] {
	//	switch v.(type) {
	//	case int64:
	//		dataFloat64[i] = float64(v.(int64))
	//	case float64:
	//		dataFloat64[i] = v.(float64)
	//	}
	//}

	var base = data[len(data)-1]
	var condition func(b float64) bool

	if max {
		condition = func(b float64) bool { return base > b }
	} else {
		condition = func(b float64) bool { return base < b }
	}

	for _, v := range data[:len(data)-1] {
		if condition(v) {
			continue
		} else {
			return false
		}
	}
	return true
}

// ThanSumPastFloat64 計算最後一個數值是否為過去幾天的總和大或小（float64）
func ThanSumPastFloat64(data []float64, days int, max bool) bool {
	return thanSumPast(data[len(data)-1-days:], max)
}

// ThanSumPastUint64 計算最後一個數值是否為過去幾天的總和大或小（uint64）
func ThanSumPastUint64(data []uint64, days int, max bool) bool {
	var dataFloat64 = make([]float64, days+1)
	for i, v := range data[len(data)-1-days:] {
		dataFloat64[i] = float64(v)
	}
	return thanSumPast(dataFloat64, max)
}

func thanSumPast(data []float64, max bool) bool {
	var result = data[len(data)-1] > SumFloat64(data[:len(data)-1])
	if max {
		return result
	}
	return !result
}

// CountCountineFloat64 計算最後一個數值為正或負值的持續天數（float64）
func CountCountineFloat64(data []float64) (int, bool) {
	var condition func(x float64) bool
	if data[len(data)-1] > 0 {
		condition = func(x float64) bool { return x > 0 }
	} else {
		condition = func(x float64) bool { return x < 0 }
	}
	counter := 1
	for i := 1; i <= len(data)-1; i++ {
		if condition(data[len(data)-1-i]) {
			counter++
		} else {
			break
		}
	}
	return counter, data[len(data)-1] > 0
}

// CalDiffFloat64 計算兩序列的差（listA - listB）
func CalDiffFloat64(listA, listB []float64) []float64 {
	var length int
	var result []float64
	if len(listA) <= len(listB) {
		length = len(listA)
	} else {
		length = len(listB)
	}
	result = make([]float64, length)
	for i := 1; i <= length; i++ {
		result[length-i] = listA[len(listA)-i] - listB[len(listB)-i]
	}
	return result
}

// CalDiffInt64 計算兩序列的差（listA - listB）
func CalDiffInt64(listA, listB []int64) []int64 {
	var length int
	var result []int64
	if len(listA) <= len(listB) {
		length = len(listA)
	} else {
		length = len(listB)
	}
	result = make([]int64, length)
	for i := 1; i <= length; i++ {
		result[length-i] = listA[len(listA)-i] - listB[len(listB)-i]
	}
	return result
}

// CalLHPower 計算兩序列與終點的比例
func CalLHPower(final, low, high []float64) []float64 {
	var result []float64
	result = make([]float64, len(final))
	for i := range result {
		result[i] = (final[i] - low[i]) / (high[i] - low[i])
	}
	return result
}

// SDUint64 計算標準差
func SDUint64(list []uint64) float64 {
	var data = make([]float64, len(list))
	for i := 0; i < len(list); i++ {
		data[i] = float64(list[i])
	}
	return SD(data)
}

// SD 計算標準差
func SD(list []float64) float64 {
	var avg = AvgFloat64(list)
	var data = make([]float64, len(list))
	for i := 0; i < len(data); i++ {
		data[i] = list[i] - avg
		data[i] *= data[i]
	}
	return math.Sqrt(AvgFloat64(data))
}

// DeltaFloat64 計算數列間距差
func DeltaFloat64(data []float64) []float64 {
	var result = make([]float64, len(data)-1)
	for i := 0; i < (len(data) - 1); i++ {
		result[i] = data[i+1] - data[i]
	}
	return result
}

// DeltaInt64 計算數列間距差
func DeltaInt64(data []int64) []int64 {
	var result = make([]int64, len(data)-1)
	for i := 0; i < (len(data) - 1); i++ {
		result[i] = data[i+1] - data[i]
	}
	return result
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	"github.com/99designs/aws-vault/keyring"
	"github.com/aws/aws-sdk-go/aws/awserr"
)

type ExecCommandInput struct {
	Profile  string
	Command  string
	Args     []string
	Keyring  keyring.Keyring
	Duration time.Duration
	WriteEnv bool
	MfaToken string
	Signals  chan os.Signal
}

func ExecCommand(ui Ui, input ExecCommandInput) {
	creds, err := NewVaultCredentials(input.Keyring, input.Profile, VaultOptions{
		SessionDuration: input.Duration,
		WriteEnv:        input.WriteEnv,
		MfaToken:        input.MfaToken,
	})
	if err != nil {
		ui.Error.Fatal(err)
	}

	val, err := creds.Get()
	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoCredentialProviders" {
			ui.Error.Fatalf("No credentials found for profile %q", input.Profile)
		} else {
			ui.Error.Fatal(err)
		}
	}

	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		ui.Error.Fatal(err)
	}

	go func() {
		log.Printf("Metadata server listening on %s", l.Addr().String())
		ui.Error.Fatal(http.Serve(l, proxyHandler(NewMetadataHandler(creds))))
	}()

	profs, err := parseProfiles()
	if err != nil {
		ui.Error.Fatal(err)
	}

	cfg, err := writeTempConfig(input.Profile, profs)
	if err != nil {
		ui.Error.Fatal(err)
	}

	env := os.Environ()
	env = overwriteEnv(env, "http_proxy", "http://"+l.Addr().String())
	env = overwriteEnv(env, "no_proxy", "amazonaws.com")
	env = overwriteEnv(env, "AWS_CONFIG_FILE", cfg.Name())
	env = overwriteEnv(env, "AWS_PROFILE", input.Profile)

	if region, ok := profs[input.Profile]["region"]; ok {
		env = overwriteEnv(env, "AWS_REGION", region)
	}

	if input.WriteEnv {
		env = overwriteEnv(env, "AWS_ACCESS_KEY_ID", val.AccessKeyID)
		env = overwriteEnv(env, "AWS_SECRET_ACCESS_KEY", val.SecretAccessKey)

		if val.SessionToken != "" {
			env = overwriteEnv(env, "AWS_SESSION_TOKEN", val.SessionToken)
			env = overwriteEnv(env, "AWS_SECURITY_TOKEN", val.SessionToken)
		}
	}

	cmd := exec.Command(input.Command, input.Args...)
	cmd.Env = env
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	go func() {
		sig := <-input.Signals
		if cmd.Process != nil {
			cmd.Process.Signal(sig)
		}
	}()

	var waitStatus syscall.WaitStatus
	if err := cmd.Run(); err != nil {
		if err != nil {
			ui.Error.Println(err)
		}
		if exitError, ok := err.(*exec.ExitError); ok {
			waitStatus = exitError.Sys().(syscall.WaitStatus)
			os.Exit(waitStatus.ExitStatus())
		}
	}

}

// write out a config excluding role switching keys
func writeTempConfig(profile string, conf profiles) (*os.File, error) {
	tmpConfig, err := ioutil.TempFile(os.TempDir(), "aws-vault")
	if err != nil {
		return nil, err
	}

	// allow some time for keychain prompt
	newConfig := map[string]string{
		"metadata_service_timeout":      "15",
		"metadata_service_num_attempts": "2",
	}

	for k, v := range conf[profile] {
		if k != "source_profile" && k != "role_arn" {
			newConfig[k] = v
		}
	}

	return tmpConfig, writeProfiles(tmpConfig, profiles{profile: newConfig})
}

func overwriteEnv(env []string, key, val string) []string {
	var found bool

	for idx, e := range env {
		if strings.HasPrefix(key+"=", e) {
			env[idx] = key + "=" + val
			found = true
		} else {
			env[idx] = e
		}
	}

	if !found {
		env = append(env, key+"="+val)
	}

	return env
}

func connectProxy(w http.ResponseWriter, r *http.Request) error {
	d, err := net.Dial("tcp", r.RequestURI)
	if err != nil {
		return err
	}
	hj, ok := w.(http.Hijacker)
	if !ok {
		return err
	}
	conn, bufrw, err := hj.Hijack()
	if err != nil {
		return err
	}
	defer conn.Close()
	defer d.Close()

	bufrw.WriteString("HTTP/1.0 200 Connection established\r\n\r\n")
	bufrw.Flush()

	go io.Copy(d, conn)
	io.Copy(conn, d)

	return nil
}

func proxyHandler(upstream http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s", r.Method, r.RequestURI)
		if r.Method == "GET" && strings.HasPrefix(r.URL.Path, "/latest/meta-data") {
			upstream.ServeHTTP(w, r)
		} else if r.Method == "CONNECT" {
			if err := connectProxy(w, r); err != nil {
				http.Error(w, "Error connecting to proxy: "+err.Error(), http.StatusGatewayTimeout)
			}
		} else {
			proxy := &httputil.ReverseProxy{Director: func(req *http.Request) {
				req.Method = "GET"
				req.URL.Scheme = "http"
				req.URL.Host = r.Host
			}}
			proxy.ServeHTTP(w, r)
		}
	})
}
<commit_msg>Some AWS env vars need to be unset, e.g AWS_CREDENTIAL_FILE<commit_after>package main

import (
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/http/httputil"
	"os"
	"os/exec"
	"strings"
	"syscall"
	"time"

	"github.com/99designs/aws-vault/keyring"
	"github.com/aws/aws-sdk-go/aws/awserr"
)

type ExecCommandInput struct {
	Profile  string
	Command  string
	Args     []string
	Keyring  keyring.Keyring
	Duration time.Duration
	WriteEnv bool
	MfaToken string
	Signals  chan os.Signal
}

func ExecCommand(ui Ui, input ExecCommandInput) {
	creds, err := NewVaultCredentials(input.Keyring, input.Profile, VaultOptions{
		SessionDuration: input.Duration,
		WriteEnv:        input.WriteEnv,
		MfaToken:        input.MfaToken,
	})
	if err != nil {
		ui.Error.Fatal(err)
	}

	val, err := creds.Get()
	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoCredentialProviders" {
			ui.Error.Fatalf("No credentials found for profile %q", input.Profile)
		} else {
			ui.Error.Fatal(err)
		}
	}

	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		ui.Error.Fatal(err)
	}

	go func() {
		log.Printf("Metadata server listening on %s", l.Addr().String())
		ui.Error.Fatal(http.Serve(l, proxyHandler(NewMetadataHandler(creds))))
	}()

	profs, err := parseProfiles()
	if err != nil {
		ui.Error.Fatal(err)
	}

	cfg, err := writeTempConfig(input.Profile, profs)
	if err != nil {
		ui.Error.Fatal(err)
	}

	env := os.Environ()
	env = overwriteEnv(env, "http_proxy", "http://"+l.Addr().String())
	env = overwriteEnv(env, "no_proxy", "amazonaws.com")
	env = overwriteEnv(env, "AWS_CONFIG_FILE", cfg.Name())
	env = overwriteEnv(env, "AWS_PROFILE", input.Profile)
	env = unsetEnv(env, "AWS_CREDENTIAL_FILE")

	if region, ok := profs[input.Profile]["region"]; ok {
		env = overwriteEnv(env, "AWS_REGION", region)
	}

	if input.WriteEnv {
		env = overwriteEnv(env, "AWS_ACCESS_KEY_ID", val.AccessKeyID)
		env = overwriteEnv(env, "AWS_SECRET_ACCESS_KEY", val.SecretAccessKey)

		if val.SessionToken != "" {
			env = overwriteEnv(env, "AWS_SESSION_TOKEN", val.SessionToken)
			env = overwriteEnv(env, "AWS_SECURITY_TOKEN", val.SessionToken)
		}
	}

	cmd := exec.Command(input.Command, input.Args...)
	cmd.Env = env
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	go func() {
		sig := <-input.Signals
		if cmd.Process != nil {
			cmd.Process.Signal(sig)
		}
	}()

	var waitStatus syscall.WaitStatus
	if err := cmd.Run(); err != nil {
		if err != nil {
			ui.Error.Println(err)
		}
		if exitError, ok := err.(*exec.ExitError); ok {
			waitStatus = exitError.Sys().(syscall.WaitStatus)
			os.Exit(waitStatus.ExitStatus())
		}
	}

}

// write out a config excluding role switching keys
func writeTempConfig(profile string, conf profiles) (*os.File, error) {
	tmpConfig, err := ioutil.TempFile(os.TempDir(), "aws-vault")
	if err != nil {
		return nil, err
	}

	// allow some time for keychain prompt
	newConfig := map[string]string{
		"metadata_service_timeout":      "15",
		"metadata_service_num_attempts": "2",
	}

	for k, v := range conf[profile] {
		if k != "source_profile" && k != "role_arn" {
			newConfig[k] = v
		}
	}

	return tmpConfig, writeProfiles(tmpConfig, profiles{profile: newConfig})
}

func unsetEnv(env []string, key string) []string {
	envCopy := []string{}

	for _, e := range env {
		if !strings.HasPrefix(key+"=", e) {
			envCopy = append(envCopy, e)
		}
	}

	return envCopy
}

func overwriteEnv(env []string, key, val string) []string {
	var found bool

	for idx, e := range env {
		if strings.HasPrefix(key+"=", e) {
			env[idx] = key + "=" + val
			found = true
		} else {
			env[idx] = e
		}
	}

	if !found {
		env = append(env, key+"="+val)
	}

	return env
}

func connectProxy(w http.ResponseWriter, r *http.Request) error {
	d, err := net.Dial("tcp", r.RequestURI)
	if err != nil {
		return err
	}
	hj, ok := w.(http.Hijacker)
	if !ok {
		return err
	}
	conn, bufrw, err := hj.Hijack()
	if err != nil {
		return err
	}
	defer conn.Close()
	defer d.Close()

	bufrw.WriteString("HTTP/1.0 200 Connection established\r\n\r\n")
	bufrw.Flush()

	go io.Copy(d, conn)
	io.Copy(conn, d)

	return nil
}

func proxyHandler(upstream http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s", r.Method, r.RequestURI)
		if r.Method == "GET" && strings.HasPrefix(r.URL.Path, "/latest/meta-data") {
			upstream.ServeHTTP(w, r)
		} else if r.Method == "CONNECT" {
			if err := connectProxy(w, r); err != nil {
				http.Error(w, "Error connecting to proxy: "+err.Error(), http.StatusGatewayTimeout)
			}
		} else {
			proxy := &httputil.ReverseProxy{Director: func(req *http.Request) {
				req.Method = "GET"
				req.URL.Scheme = "http"
				req.URL.Host = r.Host
			}}
			proxy.ServeHTTP(w, r)
		}
	})
}
<|endoftext|>


<commit_before>// Alexandria
//
// Copyright (C) 2015  Colin Benner
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package parser

import (
	"strings"

	. "github.com/yzhs/alexandria-go"
)

// Figure out what type of a document we have
func DocumentType(m Metadata) string {
	return m.Tags[0]
}

// Parse the tags in the given scroll content.
func ParseTags(doc string) Metadata {
	var source string
	var tags []string
	var found_source bool

	for _, line_ := range strings.Split(doc, "\n") {
		line := strings.TrimSpace(strings.TrimPrefix(line_, "%"))
		if line == "" {
			continue
		}

		// Ignore all but the last block of comments
		if line[0] != '%' {
			tags = []string{}
			source = ""
			found_source = false
		}

		if !found_source && strings.HasPrefix(line, "@source") {
			source = line
			found_source = true
		} else {
			tags_temp := strings.Split(line, ",")
			for i := range tags_temp {
				tags_temp[i] = strings.TrimSpace(tags_temp[i])
			}
			tags = append(tags, tags_temp...)
		}
	}
	return Metadata{source, tags}
}
<commit_msg>Add TODO<commit_after>// Alexandria
//
// Copyright (C) 2015  Colin Benner
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package parser

import (
	"strings"

	. "github.com/yzhs/alexandria-go"
)

// Figure out what type of a document we have
func DocumentType(m Metadata) string {
	return m.Tags[0]
}

// Parse the tags in the given scroll content.
func ParseTags(doc string) Metadata {
	// TODO Handle different types of tags: @source, @doctype, @keywords, and normal tags.
	var source string
	var tags []string
	var found_source bool

	for _, line_ := range strings.Split(doc, "\n") {
		line := strings.TrimSpace(strings.TrimPrefix(line_, "%"))
		if line == "" {
			continue
		}

		// Ignore all but the last block of comments
		if line[0] != '%' {
			tags = []string{}
			source = ""
			found_source = false
		}

		if !found_source && strings.HasPrefix(line, "@source") {
			source = line
			found_source = true
		} else {
			tags_temp := strings.Split(line, ",")
			for i := range tags_temp {
				tags_temp[i] = strings.TrimSpace(tags_temp[i])
			}
			tags = append(tags, tags_temp...)
		}
	}
	return Metadata{source, tags}
}
<|endoftext|>


<commit_before>package sortedmap

func (sm *SortedMap) sendRecord(ch chan Record, i int) {
	rec := Record{
		Key: sm.sorted[i],
	}
	rec.Val = sm.idx[rec.Key]
	ch <- rec
}

func (sm *SortedMap) returnRecord(i int) Record {
	rec := Record{
		Key: sm.sorted[i],
	}
	rec.Val = sm.idx[rec.Key]
	return rec
}

func (sm *SortedMap) iterCh(reversed bool, bufSize int) <-chan Record {
	ch := make(chan Record, bufSize)

	go func(ch chan Record) {
		if reversed {
			for i := len(sm.sorted) - 1; i > 0; i-- {
				sm.sendRecord(ch, i)
			}
		} else {
			for i := range sm.sorted {
				sm.sendRecord(ch, i)
			}
		}
		close(ch)
	}(ch)

	return ch
}

func (sm *SortedMap) iterBetweenCh(reversed bool, bufSize int, lowerBound, upperBound interface{}) (<-chan Record, bool) {

	iterBounds := sm.between(lowerBound, upperBound)
	if len(iterBounds) < 2 {
		return nil, false
	}

	ch := make(chan Record, bufSize)
	go func(reversed bool, iterBounds []int, ch chan Record) {
		if reversed {
			for i := iterBounds[1]; i > iterBounds[0]; i-- {
				sm.sendRecord(ch, i)
			}
		} else {
			for i := iterBounds[0]; i < iterBounds[1]; i++ {
				sm.sendRecord(ch, i)
			}
		}
		close(ch)
	}(reversed, iterBounds, ch)

	return ch, true
}

func (sm *SortedMap) iterFunc(reversed bool, f func(rec Record) bool) {
	if reversed {
		for i := len(sm.sorted) - 1; i > 0; i-- {
			if !f(sm.returnRecord(i)) {
				break
			}
		}
	} else {
		for i := range sm.sorted {
			if !f(sm.returnRecord(i)) {
				break
			}
		}
	}
}

func (sm *SortedMap) iterBetweenFunc(reversed bool, lowerBound, upperBound interface{}, f func(rec Record) bool) {
	iterBounds := sm.between(lowerBound, upperBound)
	if len(iterBounds) < 2 {
		return
	}
	if reversed {
		for i := iterBounds[1]; i > iterBounds[0]; i-- {
			if !f(sm.returnRecord(i)) {
				break
			}
		}
	} else {
		for i := iterBounds[0]; i < iterBounds[1]; i++ {
			if !f(sm.returnRecord(i)) {
				break
			}
		}
	}
}

// IterFunc passes each record to the specified callback function.
// Sort order is reversed if the reversed argument is set to true.
func (sm *SortedMap) IterFunc(reversed bool, f func(rec Record) bool) {
	sm.iterFunc(reversed, f)
}

// IterBetweenFunc starts at the lower bound value and passes all values in the collection to the callback function until reaching the upper bounds value.
// Sort order is reversed if the reversed argument is set to true.
func (sm *SortedMap) IterBetweenFunc(reversed bool, lowerBound, upperBound interface{}, f func(rec Record) bool) {
	sm.iterBetweenFunc(reversed, lowerBound, upperBound, f)
}

// IterCh returns a channel that sorted records can be read from and processed.
func (sm *SortedMap) IterCh() <-chan Record {
	return sm.iterCh(false, 0)
}

// IterChCustom returns a channel that sorted records can be read from and processed, with custom options.
func (sm *SortedMap) IterChCustom(reversed bool, bufSize int) <-chan Record {
	return sm.iterCh(reversed, bufSize)
}

// IterBetweenCh returns a channel that sorted records can be read from and processed,
// and a boolean value that indicates whether or not values in the collection fall between the given bounds.
// IterBetweenCh starts at the lower bound value and sends all values in the collection until reaching the upper bounds value.
// Sort order is reversed if the reversed argument is set to true.
func (sm *SortedMap) IterBetweenCh(lowerBound, upperBound interface{}) (<-chan Record, bool) {
	return sm.iterBetweenCh(false, 0, lowerBound, upperBound)
}

// IterBetweenChCustom returns a channel that sorted records can be read from and processed,
// and a boolean value that indicates whether or not values in the collection fall between the given bounds.
// IterBetweenChCustom starts at the lower bound value and sends all values in the collection until reaching the upper bounds value.
// Sort order is reversed if the reversed argument is set to true.
func (sm *SortedMap) IterBetweenChCustom(reversed bool, bufSize int, lowerBound, upperBound interface{}) (<-chan Record, bool) {
	return sm.iterBetweenCh(reversed, bufSize, lowerBound, upperBound)
}<commit_msg>iter.go: reorder methods<commit_after>package sortedmap

func (sm *SortedMap) sendRecord(ch chan Record, i int) {
	rec := Record{
		Key: sm.sorted[i],
	}
	rec.Val = sm.idx[rec.Key]
	ch <- rec
}

func (sm *SortedMap) returnRecord(i int) Record {
	rec := Record{
		Key: sm.sorted[i],
	}
	rec.Val = sm.idx[rec.Key]
	return rec
}

func (sm *SortedMap) iterCh(reversed bool, bufSize int) <-chan Record {
	ch := make(chan Record, bufSize)

	go func(ch chan Record) {
		if reversed {
			for i := len(sm.sorted) - 1; i > 0; i-- {
				sm.sendRecord(ch, i)
			}
		} else {
			for i := range sm.sorted {
				sm.sendRecord(ch, i)
			}
		}
		close(ch)
	}(ch)

	return ch
}

func (sm *SortedMap) iterBetweenCh(reversed bool, bufSize int, lowerBound, upperBound interface{}) (<-chan Record, bool) {

	iterBounds := sm.between(lowerBound, upperBound)
	if len(iterBounds) < 2 {
		return nil, false
	}

	ch := make(chan Record, bufSize)
	go func(reversed bool, iterBounds []int, ch chan Record) {
		if reversed {
			for i := iterBounds[1]; i > iterBounds[0]; i-- {
				sm.sendRecord(ch, i)
			}
		} else {
			for i := iterBounds[0]; i < iterBounds[1]; i++ {
				sm.sendRecord(ch, i)
			}
		}
		close(ch)
	}(reversed, iterBounds, ch)

	return ch, true
}

func (sm *SortedMap) iterFunc(reversed bool, f func(rec Record) bool) {
	if reversed {
		for i := len(sm.sorted) - 1; i > 0; i-- {
			if !f(sm.returnRecord(i)) {
				break
			}
		}
	} else {
		for i := range sm.sorted {
			if !f(sm.returnRecord(i)) {
				break
			}
		}
	}
}

func (sm *SortedMap) iterBetweenFunc(reversed bool, lowerBound, upperBound interface{}, f func(rec Record) bool) {
	iterBounds := sm.between(lowerBound, upperBound)
	if len(iterBounds) < 2 {
		return
	}
	if reversed {
		for i := iterBounds[1]; i > iterBounds[0]; i-- {
			if !f(sm.returnRecord(i)) {
				break
			}
		}
	} else {
		for i := iterBounds[0]; i < iterBounds[1]; i++ {
			if !f(sm.returnRecord(i)) {
				break
			}
		}
	}
}

// IterCh returns a channel that sorted records can be read from and processed.
func (sm *SortedMap) IterCh() <-chan Record {
	return sm.iterCh(false, 0)
}

// IterChCustom returns a channel that sorted records can be read from and processed, with custom options.
func (sm *SortedMap) IterChCustom(reversed bool, bufSize int) <-chan Record {
	return sm.iterCh(reversed, bufSize)
}

// IterBetweenCh returns a channel that sorted records can be read from and processed,
// and a boolean value that indicates whether or not values in the collection fall between the given bounds.
// IterBetweenCh starts at the lower bound value and sends all values in the collection until reaching the upper bounds value.
// Sort order is reversed if the reversed argument is set to true.
func (sm *SortedMap) IterBetweenCh(lowerBound, upperBound interface{}) (<-chan Record, bool) {
	return sm.iterBetweenCh(false, 0, lowerBound, upperBound)
}

// IterBetweenChCustom returns a channel that sorted records can be read from and processed,
// and a boolean value that indicates whether or not values in the collection fall between the given bounds.
// IterBetweenChCustom starts at the lower bound value and sends all values in the collection until reaching the upper bounds value.
// Sort order is reversed if the reversed argument is set to true.
func (sm *SortedMap) IterBetweenChCustom(reversed bool, bufSize int, lowerBound, upperBound interface{}) (<-chan Record, bool) {
	return sm.iterBetweenCh(reversed, bufSize, lowerBound, upperBound)
}

// IterFunc passes each record to the specified callback function.
// Sort order is reversed if the reversed argument is set to true.
func (sm *SortedMap) IterFunc(reversed bool, f func(rec Record) bool) {
	sm.iterFunc(reversed, f)
}

// IterBetweenFunc starts at the lower bound value and passes all values in the collection to the callback function until reaching the upper bounds value.
// Sort order is reversed if the reversed argument is set to true.
func (sm *SortedMap) IterBetweenFunc(reversed bool, lowerBound, upperBound interface{}, f func(rec Record) bool) {
	sm.iterBetweenFunc(reversed, lowerBound, upperBound, f)
}<|endoftext|>