<commit_before>package msgpack

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
)

// Type represents the type of value in the MsgPack stream.
type Type int

// list of MsgPack types.
const (
	Invalid Type = iota
	Nil
	Bool
	Int
	Uint
	Float
	ArrayLen
	MapLen
	String
	Binary
	Extension
)

var typeNames = [...]string{
	Invalid:   "Invalid",
	Nil:       "Nil",
	Bool:      "Bool",
	Int:       "Int",
	Uint:      "Uint",
	Float:     "Float",
	ArrayLen:  "ArrayLen",
	MapLen:    "MapLen",
	String:    "String",
	Binary:    "Binary",
	Extension: "Extension",
}

// String returns a string representation of the Type.
func (t Type) String() string {
	var n string

	if 0 <= t && t < Type(len(typeNames)) {
		n = typeNames[t]
	}
	if n == "" {
		n = "unknown"
	}

	return n
}

// ErrDataSizeTooLarge is the data size too large error.
var ErrDataSizeTooLarge = errors.New("msgpack: data size too large")

// Decoder reads MsgPack objects from an io.Reader.
type Decoder struct {
	extensions ExtensionMap
	err        error
	r          *bufio.Reader
	n          uint64
	p          []byte
	t          Type
	peek       bool
}

const bufioReaderSize = 4096

// NewDecoder allocates and initializes a new decoder.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{
		r: bufio.NewReaderSize(r, bufioReaderSize),
	}
}

// ExtensionMap specifies functions for converting MsgPack extensions to Go
// values.
//
// The key is the MsgPack extension type.
// The value is a function that converts the extension data to a Go value.
type ExtensionMap map[int]func([]byte) (interface{}, error)

// SetExtensions specifies functions for converting MsgPack extensions to Go
// values.
func (d *Decoder) SetExtensions(extensions ExtensionMap) {
	d.extensions = extensions
}

// Type returns the type of the current value in the stream.
func (d *Decoder) Type() Type {
	return d.t
}

// Extension returns the type of the current Extension value.
func (d *Decoder) Extension() int {
	return int(d.n)
}

// Bytes returns the current String, Binary or Extension value as a slice of
// bytes.
func (d *Decoder) Bytes() []byte {
	if d.peek {
		p := make([]byte, len(d.p))
		copy(p, d.p)
		d.p = p
	}

	return d.p
}

// BytesNoCopy returns the current String, Binary or Extension value as a slice
// of bytes. The underlying array may point to data that will be overwritten by
// a subsequent call to Unpack.
func (d *Decoder) BytesNoCopy() []byte {
	return d.p
}

// String returns the current String, Binary or Extension value as a string.
func (d *Decoder) String() string {
	return string(d.p)
}

// Int returns the current Int value.
func (d *Decoder) Int() int64 {
	return int64(d.n)
}

// Uint returns the current Uint value.
func (d *Decoder) Uint() uint64 {
	return d.n
}

// Len returns the current ArrayLen or MapLen value.
func (d *Decoder) Len() int {
	return int(d.n)
}

// Bool returns the current Bool value.
func (d *Decoder) Bool() bool {
	if d.n != 0 {
		return true
	}

	return false
}

// Float returns the current Float value.
func (d *Decoder) Float() float64 {
	return math.Float64frombits(d.n)
}

// Unpack reads the next value from the MsgPack stream. Call Type to get the
// type of the current value. Call Bool, Uint, Int, Float, Bytes or Extension
// to get the value.
func (d *Decoder) Unpack() error {
	if d.err != nil {
		return d.err
	}

	code, err := d.r.ReadByte()
	if err != nil {
		// Don't call d.fatal here because we don't want io.EOF converted to
		// io.ErrUnexpectedEOF
		d.err = err
		return err
	}

	f := formats[code]
	d.t = f.t

	d.n, err = f.n(d, code)
	if err != nil {
		return d.fatal(err)
	}

	if !f.more {
		d.p = nil
		return nil
	}

	nn := int(d.n)
	if nn < 0 {
		return d.fatal(ErrDataSizeTooLarge)
	}

	if f.t == Extension {
		var b byte
		b, err = d.r.ReadByte()
		if err != nil {
			return d.fatal(err)
		}
		d.n = uint64(b)
	}

	if nn <= bufioReaderSize {
		d.peek = true
		d.p, err = d.r.Peek(nn)
		if err != nil {
			return d.fatal(err)
		}
		d.r.Discard(nn)
	} else {
		d.peek = false
		d.p = make([]byte, nn)
		_, err := io.ReadFull(d.r, d.p)
		if err != nil {
			return d.fatal(err)
		}
	}

	return nil
}

// Skip skips over any nested values in the stream.
func (d *Decoder) Skip() error {
	n := d.skipCount()

	for n > 0 {
		n--
		if err := d.Unpack(); err != nil {
			return err
		}
		n += d.skipCount()
	}

	return nil
}

func (d *Decoder) skipCount() int {
	switch d.Type() {
	case ArrayLen:
		return d.Len()
	case MapLen:
		return 2 * d.Len()
	default:
		return 0
	}
}

var formats = [256]*struct {
	t    Type
	n    func(d *Decoder, code byte) (uint64, error)
	more bool
}{
	fixIntCodeMin: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) { return uint64(code), nil },
	},
	fixMapCodeMin: {
		t: MapLen,
		n: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - fixMapCodeMin, nil },
	},
	fixArrayCodeMin: {
		t: ArrayLen,
		n: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - fixArrayCodeMin, nil },
	},
	fixStringCodeMin: {
		t:    String,
		n:    func(d *Decoder, code byte) (uint64, error) { return uint64(code) - fixStringCodeMin, nil },
		more: true,
	},
	negFixIntCodeMin: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) { return uint64(int64(int8(code))), nil },
	},
	nilCode: {
		t: Nil,
		n: func(d *Decoder, code byte) (uint64, error) { return 0, nil },
	},
	falseCode: {
		t: Bool,
		n: func(d *Decoder, code byte) (uint64, error) { return 0, nil },
	},
	trueCode: {
		t: Bool,
		n: func(d *Decoder, code byte) (uint64, error) { return 1, nil },
	},
	float32Code: {
		t: Float,
		n: func(d *Decoder, code byte) (uint64, error) {
			n, err := d.read4(code)
			return math.Float64bits(float64(math.Float32frombits(uint32(n)))), err
		},
	},
	float64Code: {
		t: Float,
		n: (*Decoder).read8,
	},
	uint8Code: {
		t: Uint,
		n: (*Decoder).read1,
	},
	uint16Code: {
		t: Uint,
		n: (*Decoder).read2,
	},
	uint32Code: {
		t: Uint,
		n: (*Decoder).read4,
	},
	uint64Code: {
		t: Uint,
		n: (*Decoder).read8,
	},
	int8Code: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) {
			n, err := d.read1(code)
			return uint64(int64(int8(n))), err
		},
	},
	int16Code: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) {
			n, err := d.read2(code)
			return uint64(int64(int16(n))), err
		},
	},
	int32Code: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) {
			n, err := d.read4(code)
			return uint64(int64(int32(n))), err
		},
	},
	int64Code: {
		t: Int,
		n: (*Decoder).read8,
	},
	string8Code: {
		t:    String,
		n:    (*Decoder).read1,
		more: true,
	},
	string16Code: {
		t:    String,
		n:    (*Decoder).read2,
		more: true,
	},
	string32Code: {
		t:    String,
		n:    (*Decoder).read4,
		more: true,
	},
	binary8Code: {
		t:    Binary,
		n:    (*Decoder).read1,
		more: true,
	},
	binary16Code: {
		t:    Binary,
		n:    (*Decoder).read2,
		more: true,
	},
	binary32Code: {
		t:    Binary,
		n:    (*Decoder).read4,
		more: true,
	},
	array16Code: {
		t: ArrayLen,
		n: (*Decoder).read2,
	},
	array32Code: {
		t: ArrayLen,
		n: (*Decoder).read4,
	},
	map16Code: {
		t: MapLen,
		n: (*Decoder).read2,
	},
	map32Code: {
		t: MapLen,
		n: (*Decoder).read4,
	},
	fixext1Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 1, nil },
		more: true,
	},
	fixext2Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 2, nil },
		more: true,
	},
	fixext4Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 4, nil },
		more: true,
	},
	fixext8Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 8, nil },
		more: true,
	},
	fixext16Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 16, nil },
		more: true,
	},
	ext8Code: {
		t:    Extension,
		n:    (*Decoder).read1,
		more: true,
	},
	ext16Code: {
		t:    Extension,
		n:    (*Decoder).read2,
		more: true,
	},
	ext32Code: {
		t:    Extension,
		n:    (*Decoder).read4,
		more: true,
	},
	unusedCode: {
		t: Invalid,
		n: func(d *Decoder, code byte) (uint64, error) {
			return 0, fmt.Errorf("msgpack: unknown format code %x", code)
		},
	},
}

func init() {
	for i := fixIntCodeMin + 1; i <= fixIntCodeMax; i++ {
		formats[i] = formats[fixIntCodeMin]
	}

	for i := fixMapCodeMin + 1; i <= fixMapCodeMax; i++ {
		formats[i] = formats[fixMapCodeMin]
	}

	for i := fixArrayCodeMin + 1; i <= fixArrayCodeMax; i++ {
		formats[i] = formats[fixArrayCodeMin]
	}

	for i := fixStringCodeMin + 1; i <= fixStringCodeMax; i++ {
		formats[i] = formats[fixStringCodeMin]
	}

	for i := negFixIntCodeMin + 1; i <= negFixIntCodeMax; i++ {
		formats[i] = formats[negFixIntCodeMin]
	}
}

func (d *Decoder) fatal(err error) error {
	if err == io.EOF {
		err = io.ErrUnexpectedEOF
	}

	d.t = Invalid
	d.err = err
	return err
}

func (d *Decoder) read1(format byte) (uint64, error) {
	b, err := d.r.ReadByte()

	return uint64(b), err
}

func (d *Decoder) read2(format byte) (uint64, error) {
	p, err := d.r.Peek(2)
	if err != nil {
		return 0, err
	}
	d.r.Discard(2)

	return uint64(p[1]) | uint64(p[0])<<8, nil
}

func (d *Decoder) read4(format byte) (uint64, error) {
	p, err := d.r.Peek(4)
	if err != nil {
		return 0, err
	}
	d.r.Discard(4)

	return uint64(p[3]) | uint64(p[2])<<8 | uint64(p[1])<<16 | uint64(p[0])<<24, nil
}

func (d *Decoder) read8(format byte) (uint64, error) {
	p, err := d.r.Peek(8)
	if err != nil {
		return 0, err
	}
	d.r.Discard(8)

	return uint64(p[7]) | uint64(p[6])<<8 | uint64(p[5])<<16 | uint64(p[4])<<24 |
		uint64(p[3])<<32 | uint64(p[2])<<40 | uint64(p[1])<<48 | uint64(p[0])<<56, nil
}
<commit_msg>msgpack: replace MsgPack word to MessagePack in documentation<commit_after>package msgpack

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"math"
)

// Type represents the type of value in the MessagePack stream.
type Type int

// list of MessagePack types.
const (
	Invalid Type = iota
	Nil
	Bool
	Int
	Uint
	Float
	ArrayLen
	MapLen
	String
	Binary
	Extension
)

var typeNames = [...]string{
	Invalid:   "Invalid",
	Nil:       "Nil",
	Bool:      "Bool",
	Int:       "Int",
	Uint:      "Uint",
	Float:     "Float",
	ArrayLen:  "ArrayLen",
	MapLen:    "MapLen",
	String:    "String",
	Binary:    "Binary",
	Extension: "Extension",
}

// String returns a string representation of the Type.
func (t Type) String() string {
	var n string

	if 0 <= t && t < Type(len(typeNames)) {
		n = typeNames[t]
	}
	if n == "" {
		n = "unknown"
	}

	return n
}

// ErrDataSizeTooLarge is the data size too large error.
var ErrDataSizeTooLarge = errors.New("msgpack: data size too large")

// Decoder reads MessagePack objects from an io.Reader.
type Decoder struct {
	extensions ExtensionMap
	err        error
	r          *bufio.Reader
	n          uint64
	p          []byte
	t          Type
	peek       bool
}

const bufioReaderSize = 4096

// NewDecoder allocates and initializes a new decoder.
func NewDecoder(r io.Reader) *Decoder {
	return &Decoder{
		r: bufio.NewReaderSize(r, bufioReaderSize),
	}
}

// ExtensionMap specifies functions for converting MessagePack extensions to Go
// values.
//
// The key is the MessagePack extension type.
// The value is a function that converts the extension data to a Go value.
type ExtensionMap map[int]func([]byte) (interface{}, error)

// SetExtensions specifies functions for converting MessagePack extensions to Go
// values.
func (d *Decoder) SetExtensions(extensions ExtensionMap) {
	d.extensions = extensions
}

// Type returns the type of the current value in the stream.
func (d *Decoder) Type() Type {
	return d.t
}

// Extension returns the type of the current Extension value.
func (d *Decoder) Extension() int {
	return int(d.n)
}

// Bytes returns the current String, Binary or Extension value as a slice of
// bytes.
func (d *Decoder) Bytes() []byte {
	if d.peek {
		p := make([]byte, len(d.p))
		copy(p, d.p)
		d.p = p
	}

	return d.p
}

// BytesNoCopy returns the current String, Binary or Extension value as a slice
// of bytes. The underlying array may point to data that will be overwritten by
// a subsequent call to Unpack.
func (d *Decoder) BytesNoCopy() []byte {
	return d.p
}

// String returns the current String, Binary or Extension value as a string.
func (d *Decoder) String() string {
	return string(d.p)
}

// Int returns the current Int value.
func (d *Decoder) Int() int64 {
	return int64(d.n)
}

// Uint returns the current Uint value.
func (d *Decoder) Uint() uint64 {
	return d.n
}

// Len returns the current ArrayLen or MapLen value.
func (d *Decoder) Len() int {
	return int(d.n)
}

// Bool returns the current Bool value.
func (d *Decoder) Bool() bool {
	if d.n != 0 {
		return true
	}

	return false
}

// Float returns the current Float value.
func (d *Decoder) Float() float64 {
	return math.Float64frombits(d.n)
}

// Unpack reads the next value from the MessagePack stream. Call Type to get the
// type of the current value. Call Bool, Uint, Int, Float, Bytes or Extension
// to get the value.
func (d *Decoder) Unpack() error {
	if d.err != nil {
		return d.err
	}

	code, err := d.r.ReadByte()
	if err != nil {
		// Don't call d.fatal here because we don't want io.EOF converted to
		// io.ErrUnexpectedEOF
		d.err = err
		return err
	}

	f := formats[code]
	d.t = f.t

	d.n, err = f.n(d, code)
	if err != nil {
		return d.fatal(err)
	}

	if !f.more {
		d.p = nil
		return nil
	}

	nn := int(d.n)
	if nn < 0 {
		return d.fatal(ErrDataSizeTooLarge)
	}

	if f.t == Extension {
		var b byte
		b, err = d.r.ReadByte()
		if err != nil {
			return d.fatal(err)
		}
		d.n = uint64(b)
	}

	if nn <= bufioReaderSize {
		d.peek = true
		d.p, err = d.r.Peek(nn)
		if err != nil {
			return d.fatal(err)
		}
		d.r.Discard(nn)
	} else {
		d.peek = false
		d.p = make([]byte, nn)
		_, err := io.ReadFull(d.r, d.p)
		if err != nil {
			return d.fatal(err)
		}
	}

	return nil
}

// Skip skips over any nested values in the stream.
func (d *Decoder) Skip() error {
	n := d.skipCount()

	for n > 0 {
		n--
		if err := d.Unpack(); err != nil {
			return err
		}
		n += d.skipCount()
	}

	return nil
}

func (d *Decoder) skipCount() int {
	switch d.Type() {
	case ArrayLen:
		return d.Len()
	case MapLen:
		return 2 * d.Len()
	default:
		return 0
	}
}

var formats = [256]*struct {
	t    Type
	n    func(d *Decoder, code byte) (uint64, error)
	more bool
}{
	fixIntCodeMin: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) { return uint64(code), nil },
	},
	fixMapCodeMin: {
		t: MapLen,
		n: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - fixMapCodeMin, nil },
	},
	fixArrayCodeMin: {
		t: ArrayLen,
		n: func(d *Decoder, code byte) (uint64, error) { return uint64(code) - fixArrayCodeMin, nil },
	},
	fixStringCodeMin: {
		t:    String,
		n:    func(d *Decoder, code byte) (uint64, error) { return uint64(code) - fixStringCodeMin, nil },
		more: true,
	},
	negFixIntCodeMin: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) { return uint64(int64(int8(code))), nil },
	},
	nilCode: {
		t: Nil,
		n: func(d *Decoder, code byte) (uint64, error) { return 0, nil },
	},
	falseCode: {
		t: Bool,
		n: func(d *Decoder, code byte) (uint64, error) { return 0, nil },
	},
	trueCode: {
		t: Bool,
		n: func(d *Decoder, code byte) (uint64, error) { return 1, nil },
	},
	float32Code: {
		t: Float,
		n: func(d *Decoder, code byte) (uint64, error) {
			n, err := d.read4(code)
			return math.Float64bits(float64(math.Float32frombits(uint32(n)))), err
		},
	},
	float64Code: {
		t: Float,
		n: (*Decoder).read8,
	},
	uint8Code: {
		t: Uint,
		n: (*Decoder).read1,
	},
	uint16Code: {
		t: Uint,
		n: (*Decoder).read2,
	},
	uint32Code: {
		t: Uint,
		n: (*Decoder).read4,
	},
	uint64Code: {
		t: Uint,
		n: (*Decoder).read8,
	},
	int8Code: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) {
			n, err := d.read1(code)
			return uint64(int64(int8(n))), err
		},
	},
	int16Code: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) {
			n, err := d.read2(code)
			return uint64(int64(int16(n))), err
		},
	},
	int32Code: {
		t: Int,
		n: func(d *Decoder, code byte) (uint64, error) {
			n, err := d.read4(code)
			return uint64(int64(int32(n))), err
		},
	},
	int64Code: {
		t: Int,
		n: (*Decoder).read8,
	},
	string8Code: {
		t:    String,
		n:    (*Decoder).read1,
		more: true,
	},
	string16Code: {
		t:    String,
		n:    (*Decoder).read2,
		more: true,
	},
	string32Code: {
		t:    String,
		n:    (*Decoder).read4,
		more: true,
	},
	binary8Code: {
		t:    Binary,
		n:    (*Decoder).read1,
		more: true,
	},
	binary16Code: {
		t:    Binary,
		n:    (*Decoder).read2,
		more: true,
	},
	binary32Code: {
		t:    Binary,
		n:    (*Decoder).read4,
		more: true,
	},
	array16Code: {
		t: ArrayLen,
		n: (*Decoder).read2,
	},
	array32Code: {
		t: ArrayLen,
		n: (*Decoder).read4,
	},
	map16Code: {
		t: MapLen,
		n: (*Decoder).read2,
	},
	map32Code: {
		t: MapLen,
		n: (*Decoder).read4,
	},
	fixext1Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 1, nil },
		more: true,
	},
	fixext2Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 2, nil },
		more: true,
	},
	fixext4Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 4, nil },
		more: true,
	},
	fixext8Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 8, nil },
		more: true,
	},
	fixext16Code: {
		t:    Extension,
		n:    func(d *Decoder, code byte) (uint64, error) { return 16, nil },
		more: true,
	},
	ext8Code: {
		t:    Extension,
		n:    (*Decoder).read1,
		more: true,
	},
	ext16Code: {
		t:    Extension,
		n:    (*Decoder).read2,
		more: true,
	},
	ext32Code: {
		t:    Extension,
		n:    (*Decoder).read4,
		more: true,
	},
	unusedCode: {
		t: Invalid,
		n: func(d *Decoder, code byte) (uint64, error) {
			return 0, fmt.Errorf("msgpack: unknown format code %x", code)
		},
	},
}

func init() {
	for i := fixIntCodeMin + 1; i <= fixIntCodeMax; i++ {
		formats[i] = formats[fixIntCodeMin]
	}

	for i := fixMapCodeMin + 1; i <= fixMapCodeMax; i++ {
		formats[i] = formats[fixMapCodeMin]
	}

	for i := fixArrayCodeMin + 1; i <= fixArrayCodeMax; i++ {
		formats[i] = formats[fixArrayCodeMin]
	}

	for i := fixStringCodeMin + 1; i <= fixStringCodeMax; i++ {
		formats[i] = formats[fixStringCodeMin]
	}

	for i := negFixIntCodeMin + 1; i <= negFixIntCodeMax; i++ {
		formats[i] = formats[negFixIntCodeMin]
	}
}

func (d *Decoder) fatal(err error) error {
	if err == io.EOF {
		err = io.ErrUnexpectedEOF
	}

	d.t = Invalid
	d.err = err
	return err
}

func (d *Decoder) read1(format byte) (uint64, error) {
	b, err := d.r.ReadByte()

	return uint64(b), err
}

func (d *Decoder) read2(format byte) (uint64, error) {
	p, err := d.r.Peek(2)
	if err != nil {
		return 0, err
	}
	d.r.Discard(2)

	return uint64(p[1]) | uint64(p[0])<<8, nil
}

func (d *Decoder) read4(format byte) (uint64, error) {
	p, err := d.r.Peek(4)
	if err != nil {
		return 0, err
	}
	d.r.Discard(4)

	return uint64(p[3]) | uint64(p[2])<<8 | uint64(p[1])<<16 | uint64(p[0])<<24, nil
}

func (d *Decoder) read8(format byte) (uint64, error) {
	p, err := d.r.Peek(8)
	if err != nil {
		return 0, err
	}
	d.r.Discard(8)

	return uint64(p[7]) | uint64(p[6])<<8 | uint64(p[5])<<16 | uint64(p[4])<<24 |
		uint64(p[3])<<32 | uint64(p[2])<<40 | uint64(p[1])<<48 | uint64(p[0])<<56, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2020 The Knative Authors

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

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

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

// knativeserving.go provides methods to perform actions on the KnativeServing resource.

package resources

import (
	"context"
	"fmt"
	"time"

	"github.com/pkg/errors"
	v1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/cache"

	"knative.dev/pkg/test/logging"
	"knative.dev/serving-operator/pkg/apis/serving/v1alpha1"
	servingv1alpha1 "knative.dev/serving-operator/pkg/client/clientset/versioned/typed/serving/v1alpha1"
	"knative.dev/serving-operator/test"
)

const (
	// Interval specifies the time between two polls.
	Interval = 10 * time.Second
	// Timeout specifies the timeout for the function PollImmediate to reach a certain status.
	Timeout = 5 * time.Minute
	// LoggingConfigKey specifies specifies the key name of the logging config map.
	LoggingConfigKey = "logging"
	// DefaultsConfigKey specifies the key name of the default config map.
	DefaultsConfigKey = "defaults"
)

// WaitForKnativeServingState polls the status of the KnativeServing called name
// from client every `interval` until `inState` returns `true` indicating it
// is done, returns an error or timeout.
func WaitForKnativeServingState(clients servingv1alpha1.KnativeServingInterface, name string,
	inState func(s *v1alpha1.KnativeServing, err error) (bool, error)) (*v1alpha1.KnativeServing, error) {
	span := logging.GetEmitableSpan(context.Background(), fmt.Sprintf("WaitForKnativeServingState/%s/%s", name, "KnativeServingIsReady"))
	defer span.End()

	var lastState *v1alpha1.KnativeServing
	waitErr := wait.PollImmediate(Interval, Timeout, func() (bool, error) {
		lastState, err := clients.Get(name, metav1.GetOptions{})
		return inState(lastState, err)
	})

	if waitErr != nil {
		return lastState, errors.Wrapf(waitErr, "knativeserving %s is not in desired state, got: %+v", name, lastState)
	}
	return lastState, nil
}

// EnsureKnativeServingExists creates a KnativeServing with the name names.KnativeServing under the namespace names.Namespace, if it does not exist.
func EnsureKnativeServingExists(clients servingv1alpha1.KnativeServingInterface, names test.ResourceNames) (*v1alpha1.KnativeServing, error) {
	// If this function is called by the upgrade tests, we only create the custom resource, if it does not exist.
	ks, err := clients.Get(names.KnativeServing, metav1.GetOptions{})
	if apierrs.IsNotFound(err) {
		ks := &v1alpha1.KnativeServing{
			ObjectMeta: metav1.ObjectMeta{
				Name:      names.KnativeServing,
				Namespace: names.Namespace,
			},
		}
		return clients.Create(ks)
	}
	return ks, err
}

// WaitForConfigMap takes a condition function that evaluates ConfigMap data
func WaitForConfigMap(name string, client *kubernetes.Clientset, fn func(map[string]string) bool) error {
	ns, cm, _ := cache.SplitMetaNamespaceKey(name)
	return wait.PollImmediate(Interval, Timeout, func() (bool, error) {
		cm, err := client.CoreV1().ConfigMaps(ns).Get(cm, metav1.GetOptions{})
		if err != nil {
			return false, err
		}
		return fn(cm.Data), nil
	})
}

// IsKnativeServingReady will check the status conditions of the KnativeServing and return true if the KnativeServing is ready.
func IsKnativeServingReady(s *v1alpha1.KnativeServing, err error) (bool, error) {
	return s.Status.IsReady(), err
}

// IsDeploymentAvailable will check the status conditions of the deployment and return true if the deployment is available.
func IsDeploymentAvailable(d *v1.Deployment) (bool, error) {
	return getDeploymentStatus(d) == "True", nil
}

func getDeploymentStatus(d *v1.Deployment) corev1.ConditionStatus {
	for _, dc := range d.Status.Conditions {
		if dc.Type == "Available" {
			return dc.Status
		}
	}
	return "unknown"
}

func getTestKSOperatorCRSpec() v1alpha1.KnativeServingSpec {
	return v1alpha1.KnativeServingSpec{
		Config: map[string]map[string]string{
			DefaultsConfigKey: {
				"revision-timeout-seconds": "200",
			},
			LoggingConfigKey: {
				"loglevel.controller": "debug",
				"loglevel.autoscaler": "debug",
			},
		},
	}
}

// WaitForKnativeServingDeploymentState polls the status of the Knative deployments every `interval`
// until `inState` returns `true` indicating the deployments match the desired deployments.
func WaitForKnativeServingDeploymentState(clients *test.Clients, namespace string, expectedDeployments []string,
	inState func(deps *v1.DeploymentList, expectedDeployments []string, err error) (bool, error)) (*v1alpha1.KnativeServing, error) {
	span := logging.GetEmitableSpan(context.Background(), fmt.Sprintf("WaitForKnativeDeploymentState/%s/%s", expectedDeployments, "KnativeDeploymentIsReady"))
	defer span.End()

	var lastState *v1alpha1.KnativeServing
	waitErr := wait.PollImmediate(Interval, Timeout, func() (bool, error) {
		dpList, err := clients.KubeClient.Kube.AppsV1().Deployments(namespace).List(metav1.ListOptions{})
		return inState(dpList, expectedDeployments, err)
	})

	if waitErr != nil {
		return lastState, waitErr
	}
	return lastState, nil
}

// IsKnativeServingDeploymentReady will check the status conditions of the deployments and return true if the deployments meet the desired status.
func IsKnativeServingDeploymentReady(dpList *v1.DeploymentList, expectedDeployments []string, err error) (bool, error) {
	if err != nil {
		return false, err
	}
	if len(dpList.Items) != len(expectedDeployments) {
		errMessage := fmt.Sprintf("The expected number of deployments is %v, and got %v.", len(expectedDeployments), len(dpList.Items))
		return false, errors.New(errMessage)
	}
	for _, deployment := range dpList.Items {
		if !stringInList(deployment.Name, expectedDeployments) {
			errMessage := fmt.Sprintf("The deployment %v is not found in the expected list of deployment.", deployment.Name)
			return false, errors.New(errMessage)
		}
		for _, c := range deployment.Status.Conditions {
			if c.Type == v1.DeploymentAvailable && c.Status != corev1.ConditionTrue {
				errMessage := fmt.Sprintf("The deployment %v is not ready.", deployment.Name)
				return false, errors.New(errMessage)
			}
		}
	}
	return true, nil
}

func stringInList(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}
<commit_msg>golang format tools (#318)<commit_after>/*
Copyright 2020 The Knative Authors

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

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

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

// knativeserving.go provides methods to perform actions on the KnativeServing resource.

package resources

import (
	"context"
	"fmt"
	"time"

	"github.com/pkg/errors"
	v1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"
	apierrs "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/cache"

	"knative.dev/pkg/test/logging"
	"knative.dev/serving-operator/pkg/apis/serving/v1alpha1"
	servingv1alpha1 "knative.dev/serving-operator/pkg/client/clientset/versioned/typed/serving/v1alpha1"
	"knative.dev/serving-operator/test"
)

const (
	// Interval specifies the time between two polls.
	Interval = 10 * time.Second
	// Timeout specifies the timeout for the function PollImmediate to reach a certain status.
	Timeout = 5 * time.Minute
	// LoggingConfigKey specifies specifies the key name of the logging config map.
	LoggingConfigKey = "logging"
	// DefaultsConfigKey specifies the key name of the default config map.
	DefaultsConfigKey = "defaults"
)

// WaitForKnativeServingState polls the status of the KnativeServing called name
// from client every `interval` until `inState` returns `true` indicating it
// is done, returns an error or timeout.
func WaitForKnativeServingState(clients servingv1alpha1.KnativeServingInterface, name string,
	inState func(s *v1alpha1.KnativeServing, err error) (bool, error)) (*v1alpha1.KnativeServing, error) {
	span := logging.GetEmitableSpan(context.Background(), fmt.Sprintf("WaitForKnativeServingState/%s/%s", name, "KnativeServingIsReady"))
	defer span.End()

	var lastState *v1alpha1.KnativeServing
	waitErr := wait.PollImmediate(Interval, Timeout, func() (bool, error) {
		lastState, err := clients.Get(name, metav1.GetOptions{})
		return inState(lastState, err)
	})

	if waitErr != nil {
		return lastState, errors.Wrapf(waitErr, "knativeserving %s is not in desired state, got: %+v", name, lastState)
	}
	return lastState, nil
}

// EnsureKnativeServingExists creates a KnativeServing with the name names.KnativeServing under the namespace names.Namespace, if it does not exist.
func EnsureKnativeServingExists(clients servingv1alpha1.KnativeServingInterface, names test.ResourceNames) (*v1alpha1.KnativeServing, error) {
	// If this function is called by the upgrade tests, we only create the custom resource, if it does not exist.
	ks, err := clients.Get(names.KnativeServing, metav1.GetOptions{})
	if apierrs.IsNotFound(err) {
		ks := &v1alpha1.KnativeServing{
			ObjectMeta: metav1.ObjectMeta{
				Name:      names.KnativeServing,
				Namespace: names.Namespace,
			},
		}
		return clients.Create(ks)
	}
	return ks, err
}

// WaitForConfigMap takes a condition function that evaluates ConfigMap data
func WaitForConfigMap(name string, client *kubernetes.Clientset, fn func(map[string]string) bool) error {
	ns, cm, _ := cache.SplitMetaNamespaceKey(name)
	return wait.PollImmediate(Interval, Timeout, func() (bool, error) {
		cm, err := client.CoreV1().ConfigMaps(ns).Get(cm, metav1.GetOptions{})
		if err != nil {
			return false, err
		}
		return fn(cm.Data), nil
	})
}

// IsKnativeServingReady will check the status conditions of the KnativeServing and return true if the KnativeServing is ready.
func IsKnativeServingReady(s *v1alpha1.KnativeServing, err error) (bool, error) {
	return s.Status.IsReady(), err
}

// IsDeploymentAvailable will check the status conditions of the deployment and return true if the deployment is available.
func IsDeploymentAvailable(d *v1.Deployment) (bool, error) {
	return getDeploymentStatus(d) == "True", nil
}

func getDeploymentStatus(d *v1.Deployment) corev1.ConditionStatus {
	for _, dc := range d.Status.Conditions {
		if dc.Type == "Available" {
			return dc.Status
		}
	}
	return "unknown"
}

func getTestKSOperatorCRSpec() v1alpha1.KnativeServingSpec {
	return v1alpha1.KnativeServingSpec{
		Config: map[string]map[string]string{
			DefaultsConfigKey: {
				"revision-timeout-seconds": "200",
			},
			LoggingConfigKey: {
				"loglevel.controller": "debug",
				"loglevel.autoscaler": "debug",
			},
		},
	}
}

// WaitForKnativeServingDeploymentState polls the status of the Knative deployments every `interval`
// until `inState` returns `true` indicating the deployments match the desired deployments.
func WaitForKnativeServingDeploymentState(clients *test.Clients, namespace string, expectedDeployments []string,
	inState func(deps *v1.DeploymentList, expectedDeployments []string, err error) (bool, error)) (*v1alpha1.KnativeServing, error) {
	span := logging.GetEmitableSpan(context.Background(), fmt.Sprintf("WaitForKnativeDeploymentState/%s/%s", expectedDeployments, "KnativeDeploymentIsReady"))
	defer span.End()

	var lastState *v1alpha1.KnativeServing
	waitErr := wait.PollImmediate(Interval, Timeout, func() (bool, error) {
		dpList, err := clients.KubeClient.Kube.AppsV1().Deployments(namespace).List(metav1.ListOptions{})
		return inState(dpList, expectedDeployments, err)
	})

	if waitErr != nil {
		return lastState, waitErr
	}
	return lastState, nil
}

// IsKnativeServingDeploymentReady will check the status conditions of the deployments and return true if the deployments meet the desired status.
func IsKnativeServingDeploymentReady(dpList *v1.DeploymentList, expectedDeployments []string, err error) (bool, error) {
	if err != nil {
		return false, err
	}
	if len(dpList.Items) != len(expectedDeployments) {
		errMessage := fmt.Sprintf("The expected number of deployments is %v, and got %v.", len(expectedDeployments), len(dpList.Items))
		return false, errors.New(errMessage)
	}
	for _, deployment := range dpList.Items {
		if !stringInList(deployment.Name, expectedDeployments) {
			errMessage := fmt.Sprintf("The deployment %v is not found in the expected list of deployment.", deployment.Name)
			return false, errors.New(errMessage)
		}
		for _, c := range deployment.Status.Conditions {
			if c.Type == v1.DeploymentAvailable && c.Status != corev1.ConditionTrue {
				errMessage := fmt.Sprintf("The deployment %v is not ready.", deployment.Name)
				return false, errors.New(errMessage)
			}
		}
	}
	return true, nil
}

func stringInList(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>package virtualmachine

const AnnotationVirtualMachineVncWebSocketPort = "n0core/provisioning/virtual_machine/vnc_websocket_port"

const AnnotationComputeReservedBy = "n0core/provisioning/virtual_machine/virtual_machine/reserved_by"

const AnnotationNetworkInterfaceIsGateway = "n0core/provisioning/virtual_machine/is_gateway"

const AnnotationNetworkVlanID = "n0core/provisioning/virtual_machine/vlan_id"

const AnnotationVirtualMachineRequestNodeName = "n0core/provisioning/virtual_machine/request_node_name"
<commit_msg>delete unused annotation<commit_after>package virtualmachine

const AnnotationVirtualMachineVncWebSocketPort = "n0core/provisioning/virtual_machine/vnc_websocket_port"

const AnnotationComputeReservedBy = "n0core/provisioning/virtual_machine/virtual_machine/reserved_by"

const AnnotationNetworkInterfaceIsGateway = "n0core/provisioning/virtual_machine/is_gateway"

const AnnotationVirtualMachineRequestNodeName = "n0core/provisioning/virtual_machine/request_node_name"
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/moby/src/initrd"
)

// Process the build arguments and execute build
func build(args []string) {
	buildCmd := flag.NewFlagSet("build", flag.ExitOnError)
	buildCmd.Usage = func() {
		fmt.Printf("USAGE: %s build [options] <file>[.yml]\n\n", os.Args[0])
		fmt.Printf("Options:\n")
		buildCmd.PrintDefaults()
	}
	buildName := buildCmd.String("name", "", "Name to use for output files")
	buildPull := buildCmd.Bool("pull", false, "Always pull images")

	buildCmd.Parse(args)
	remArgs := buildCmd.Args()

	if len(remArgs) == 0 {
		fmt.Println("Please specify a configuration file")
		buildCmd.Usage()
		os.Exit(1)
	}
	conf := remArgs[0]
	if !(filepath.Ext(conf) == ".yml" || filepath.Ext(conf) == ".yaml") {
		conf = conf + ".yml"
	}

	buildInternal(*buildName, *buildPull, conf)
}

func initrdAppend(iw *initrd.Writer, r io.Reader) {
	_, err := initrd.Copy(iw, r)
	if err != nil {
		log.Fatalf("initrd write error: %v", err)
	}
}

func enforceContentTrust(fullImageName string, config *TrustConfig) bool {
	for _, img := range config.Image {
		// First check for an exact tag match
		if img == fullImageName {
			return true
		}
		// Also check for an image name only match:
		if img == strings.TrimSuffix(fullImageName, ":") {
			return true
		}
	}

	for _, org := range config.Org {
		if strings.HasPrefix(fullImageName, org+"/") {
		}
		return true
	}
	return false
}

// Perform the actual build process
func buildInternal(name string, pull bool, conf string) {
	if name == "" {
		name = filepath.Base(conf)
		ext := filepath.Ext(conf)
		if ext != "" {
			name = name[:len(name)-len(ext)]
		}
	}

	config, err := ioutil.ReadFile(conf)
	if err != nil {
		log.Fatalf("Cannot open config file: %v", err)
	}

	m, err := NewConfig(config)
	if err != nil {
		log.Fatalf("Invalid config: %v", err)
	}

	w := new(bytes.Buffer)
	iw := initrd.NewWriter(w)

	if pull || enforceContentTrust(m.Kernel.Image, &m.Trust) {
		log.Infof("Pull kernel image: %s", m.Kernel.Image)
		err := dockerPull(m.Kernel.Image, enforceContentTrust(m.Kernel.Image, &m.Trust))
		if err != nil {
			log.Fatalf("Could not pull image %s: %v", m.Kernel.Image, err)
		}
	}
	// get kernel bzImage and initrd tarball from container
	// TODO examine contents to see what names they might have
	log.Infof("Extract kernel image: %s", m.Kernel.Image)
	const (
		bzimageName = "bzImage"
		ktarName    = "kernel.tar"
	)
	out, err := dockerRun(m.Kernel.Image, "tar", "cf", "-", bzimageName, ktarName)
	if err != nil {
		log.Fatalf("Failed to extract kernel image and tarball: %v", err)
	}
	buf := bytes.NewBuffer(out)
	bzimage, ktar, err := untarKernel(buf, bzimageName, ktarName)
	if err != nil {
		log.Fatalf("Could not extract bzImage and kernel filesystem from tarball. %v", err)
	}
	initrdAppend(iw, ktar)

	// convert init images to tarballs
	log.Infof("Add init containers:")
	for _, ii := range m.Init {
		if pull || enforceContentTrust(ii, &m.Trust) {
			log.Infof("Pull init image: %s", ii)
			err := dockerPull(ii, enforceContentTrust(ii, &m.Trust))
			if err != nil {
				log.Fatalf("Could not pull image %s: %v", ii, err)
			}
		}
		log.Infof("Process init image: %s", ii)
		init, err := ImageExtract(ii, "")
		if err != nil {
			log.Fatalf("Failed to build init tarball from %s: %v", ii, err)
		}
		buffer := bytes.NewBuffer(init)
		initrdAppend(iw, buffer)
	}

	log.Infof("Add onboot containers:")
	for i, image := range m.Onboot {
		if pull || enforceContentTrust(image.Image, &m.Trust) {
			log.Infof("  Pull: %s", image.Image)
			err := dockerPull(image.Image, enforceContentTrust(image.Image, &m.Trust))
			if err != nil {
				log.Fatalf("Could not pull image %s: %v", image.Image, err)
			}
		}
		log.Infof("  Create OCI config for %s", image.Image)
		config, err := ConfigToOCI(&image)
		if err != nil {
			log.Fatalf("Failed to create config.json for %s: %v", image.Image, err)
		}
		so := fmt.Sprintf("%03d", i)
		path := "containers/onboot/" + so + "-" + image.Name
		out, err := ImageBundle(path, image.Image, config)
		if err != nil {
			log.Fatalf("Failed to extract root filesystem for %s: %v", image.Image, err)
		}
		buffer := bytes.NewBuffer(out)
		initrdAppend(iw, buffer)
	}

	log.Infof("Add service containers:")
	for _, image := range m.Services {
		if pull || enforceContentTrust(image.Image, &m.Trust) {
			log.Infof("  Pull: %s", image.Image)
			err := dockerPull(image.Image, enforceContentTrust(image.Image, &m.Trust))
			if err != nil {
				log.Fatalf("Could not pull image %s: %v", image.Image, err)
			}
		}
		log.Infof("  Create OCI config for %s", image.Image)
		config, err := ConfigToOCI(&image)
		if err != nil {
			log.Fatalf("Failed to create config.json for %s: %v", image.Image, err)
		}
		path := "containers/services/" + image.Name
		out, err := ImageBundle(path, image.Image, config)
		if err != nil {
			log.Fatalf("Failed to extract root filesystem for %s: %v", image.Image, err)
		}
		buffer := bytes.NewBuffer(out)
		initrdAppend(iw, buffer)
	}

	// add files
	buffer, err := filesystem(m)
	if err != nil {
		log.Fatalf("failed to add filesystem parts: %v", err)
	}
	initrdAppend(iw, buffer)
	err = iw.Close()
	if err != nil {
		log.Fatalf("initrd close error: %v", err)
	}

	log.Infof("Create outputs:")
	err = outputs(m, name, bzimage.Bytes(), w.Bytes())
	if err != nil {
		log.Fatalf("Error writing outputs: %v", err)
	}
}

func untarKernel(buf *bytes.Buffer, bzimageName, ktarName string) (*bytes.Buffer, *bytes.Buffer, error) {
	tr := tar.NewReader(buf)

	var bzimage, ktar *bytes.Buffer

	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalln(err)
		}
		switch hdr.Name {
		case bzimageName:
			bzimage = new(bytes.Buffer)
			_, err := io.Copy(bzimage, tr)
			if err != nil {
				return nil, nil, err
			}
		case ktarName:
			ktar = new(bytes.Buffer)
			_, err := io.Copy(ktar, tr)
			if err != nil {
				return nil, nil, err
			}
		default:
			continue
		}
	}

	if ktar == nil || bzimage == nil {
		return nil, nil, errors.New("did not find bzImage and kernel.tar in tarball")
	}

	return bzimage, ktar, nil
}
<commit_msg>trust: clean up logic for digests and orgs<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	log "github.com/Sirupsen/logrus"
	"github.com/docker/moby/src/initrd"
)

// Process the build arguments and execute build
func build(args []string) {
	buildCmd := flag.NewFlagSet("build", flag.ExitOnError)
	buildCmd.Usage = func() {
		fmt.Printf("USAGE: %s build [options] <file>[.yml]\n\n", os.Args[0])
		fmt.Printf("Options:\n")
		buildCmd.PrintDefaults()
	}
	buildName := buildCmd.String("name", "", "Name to use for output files")
	buildPull := buildCmd.Bool("pull", false, "Always pull images")

	buildCmd.Parse(args)
	remArgs := buildCmd.Args()

	if len(remArgs) == 0 {
		fmt.Println("Please specify a configuration file")
		buildCmd.Usage()
		os.Exit(1)
	}
	conf := remArgs[0]
	if !(filepath.Ext(conf) == ".yml" || filepath.Ext(conf) == ".yaml") {
		conf = conf + ".yml"
	}

	buildInternal(*buildName, *buildPull, conf)
}

func initrdAppend(iw *initrd.Writer, r io.Reader) {
	_, err := initrd.Copy(iw, r)
	if err != nil {
		log.Fatalf("initrd write error: %v", err)
	}
}

func enforceContentTrust(fullImageName string, config *TrustConfig) bool {
	for _, img := range config.Image {
		// First check for an exact name match
		if img == fullImageName {
			return true
		}
		// Also check for an image name only match
		// by removing a possible tag (with possibly added digest):
		if img == strings.TrimSuffix(fullImageName, ":") {
			return true
		}
		// and by removing a possible digest:
		if img == strings.TrimSuffix(fullImageName, "@sha256:") {
			return true
		}
	}

	for _, org := range config.Org {
		if strings.HasPrefix(fullImageName, org+"/") {
			return true
		}
	}
	return false
}

// Perform the actual build process
func buildInternal(name string, pull bool, conf string) {
	if name == "" {
		name = filepath.Base(conf)
		ext := filepath.Ext(conf)
		if ext != "" {
			name = name[:len(name)-len(ext)]
		}
	}

	config, err := ioutil.ReadFile(conf)
	if err != nil {
		log.Fatalf("Cannot open config file: %v", err)
	}

	m, err := NewConfig(config)
	if err != nil {
		log.Fatalf("Invalid config: %v", err)
	}

	w := new(bytes.Buffer)
	iw := initrd.NewWriter(w)

	if pull || enforceContentTrust(m.Kernel.Image, &m.Trust) {
		log.Infof("Pull kernel image: %s", m.Kernel.Image)
		err := dockerPull(m.Kernel.Image, enforceContentTrust(m.Kernel.Image, &m.Trust))
		if err != nil {
			log.Fatalf("Could not pull image %s: %v", m.Kernel.Image, err)
		}
	}
	// get kernel bzImage and initrd tarball from container
	// TODO examine contents to see what names they might have
	log.Infof("Extract kernel image: %s", m.Kernel.Image)
	const (
		bzimageName = "bzImage"
		ktarName    = "kernel.tar"
	)
	out, err := dockerRun(m.Kernel.Image, "tar", "cf", "-", bzimageName, ktarName)
	if err != nil {
		log.Fatalf("Failed to extract kernel image and tarball: %v", err)
	}
	buf := bytes.NewBuffer(out)
	bzimage, ktar, err := untarKernel(buf, bzimageName, ktarName)
	if err != nil {
		log.Fatalf("Could not extract bzImage and kernel filesystem from tarball. %v", err)
	}
	initrdAppend(iw, ktar)

	// convert init images to tarballs
	log.Infof("Add init containers:")
	for _, ii := range m.Init {
		if pull || enforceContentTrust(ii, &m.Trust) {
			log.Infof("Pull init image: %s", ii)
			err := dockerPull(ii, enforceContentTrust(ii, &m.Trust))
			if err != nil {
				log.Fatalf("Could not pull image %s: %v", ii, err)
			}
		}
		log.Infof("Process init image: %s", ii)
		init, err := ImageExtract(ii, "")
		if err != nil {
			log.Fatalf("Failed to build init tarball from %s: %v", ii, err)
		}
		buffer := bytes.NewBuffer(init)
		initrdAppend(iw, buffer)
	}

	log.Infof("Add onboot containers:")
	for i, image := range m.Onboot {
		if pull || enforceContentTrust(image.Image, &m.Trust) {
			log.Infof("  Pull: %s", image.Image)
			err := dockerPull(image.Image, enforceContentTrust(image.Image, &m.Trust))
			if err != nil {
				log.Fatalf("Could not pull image %s: %v", image.Image, err)
			}
		}
		log.Infof("  Create OCI config for %s", image.Image)
		config, err := ConfigToOCI(&image)
		if err != nil {
			log.Fatalf("Failed to create config.json for %s: %v", image.Image, err)
		}
		so := fmt.Sprintf("%03d", i)
		path := "containers/onboot/" + so + "-" + image.Name
		out, err := ImageBundle(path, image.Image, config)
		if err != nil {
			log.Fatalf("Failed to extract root filesystem for %s: %v", image.Image, err)
		}
		buffer := bytes.NewBuffer(out)
		initrdAppend(iw, buffer)
	}

	log.Infof("Add service containers:")
	for _, image := range m.Services {
		if pull || enforceContentTrust(image.Image, &m.Trust) {
			log.Infof("  Pull: %s", image.Image)
			err := dockerPull(image.Image, enforceContentTrust(image.Image, &m.Trust))
			if err != nil {
				log.Fatalf("Could not pull image %s: %v", image.Image, err)
			}
		}
		log.Infof("  Create OCI config for %s", image.Image)
		config, err := ConfigToOCI(&image)
		if err != nil {
			log.Fatalf("Failed to create config.json for %s: %v", image.Image, err)
		}
		path := "containers/services/" + image.Name
		out, err := ImageBundle(path, image.Image, config)
		if err != nil {
			log.Fatalf("Failed to extract root filesystem for %s: %v", image.Image, err)
		}
		buffer := bytes.NewBuffer(out)
		initrdAppend(iw, buffer)
	}

	// add files
	buffer, err := filesystem(m)
	if err != nil {
		log.Fatalf("failed to add filesystem parts: %v", err)
	}
	initrdAppend(iw, buffer)
	err = iw.Close()
	if err != nil {
		log.Fatalf("initrd close error: %v", err)
	}

	log.Infof("Create outputs:")
	err = outputs(m, name, bzimage.Bytes(), w.Bytes())
	if err != nil {
		log.Fatalf("Error writing outputs: %v", err)
	}
}

func untarKernel(buf *bytes.Buffer, bzimageName, ktarName string) (*bytes.Buffer, *bytes.Buffer, error) {
	tr := tar.NewReader(buf)

	var bzimage, ktar *bytes.Buffer

	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			log.Fatalln(err)
		}
		switch hdr.Name {
		case bzimageName:
			bzimage = new(bytes.Buffer)
			_, err := io.Copy(bzimage, tr)
			if err != nil {
				return nil, nil, err
			}
		case ktarName:
			ktar = new(bytes.Buffer)
			_, err := io.Copy(ktar, tr)
			if err != nil {
				return nil, nil, err
			}
		default:
			continue
		}
	}

	if ktar == nil || bzimage == nil {
		return nil, nil, errors.New("did not find bzImage and kernel.tar in tarball")
	}

	return bzimage, ktar, nil
}
<|endoftext|>


<commit_before>package sqlfmt_test

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"testing"

	"github.com/jackc/sqlfmt"
)

func TestIntegration(t *testing.T) {
	tests := []struct {
		inputFile          string
		expectedOutputFile string
	}{
		{
			inputFile:          "simple_select_without_from.sql",
			expectedOutputFile: "simple_select_without_from.fmt.sql",
		},
		{
			inputFile:          "simple_select_with_from.sql",
			expectedOutputFile: "simple_select_with_from.fmt.sql",
		},
		{
			inputFile:          "select_from_aliased.sql",
			expectedOutputFile: "select_from_aliased.fmt.sql",
		},
		{
			inputFile:          "simple_select_with_selection_alias.sql",
			expectedOutputFile: "simple_select_with_selection_alias.fmt.sql",
		},
		{
			inputFile:          "simple_select_with_selection_alias_no_as.sql",
			expectedOutputFile: "simple_select_with_selection_alias.fmt.sql",
		},
		{
			inputFile:          "select_table_dot_column.sql",
			expectedOutputFile: "select_table_dot_column.fmt.sql",
		},
		{
			inputFile:          "simple_select_literal_integer.sql",
			expectedOutputFile: "simple_select_literal_integer.fmt.sql",
		},
		{
			inputFile:          "simple_select_literal_text.sql",
			expectedOutputFile: "simple_select_literal_text.fmt.sql",
		},
		{
			inputFile:          "arithmetic_expression.sql",
			expectedOutputFile: "arithmetic_expression.fmt.sql",
		},
		{
			inputFile:          "paren_expression.sql",
			expectedOutputFile: "paren_expression.fmt.sql",
		},
		{
			inputFile:          "subselect_expression.sql",
			expectedOutputFile: "subselect_expression.fmt.sql",
		},
		{
			inputFile:          "comparison_expression.sql",
			expectedOutputFile: "comparison_expression.fmt.sql",
		},
		{
			inputFile:          "select_from_comma_join.sql",
			expectedOutputFile: "select_from_comma_join.fmt.sql",
		},
		{
			inputFile:          "select_from_cross_join.sql",
			expectedOutputFile: "select_from_cross_join.fmt.sql",
		},
		{
			inputFile:          "select_from_natural_join.sql",
			expectedOutputFile: "select_from_natural_join.fmt.sql",
		},
		{
			inputFile:          "select_from_join_using.sql",
			expectedOutputFile: "select_from_join_using.fmt.sql",
		},
		{
			inputFile:          "select_from_join_using_multiple.sql",
			expectedOutputFile: "select_from_join_using_multiple.fmt.sql",
		},
		{
			inputFile:          "select_from_join_on.sql",
			expectedOutputFile: "select_from_join_on.fmt.sql",
		},
		{
			inputFile:          "quoted_identifier.sql",
			expectedOutputFile: "quoted_identifier.fmt.sql",
		},
		{
			inputFile:          "boolean_binary_op.sql",
			expectedOutputFile: "boolean_binary_op.fmt.sql",
		},
		{
			inputFile:          "boolean_not.sql",
			expectedOutputFile: "boolean_not.fmt.sql",
		},
		{
			inputFile:          "select_where.sql",
			expectedOutputFile: "select_where.fmt.sql",
		},
		{
			inputFile:          "order.sql",
			expectedOutputFile: "order.fmt.sql",
		},
		{
			inputFile:          "order_column_num.sql",
			expectedOutputFile: "order_column_num.fmt.sql",
		},
		{
			inputFile:          "order_desc.sql",
			expectedOutputFile: "order_desc.fmt.sql",
		},
		{
			inputFile:          "order_multiple.sql",
			expectedOutputFile: "order_multiple.fmt.sql",
		},
		{
			inputFile:          "select_wrapped_by_parens.sql",
			expectedOutputFile: "select_wrapped_by_parens.fmt.sql",
		},
		{
			inputFile:          "order_nulls.sql",
			expectedOutputFile: "order_nulls.fmt.sql",
		},
		{
			inputFile:          "order_using.sql",
			expectedOutputFile: "order_using.fmt.sql",
		},
		{
			inputFile:          "distinct.sql",
			expectedOutputFile: "distinct.fmt.sql",
		},
		{
			inputFile:          "distinct_on.sql",
			expectedOutputFile: "distinct_on.fmt.sql",
		},
		{
			inputFile:          "group_by.sql",
			expectedOutputFile: "group_by.fmt.sql",
		},
		{
			inputFile:          "having.sql",
			expectedOutputFile: "having.fmt.sql",
		},
		{
			inputFile:          "limit.sql",
			expectedOutputFile: "limit.fmt.sql",
		},
		{
			inputFile:          "limit_fetch.sql",
			expectedOutputFile: "limit.fmt.sql",
		},
		{
			inputFile:          "offset.sql",
			expectedOutputFile: "offset.fmt.sql",
		},
		{
			inputFile:          "limit_offset.sql",
			expectedOutputFile: "limit_offset.fmt.sql",
		},
		{
			inputFile:          "offset_limit.sql",
			expectedOutputFile: "limit_offset.fmt.sql",
		},
		{
			inputFile:          "offset_fetch.sql",
			expectedOutputFile: "limit_offset.fmt.sql",
		},
		{
			inputFile:          "select_for_update.sql",
			expectedOutputFile: "select_for_update.fmt.sql",
		},
		{
			inputFile:          "select_for_no_key_update.sql",
			expectedOutputFile: "select_for_no_key_update.fmt.sql",
		},
		{
			inputFile:          "select_for_share.sql",
			expectedOutputFile: "select_for_share.fmt.sql",
		},
		{
			inputFile:          "select_for_key_share.sql",
			expectedOutputFile: "select_for_key_share.fmt.sql",
		},
		{
			inputFile:          "select_for_update_of.sql",
			expectedOutputFile: "select_for_update_of.fmt.sql",
		},
		{
			inputFile:          "select_for_update_nowait.sql",
			expectedOutputFile: "select_for_update_nowait.fmt.sql",
		},
		{
			inputFile:          "select_star.sql",
			expectedOutputFile: "select_star.fmt.sql",
		},
		{
			inputFile:          "select_table_dot_star.sql",
			expectedOutputFile: "select_table_dot_star.fmt.sql",
		},
		{
			inputFile:          "table.sql",
			expectedOutputFile: "table.fmt.sql",
		},
		{
			inputFile:          "table_star.sql",
			expectedOutputFile: "table_star.fmt.sql",
		},
		{
			inputFile:          "table_only.sql",
			expectedOutputFile: "table_only.fmt.sql",
		},
		{
			inputFile:          "table_only_paren.sql",
			expectedOutputFile: "table_only.fmt.sql",
		},
		{
			inputFile:          "case_full.sql",
			expectedOutputFile: "case_full.fmt.sql",
		},
		{
			inputFile:          "case_implicit.sql",
			expectedOutputFile: "case_implicit.fmt.sql",
		},
		{
			inputFile:          "typecast.sql",
			expectedOutputFile: "typecast.fmt.sql",
		},
		{
			inputFile:          "unary.sql",
			expectedOutputFile: "unary.fmt.sql",
		},
		{
			inputFile:          "values.sql",
			expectedOutputFile: "values.fmt.sql",
		},
		{
			inputFile:          "values_order.sql",
			expectedOutputFile: "values_order.fmt.sql",
		},
		{
			inputFile:          "values_default.sql",
			expectedOutputFile: "values_default.fmt.sql",
		},
		{
			inputFile:          "collate.sql",
			expectedOutputFile: "collate.fmt.sql",
		},
		{
			inputFile:          "at_time_zone.sql",
			expectedOutputFile: "at_time_zone.fmt.sql",
		},
		{
			inputFile:          "like.sql",
			expectedOutputFile: "like.fmt.sql",
		},
		{
			inputFile:          "is_null.sql",
			expectedOutputFile: "is_null.fmt.sql",
		},
		{
			inputFile:          "is_bool_op.sql",
			expectedOutputFile: "is_bool_op.fmt.sql",
		},
		{
			inputFile:          "is_distinct_from.sql",
			expectedOutputFile: "is_distinct_from.fmt.sql",
		},
		{
			inputFile:          "union.sql",
			expectedOutputFile: "union.fmt.sql",
		},
		{
			inputFile:          "intersect.sql",
			expectedOutputFile: "intersect.fmt.sql",
		},
		{
			inputFile:          "except.sql",
			expectedOutputFile: "except.fmt.sql",
		},
		{
			inputFile:          "function_call_without_args.sql",
			expectedOutputFile: "function_call_without_args.fmt.sql",
		},
		{
			inputFile:          "function_call_with_star_arg.sql",
			expectedOutputFile: "function_call_with_star_arg.fmt.sql",
		},
		{
			inputFile:          "function_call_with_positional_args.sql",
			expectedOutputFile: "function_call_with_positional_args.fmt.sql",
		},
		{
			inputFile:          "function_call_with_pg_named_args.sql",
			expectedOutputFile: "function_call_with_pg_named_args.fmt.sql",
		},
		{
			inputFile:          "function_call_with_sql_named_args.sql",
			expectedOutputFile: "function_call_with_sql_named_args.fmt.sql",
		},
		{
			inputFile:          "function_call_with_order.sql",
			expectedOutputFile: "function_call_with_order.fmt.sql", // TODO - fix formatting when order by is inside function call
		},
		{
			inputFile:          "function_call_with_all.sql",
			expectedOutputFile: "function_call_with_all.fmt.sql",
		},
		{
			inputFile:          "function_call_with_distinct.sql",
			expectedOutputFile: "function_call_with_distinct.fmt.sql",
		},
		{
			inputFile:          "function_call_with_filter.sql",
			expectedOutputFile: "function_call_with_filter.fmt.sql",
		},
		{
			inputFile:          "null.sql",
			expectedOutputFile: "null.fmt.sql",
		},
		{
			inputFile:          "window_function.sql",
			expectedOutputFile: "window_function.fmt.sql",
		},
		{
			inputFile:          "window_function_partition_by.sql",
			expectedOutputFile: "window_function_partition_by.fmt.sql",
		},
		{
			inputFile:          "window_function_order_by.sql", // TODO - fix formatting when order by is inside function call
			expectedOutputFile: "window_function_order_by.fmt.sql",
		},
		{
			inputFile:          "window_function_named.sql",
			expectedOutputFile: "window_function_named.fmt.sql",
		},
		{
			inputFile:          "window_function_named_multiple.sql",
			expectedOutputFile: "window_function_named_multiple.fmt.sql",
		},
		{
			inputFile:          "window_function_frame.sql",
			expectedOutputFile: "window_function_frame.fmt.sql",
		},
		{
			inputFile:          "exists.sql",
			expectedOutputFile: "exists.fmt.sql",
		},
		{
			inputFile:          "array_constructor.sql",
			expectedOutputFile: "array_constructor.fmt.sql",
		},
		{
			inputFile:          "array_index.sql",
			expectedOutputFile: "array_index.fmt.sql",
		},
		{
			inputFile:          "array_slice.sql",
			expectedOutputFile: "array_slice.fmt.sql",
		},
	}

	for i, tt := range tests {
		input, err := ioutil.ReadFile(path.Join("testdata", tt.inputFile))
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		expected, err := ioutil.ReadFile(path.Join("testdata", tt.expectedOutputFile))
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		lexer := sqlfmt.NewSqlLexer(string(input))
		stmt, err := sqlfmt.Parse(lexer)
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		var outBuf bytes.Buffer
		r := sqlfmt.NewTextRenderer(&outBuf)
		stmt.RenderTo(r)

		if outBuf.String() != string(expected) {
			actualFileName := path.Join("tmp", fmt.Sprintf("%d.sql", i))
			err = ioutil.WriteFile(actualFileName, outBuf.Bytes(), os.ModePerm)
			if err != nil {
				t.Fatal(err)
			}

			t.Errorf("%d. Given %s, did not receive %s. Unexpected output written to %s", i, tt.inputFile, tt.expectedOutputFile, actualFileName)
		}
	}
}
<commit_msg>Compress test table<commit_after>package sqlfmt_test

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"testing"

	"github.com/jackc/sqlfmt"
)

func TestIntegration(t *testing.T) {
	tests := []struct {
		inputFile          string
		expectedOutputFile string
	}{
		{inputFile: "simple_select_without_from.sql"},
		{inputFile: "simple_select_with_from.sql"},
		{inputFile: "select_from_aliased.sql"},
		{inputFile: "simple_select_with_selection_alias.sql"},
		{
			inputFile:          "simple_select_with_selection_alias_no_as.sql",
			expectedOutputFile: "simple_select_with_selection_alias.fmt.sql",
		},
		{inputFile: "select_table_dot_column.sql"},
		{inputFile: "simple_select_literal_integer.sql"},
		{inputFile: "simple_select_literal_text.sql"},
		{inputFile: "arithmetic_expression.sql"},
		{inputFile: "paren_expression.sql"},
		{inputFile: "subselect_expression.sql"},
		{inputFile: "comparison_expression.sql"},
		{inputFile: "select_from_comma_join.sql"},
		{inputFile: "select_from_cross_join.sql"},
		{inputFile: "select_from_natural_join.sql"},
		{inputFile: "select_from_join_using.sql"},
		{inputFile: "select_from_join_using_multiple.sql"},
		{inputFile: "select_from_join_on.sql"},
		{inputFile: "quoted_identifier.sql"},
		{inputFile: "boolean_binary_op.sql"},
		{inputFile: "boolean_not.sql"},
		{inputFile: "select_where.sql"},
		{inputFile: "order.sql"},
		{inputFile: "order_column_num.sql"},
		{inputFile: "order_desc.sql"},
		{inputFile: "order_multiple.sql"},
		{inputFile: "select_wrapped_by_parens.sql"},
		{inputFile: "order_nulls.sql"},
		{inputFile: "order_using.sql"},
		{inputFile: "distinct.sql"},
		{inputFile: "distinct_on.sql"},
		{inputFile: "group_by.sql"},
		{inputFile: "having.sql"},
		{inputFile: "limit.sql"},
		{
			inputFile:          "limit_fetch.sql",
			expectedOutputFile: "limit.fmt.sql",
		},
		{inputFile: "offset.sql"},
		{inputFile: "limit_offset.sql"},
		{
			inputFile:          "offset_limit.sql",
			expectedOutputFile: "limit_offset.fmt.sql",
		},
		{
			inputFile:          "offset_fetch.sql",
			expectedOutputFile: "limit_offset.fmt.sql",
		},
		{inputFile: "select_for_update.sql"},
		{inputFile: "select_for_no_key_update.sql"},
		{inputFile: "select_for_share.sql"},
		{inputFile: "select_for_key_share.sql"},
		{inputFile: "select_for_update_of.sql"},
		{inputFile: "select_for_update_nowait.sql"},
		{inputFile: "select_star.sql"},
		{inputFile: "select_table_dot_star.sql"},
		{inputFile: "table.sql"},
		{inputFile: "table_star.sql"},
		{inputFile: "table_only.sql"},
		{
			inputFile:          "table_only_paren.sql",
			expectedOutputFile: "table_only.fmt.sql",
		},
		{inputFile: "case_full.sql"},
		{inputFile: "case_implicit.sql"},
		{inputFile: "typecast.sql"},
		{inputFile: "unary.sql"},
		{inputFile: "values.sql"},
		{inputFile: "values_order.sql"},
		{inputFile: "values_default.sql"},
		{inputFile: "collate.sql"},
		{inputFile: "at_time_zone.sql"},
		{inputFile: "like.sql"},
		{inputFile: "is_null.sql"},
		{inputFile: "is_bool_op.sql"},
		{inputFile: "is_distinct_from.sql"},
		{inputFile: "union.sql"},
		{inputFile: "intersect.sql"},
		{inputFile: "except.sql"},
		{inputFile: "function_call_without_args.sql"},
		{inputFile: "function_call_with_star_arg.sql"},
		{inputFile: "function_call_with_positional_args.sql"},
		{inputFile: "function_call_with_pg_named_args.sql"},
		{inputFile: "function_call_with_sql_named_args.sql"},
		{inputFile: "function_call_with_order.sql"}, // TODO - fix formatting when order by is inside function call
		{inputFile: "function_call_with_all.sql"},
		{inputFile: "function_call_with_distinct.sql"},
		{inputFile: "function_call_with_filter.sql"},
		{inputFile: "null.sql"},
		{inputFile: "window_function.sql"},
		{inputFile: "window_function_partition_by.sql"},
		{inputFile: "window_function_order_by.sql"}, // TODO - fix formatting when order by is inside function call
		{inputFile: "window_function_named.sql"},
		{inputFile: "window_function_named_multiple.sql"},
		{inputFile: "window_function_frame.sql"},
		{inputFile: "exists.sql"},
		{inputFile: "array_constructor.sql"},
		{inputFile: "array_index.sql"},
		{inputFile: "array_slice.sql"},
	}

	for i, tt := range tests {
		input, err := ioutil.ReadFile(path.Join("testdata", tt.inputFile))
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		if tt.expectedOutputFile == "" {
			tt.expectedOutputFile = tt.inputFile[:len(tt.inputFile)-3] + "fmt.sql"
		}

		expected, err := ioutil.ReadFile(path.Join("testdata", tt.expectedOutputFile))
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		lexer := sqlfmt.NewSqlLexer(string(input))
		stmt, err := sqlfmt.Parse(lexer)
		if err != nil {
			t.Errorf("%d. %v", i, err)
			continue
		}

		var outBuf bytes.Buffer
		r := sqlfmt.NewTextRenderer(&outBuf)
		stmt.RenderTo(r)

		if outBuf.String() != string(expected) {
			actualFileName := path.Join("tmp", fmt.Sprintf("%d.sql", i))
			err = ioutil.WriteFile(actualFileName, outBuf.Bytes(), os.ModePerm)
			if err != nil {
				t.Fatal(err)
			}

			t.Errorf("%d. Given %s, did not receive %s. Unexpected output written to %s", i, tt.inputFile, tt.expectedOutputFile, actualFileName)
		}
	}
}
<|endoftext|>


<commit_before>package cui

import (
	"context"
	"fmt"

	"github.com/gopasspw/gopass/internal/termio"
	"github.com/gopasspw/gopass/pkg/ctxutil"
)

// GetSelection show a navigateable multiple-choice list to the user
// and returns the selected entry along with the action
func GetSelection(ctx context.Context, prompt string, choices []string) (string, int) {
	if ctxutil.IsAlwaysYes(ctx) || !ctxutil.IsInteractive(ctx) {
		return "impossible", 0
	}
	for i, c := range choices {
		fmt.Printf("[%  d] %s\n", i, c)
	}
	fmt.Println()
	var i int
	for {
		var err error
		i, err = termio.AskForInt(ctx, prompt, 0)
		if err == nil && i < len(choices) {
			break
		}
		if err == termio.ErrAborted {
			return "aborted", 0
		}
		fmt.Println(err.Error())
	}
	fmt.Println(i)
	return "default", i
}
<commit_msg>Fix nil error panic (#1604)<commit_after>package cui

import (
	"context"
	"errors"
	"fmt"

	"github.com/gopasspw/gopass/internal/termio"
	"github.com/gopasspw/gopass/pkg/ctxutil"
)

// GetSelection show a navigateable multiple-choice list to the user
// and returns the selected entry along with the action
func GetSelection(ctx context.Context, prompt string, choices []string) (string, int) {
	if ctxutil.IsAlwaysYes(ctx) || !ctxutil.IsInteractive(ctx) {
		return "impossible", 0
	}
	for i, c := range choices {
		fmt.Printf("[%  d] %s\n", i, c)
	}
	fmt.Println()
	var i int
	for {
		var err error
		i, err = termio.AskForInt(ctx, prompt, 0)
		if err == nil && i < len(choices) {
			break
		}
		if errors.Is(err, termio.ErrAborted) {
			return "aborted", 0
		}
		if err != nil {
			fmt.Println(err.Error())
		}
	}
	fmt.Println(i)
	return "default", i
}
<|endoftext|>


<commit_before>package internal

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
)

func initRequest(req *http.Request) {
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("User-Agent", "Sailabove sail CLI/"+VERSION)
}

func getHTTPClient() *http.Client {
	tr := &http.Transport{}
	return &http.Client{Transport: tr}
}

// GetWantJSON GET on path and return []byte of JSON
func GetWantJSON(path string) []byte {
	return ReqWant("GET", http.StatusOK, path, nil)
}

// PostWantJSON POST on path and return []byte of JSON
func PostWantJSON(path string) []byte {
	return ReqWant("POST", http.StatusCreated, path, nil)
}

// PostBodyWantJSON POST a body on path and return []byte of JSON
func PostBodyWantJSON(path string, body []byte) []byte {
	return ReqWant("POST", http.StatusCreated, path, body)
}

// DeleteWantJSON on path and return []byte of JSON
func DeleteWantJSON(path string) []byte {
	return ReqWant("DELETE", http.StatusOK, path, nil)
}

// DeleteBodyWantJSON on path and return []byte of JSON
func DeleteBodyWantJSON(path string, body []byte) []byte {
	return ReqWant("DELETE", http.StatusOK, path, body)
}

// ReqWantJSON requests with a method on a path, check wantCode and returns []byte of JSON
func ReqWantJSON(method string, wantCode int, path string, body []byte) []byte {
	return ReqWant(method, wantCode, path, body)
}

// StreamWant request a path with method and stream result
func StreamWant(method string, wantCode int, path string, jsonStr []byte) {
	apiRequest(method, wantCode, path, jsonStr, true)
}

// StreamPrint opens a stream and print it in a goroutine
func StreamPrint(method string, path string, args []byte, mods ...RequestModifier) {
	reader, _, err := Stream(method, path, args, mods...)

	if err != nil {
		Exit("Error while attach: %s\n", err)
	}

	go func(stream io.ReadCloser) {
		DisplayStream(reader)
	}(reader)
}

// ReqWant requests with a method on a path, check wantCode and returns []byte
func ReqWant(method string, wantCode int, path string, jsonStr []byte) []byte {
	return apiRequest(method, wantCode, path, jsonStr, false)
}

// apiRequest helper, issue the request and consume stream if requested. Otherwise, return full body
func apiRequest(method string, wantCode int, path string, jsonStr []byte, stream bool) []byte {
	bodyStream, code, err := doRequest(method, path, jsonStr)
	Check(err)

	defer bodyStream.Close()

	if stream && code == wantCode {
		DisplayStream(bodyStream)
		return nil
	}

	var body []byte
	body, err = ioutil.ReadAll(bodyStream)
	Check(err)

	if code != wantCode {
		if err == nil {
			FormatOutputDef(body)
		}
		os.Exit(1)
	}

	if Verbose {
		fmt.Fprintf(os.Stderr, "Response Body: %s\n", string(body))
	}
	return body

}

// RequestModifier is used to modify behavior of Request and Steam functions
type RequestModifier func(req *http.Request)

// SetHeader modify headers of http.Request
func SetHeader(key, value string) RequestModifier {
	return func(req *http.Request) {
		req.Header.Set(key, value)
	}
}

// Request executes an authentificated HTTP request on $path given $method and $args
func Request(method string, path string, args []byte, mods ...RequestModifier) ([]byte, int, error) {

	respBody, code, err := doRequest(method, path, args, mods...)
	if err != nil {
		return nil, 0, err
	}
	defer respBody.Close()

	var body []byte
	body, err = ioutil.ReadAll(respBody)
	if err != nil {
		return nil, 0, err
	}

	if Verbose {
		fmt.Fprintf(os.Stderr, "Response Body: %s\n", body)
	}

	return body, code, nil
}

// Stream makes an authenticated http request and return io.ReadCloser
func Stream(method string, path string, args []byte, mods ...RequestModifier) (io.ReadCloser, int, error) {
	return doRequest(method, path, args, mods...)
}

//doRequest builds the request and return io.ReadCloser
func doRequest(method string, path string, args []byte, mods ...RequestModifier) (io.ReadCloser, int, error) {

	err := ReadConfig()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error reading configuration: %s\n", err)
		os.Exit(1)
	}

	var req *http.Request
	if args != nil {
		req, _ = http.NewRequest(method, Host+path, bytes.NewReader(args))
	} else {
		req, _ = http.NewRequest(method, Host+path, nil)
	}
	initRequest(req)

	for i := range mods {
		mods[i](req)
	}

	for key, val := range Headers {
		if Verbose {
			fmt.Fprintf(os.Stderr, "Request header: %s=%s\n", key, val)
		}
		req.Header.Set(key, val)
	}

	req.SetBasicAuth(User, Password)
	resp, err := getHTTPClient().Do(req)
	if err != nil {
		return nil, 0, err
	}

	if Verbose {
		fmt.Fprintf(os.Stderr, "Response Status: %s\n", resp.Status)
		fmt.Fprintf(os.Stderr, "Request path: %s\n", Host+path)
		fmt.Fprintf(os.Stderr, "Request Headers: %s\n", req.Header)
		fmt.Fprintf(os.Stderr, "Request Body: %s\n", string(args))
		fmt.Fprintf(os.Stderr, "Response Headers: %s\n", resp.Header)
	}

	return resp.Body, resp.StatusCode, nil
}

// DisplayStream decode each line from http buffer and print either message or error. Return last read line
func DisplayStream(buffer io.ReadCloser) ([]byte, error) {
	reader := bufio.NewReader(buffer)

	for {
		line, err := reader.ReadBytes('\n')
		if Verbose {
			fmt.Fprintf(os.Stderr, "Received message: %v\n", string(line))
		}

		// Progress message
		m := DecodeMessage(line)
		if m != nil {
			fmt.Fprintln(os.Stderr, m.Message)
			continue
		}

		// Error message (will be last message)
		e := DecodeError(line)
		if e != nil {
			return line, fmt.Errorf(e.Message)
		}

		// Final message
		if err == io.EOF {
			return line, nil
		}

		// Default
		fmt.Printf(string(line))
	}
}

// GetListApplications returns list of applications, GET on /applications
func GetListApplications(args []string) []string {
	apps := []string{}
	if len(args) == 0 {
		b := ReqWant("GET", http.StatusOK, "/applications", nil)
		err := json.Unmarshal(b, &apps)
		Check(err)
	}
	return apps
}

// Check checks e and panic if not nil
func Check(err error) {
	if err != nil {
		if Verbose {
			panic(err)
		}
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		os.Exit(1)
	}
}
<commit_msg>fix: display error when stream ends with error<commit_after>package internal

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
)

func initRequest(req *http.Request) {
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("User-Agent", "Sailabove sail CLI/"+VERSION)
}

func getHTTPClient() *http.Client {
	tr := &http.Transport{}
	return &http.Client{Transport: tr}
}

// GetWantJSON GET on path and return []byte of JSON
func GetWantJSON(path string) []byte {
	return ReqWant("GET", http.StatusOK, path, nil)
}

// PostWantJSON POST on path and return []byte of JSON
func PostWantJSON(path string) []byte {
	return ReqWant("POST", http.StatusCreated, path, nil)
}

// PostBodyWantJSON POST a body on path and return []byte of JSON
func PostBodyWantJSON(path string, body []byte) []byte {
	return ReqWant("POST", http.StatusCreated, path, body)
}

// DeleteWantJSON on path and return []byte of JSON
func DeleteWantJSON(path string) []byte {
	return ReqWant("DELETE", http.StatusOK, path, nil)
}

// DeleteBodyWantJSON on path and return []byte of JSON
func DeleteBodyWantJSON(path string, body []byte) []byte {
	return ReqWant("DELETE", http.StatusOK, path, body)
}

// ReqWantJSON requests with a method on a path, check wantCode and returns []byte of JSON
func ReqWantJSON(method string, wantCode int, path string, body []byte) []byte {
	return ReqWant(method, wantCode, path, body)
}

// StreamWant request a path with method and stream result
func StreamWant(method string, wantCode int, path string, jsonStr []byte) {
	apiRequest(method, wantCode, path, jsonStr, true)
}

// StreamPrint opens a stream and print it in a goroutine
func StreamPrint(method string, path string, args []byte, mods ...RequestModifier) {
	reader, _, err := Stream(method, path, args, mods...)

	if err != nil {
		Exit("Error while attach: %s\n", err)
	}

	go func(stream io.ReadCloser) {
		DisplayStream(reader)
	}(reader)
}

// ReqWant requests with a method on a path, check wantCode and returns []byte
func ReqWant(method string, wantCode int, path string, jsonStr []byte) []byte {
	return apiRequest(method, wantCode, path, jsonStr, false)
}

// apiRequest helper, issue the request and consume stream if requested. Otherwise, return full body
func apiRequest(method string, wantCode int, path string, jsonStr []byte, stream bool) []byte {
	bodyStream, code, err := doRequest(method, path, jsonStr)
	Check(err)

	defer bodyStream.Close()

	if stream && code == wantCode {
		DisplayStream(bodyStream)
		return nil
	}

	var body []byte
	body, err = ioutil.ReadAll(bodyStream)
	Check(err)

	if code != wantCode {
		if err == nil {
			FormatOutputDef(body)
		}
		os.Exit(1)
	}

	if Verbose {
		fmt.Fprintf(os.Stderr, "Response Body: %s\n", string(body))
	}
	return body

}

// RequestModifier is used to modify behavior of Request and Steam functions
type RequestModifier func(req *http.Request)

// SetHeader modify headers of http.Request
func SetHeader(key, value string) RequestModifier {
	return func(req *http.Request) {
		req.Header.Set(key, value)
	}
}

// Request executes an authentificated HTTP request on $path given $method and $args
func Request(method string, path string, args []byte, mods ...RequestModifier) ([]byte, int, error) {

	respBody, code, err := doRequest(method, path, args, mods...)
	if err != nil {
		return nil, 0, err
	}
	defer respBody.Close()

	var body []byte
	body, err = ioutil.ReadAll(respBody)
	if err != nil {
		return nil, 0, err
	}

	if Verbose {
		fmt.Fprintf(os.Stderr, "Response Body: %s\n", body)
	}

	return body, code, nil
}

// Stream makes an authenticated http request and return io.ReadCloser
func Stream(method string, path string, args []byte, mods ...RequestModifier) (io.ReadCloser, int, error) {
	return doRequest(method, path, args, mods...)
}

//doRequest builds the request and return io.ReadCloser
func doRequest(method string, path string, args []byte, mods ...RequestModifier) (io.ReadCloser, int, error) {

	err := ReadConfig()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error reading configuration: %s\n", err)
		os.Exit(1)
	}

	var req *http.Request
	if args != nil {
		req, _ = http.NewRequest(method, Host+path, bytes.NewReader(args))
	} else {
		req, _ = http.NewRequest(method, Host+path, nil)
	}
	initRequest(req)

	for i := range mods {
		mods[i](req)
	}

	for key, val := range Headers {
		if Verbose {
			fmt.Fprintf(os.Stderr, "Request header: %s=%s\n", key, val)
		}
		req.Header.Set(key, val)
	}

	req.SetBasicAuth(User, Password)
	resp, err := getHTTPClient().Do(req)
	if err != nil {
		return nil, 0, err
	}

	if Verbose {
		fmt.Fprintf(os.Stderr, "Response Status: %s\n", resp.Status)
		fmt.Fprintf(os.Stderr, "Request path: %s\n", Host+path)
		fmt.Fprintf(os.Stderr, "Request Headers: %s\n", req.Header)
		fmt.Fprintf(os.Stderr, "Request Body: %s\n", string(args))
		fmt.Fprintf(os.Stderr, "Response Headers: %s\n", resp.Header)
	}

	return resp.Body, resp.StatusCode, nil
}

// DisplayStream decode each line from http buffer and print either message or error. Return last read line
func DisplayStream(buffer io.ReadCloser) ([]byte, error) {
	reader := bufio.NewReader(buffer)

	for {
		line, err := reader.ReadBytes('\n')
		if Verbose {
			fmt.Fprintf(os.Stderr, "Received message: %v\n", string(line))
		}

		// Progress message
		m := DecodeMessage(line)
		if m != nil {
			fmt.Fprintln(os.Stderr, m.Message)
			continue
		}

		// Error message (will be last message)
		e := DecodeError(line)
		if e != nil {
			fmt.Fprintf(os.Stderr, "Error: %s\n", line)
			return line, fmt.Errorf(e.Message)
		}

		// Final message
		if err == io.EOF {
			return line, nil
		}

		// Default
		fmt.Printf(string(line))
	}
}

// GetListApplications returns list of applications, GET on /applications
func GetListApplications(args []string) []string {
	apps := []string{}
	if len(args) == 0 {
		b := ReqWant("GET", http.StatusOK, "/applications", nil)
		err := json.Unmarshal(b, &apps)
		Check(err)
	}
	return apps
}

// Check checks e and panic if not nil
func Check(err error) {
	if err != nil {
		if Verbose {
			panic(err)
		}
		fmt.Fprintf(os.Stderr, "Error: %s\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// 2 january 2016
package ui

import (
	"fmt"
	"runtime"
	"sync"
)

// #cgo CFLAGS: -mmacosx-version-min=10.11 -DMACOSX_DEPLOYMENT_TARGET=10.11
// #cgo LDFLAGS: -mmacosx-version-min=10.11 -lobjc -framework Foundation -framework AppKit -framework WebKit -framework CoreServices -lpthread
// #include "ui.h"
import "C"

func Main(f func()) error {
	err := make(chan error)
	go main(f, err)
	return <-err
}

func main(f func(), errchan chan error) {
	runtime.LockOSThread()
	e := C.initUIThread()
	if e != nil {
		errchan <- fmt.Errorf("%s", C.GoString(e))
		return
	}
	QueueMain(f)
	C.runUIThread()
	errchan <- nil
}

func Quit() {
	C.stopUIThread()
}

// These prevent the passing of Go functions into C land.
// TODO make an actual sparse list instead of this monotonic map thingy
var (
	qmmap = make(map[C.uintptr_t]func())
	qmcurrent = C.uintptr_t(0)
	qmlock sync.Mutex
)

func QueueMain(f func()) {
	qmlock.Lock()
	defer qmlock.Unlock()

	n := C.uintptr_t(0)
	for {
		n = qmcurrent
		qmcurrent++
		if qmmap[n] == nil {
			break
		}
	}
	qmmap[n] = f
	C.queueUIThread(n)
}

//export doQueued
func doQueued(n C.uintptr_t) {
	qmlock.Lock()

	f := qmmap[n]
	delete(qmmap, n)

	// allow QueueMain() to be called by a queued function
	qmlock.Unlock()

	f()
}

// no need to lock this; this API is only safe on the main thread
var shouldQuitFunc func() bool

func OnShouldQuit(f func() bool) {
	shouldQuitFunc = f
}

//export shouldQuit
func shouldQuit() C.int {
	if shouldQuitFunc == nil {
		return 0
	}
	return frombool(shouldQuitFunc())
}
<commit_msg>More TODOs.<commit_after>// 2 january 2016
package ui

// TODOs:
// - make sure all object lifetimes are correct (alloc/init vs typeName)

import (
	"fmt"
	"runtime"
	"sync"
)

// #cgo CFLAGS: -mmacosx-version-min=10.11 -DMACOSX_DEPLOYMENT_TARGET=10.11
// #cgo LDFLAGS: -mmacosx-version-min=10.11 -lobjc -framework Foundation -framework AppKit -framework WebKit -framework CoreServices -lpthread
// #include "ui.h"
import "C"

func Main(f func()) error {
	err := make(chan error)
	go main(f, err)
	return <-err
}

func main(f func(), errchan chan error) {
	runtime.LockOSThread()
	e := C.initUIThread()
	if e != nil {
		errchan <- fmt.Errorf("%s", C.GoString(e))
		return
	}
	QueueMain(f)
	C.runUIThread()
	errchan <- nil
}

func Quit() {
	C.stopUIThread()
}

// These prevent the passing of Go functions into C land.
// TODO make an actual sparse list instead of this monotonic map thingy
var (
	qmmap = make(map[C.uintptr_t]func())
	qmcurrent = C.uintptr_t(0)
	qmlock sync.Mutex
)

func QueueMain(f func()) {
	qmlock.Lock()
	defer qmlock.Unlock()

	n := C.uintptr_t(0)
	for {
		n = qmcurrent
		qmcurrent++
		if qmmap[n] == nil {
			break
		}
	}
	qmmap[n] = f
	C.queueUIThread(n)
}

//export doQueued
func doQueued(n C.uintptr_t) {
	qmlock.Lock()

	f := qmmap[n]
	delete(qmmap, n)

	// allow QueueMain() to be called by a queued function
	qmlock.Unlock()

	f()
}

// no need to lock this; this API is only safe on the main thread
var shouldQuitFunc func() bool

func OnShouldQuit(f func() bool) {
	shouldQuitFunc = f
}

//export shouldQuit
func shouldQuit() C.int {
	if shouldQuitFunc == nil {
		return 0
	}
	return frombool(shouldQuitFunc())
}
<|endoftext|>


<commit_before>package wspacego

import (
	. "github.com/r7kamura/gospel"
	"path"
	"runtime"
	"testing"
)

func TestInterpretor(t *testing.T) {
	Describe(t, "インタープリターのテスト", func() {
		data := []byte{'A', ' ', 'B', '\t', '\r', '\n'}
		Context("インスタンス生成", func() {
			It("インスタンスが生成できること", func() {
				actual := NewInterpreter(data)
				Expect(actual).To(Exist)
				Expect(actual.origin).To(Equal, data)
			})
		})
		Context("不要な文字を排除する関数", func() {
			It("不要なデータ以外排除されていること", func() {
				sut := NewInterpreter(data)
				sut.filter()
				Expect(sut.source).To(Equal, []byte{' ', '\t', '\n'})
			})
			It("不要なデータ以外排除されていること（改行を増やす）", func() {
				data = append(data, '\n')
				sut := NewInterpreter(data)
				sut.filter()
				Expect(sut.source).To(Equal, []byte{' ', '\t', '\n', '\n'})
			})
		})
		Context("ソースファイルをコマンドリストに変換する関数", func() {
			It("スタックに１をプッシュするコマンドが作成されること", func() {
				data = []byte{'P', 'u', 's', 'h', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommandWithParam("stack", "push", 1))
			})
			It("スタックをコピーするコマンドが作成されること", func() {
				data = []byte{'C', 'o', 'p', 'y', ' ', '\n', ' '}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("stack", "copy"))
			})
			It("スタックを入れ替えるコマンドが作成されること", func() {
				data = []byte{'S', 'w', 'a', 'p', ' ', '\n', '\t'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("stack", "swap"))
			})
			It("スタックを削除するコマンドが作成されること", func() {
				data = []byte{'R', 'e', 'm', 'o', 'v', 'e', ' ', '\n', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("stack", "remove"))
			})
			It("定義されていない命令が指定されたときにundefinedの命令が作成されること", func() {
				data = []byte{'u', 'n', 'k', 'n', 'o', 'w', 'n', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				err := sut.parseCommands()
				Expect(sut.commands).To(NotExist)
				Expect(err).To(Exist)
			})
			It("ラベルを定義するコマンドが作成されること", func() {
				data = []byte{'L', 'a', 'b', 'l', '\n', ' ', ' ', '\t', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("label", "1001"))
			})
			It("ラベルを呼び出すコマンドが作成されること", func() {
				data = []byte{'C', 'a', 'l', 'l', '\n', ' ', '\t', '\t', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("call", "1001"))
			})
			It("ラベルを呼び出すコマンドが作成されること", func() {
				data = []byte{'G', 'o', 't', 'o', '\n', ' ', '\n', '\t', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("goto", "1001"))
			})
		})
	})
}

func current_dir() string {
	_, fpath, _, _ := runtime.Caller(0)
	return path.Dir(fpath)
}
<commit_msg>スタックの値が０のときにgotoを実行する命令を実装<commit_after>package wspacego

import (
	. "github.com/r7kamura/gospel"
	"path"
	"runtime"
	"testing"
)

func TestInterpretor(t *testing.T) {
	Describe(t, "インタープリターのテスト", func() {
		data := []byte{'A', ' ', 'B', '\t', '\r', '\n'}
		Context("インスタンス生成", func() {
			It("インスタンスが生成できること", func() {
				actual := NewInterpreter(data)
				Expect(actual).To(Exist)
				Expect(actual.origin).To(Equal, data)
			})
		})
		Context("不要な文字を排除する関数", func() {
			It("不要なデータ以外排除されていること", func() {
				sut := NewInterpreter(data)
				sut.filter()
				Expect(sut.source).To(Equal, []byte{' ', '\t', '\n'})
			})
			It("不要なデータ以外排除されていること（改行を増やす）", func() {
				data = append(data, '\n')
				sut := NewInterpreter(data)
				sut.filter()
				Expect(sut.source).To(Equal, []byte{' ', '\t', '\n', '\n'})
			})
		})
		Context("ソースファイルをコマンドリストに変換する関数", func() {
			It("スタックに１をプッシュするコマンドが作成されること", func() {
				data = []byte{'P', 'u', 's', 'h', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommandWithParam("stack", "push", 1))
			})
			It("スタックをコピーするコマンドが作成されること", func() {
				data = []byte{'C', 'o', 'p', 'y', ' ', '\n', ' '}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("stack", "copy"))
			})
			It("スタックを入れ替えるコマンドが作成されること", func() {
				data = []byte{'S', 'w', 'a', 'p', ' ', '\n', '\t'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("stack", "swap"))
			})
			It("スタックを削除するコマンドが作成されること", func() {
				data = []byte{'R', 'e', 'm', 'o', 'v', 'e', ' ', '\n', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("stack", "remove"))
			})
			It("定義されていない命令が指定されたときにundefinedの命令が作成されること", func() {
				data = []byte{'u', 'n', 'k', 'n', 'o', 'w', 'n', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				err := sut.parseCommands()
				Expect(sut.commands).To(NotExist)
				Expect(err).To(Exist)
			})
			It("ラベルを定義するコマンドが作成されること", func() {
				data = []byte{'L', 'a', 'b', 'l', '\n', ' ', ' ', '\t', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("label", "1001"))
			})
			It("ラベルを呼び出すコマンドが作成されること", func() {
				data = []byte{'C', 'a', 'l', 'l', '\n', ' ', '\t', '\t', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("call", "1001"))
			})
			It("ラベルを呼び出すコマンドが作成されること", func() {
				data = []byte{'G', 'o', 't', 'o', '\n', ' ', '\n', '\t', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("goto", "1001"))
			})
			It("スタックの値が０のときにラベルを呼び出すコマンドが作成されること", func() {
				data = []byte{'G', 'o', 't', 'o', '\n', '\t', ' ', '\t', ' ', ' ', '\t', '\n'}
				sut := NewInterpreter(data)
				sut.filter()
				sut.parseCommands()
				Expect(sut.commands).To(Exist)
				Expect(sut.commands.Len()).To(Equal, 1)
				Expect(sut.commands.Get(1)).To(Equal, NewSubCommand("if stack==0 then goto", "1001"))
			})
		})
	})
}

func current_dir() string {
	_, fpath, _, _ := runtime.Caller(0)
	return path.Dir(fpath)
}
<|endoftext|>


<commit_before>package state

import (
	"github.com/hashicorp/terraform/terraform"
)

// BackupState wraps a State that backs up the state on the first time that
// a WriteState or PersistState is called.
//
// If Path exists, it will be overwritten.
type BackupState struct {
	Real State
	Path string

	done bool
}

func (s *BackupState) State() *terraform.State {
	return s.Real.State()
}

func (s *BackupState) RefreshState() error {
	return s.Real.RefreshState()
}

func (s *BackupState) WriteState(state *terraform.State) error {
	if !s.done {
		if err := s.backup(); err != nil {
			return err
		}
	}

	return s.Real.WriteState(state)
}

func (s *BackupState) PersistState() error {
	if !s.done {
		if err := s.backup(); err != nil {
			return err
		}
	}

	return s.Real.PersistState()
}

// all states get wrapped by BackupState, so it has to be a Locker
func (s *BackupState) Lock(reason string) error {
	if s, ok := s.Real.(Locker); ok {
		return s.Lock(reason)
	}
	return nil
}

func (s *BackupState) Unlock() error {
	if s, ok := s.Real.(Locker); ok {
		return s.Unlock()
	}
	return nil
}

func (s *BackupState) backup() error {
	state := s.Real.State()
	if state == nil {
		if err := s.Real.RefreshState(); err != nil {
			return err
		}

		state = s.Real.State()
	}

	ls := &LocalState{Path: s.Path}
	if err := ls.WriteState(state); err != nil {
		return err
	}

	s.done = true
	return nil
}
<commit_msg>Don't create empty backups<commit_after>package state

import "github.com/hashicorp/terraform/terraform"

// BackupState wraps a State that backs up the state on the first time that
// a WriteState or PersistState is called.
//
// If Path exists, it will be overwritten.
type BackupState struct {
	Real State
	Path string

	done bool
}

func (s *BackupState) State() *terraform.State {
	return s.Real.State()
}

func (s *BackupState) RefreshState() error {
	return s.Real.RefreshState()
}

func (s *BackupState) WriteState(state *terraform.State) error {
	if !s.done {
		if err := s.backup(); err != nil {
			return err
		}
	}

	return s.Real.WriteState(state)
}

func (s *BackupState) PersistState() error {
	if !s.done {
		if err := s.backup(); err != nil {
			return err
		}
	}

	return s.Real.PersistState()
}

// all states get wrapped by BackupState, so it has to be a Locker
func (s *BackupState) Lock(reason string) error {
	if s, ok := s.Real.(Locker); ok {
		return s.Lock(reason)
	}
	return nil
}

func (s *BackupState) Unlock() error {
	if s, ok := s.Real.(Locker); ok {
		return s.Unlock()
	}
	return nil
}

func (s *BackupState) backup() error {
	state := s.Real.State()
	if state == nil {
		if err := s.Real.RefreshState(); err != nil {
			return err
		}

		state = s.Real.State()
	}

	// LocalState.WriteState ensures that a file always exists for locking
	// purposes, but we don't need a backup or lock if the state is empty, so
	// skip this with a nil state.
	if state != nil {
		ls := &LocalState{Path: s.Path}
		if err := ls.WriteState(state); err != nil {
			return err
		}
	}

	s.done = true
	return nil
}
<|endoftext|>