<commit_before>// Package dec provides Brotli decoder bindings
package dec // import "gopkg.in/kothar/brotli-go.v0/dec"

/*
#include "./decode.h"

typedef uint8_t dict[122784];
dict* decodeBrotliDictionary;

// Wrap the C method to avoid modifying pointers in Go-allocated memory
BrotliResult BrotliDecompressStream_Wrapper(
	size_t* available_in, const uint8_t* input,
	size_t* available_out, uint8_t* output,
    size_t* total_out, BrotliState* s
) {
	// Make copy of nextOut to avoid leaking back to Go
	const uint8_t* next_in = input;
	uint8_t* next_out = output;

	return BrotliDecompressStream(
		available_in, &next_in,
		available_out, &next_out,
		total_out, s
	);
}

*/
import "C"

import (
	"errors"
	"io"
	"runtime"
	"unsafe"

	"gopkg.in/kothar/brotli-go.v0/shared"
)

func init() {
	// Set up the default dictionary from the data in the shared package
	C.decodeBrotliDictionary = (*C.dict)(shared.GetDictionary())
}

// DecompressBuffer decompress a Brotli-encoded buffer. Uses decodedBuffer as the destination buffer unless it is too small,
// in which case a new buffer is allocated.
// Returns the slice of the decodedBuffer containing the output, or an error.
func DecompressBuffer(encodedBuffer []byte, decodedBuffer []byte) ([]byte, error) {
	encodedLength := len(encodedBuffer)
	var decodedSize C.size_t

	// If the user has provided a sensibly size buffer, assume they know how long the output should be
	// Otherwise try to determine the correct length from the input
	if len(decodedBuffer) < len(encodedBuffer) {
		success := C.BrotliDecompressedSize(C.size_t(encodedLength), toC(encodedBuffer), &decodedSize)
		if success != 1 {
			// We can't know in advance how much buffer to allocate, so we will just have to guess
			decodedSize = C.size_t(len(encodedBuffer) * 6)
		}

		if len(decodedBuffer) < int(decodedSize) {
			decodedBuffer = make([]byte, decodedSize)
		}
	}

	// The size of the ouput buffer available
	decodedLength := C.size_t(len(decodedBuffer))
	result := C.BrotliDecompressBuffer(C.size_t(encodedLength), toC(encodedBuffer), &decodedLength, toC(decodedBuffer))
	switch result {
	case C.BROTLI_RESULT_SUCCESS:
		// We're finished
		return decodedBuffer[0:decodedLength], nil
	case C.BROTLI_RESULT_NEEDS_MORE_OUTPUT:
		// We needed more output buffer
		decodedBuffer = make([]byte, len(decodedBuffer)*2)
		return DecompressBuffer(encodedBuffer, decodedBuffer)
	case C.BROTLI_RESULT_ERROR:
		return nil, errors.New("Brotli decompression error")
	case C.BROTLI_RESULT_NEEDS_MORE_INPUT:
		// We can't handle streaming more input results here
		return nil, errors.New("Brotli decompression error: needs more input")
	default:
		return nil, errors.New("Unrecognised Brotli decompression error")
	}
}

// DecompressBuffer decompress a Brotli-encoded buffer. Uses decodedBuffer as the destination buffer unless it is too small,
// in which case a new buffer is allocated.
// Returns the slice of the decodedBuffer containing the output, or an error.
func DecompressBufferDict(encodedBuffer []byte, inputDict []byte, decodedBuffer []byte) ([]byte, error) {
	encodedLength := len(encodedBuffer)
	dictLength := len(inputDict)
	var decodedSize C.size_t

	// If the user has provided a sensibly size buffer, assume they know how long the output should be
	// Otherwise try to determine the correct length from the input
	if len(decodedBuffer) < len(encodedBuffer) {
		success := C.BrotliDecompressedSize(C.size_t(encodedLength), toC(encodedBuffer), &decodedSize)
		if success != 1 {
			// We can't know in advance how much buffer to allocate, so we will just have to guess
			decodedSize = C.size_t(len(encodedBuffer) * 6)
		}

		if len(decodedBuffer) < int(decodedSize) {
			decodedBuffer = make([]byte, decodedSize)
		}
	}

	// The size of the ouput buffer available
	decodedLength := C.size_t(len(decodedBuffer))

	result := C.BrotliDecompressBufferDict(
		C.size_t(encodedLength), toC(encodedBuffer),
		C.size_t(dictLength), toC(inputDict),
		&decodedLength, toC(decodedBuffer))
	switch result {
	case C.BROTLI_RESULT_SUCCESS:
		// We're finished
		return decodedBuffer[0:decodedLength], nil
	case C.BROTLI_RESULT_NEEDS_MORE_OUTPUT:
		// We needed more output buffer
		decodedBuffer = make([]byte, len(decodedBuffer)*2)
		return DecompressBufferDict(encodedBuffer, inputDict, decodedBuffer)
	case C.BROTLI_RESULT_ERROR:
		return nil, errors.New("Brotli decompression error")
	case C.BROTLI_RESULT_NEEDS_MORE_INPUT:
		// We can't handle streaming more input results here
		return nil, errors.New("Brotli decompression error: needs more input")
	default:
		return nil, errors.New("Unrecognised Brotli decompression error")
	}
}

func toC(array []byte) *C.uint8_t {
	return (*C.uint8_t)(unsafe.Pointer(&array[0]))
}

// BrotliReader decompresses a Brotli-encoded stream using the io.Reader interface
type BrotliReader struct {
	reader io.Reader
	closed bool

	// C-allocated state. Must be cleaned up by calling Close() or a memory leak will occur
	state unsafe.Pointer

	needOutput bool  // State bounces between needing input and output
	err        error // Persistent error

	buffer     []byte // Internal buffer for compressed data
	bufferRead int    // How many bytes in the buffer are valid

	availableIn C.size_t
	totalOut    C.size_t
}

// Fill a buffer, p, with the decompressed contents of the stream.
// Returns the number of bytes read, or an error
func (r *BrotliReader) Read(p []byte) (n int, err error) {
	if len(p) == 0 || r.err != nil {
		return 0, r.err
	}

	// Prepare arguments
	maxOutput := len(p)
	availableOut := C.size_t(maxOutput)

	if r.err == nil {
		// Read more compressed data
		if r.availableIn == 0 && !r.needOutput {
			read, err := r.reader.Read(r.buffer)
			if read > 0 && err == io.EOF {
				err = nil // Let next Read call return (0, io.EOF)
			}
			if err != nil {
				if err == io.EOF {
					err = io.ErrUnexpectedEOF
				}
				r.err = err
			}
			r.bufferRead = read
			r.availableIn = C.size_t(read)
		}

		if r.availableIn > 0 || r.needOutput {
			// Decompress
			inputPosition := r.bufferRead - int(r.availableIn)
			result := C.BrotliDecompressStream_Wrapper(
				&r.availableIn,
				(*C.uint8_t)(unsafe.Pointer(&r.buffer[inputPosition])),
				&availableOut,
				(*C.uint8_t)(unsafe.Pointer(&p[0])),
				&r.totalOut,
				(*C.BrotliState)(r.state),
			)

			n = maxOutput - int(availableOut)

			switch result {
			case C.BROTLI_RESULT_SUCCESS:
				r.err = io.EOF
			case C.BROTLI_RESULT_NEEDS_MORE_OUTPUT:
				r.needOutput = true
				if n > 0 {
					return n, r.err
				}
				r.err = errors.New("Brotli decompression error: needs more output buffer")
			case C.BROTLI_RESULT_ERROR:
				r.err = errors.New("Brotli decompression error")
			case C.BROTLI_RESULT_NEEDS_MORE_INPUT:
				r.needOutput = false
			default:
				r.err = errors.New("Unrecognized Brotli decompression error")
			}
		}
	}

	if r.err == io.EOF && n > 0 {
		return n, nil
	}
	return n, r.err
}

// Close the reader and clean up any decompressor state.
func (r *BrotliReader) Close() error {
	if r.closed {
		return r.err
	}
	C.BrotliStateCleanup((*C.BrotliState)(r.state))
	C.BrotliDestroyState((*C.BrotliState)(r.state))
	r.closed = true
	if r.err == nil || r.err == io.EOF {
		r.err = io.ErrClosedPipe // Make sure future operations fail
		return nil
	}
	return r.err
}

// NewBrotliReader returns a Reader that decompresses the stream from another reader.
//
// Ensure that you Close the stream when you are finished in order to clean up the
// Brotli decompression state.
//
// The internal decompression buffer defaults to 128kb
func NewBrotliReader(stream io.Reader) *BrotliReader {
	return NewBrotliReaderSize(stream, 128*1024)
}

// NewBrotliReaderSize is the same as NewBrotliReader, but allows the internal buffer size to be set.
//
// The size of the internal buffer may be specified which will hold compressed data
// before being read by the decompressor
func NewBrotliReaderSize(stream io.Reader, size int) *BrotliReader {
	r := &BrotliReader{
		reader: stream,
		buffer: make([]byte, size),
	}

	r.state = unsafe.Pointer(C.BrotliCreateState(nil, nil, nil))
	C.BrotliStateInit((*C.BrotliState)(r.state))

	runtime.SetFinalizer(r, func(c io.Closer) { c.Close() })

	return r
}
<commit_msg>Fix lint issue.<commit_after>// Package dec provides Brotli decoder bindings
package dec // import "gopkg.in/kothar/brotli-go.v0/dec"

/*
#include "./decode.h"

typedef uint8_t dict[122784];
dict* decodeBrotliDictionary;

// Wrap the C method to avoid modifying pointers in Go-allocated memory
BrotliResult BrotliDecompressStream_Wrapper(
	size_t* available_in, const uint8_t* input,
	size_t* available_out, uint8_t* output,
    size_t* total_out, BrotliState* s
) {
	// Make copy of nextOut to avoid leaking back to Go
	const uint8_t* next_in = input;
	uint8_t* next_out = output;

	return BrotliDecompressStream(
		available_in, &next_in,
		available_out, &next_out,
		total_out, s
	);
}

*/
import "C"

import (
	"errors"
	"io"
	"runtime"
	"unsafe"

	"gopkg.in/kothar/brotli-go.v0/shared"
)

func init() {
	// Set up the default dictionary from the data in the shared package
	C.decodeBrotliDictionary = (*C.dict)(shared.GetDictionary())
}

// DecompressBuffer decompress a Brotli-encoded buffer. Uses decodedBuffer as the destination buffer unless it is too small,
// in which case a new buffer is allocated.
// Returns the slice of the decodedBuffer containing the output, or an error.
func DecompressBuffer(encodedBuffer []byte, decodedBuffer []byte) ([]byte, error) {
	encodedLength := len(encodedBuffer)
	var decodedSize C.size_t

	// If the user has provided a sensibly size buffer, assume they know how long the output should be
	// Otherwise try to determine the correct length from the input
	if len(decodedBuffer) < len(encodedBuffer) {
		success := C.BrotliDecompressedSize(C.size_t(encodedLength), toC(encodedBuffer), &decodedSize)
		if success != 1 {
			// We can't know in advance how much buffer to allocate, so we will just have to guess
			decodedSize = C.size_t(len(encodedBuffer) * 6)
		}

		if len(decodedBuffer) < int(decodedSize) {
			decodedBuffer = make([]byte, decodedSize)
		}
	}

	// The size of the ouput buffer available
	decodedLength := C.size_t(len(decodedBuffer))
	result := C.BrotliDecompressBuffer(C.size_t(encodedLength), toC(encodedBuffer), &decodedLength, toC(decodedBuffer))
	switch result {
	case C.BROTLI_RESULT_SUCCESS:
		// We're finished
		return decodedBuffer[0:decodedLength], nil
	case C.BROTLI_RESULT_NEEDS_MORE_OUTPUT:
		// We needed more output buffer
		decodedBuffer = make([]byte, len(decodedBuffer)*2)
		return DecompressBuffer(encodedBuffer, decodedBuffer)
	case C.BROTLI_RESULT_ERROR:
		return nil, errors.New("Brotli decompression error")
	case C.BROTLI_RESULT_NEEDS_MORE_INPUT:
		// We can't handle streaming more input results here
		return nil, errors.New("Brotli decompression error: needs more input")
	default:
		return nil, errors.New("Unrecognised Brotli decompression error")
	}
}

// DecompressBufferDict decompress a Brotli-encoded buffer. Uses decodedBuffer as the destination buffer unless it is too small,
// in which case a new buffer is allocated.
// Returns the slice of the decodedBuffer containing the output, or an error.
func DecompressBufferDict(encodedBuffer []byte, inputDict []byte, decodedBuffer []byte) ([]byte, error) {
	encodedLength := len(encodedBuffer)
	dictLength := len(inputDict)
	var decodedSize C.size_t

	// If the user has provided a sensibly size buffer, assume they know how long the output should be
	// Otherwise try to determine the correct length from the input
	if len(decodedBuffer) < len(encodedBuffer) {
		success := C.BrotliDecompressedSize(C.size_t(encodedLength), toC(encodedBuffer), &decodedSize)
		if success != 1 {
			// We can't know in advance how much buffer to allocate, so we will just have to guess
			decodedSize = C.size_t(len(encodedBuffer) * 6)
		}

		if len(decodedBuffer) < int(decodedSize) {
			decodedBuffer = make([]byte, decodedSize)
		}
	}

	// The size of the ouput buffer available
	decodedLength := C.size_t(len(decodedBuffer))

	result := C.BrotliDecompressBufferDict(
		C.size_t(encodedLength), toC(encodedBuffer),
		C.size_t(dictLength), toC(inputDict),
		&decodedLength, toC(decodedBuffer))
	switch result {
	case C.BROTLI_RESULT_SUCCESS:
		// We're finished
		return decodedBuffer[0:decodedLength], nil
	case C.BROTLI_RESULT_NEEDS_MORE_OUTPUT:
		// We needed more output buffer
		decodedBuffer = make([]byte, len(decodedBuffer)*2)
		return DecompressBufferDict(encodedBuffer, inputDict, decodedBuffer)
	case C.BROTLI_RESULT_ERROR:
		return nil, errors.New("Brotli decompression error")
	case C.BROTLI_RESULT_NEEDS_MORE_INPUT:
		// We can't handle streaming more input results here
		return nil, errors.New("Brotli decompression error: needs more input")
	default:
		return nil, errors.New("Unrecognised Brotli decompression error")
	}
}

func toC(array []byte) *C.uint8_t {
	return (*C.uint8_t)(unsafe.Pointer(&array[0]))
}

// BrotliReader decompresses a Brotli-encoded stream using the io.Reader interface
type BrotliReader struct {
	reader io.Reader
	closed bool

	// C-allocated state. Must be cleaned up by calling Close() or a memory leak will occur
	state unsafe.Pointer

	needOutput bool  // State bounces between needing input and output
	err        error // Persistent error

	buffer     []byte // Internal buffer for compressed data
	bufferRead int    // How many bytes in the buffer are valid

	availableIn C.size_t
	totalOut    C.size_t
}

// Fill a buffer, p, with the decompressed contents of the stream.
// Returns the number of bytes read, or an error
func (r *BrotliReader) Read(p []byte) (n int, err error) {
	if len(p) == 0 || r.err != nil {
		return 0, r.err
	}

	// Prepare arguments
	maxOutput := len(p)
	availableOut := C.size_t(maxOutput)

	if r.err == nil {
		// Read more compressed data
		if r.availableIn == 0 && !r.needOutput {
			read, err := r.reader.Read(r.buffer)
			if read > 0 && err == io.EOF {
				err = nil // Let next Read call return (0, io.EOF)
			}
			if err != nil {
				if err == io.EOF {
					err = io.ErrUnexpectedEOF
				}
				r.err = err
			}
			r.bufferRead = read
			r.availableIn = C.size_t(read)
		}

		if r.availableIn > 0 || r.needOutput {
			// Decompress
			inputPosition := r.bufferRead - int(r.availableIn)
			result := C.BrotliDecompressStream_Wrapper(
				&r.availableIn,
				(*C.uint8_t)(unsafe.Pointer(&r.buffer[inputPosition])),
				&availableOut,
				(*C.uint8_t)(unsafe.Pointer(&p[0])),
				&r.totalOut,
				(*C.BrotliState)(r.state),
			)

			n = maxOutput - int(availableOut)

			switch result {
			case C.BROTLI_RESULT_SUCCESS:
				r.err = io.EOF
			case C.BROTLI_RESULT_NEEDS_MORE_OUTPUT:
				r.needOutput = true
				if n > 0 {
					return n, r.err
				}
				r.err = errors.New("Brotli decompression error: needs more output buffer")
			case C.BROTLI_RESULT_ERROR:
				r.err = errors.New("Brotli decompression error")
			case C.BROTLI_RESULT_NEEDS_MORE_INPUT:
				r.needOutput = false
			default:
				r.err = errors.New("Unrecognized Brotli decompression error")
			}
		}
	}

	if r.err == io.EOF && n > 0 {
		return n, nil
	}
	return n, r.err
}

// Close the reader and clean up any decompressor state.
func (r *BrotliReader) Close() error {
	if r.closed {
		return r.err
	}
	C.BrotliStateCleanup((*C.BrotliState)(r.state))
	C.BrotliDestroyState((*C.BrotliState)(r.state))
	r.closed = true
	if r.err == nil || r.err == io.EOF {
		r.err = io.ErrClosedPipe // Make sure future operations fail
		return nil
	}
	return r.err
}

// NewBrotliReader returns a Reader that decompresses the stream from another reader.
//
// Ensure that you Close the stream when you are finished in order to clean up the
// Brotli decompression state.
//
// The internal decompression buffer defaults to 128kb
func NewBrotliReader(stream io.Reader) *BrotliReader {
	return NewBrotliReaderSize(stream, 128*1024)
}

// NewBrotliReaderSize is the same as NewBrotliReader, but allows the internal buffer size to be set.
//
// The size of the internal buffer may be specified which will hold compressed data
// before being read by the decompressor
func NewBrotliReaderSize(stream io.Reader, size int) *BrotliReader {
	r := &BrotliReader{
		reader: stream,
		buffer: make([]byte, size),
	}

	r.state = unsafe.Pointer(C.BrotliCreateState(nil, nil, nil))
	C.BrotliStateInit((*C.BrotliState)(r.state))

	runtime.SetFinalizer(r, func(c io.Closer) { c.Close() })

	return r
}
<|endoftext|>


<commit_before>package etcdfs

import(
  "log"
  "strings"

  "github.com/hanwen/go-fuse/fuse"
  "github.com/hanwen/go-fuse/fuse/nodefs"
  "github.com/hanwen/go-fuse/fuse/pathfs"

  "github.com/coreos/go-etcd/etcd"
)

type EtcdFs struct {
  pathfs.FileSystem
  EtcdEndpoint string
}

func (me *EtcdFs) NewEtcdClient() *etcd.Client {
  return etcd.NewClient([]string{me.EtcdEndpoint})
}

func (me *EtcdFs) Unlink(name string, context *fuse.Context) (code fuse.Status) {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().Delete(name, false)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().RawDelete(name, true, true)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
  _, err := me.NewEtcdClient().Set(name, "", 0)

  if err != nil {
    log.Println("Create Error:", err)
    return nil, fuse.ENOENT
  }

  return NewEtcdFile(me.NewEtcdClient(), name), fuse.OK
}

func (me *EtcdFs) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().CreateDir(name, 0)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
  if name == "" {
    return &fuse.Attr{
      Mode: fuse.S_IFDIR | 0666,
    }, fuse.OK
  }

  res, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    return nil, fuse.ENOENT
  }

  var attr fuse.Attr

  if res.Node.Dir {
    attr = fuse.Attr{
      Mode: fuse.S_IFDIR | 0666,
    }
  } else {
    attr = fuse.Attr{
      Mode: fuse.S_IFREG | 0666, Size: uint64(len(res.Node.Value)),
    }
  }

  return &attr, fuse.OK
}

func (me *EtcdFs) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntry, code fuse.Status) {
  res, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    log.Println("OpenDir Error:", err)
    return nil, fuse.ENOENT
  }

  entries := []fuse.DirEntry{}

  for _, e := range(res.Node.Nodes) {
    chunks := strings.Split(e.Key, "/")
    file := chunks[len(chunks)-1]
    if e.Dir {
      entries = append(entries, fuse.DirEntry{Name: file, Mode: fuse.S_IFDIR})
    } else {
      entries = append(entries, fuse.DirEntry{Name: file, Mode: fuse.S_IFREG})
    }
  }

  return entries, fuse.OK
}

func (me *EtcdFs) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
  _, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    log.Println("Open Error:", err)
    return nil, fuse.ENOENT
  }

  return NewEtcdFile(me.NewEtcdClient(), name), fuse.OK
}

func (me *EtcdFs) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
  etcdClient, err := me.NewEtcdClient()
  content := etcdClient.Get(oldName, false, false)
  _, err := etcdClient().Set(newName, content, 0)
  _, err := etcdClient.Delete(oldName, false)
}
<commit_msg>Fix compilation errors.<commit_after>package etcdfs

import(
  "log"
  "strings"

  "github.com/hanwen/go-fuse/fuse"
  "github.com/hanwen/go-fuse/fuse/nodefs"
  "github.com/hanwen/go-fuse/fuse/pathfs"

  "github.com/coreos/go-etcd/etcd"
)

type EtcdFs struct {
  pathfs.FileSystem
  EtcdEndpoint string
}

func (me *EtcdFs) NewEtcdClient() *etcd.Client {
  return etcd.NewClient([]string{me.EtcdEndpoint})
}

func (me *EtcdFs) Unlink(name string, context *fuse.Context) (code fuse.Status) {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().Delete(name, false)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) Rmdir(name string, context *fuse.Context) (code fuse.Status) {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().RawDelete(name, true, true)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) Create(name string, flags uint32, mode uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
  _, err := me.NewEtcdClient().Set(name, "", 0)

  if err != nil {
    log.Println("Create Error:", err)
    return nil, fuse.ENOENT
  }

  return NewEtcdFile(me.NewEtcdClient(), name), fuse.OK
}

func (me *EtcdFs) Mkdir(name string, mode uint32, context *fuse.Context) fuse.Status {
  if name == "" {
    return fuse.OK
  }

  _, err := me.NewEtcdClient().CreateDir(name, 0)

  if err != nil {
    log.Println(err)
    return fuse.ENOENT
  }

  return fuse.OK
}

func (me *EtcdFs) GetAttr(name string, context *fuse.Context) (*fuse.Attr, fuse.Status) {
  if name == "" {
    return &fuse.Attr{
      Mode: fuse.S_IFDIR | 0666,
    }, fuse.OK
  }

  res, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    return nil, fuse.ENOENT
  }

  var attr fuse.Attr

  if res.Node.Dir {
    attr = fuse.Attr{
      Mode: fuse.S_IFDIR | 0666,
    }
  } else {
    attr = fuse.Attr{
      Mode: fuse.S_IFREG | 0666, Size: uint64(len(res.Node.Value)),
    }
  }

  return &attr, fuse.OK
}

func (me *EtcdFs) OpenDir(name string, context *fuse.Context) (c []fuse.DirEntry, code fuse.Status) {
  res, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    log.Println("OpenDir Error:", err)
    return nil, fuse.ENOENT
  }

  entries := []fuse.DirEntry{}

  for _, e := range(res.Node.Nodes) {
    chunks := strings.Split(e.Key, "/")
    file := chunks[len(chunks)-1]
    if e.Dir {
      entries = append(entries, fuse.DirEntry{Name: file, Mode: fuse.S_IFDIR})
    } else {
      entries = append(entries, fuse.DirEntry{Name: file, Mode: fuse.S_IFREG})
    }
  }

  return entries, fuse.OK
}

func (me *EtcdFs) Open(name string, flags uint32, context *fuse.Context) (file nodefs.File, code fuse.Status) {
  _, err := me.NewEtcdClient().Get(name, false, false)

  if err != nil {
    log.Println("Open Error:", err)
    return nil, fuse.ENOENT
  }

  return NewEtcdFile(me.NewEtcdClient(), name), fuse.OK
}

func (me *EtcdFs) Rename(oldName string, newName string, context *fuse.Context) (code fuse.Status) {
  etcdClient := me.NewEtcdClient()
  res, err := etcdClient.Get(oldName, false, false)
  originalValue := []byte(res.Node.Value)
  _, err := etcdClient.Set(newName, originalValue, 0)
  _, err := etcdClient.Delete(oldName, false)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"regexp"
	"strconv"
)

const (
	Unicoded     byte   = 100
	Unicodei     byte   = 105
	Unicodel     byte   = 108
	Unicode0     byte   = 48
	Unicode1     byte   = 49
	Unicode2     byte   = 50
	Unicode3     byte   = 51
	Unicode4     byte   = 52
	Unicode5     byte   = 53
	Unicode6     byte   = 54
	Unicode7     byte   = 55
	Unicode8     byte   = 56
	Unicode9     byte   = 57
	BeIntPattern string = "^(0|-[1-9]\\d*|[1-9]\\d*)$"
)

func BeDecode(reader io.Reader) {
	r := bufio.NewReader(reader)
outer:
	for {
		if b, err := r.Peek(1); err != nil {
			if err == io.EOF {
				break
			} else {
				log.Fatal(err)
			}
		} else {
			switch b[0] {
			case Unicodei:
				DecodeInteger(r)
			case Unicode0, Unicode1, Unicode2, Unicode3, Unicode4, Unicode5, Unicode6, Unicode7, Unicode8, Unicode9:
				DecodeString(r)
			case Unicodel:
				DecodeList(r)
			case Unicoded:
				DecodeDictionary(r)
			default:
				break outer
			}
		}
	}
}

func DecodeInteger(reader *bufio.Reader) *BeInteger {
	var str string
	if b, err := reader.ReadBytes('e'); err != nil {
		if err == io.EOF {
			panic(err)
		} else {
			log.Fatal(err)
		}
	} else {
		str = fmt.Sprintf("%s", string(b[1:len(b)-1]))
		if b, err := regexp.MatchString(BeIntPattern, str); err != nil || b == false {
			panic(fmt.Sprintf("Could not parse integer: %s", str))
		}
	}
	log.Printf("INFO: Decoded integer. Returning %v", BeInteger{str})
	return &BeInteger{str}
}

func DecodeString(reader *bufio.Reader) *BeString {
	var length int
	// get the length of the BeString
	if b, err := reader.ReadBytes(':'); err != nil {
		if err == io.EOF {
			panic(err)
		} else {
			log.Fatal(err)
		}
	} else {
		str := fmt.Sprintf("%s", string(b[:len(b)-1]))
		length, err = strconv.Atoi(str)
		if err != nil {
			panic(err)
		}
	}

	// get the value of the BeString
	var buf bytes.Buffer
	for i := 0; i < length; i++ {
		if b, err := reader.ReadByte(); err != nil {
			if err == io.EOF {
				break
			} else {
				log.Fatal(err)
			}
		} else {
			buf.WriteByte(b)
		}
	}
	log.Printf("INFO: Decoded string. Returning %v in %v", buf.String(), BeString{length, buf.Bytes()})
	return &BeString{length, buf.Bytes()}
}

func DecodeList(reader *bufio.Reader) *BeList {
	var list BeList
	reader.ReadByte()
outer:
	for {
		if b, err := reader.Peek(1); err != nil {
			if err == io.EOF {
				break
			} else {
				log.Fatal(err)
			}
		} else {
			switch b[0] {
			case Unicodei:
				list.Node = append(list.Node, BeNode{DecodeInteger(reader)})
			case Unicode0, Unicode1, Unicode2, Unicode3, Unicode4, Unicode5, Unicode6, Unicode7, Unicode8, Unicode9:
				list.Node = append(list.Node, BeNode{DecodeString(reader)})
			case Unicodel:
				list.Node = append(list.Node, BeNode{DecodeList(reader)})
			case Unicoded:
				list.Node = append(list.Node, BeNode{DecodeDictionary(reader)})
			default:
				break outer
			}
		}
	}
	fmt.Printf("List is: %v\n", list)
	return &list
}

func DecodeDictionary(reader *bufio.Reader) *BeDict {
	var dict BeDict
	reader.ReadByte()
	for {
		key, ok := getBencodeEntity(reader).(*BeString)
		if key == nil {
			break
		}
		if !ok {
			log.Fatal("Dict key was not a string.")
		}
		value := BeNode{getBencodeEntity(reader)}
		dict.Entry = append(dict.Entry, BeDictEntry{*key, value})
	}
	fmt.Printf("Dictionary is: %v\n", dict)
	return &dict
}

func getBencodeEntity(reader *bufio.Reader) interface{} {
	var bencodeEntity interface{}
	if b, err := reader.Peek(1); err != nil {
		if err == io.EOF {
			return nil
		} else {
			log.Fatal(err)
		}
	} else {
		switch b[0] {
		case Unicodei:
			bencodeEntity = DecodeInteger(reader)
		case Unicode0, Unicode1, Unicode2, Unicode3, Unicode4, Unicode5, Unicode6, Unicode7, Unicode8, Unicode9:
			bencodeEntity = DecodeString(reader)
		case Unicodel:
			bencodeEntity = DecodeList(reader)
		case Unicoded:
			bencodeEntity = DecodeDictionary(reader)
		default:
			bencodeEntity = nil
		}
	}
	return bencodeEntity
}
<commit_msg>Refactoring with generic method<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"regexp"
	"strconv"
)

const (
	Unicoded     byte   = 100
	Unicodei     byte   = 105
	Unicodel     byte   = 108
	Unicode0     byte   = 48
	Unicode1     byte   = 49
	Unicode2     byte   = 50
	Unicode3     byte   = 51
	Unicode4     byte   = 52
	Unicode5     byte   = 53
	Unicode6     byte   = 54
	Unicode7     byte   = 55
	Unicode8     byte   = 56
	Unicode9     byte   = 57
	BeIntPattern string = "^(0|-[1-9]\\d*|[1-9]\\d*)$"
)

func BeDecode(reader io.Reader) interface{} {
	r := bufio.NewReader(reader)
	var entity interface{}
	for {
		entity = DecodeEntity(r)
		if entity == nil {
			break
		}
	}
	return entity
}

func DecodeInteger(reader *bufio.Reader) *BeInteger {
	var str string
	if b, err := reader.ReadBytes('e'); err != nil {
		if err == io.EOF {
			panic(err)
		} else {
			log.Fatal(err)
		}
	} else {
		str = fmt.Sprintf("%s", string(b[1:len(b)-1]))
		if b, err := regexp.MatchString(BeIntPattern, str); err != nil || b == false {
			panic(fmt.Sprintf("Could not parse integer: %s", str))
		}
	}
	log.Printf("INFO: Decoded integer. Returning %v", BeInteger{str})
	return &BeInteger{str}
}

func DecodeString(reader *bufio.Reader) *BeString {
	var length int
	// get the length of the BeString
	if b, err := reader.ReadBytes(':'); err != nil {
		if err == io.EOF {
			panic(err)
		} else {
			log.Fatal(err)
		}
	} else {
		str := fmt.Sprintf("%s", string(b[:len(b)-1]))
		length, err = strconv.Atoi(str)
		if err != nil {
			panic(err)
		}
	}
	// get the value of the BeString
	var buf bytes.Buffer
	for i := 0; i < length; i++ {
		if b, err := reader.ReadByte(); err != nil {
			if err == io.EOF {
				break
			} else {
				log.Fatal(err)
			}
		} else {
			buf.WriteByte(b)
		}
	}
	log.Printf("INFO: Decoded string. Returning %v in %v", buf.String(), BeString{length, buf.Bytes()})
	return &BeString{length, buf.Bytes()}
}

func DecodeList(reader *bufio.Reader) *BeList {
	var list BeList
	reader.ReadByte()
	for {
		value := DecodeEntity(reader)
		if value == nil {
			break
		}
		list.Node = append(list.Node, BeNode{value})
	}
	log.Printf("INFO: Decoded list. Returning %v", list)
	return &list
}

func DecodeDictionary(reader *bufio.Reader) *BeDict {
	var dict BeDict
	reader.ReadByte()
	for {
		key, ok := DecodeEntity(reader).(*BeString)
		if key == nil {
			break
		}
		if !ok {
			log.Fatal("Dict key was not a string.")
		}
		value := BeNode{DecodeEntity(reader)}
		dict.Entry = append(dict.Entry, BeDictEntry{*key, value})
	}
	log.Printf("INFO: Decoded dictionary. Returning %v", dict)
	return &dict
}

func DecodeEntity(reader *bufio.Reader) interface{} {
	var bencodeEntity interface{}
	if b, err := reader.Peek(1); err != nil {
		if err == io.EOF {
			return nil
		} else {
			log.Fatal(err)
		}
	} else {
		switch b[0] {
		case Unicodei:
			bencodeEntity = DecodeInteger(reader)
		case Unicode0, Unicode1, Unicode2, Unicode3, Unicode4, Unicode5, Unicode6, Unicode7, Unicode8, Unicode9:
			bencodeEntity = DecodeString(reader)
		case Unicodel:
			bencodeEntity = DecodeList(reader)
		case Unicoded:
			bencodeEntity = DecodeDictionary(reader)
		default:
			bencodeEntity = nil
		}
	}
	return bencodeEntity
}
<|endoftext|>


<commit_before>package normjson

// T holds data.
type T struct {
	Label  interface{} `json:"label,omitempty"`
	Active interface{} `json:"active,omitempty"`
	Number interface{} `json:"number,omitempty"`
}

func normalize(t T) T {
	fields := []interface{}{
		t.Label,
		t.Active,
		t.Number,
	}

	for _, v := range fields {
		switch v.(type) {
		case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
			if v == 0 {
				v = nil
			}
		case float32, float64:
			if v == 0 {
				v = nil
			}
		case string:
			if v == "" {
				v = nil
			}
		}

		//if *v == 0 || *v == "0" || *v == "false" || *v == false || *v == "" {
		//	*v = nil
		//}
	}
	return t
}
<commit_msg>normjson: add T.normalize func<commit_after>package normjson

import (
	"reflect"
)

// T holds data.
type T struct {
	I int64   `json:"i,omitempty"`
	F float64 `json:"f,omitempty"`
	B bool    `json:"b,omitempty"`
	S string  `json:"s,omitempty"`

	Label  interface{} `json:"label,omitempty"`
	Active interface{} `json:"active,omitempty"`
	Number interface{} `json:"number,omitempty"`
}

func (t *T) normalize() {
	e := reflect.ValueOf(t).Elem()
	//et := e.Type()
	var f reflect.Value
	for i, max := 0, e.NumField(); i < max; i++ {
		f = e.Field(i)
		if f.Type().String() != "interface {}" {
			continue
		}

		v := f.Interface()
		if v == "" ||
			v == "undefined" ||
			v == "null" ||
			v == "NaN" ||
			v == "0" ||
			v == float64(0) ||
			v == int64(0) ||
			v == 0 ||
			v == false ||
			v == "false" {
			f.Set(reflect.Zero(f.Type()))
		}
		//fmt.Printf("%q %q = %v\n",
		//	et.Field(i).Name, f.Type(), f.Interface())
	}
}

func old(t T) T {
	fields := []interface{}{
		t.Label,
		t.Active,
		t.Number,
	}

	for _, v := range fields {
		switch v.(type) {
		case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
			if v == 0 {
				v = nil
			}
		case float32, float64:
			if v == 0 {
				v = nil
			}
		case string:
			if v == "" {
				v = nil
			}
		}

		//if *v == 0 || *v == "0" || *v == "false" || *v == false || *v == "" {
		//	*v = nil
		//}
	}
	return t
}
<|endoftext|>


<commit_before>package termloop

import "github.com/nsf/termbox-go"

// Provides a general Drawable to be rendered.
type Entity struct {
	canvas Canvas
	x      int
	y      int
	width  int
	height int
}

// NewEntity creates a new Entity, with position (x, y) and size
// (width, height).
// Returns a pointer to the new Entity.
func NewEntity(x, y, width, height int) *Entity {
	canvas := make(Canvas, width)
	for i := range canvas {
		canvas[i] = make([]Cell, height)
	}
	e := Entity{x: x, y: y, width: width, height: height,
		canvas: canvas}
	return &e
}

// Draw draws the entity to its current position on the screen.
// This is usually called every frame.
func (e *Entity) Draw(s *Screen) {
	for i := 0; i < e.width; i++ {
		for j := 0; j < e.height; j++ {
			s.RenderCell(e.x+i, e.y+j, &e.canvas[i][j])
		}
	}
}

func (e *Entity) Tick(ev termbox.Event) {}

// Position returns the (x, y) coordinates of the Entity.
func (e *Entity) Position() (int, int) {
	return e.x, e.y
}

// Size returns the width and height of the entity, in characters.
func (e *Entity) Size() (int, int) {
	return e.width, e.height
}

// SetPosition sets the x and y coordinates of the Entity.
func (e *Entity) SetPosition(x, y int) {
	e.x = x
	e.y = y
}

// SetCell updates the attribute of the Cell at x, y to match those of c.
// The coordinates are relative to the entity itself, not the Screen.
func (e *Entity) SetCell(x, y int, c *Cell) {
	renderCell(&e.canvas[x][y], c)
}
<commit_msg>Fixup entity: Tick expects a termloop Event<commit_after>package termloop

// Provides a general Drawable to be rendered.
type Entity struct {
	canvas Canvas
	x      int
	y      int
	width  int
	height int
}

// NewEntity creates a new Entity, with position (x, y) and size
// (width, height).
// Returns a pointer to the new Entity.
func NewEntity(x, y, width, height int) *Entity {
	canvas := make(Canvas, width)
	for i := range canvas {
		canvas[i] = make([]Cell, height)
	}
	e := Entity{x: x, y: y, width: width, height: height,
		canvas: canvas}
	return &e
}

// Draw draws the entity to its current position on the screen.
// This is usually called every frame.
func (e *Entity) Draw(s *Screen) {
	for i := 0; i < e.width; i++ {
		for j := 0; j < e.height; j++ {
			s.RenderCell(e.x+i, e.y+j, &e.canvas[i][j])
		}
	}
}

func (e *Entity) Tick(ev Event) {}

// Position returns the (x, y) coordinates of the Entity.
func (e *Entity) Position() (int, int) {
	return e.x, e.y
}

// Size returns the width and height of the entity, in characters.
func (e *Entity) Size() (int, int) {
	return e.width, e.height
}

// SetPosition sets the x and y coordinates of the Entity.
func (e *Entity) SetPosition(x, y int) {
	e.x = x
	e.y = y
}

// SetCell updates the attribute of the Cell at x, y to match those of c.
// The coordinates are relative to the entity itself, not the Screen.
func (e *Entity) SetCell(x, y int, c *Cell) {
	renderCell(&e.canvas[x][y], c)
}
<|endoftext|>


<commit_before>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ogletest

import (
	"fmt"
	"math"
	"reflect"
)

// Equals returns a matcher that matches any value v such that v == x, with the
// exception that if x is a numeric type, Equals(x) will match equivalent
// numeric values of any type.
func Equals(x interface{}) Matcher {
	return &equalsMatcher{reflect.ValueOf(x)}
}

type equalsMatcher struct {
	expectedValue reflect.Value
}

////////////////////////////////////////////////////////////
// Numeric types
////////////////////////////////////////////////////////////

func isSignedInteger(v reflect.Value) bool {
	k := v.Kind()
	return k >= reflect.Int && k <= reflect.Int64
}

func isUnsignedInteger(v reflect.Value) bool {
	k := v.Kind()
	return k >= reflect.Uint && k <= reflect.Uint64
}

func isInteger(v reflect.Value) bool {
	return isSignedInteger(v) || isUnsignedInteger(v)
}

func isFloat(v reflect.Value) bool {
	k := v.Kind()
	return k == reflect.Float32 || k == reflect.Float64
}

func isComplex(v reflect.Value) bool {
	k := v.Kind()
	return k == reflect.Complex64 || k == reflect.Complex128
}

func checkAgainstInt64(e int64, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE

	switch {
	case isSignedInteger(c):
		if c.Int() == e {
			res = MATCH_TRUE
		}

	case isUnsignedInteger(c):
		u := c.Uint()
		if u <= math.MaxInt64 && int64(u) == e {
			res = MATCH_TRUE
		}

	// Turn around the various floating point types so that the checkAgainst*
	// functions for them can deal with precision issues.
	case isFloat(c), isComplex(c):
		return Equals(c.Interface()).Matches(e)

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstUint64(e uint64, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE

	switch {
	case isSignedInteger(c):
		i := c.Int()
		if i >= 0 && uint64(i) == e {
			res = MATCH_TRUE
		}

	case isUnsignedInteger(c):
		if c.Uint() == e {
			res = MATCH_TRUE
		}

	// Turn around the various floating point types so that the checkAgainst*
	// functions for them can deal with precision issues.
	case isFloat(c), isComplex(c):
		return Equals(c.Interface()).Matches(e)

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstFloat32(e float32, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE

	switch {
	case isSignedInteger(c):
		if float32(c.Int()) == e {
			res = MATCH_TRUE
		}

	case isUnsignedInteger(c):
		if float32(c.Uint()) == e {
			res = MATCH_TRUE
		}

	case isFloat(c):
		// Compare using float32 to avoid a false sense of precision; otherwise
		// e.g. Equals(float32(0.1)) won't match float32(0.1).
		if float32(c.Float()) == e {
			res = MATCH_TRUE
		}

	case isComplex(c):
		comp := c.Complex()
		rl := real(comp)
		im := imag(comp)

		// Compare using float32 to avoid a false sense of precision; otherwise
		// e.g. Equals(float32(0.1)) won't match (0.1 + 0i).
		if im == 0 && float32(rl) == e {
			res = MATCH_TRUE
		}

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstFloat64(e float64, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE

	ck := c.Kind()

	switch {
	case isSignedInteger(c):
		if float64(c.Int()) == e {
			res = MATCH_TRUE
		}

	case isUnsignedInteger(c):
		if float64(c.Uint()) == e {
			res = MATCH_TRUE
		}

	// If the actual value is lower precision, turn the comparison around so we
	// apply the low-precision rules. Otherwise, e.g. Equals(0.1) may not match
	// float32(0.1).
	case ck == reflect.Float32 || ck == reflect.Complex64:
		return Equals(c.Interface()).Matches(e)

  // Otherwise, compare with double precision.
	case isFloat(c):
		if c.Float() == e {
			res = MATCH_TRUE
		}

	case isComplex(c):
		comp := c.Complex()
		rl := real(comp)
		im := imag(comp)

		if im == 0 && rl == e {
			res = MATCH_TRUE
		}

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstComplex64(e complex64, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE
	realPart := real(e)
	imaginaryPart := imag(e)

	switch {
	case isInteger(c) || isFloat(c):
		// If we have no imaginary part, then we should just compare against the
		// real part. Otherwise, we can't be equal.
		if imaginaryPart != 0 {
			res = MATCH_FALSE
			return
		}

		return checkAgainstFloat32(realPart, c)

	case isComplex(c):
		// Compare using complex64 to avoid a false sense of precision; otherwise
		// e.g. Equals(0.1 + 0i) won't match float32(0.1).
		if complex64(c.Complex()) == e {
			res = MATCH_TRUE
		}

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstComplex128(e complex128, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE
	realPart := real(e)
	imaginaryPart := imag(e)

	switch {
	case isInteger(c) || isFloat(c):
		// If we have no imaginary part, then we should just compare against the
		// real part. Otherwise, we can't be equal.
		if imaginaryPart != 0 {
			res = MATCH_FALSE
			return
		}

		return checkAgainstFloat64(realPart, c)

	case isComplex(c):
		if c.Complex() == e {
			res = MATCH_TRUE
		}

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

////////////////////////////////////////////////////////////
// Other types
////////////////////////////////////////////////////////////

func checkAgainstBool(e bool, c reflect.Value) (res MatchResult, err string) {
	if c.Kind() != reflect.Bool {
		res = MATCH_UNDEFINED
		err = "which is not a bool"
		return
	}

	res = MATCH_FALSE
	if c.Bool() == e {
		res = MATCH_TRUE
	}
	return
}

func checkAgainstUintptr(e uintptr, c reflect.Value) (res MatchResult, err string) {
	if c.Kind() != reflect.Uintptr {
		res = MATCH_UNDEFINED
		err = "which is not a uintptr"
		return
	}

	res = MATCH_FALSE
	if uintptr(c.Uint()) == e {
		res = MATCH_TRUE
	}
	return
}

func checkAgainstChan(e reflect.Value, c reflect.Value) (res MatchResult, err string) {
	// Create a description of e's type, e.g. "chan int".
	typeStr := fmt.Sprintf("%s %s", e.Type().ChanDir(), e.Type().Elem())

	// Make sure c is a chan of the correct type.
	if c.Kind() != reflect.Chan ||
	   c.Type().ChanDir() != e.Type().ChanDir() ||
		 c.Type().Elem() != e.Type().Elem() {
		res = MATCH_UNDEFINED
		err = fmt.Sprintf("which is not a %s", typeStr)
		return
	}

	res = MATCH_FALSE
	if c.Pointer() == e.Pointer() {
		res = MATCH_TRUE
	}
	return
}

////////////////////////////////////////////////////////////
// Public implementation
////////////////////////////////////////////////////////////

func (m *equalsMatcher) Matches(candidate interface{}) (MatchResult, string) {
	e := m.expectedValue
	c := reflect.ValueOf(candidate)
	ek := e.Kind()

	switch {
	case ek == reflect.Bool:
		return checkAgainstBool(e.Bool(), c)

	case isSignedInteger(e):
		return checkAgainstInt64(e.Int(), c)

	case isUnsignedInteger(e):
		return checkAgainstUint64(e.Uint(), c)

	case ek == reflect.Uintptr:
		return checkAgainstUintptr(uintptr(e.Uint()), c)

	case ek == reflect.Float32:
		return checkAgainstFloat32(float32(e.Float()), c)

	case ek == reflect.Float64:
		return checkAgainstFloat64(e.Float(), c)

	case ek == reflect.Complex64:
		return checkAgainstComplex64(complex64(e.Complex()), c)

	case ek == reflect.Complex128:
		return checkAgainstComplex128(complex128(e.Complex()), c)

	case ek == reflect.Chan:
		return checkAgainstChan(e, c)
	}

	return MATCH_UNDEFINED, "TODO"
}

func (m *equalsMatcher) Description() string {
	return fmt.Sprintf("%v", m.expectedValue.Interface())
}
<commit_msg>Implemented arrays and structs.<commit_after>// Copyright 2011 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package ogletest

import (
	"fmt"
	"math"
	"reflect"
)

// Equals returns a matcher that matches any value v such that v == x, with the
// exception that if x is a numeric type, Equals(x) will match equivalent
// numeric values of any type.
func Equals(x interface{}) Matcher {
	v := reflect.ValueOf(x)

	// The == operator is not defined for array or struct types.
	if v.Kind() == reflect.Array || v.Kind() == reflect.Struct {
		panic(fmt.Sprintf("ogletest.Equals: unsupported type", v.Kind()))
	}

	return &equalsMatcher{v}
}

type equalsMatcher struct {
	expectedValue reflect.Value
}

////////////////////////////////////////////////////////////
// Numeric types
////////////////////////////////////////////////////////////

func isSignedInteger(v reflect.Value) bool {
	k := v.Kind()
	return k >= reflect.Int && k <= reflect.Int64
}

func isUnsignedInteger(v reflect.Value) bool {
	k := v.Kind()
	return k >= reflect.Uint && k <= reflect.Uint64
}

func isInteger(v reflect.Value) bool {
	return isSignedInteger(v) || isUnsignedInteger(v)
}

func isFloat(v reflect.Value) bool {
	k := v.Kind()
	return k == reflect.Float32 || k == reflect.Float64
}

func isComplex(v reflect.Value) bool {
	k := v.Kind()
	return k == reflect.Complex64 || k == reflect.Complex128
}

func checkAgainstInt64(e int64, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE

	switch {
	case isSignedInteger(c):
		if c.Int() == e {
			res = MATCH_TRUE
		}

	case isUnsignedInteger(c):
		u := c.Uint()
		if u <= math.MaxInt64 && int64(u) == e {
			res = MATCH_TRUE
		}

	// Turn around the various floating point types so that the checkAgainst*
	// functions for them can deal with precision issues.
	case isFloat(c), isComplex(c):
		return Equals(c.Interface()).Matches(e)

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstUint64(e uint64, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE

	switch {
	case isSignedInteger(c):
		i := c.Int()
		if i >= 0 && uint64(i) == e {
			res = MATCH_TRUE
		}

	case isUnsignedInteger(c):
		if c.Uint() == e {
			res = MATCH_TRUE
		}

	// Turn around the various floating point types so that the checkAgainst*
	// functions for them can deal with precision issues.
	case isFloat(c), isComplex(c):
		return Equals(c.Interface()).Matches(e)

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstFloat32(e float32, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE

	switch {
	case isSignedInteger(c):
		if float32(c.Int()) == e {
			res = MATCH_TRUE
		}

	case isUnsignedInteger(c):
		if float32(c.Uint()) == e {
			res = MATCH_TRUE
		}

	case isFloat(c):
		// Compare using float32 to avoid a false sense of precision; otherwise
		// e.g. Equals(float32(0.1)) won't match float32(0.1).
		if float32(c.Float()) == e {
			res = MATCH_TRUE
		}

	case isComplex(c):
		comp := c.Complex()
		rl := real(comp)
		im := imag(comp)

		// Compare using float32 to avoid a false sense of precision; otherwise
		// e.g. Equals(float32(0.1)) won't match (0.1 + 0i).
		if im == 0 && float32(rl) == e {
			res = MATCH_TRUE
		}

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstFloat64(e float64, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE

	ck := c.Kind()

	switch {
	case isSignedInteger(c):
		if float64(c.Int()) == e {
			res = MATCH_TRUE
		}

	case isUnsignedInteger(c):
		if float64(c.Uint()) == e {
			res = MATCH_TRUE
		}

	// If the actual value is lower precision, turn the comparison around so we
	// apply the low-precision rules. Otherwise, e.g. Equals(0.1) may not match
	// float32(0.1).
	case ck == reflect.Float32 || ck == reflect.Complex64:
		return Equals(c.Interface()).Matches(e)

  // Otherwise, compare with double precision.
	case isFloat(c):
		if c.Float() == e {
			res = MATCH_TRUE
		}

	case isComplex(c):
		comp := c.Complex()
		rl := real(comp)
		im := imag(comp)

		if im == 0 && rl == e {
			res = MATCH_TRUE
		}

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstComplex64(e complex64, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE
	realPart := real(e)
	imaginaryPart := imag(e)

	switch {
	case isInteger(c) || isFloat(c):
		// If we have no imaginary part, then we should just compare against the
		// real part. Otherwise, we can't be equal.
		if imaginaryPart != 0 {
			res = MATCH_FALSE
			return
		}

		return checkAgainstFloat32(realPart, c)

	case isComplex(c):
		// Compare using complex64 to avoid a false sense of precision; otherwise
		// e.g. Equals(0.1 + 0i) won't match float32(0.1).
		if complex64(c.Complex()) == e {
			res = MATCH_TRUE
		}

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

func checkAgainstComplex128(e complex128, c reflect.Value) (res MatchResult, err string) {
	res = MATCH_FALSE
	realPart := real(e)
	imaginaryPart := imag(e)

	switch {
	case isInteger(c) || isFloat(c):
		// If we have no imaginary part, then we should just compare against the
		// real part. Otherwise, we can't be equal.
		if imaginaryPart != 0 {
			res = MATCH_FALSE
			return
		}

		return checkAgainstFloat64(realPart, c)

	case isComplex(c):
		if c.Complex() == e {
			res = MATCH_TRUE
		}

	default:
		res = MATCH_UNDEFINED
		err = "which is not numeric"
	}

	return
}

////////////////////////////////////////////////////////////
// Other types
////////////////////////////////////////////////////////////

func checkAgainstBool(e bool, c reflect.Value) (res MatchResult, err string) {
	if c.Kind() != reflect.Bool {
		res = MATCH_UNDEFINED
		err = "which is not a bool"
		return
	}

	res = MATCH_FALSE
	if c.Bool() == e {
		res = MATCH_TRUE
	}
	return
}

func checkAgainstUintptr(e uintptr, c reflect.Value) (res MatchResult, err string) {
	if c.Kind() != reflect.Uintptr {
		res = MATCH_UNDEFINED
		err = "which is not a uintptr"
		return
	}

	res = MATCH_FALSE
	if uintptr(c.Uint()) == e {
		res = MATCH_TRUE
	}
	return
}

func checkAgainstChan(e reflect.Value, c reflect.Value) (res MatchResult, err string) {
	// Create a description of e's type, e.g. "chan int".
	typeStr := fmt.Sprintf("%s %s", e.Type().ChanDir(), e.Type().Elem())

	// Make sure c is a chan of the correct type.
	if c.Kind() != reflect.Chan ||
	   c.Type().ChanDir() != e.Type().ChanDir() ||
		 c.Type().Elem() != e.Type().Elem() {
		res = MATCH_UNDEFINED
		err = fmt.Sprintf("which is not a %s", typeStr)
		return
	}

	res = MATCH_FALSE
	if c.Pointer() == e.Pointer() {
		res = MATCH_TRUE
	}
	return
}

////////////////////////////////////////////////////////////
// Public implementation
////////////////////////////////////////////////////////////

func (m *equalsMatcher) Matches(candidate interface{}) (MatchResult, string) {
	e := m.expectedValue
	c := reflect.ValueOf(candidate)
	ek := e.Kind()

	switch {
	case ek == reflect.Bool:
		return checkAgainstBool(e.Bool(), c)

	case isSignedInteger(e):
		return checkAgainstInt64(e.Int(), c)

	case isUnsignedInteger(e):
		return checkAgainstUint64(e.Uint(), c)

	case ek == reflect.Uintptr:
		return checkAgainstUintptr(uintptr(e.Uint()), c)

	case ek == reflect.Float32:
		return checkAgainstFloat32(float32(e.Float()), c)

	case ek == reflect.Float64:
		return checkAgainstFloat64(e.Float(), c)

	case ek == reflect.Complex64:
		return checkAgainstComplex64(complex64(e.Complex()), c)

	case ek == reflect.Complex128:
		return checkAgainstComplex128(complex128(e.Complex()), c)

	case ek == reflect.Chan:
		return checkAgainstChan(e, c)
	}

	return MATCH_UNDEFINED, "TODO"
}

func (m *equalsMatcher) Description() string {
	return fmt.Sprintf("%v", m.expectedValue.Interface())
}
<|endoftext|>


<commit_before>package neutrino

import "errors"

var (
	// ErrShuttingDown signals that neutrino received a shutdown request.
	ErrShuttingDown = errors.New("neutrino shutting down")
)
<commit_msg>errors: add ErrGetUtxoCancelled error<commit_after>package neutrino

import "errors"

var (
	// ErrGetUtxoCancelled signals that a GetUtxo request was cancelled.
	ErrGetUtxoCancelled = errors.New("get utxo request cancelled")

	// ErrShuttingDown signals that neutrino received a shutdown request.
	ErrShuttingDown = errors.New("neutrino shutting down")
)
<|endoftext|>


<commit_before>package merry

// The merry package augments standard golang errors with stacktraces
// and other context information.
//
// You can add any context information to an error with `e = merry.WithValue(e, "code", 12345)`
// You can retrieve that value with `v, _ := merry.Value(e, "code").(int)`
//
// Any error augmented like this will automatically get a stacktrace attached, if it doesn't have one
// already.  If you just want to add the stacktrace, use `Wrap(e)`
//
// It also providers a way to override an error's message:
//
//     var InvalidInputs = errors.New("Bad inputs")
//
// `Here()` captures a new stacktrace, and WithMessagef() sets a new error message:
//
//     return merry.Here(InvalidInputs).WithMessagef("Bad inputs: %v", inputs)
//
// Errors are immutable.  All functions and methods which add context return new errors.
// But errors can still be compared to the originals with `Is()`
//
//     if merry.Is(err, InvalidInputs) {
//
// Functions which add context to errors have equivalent methods on *Error, to allow
// convenient chaining:
//
//     return merry.New("Invalid body").WithHTTPCode(400)

import (
	"errors"
	"fmt"
	"runtime"
)

// The maximum number of stackframes on any error.
var MaxStackDepth = 50

type Error interface {
	error
	Appendf(format string, args ...interface{}) Error
	Append(msg string) Error
	WithMessage(msg string) Error
	WithMessagef(format string, args ...interface{}) Error
	WithValue(key, value interface{}) Error
	Here() Error
	WithStackSkipping(skip int) Error
	WithHTTPCode(code int) Error
}

// Create a new error, with a stack attached.  The equivalent of golang's errors.New()
func New(msg string) Error {
	return WrapSkipping(errors.New(msg), 1)
}

// Create a new error with a formatted message and a stack.  The equivalent of golang's fmt.Errorf()
func Errorf(format string, a ...interface{}) Error {
	return WrapSkipping(fmt.Errorf(format, a...), 1)
}

// Cast e to *Error, or wrap e in a new *Error with stack
func Wrap(e error) Error {
	return WrapSkipping(e, 1)
}

// Cast e to *Error, or wrap e in a new *Error with stack
// Skip `skip` frames (0 is the call site of `WrapSkipping()`)
func WrapSkipping(e error, skip int) Error {
	switch e1 := e.(type) {
	case nil:
		return nil
	case *merryErr:
		return e1
	default:
		return &merryErr{
			err:   e,
			key:   stack,
			value: captureStack(skip + 1),
		}
	}
}

// Add a context an error.  If the key was already set on e,
// the new value will take precedence.
func WithValue(e error, key, value interface{}) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).WithValue(key, value)
}

// Return the value for key, or nil if not set
func Value(e error, key interface{}) interface{} {
	if e == nil {
		return nil
	}
	for {
		switch m := e.(type) {
		case nil:
			return nil
		case *merryErr:
			if m.key == key {
				return m.value
			}
			e = m.err
		default:
			return nil
		}
	}
}

// Attach a new stack to the error, at the call site of Here().
// Useful when returning copies of exported package errors
func Here(e error) Error {
	switch m := e.(type) {
	case nil:
		return nil
	case *merryErr:
		// optimization: only capture the stack once, since its expensive
		return m.WithStackSkipping(1)
	default:
		return WrapSkipping(e, 1)
	}
}

// Return the stack attached to an error, or nil if one is not attached
func Stack(e error) []uintptr {
	stack, _ := Value(e, stack).([]uintptr)
	return stack
}

// Return an error with an http code attached.
func WithHTTPCode(e error, code int) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).WithHTTPCode(code)
}

// Convert an error to an http status code.  All errors
// map to 500, unless the error has an http code attached.
func HTTPCode(e error) int {
	if e == nil {
		return 200
	}
	code, _ := Value(e, httpCode).(int)
	if code == 0 {
		return 500
	}
	return code
}

// Override the message of error.
// The resulting error's Error() method will return
// the new message
func WithMessage(e error, msg string) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).WithValue(message, msg)
}

// Same as WithMessage(), using fmt.Sprint()
func WithMessagef(e error, format string, a ...interface{}) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).WithMessagef(format, a...)
}

func Append(e error, msg string) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).Append(msg)
}

func Appendf(e error, format string, args ...interface{}) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).Appendf(format, args...)
}

// Check whether e is equal to or wraps the original, at any depth
func Is(e error, original error) bool {
	for {
		if e == original {
			return true
		}
		if e == nil || original == nil {
			return false
		}
		w, ok := e.(*merryErr)
		if !ok {
			return false
		}
		e = w.err
	}
}

// Return the innermost underlying error.
// Only useful in advanced cases, like if you need to
// cast the underlying error to some type to get
// additional information from it.
func Unwrap(e error) error {
	if e == nil {
		return nil
	}
	for {
		w, ok := e.(*merryErr)
		if !ok {
			return e
		}
		e = w.err
	}
	return e
}

func captureStack(skip int) []uintptr {
	stack := make([]uintptr, MaxStackDepth)
	length := runtime.Callers(2+skip, stack[:])
	return stack[:length]
}

type errorProperty string

const (
	stack    errorProperty = "stack"
	message                = "message"
	httpCode               = "http status code"
)

type merryErr struct {
	err        error
	key, value interface{}
}

// implements golang's error interface
// returns the message value if set, otherwise
// delegates to inner error
func (e *merryErr) Error() string {
	m, _ := Value(e, message).(string)
	if m == "" {
		return Unwrap(e).Error()
	}
	return m
}

// return a new error with additional context
func (e *merryErr) WithValue(key, value interface{}) Error {
	if e == nil {
		return nil
	}
	return &merryErr{
		err:   e,
		key:   key,
		value: value,
	}
}

// Shorthand for capturing a new stack trace
func (e *merryErr) Here() Error {
	if e == nil {
		return nil
	}
	return e.WithStackSkipping(1)
}

// return a new error with a new stack capture
func (e *merryErr) WithStackSkipping(skip int) Error {
	if e == nil {
		return nil
	}
	return &merryErr{
		err:   e,
		key:   stack,
		value: captureStack(skip + 1),
	}
}

// return a new error with an http status code attached
func (e *merryErr) WithHTTPCode(code int) Error {
	if e == nil {
		return nil
	}
	return e.WithValue(httpCode, code)
}

// return a new error with a new message
func (e *merryErr) WithMessage(msg string) Error {
	if e == nil {
		return nil
	}
	return e.WithValue(message, msg)
}

// return a new error with a new formatted message
func (e *merryErr) WithMessagef(format string, a ...interface{}) Error {
	if e == nil {
		return nil
	}
	return e.WithMessage(fmt.Sprintf(format, a...))
}

//
func (e *merryErr) Append(msg string) Error {
	if e == nil {
		return nil
	}
	return e.WithMessagef("%s: %s", e.Error(), msg)
}

//
func (e *merryErr) Appendf(format string, args ...interface{}) Error {
	if e == nil {
		return nil
	}
	return e.Append(fmt.Sprintf(format, args...))
}
<commit_msg>Unnecessary<commit_after>package merry

// The merry package augments standard golang errors with stacktraces
// and other context information.
//
// You can add any context information to an error with `e = merry.WithValue(e, "code", 12345)`
// You can retrieve that value with `v, _ := merry.Value(e, "code").(int)`
//
// Any error augmented like this will automatically get a stacktrace attached, if it doesn't have one
// already.  If you just want to add the stacktrace, use `Wrap(e)`
//
// It also providers a way to override an error's message:
//
//     var InvalidInputs = errors.New("Bad inputs")
//
// `Here()` captures a new stacktrace, and WithMessagef() sets a new error message:
//
//     return merry.Here(InvalidInputs).WithMessagef("Bad inputs: %v", inputs)
//
// Errors are immutable.  All functions and methods which add context return new errors.
// But errors can still be compared to the originals with `Is()`
//
//     if merry.Is(err, InvalidInputs) {
//
// Functions which add context to errors have equivalent methods on *Error, to allow
// convenient chaining:
//
//     return merry.New("Invalid body").WithHTTPCode(400)

import (
	"errors"
	"fmt"
	"runtime"
)

// The maximum number of stackframes on any error.
var MaxStackDepth = 50

type Error interface {
	error
	Appendf(format string, args ...interface{}) Error
	Append(msg string) Error
	WithMessage(msg string) Error
	WithMessagef(format string, args ...interface{}) Error
	WithValue(key, value interface{}) Error
	Here() Error
	WithStackSkipping(skip int) Error
	WithHTTPCode(code int) Error
}

// Create a new error, with a stack attached.  The equivalent of golang's errors.New()
func New(msg string) Error {
	return WrapSkipping(errors.New(msg), 1)
}

// Create a new error with a formatted message and a stack.  The equivalent of golang's fmt.Errorf()
func Errorf(format string, a ...interface{}) Error {
	return WrapSkipping(fmt.Errorf(format, a...), 1)
}

// Cast e to *Error, or wrap e in a new *Error with stack
func Wrap(e error) Error {
	return WrapSkipping(e, 1)
}

// Cast e to *Error, or wrap e in a new *Error with stack
// Skip `skip` frames (0 is the call site of `WrapSkipping()`)
func WrapSkipping(e error, skip int) Error {
	switch e1 := e.(type) {
	case nil:
		return nil
	case *merryErr:
		return e1
	default:
		return &merryErr{
			err:   e,
			key:   stack,
			value: captureStack(skip + 1),
		}
	}
}

// Add a context an error.  If the key was already set on e,
// the new value will take precedence.
func WithValue(e error, key, value interface{}) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).WithValue(key, value)
}

// Return the value for key, or nil if not set
func Value(e error, key interface{}) interface{} {
	for {
		switch m := e.(type) {
		case nil:
			return nil
		case *merryErr:
			if m.key == key {
				return m.value
			}
			e = m.err
		default:
			return nil
		}
	}
}

// Attach a new stack to the error, at the call site of Here().
// Useful when returning copies of exported package errors
func Here(e error) Error {
	switch m := e.(type) {
	case nil:
		return nil
	case *merryErr:
		// optimization: only capture the stack once, since its expensive
		return m.WithStackSkipping(1)
	default:
		return WrapSkipping(e, 1)
	}
}

// Return the stack attached to an error, or nil if one is not attached
func Stack(e error) []uintptr {
	stack, _ := Value(e, stack).([]uintptr)
	return stack
}

// Return an error with an http code attached.
func WithHTTPCode(e error, code int) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).WithHTTPCode(code)
}

// Convert an error to an http status code.  All errors
// map to 500, unless the error has an http code attached.
func HTTPCode(e error) int {
	if e == nil {
		return 200
	}
	code, _ := Value(e, httpCode).(int)
	if code == 0 {
		return 500
	}
	return code
}

// Override the message of error.
// The resulting error's Error() method will return
// the new message
func WithMessage(e error, msg string) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).WithValue(message, msg)
}

// Same as WithMessage(), using fmt.Sprint()
func WithMessagef(e error, format string, a ...interface{}) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).WithMessagef(format, a...)
}

func Append(e error, msg string) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).Append(msg)
}

func Appendf(e error, format string, args ...interface{}) Error {
	if e == nil {
		return nil
	}
	return Wrap(e).Appendf(format, args...)
}

// Check whether e is equal to or wraps the original, at any depth
func Is(e error, original error) bool {
	for {
		if e == original {
			return true
		}
		if e == nil || original == nil {
			return false
		}
		w, ok := e.(*merryErr)
		if !ok {
			return false
		}
		e = w.err
	}
}

// Return the innermost underlying error.
// Only useful in advanced cases, like if you need to
// cast the underlying error to some type to get
// additional information from it.
func Unwrap(e error) error {
	if e == nil {
		return nil
	}
	for {
		w, ok := e.(*merryErr)
		if !ok {
			return e
		}
		e = w.err
	}
	return e
}

func captureStack(skip int) []uintptr {
	stack := make([]uintptr, MaxStackDepth)
	length := runtime.Callers(2+skip, stack[:])
	return stack[:length]
}

type errorProperty string

const (
	stack    errorProperty = "stack"
	message                = "message"
	httpCode               = "http status code"
)

type merryErr struct {
	err        error
	key, value interface{}
}

// implements golang's error interface
// returns the message value if set, otherwise
// delegates to inner error
func (e *merryErr) Error() string {
	m, _ := Value(e, message).(string)
	if m == "" {
		return Unwrap(e).Error()
	}
	return m
}

// return a new error with additional context
func (e *merryErr) WithValue(key, value interface{}) Error {
	if e == nil {
		return nil
	}
	return &merryErr{
		err:   e,
		key:   key,
		value: value,
	}
}

// Shorthand for capturing a new stack trace
func (e *merryErr) Here() Error {
	if e == nil {
		return nil
	}
	return e.WithStackSkipping(1)
}

// return a new error with a new stack capture
func (e *merryErr) WithStackSkipping(skip int) Error {
	if e == nil {
		return nil
	}
	return &merryErr{
		err:   e,
		key:   stack,
		value: captureStack(skip + 1),
	}
}

// return a new error with an http status code attached
func (e *merryErr) WithHTTPCode(code int) Error {
	if e == nil {
		return nil
	}
	return e.WithValue(httpCode, code)
}

// return a new error with a new message
func (e *merryErr) WithMessage(msg string) Error {
	if e == nil {
		return nil
	}
	return e.WithValue(message, msg)
}

// return a new error with a new formatted message
func (e *merryErr) WithMessagef(format string, a ...interface{}) Error {
	if e == nil {
		return nil
	}
	return e.WithMessage(fmt.Sprintf(format, a...))
}

//
func (e *merryErr) Append(msg string) Error {
	if e == nil {
		return nil
	}
	return e.WithMessagef("%s: %s", e.Error(), msg)
}

//
func (e *merryErr) Appendf(format string, args ...interface{}) Error {
	if e == nil {
		return nil
	}
	return e.Append(fmt.Sprintf(format, args...))
}
<|endoftext|>


<commit_before>package zmq3

/*
#include <zmq.h>
*/
import "C"

import (
	"syscall"
)

// An Errno is an unsigned number describing an error condition as returned by a call to ZeroMQ.
// It implements the error interface.
// The number is either a standard system error, or an error defined by the C library of ZeroMQ.
type Errno uintptr

// Error conditions defined by the C library of ZeroMQ.
const (
	// On Windows platform some of the standard POSIX errnos are not defined.
	EADDRINUSE      = Errno(C.EADDRINUSE)
	EADDRNOTAVAIL   = Errno(C.EADDRNOTAVAIL)
	EAFNOSUPPORT    = Errno(C.EAFNOSUPPORT)
	ECONNABORTED    = Errno(C.ECONNABORTED)
	ECONNREFUSED    = Errno(C.ECONNREFUSED)
	ECONNRESET      = Errno(C.ECONNRESET)
	EHOSTUNREACH    = Errno(C.EHOSTUNREACH)
	EINPROGRESS     = Errno(C.EINPROGRESS)
	EMSGSIZE        = Errno(C.EMSGSIZE)
	ENETDOWN        = Errno(C.ENETDOWN)
	ENETRESET       = Errno(C.ENETRESET)
	ENETUNREACH     = Errno(C.ENETUNREACH)
	ENOBUFS         = Errno(C.ENOBUFS)
	ENOTCONN        = Errno(C.ENOTCONN)
	ENOTSOCK        = Errno(C.ENOTSOCK)
	ENOTSUP         = Errno(C.ENOTSUP)
	EPROTONOSUPPORT = Errno(C.EPROTONOSUPPORT)
	ETIMEDOUT       = Errno(C.ETIMEDOUT)

	// Native 0MQ error codes.
	EFSM           = Errno(C.EFSM)
	EMTHREAD       = Errno(C.EMTHREAD)
	ENOCOMPATPROTO = Errno(C.ENOCOMPATPROTO)
	ETERM          = Errno(C.ETERM)
)

func errget(err error) error {
	eno, ok := err.(syscall.Errno)
	if ok {
		return Errno(eno)
	}
	return err
}

// Return Errno as string.
func (errno Errno) Error() string {
	if errno >= C.ZMQ_HAUSNUMERO {
		return C.GoString(C.zmq_strerror(C.int(errno)))
	}
	return syscall.Errno(errno).Error()
}

/*
Covert error to Errno.

Example usage:

    switch AsErrno(err) {

    case zmq.Errno(syscall.EINTR):
        // standard system error

        // call was interrupted

    case zmq.ETERM:
        // error defined by ZeroMQ

        // context was terminated

    }

See also: examples/interrupt.go
*/
func AsErrno(err error) Errno {
	if eno, ok := err.(Errno); ok {
		return eno
	}
	if eno, ok := err.(syscall.Errno); ok {
		return Errno(eno)
	}
	return Errno(0)
}
<commit_msg>Moved comment<commit_after>package zmq3

/*
#include <zmq.h>
*/
import "C"

import (
	"syscall"
)

// An Errno is an unsigned number describing an error condition as returned by a call to ZeroMQ.
// It implements the error interface.
// The number is either a standard system error, or an error defined by the C library of ZeroMQ.
type Errno uintptr

const (
	// Error conditions defined by the C library of ZeroMQ.

	// On Windows platform some of the standard POSIX errnos are not defined.
	EADDRINUSE      = Errno(C.EADDRINUSE)
	EADDRNOTAVAIL   = Errno(C.EADDRNOTAVAIL)
	EAFNOSUPPORT    = Errno(C.EAFNOSUPPORT)
	ECONNABORTED    = Errno(C.ECONNABORTED)
	ECONNREFUSED    = Errno(C.ECONNREFUSED)
	ECONNRESET      = Errno(C.ECONNRESET)
	EHOSTUNREACH    = Errno(C.EHOSTUNREACH)
	EINPROGRESS     = Errno(C.EINPROGRESS)
	EMSGSIZE        = Errno(C.EMSGSIZE)
	ENETDOWN        = Errno(C.ENETDOWN)
	ENETRESET       = Errno(C.ENETRESET)
	ENETUNREACH     = Errno(C.ENETUNREACH)
	ENOBUFS         = Errno(C.ENOBUFS)
	ENOTCONN        = Errno(C.ENOTCONN)
	ENOTSOCK        = Errno(C.ENOTSOCK)
	ENOTSUP         = Errno(C.ENOTSUP)
	EPROTONOSUPPORT = Errno(C.EPROTONOSUPPORT)
	ETIMEDOUT       = Errno(C.ETIMEDOUT)

	// Native 0MQ error codes.
	EFSM           = Errno(C.EFSM)
	EMTHREAD       = Errno(C.EMTHREAD)
	ENOCOMPATPROTO = Errno(C.ENOCOMPATPROTO)
	ETERM          = Errno(C.ETERM)
)

func errget(err error) error {
	eno, ok := err.(syscall.Errno)
	if ok {
		return Errno(eno)
	}
	return err
}

// Return Errno as string.
func (errno Errno) Error() string {
	if errno >= C.ZMQ_HAUSNUMERO {
		return C.GoString(C.zmq_strerror(C.int(errno)))
	}
	return syscall.Errno(errno).Error()
}

/*
Covert error to Errno.

Example usage:

    switch AsErrno(err) {

    case zmq.Errno(syscall.EINTR):
        // standard system error

        // call was interrupted

    case zmq.ETERM:
        // error defined by ZeroMQ

        // context was terminated

    }

See also: examples/interrupt.go
*/
func AsErrno(err error) Errno {
	if eno, ok := err.(Errno); ok {
		return eno
	}
	if eno, ok := err.(syscall.Errno); ok {
		return Errno(eno)
	}
	return Errno(0)
}
<|endoftext|>


<commit_before>package cli

import (
	"context"
	"encoding/json"
	"github.com/drewsonne/go-gocd/gocd"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
	"io/ioutil"
)

// List of command name and descriptions
const (
	CreatePipelineConfigCommandName  = "create-pipeline-config"
	CreatePipelineConfigCommandUsage = "Create Pipeline config"
	UpdatePipelineConfigCommandName  = "update-pipeline-config"
	UpdatePipelineConfigCommandUsage = "Update Pipeline config"
	DeletePipelineConfigCommandName  = "delete-pipeline-config"
	DeletePipelineConfigCommandUsage = "Remove Pipeline. This will not delete the pipeline history, which will be stored in the database"
)

// CreatePipelineConfigAction handles the interaction between the cli flags and the action handler for
// create-pipeline-config-action
func CreatePipelineConfigAction(c *cli.Context) error {
	group := c.String("group")
	if group == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--group' is missing"))
	}

	pipeline := c.String("pipeline")
	pipelineFile := c.String("pipeline-file")
	if pipeline == "" && pipelineFile == "" {
		return handeErrOutput(
			"CreatePipelineConfig",
			errors.New("One of '--pipeline-file' or '--pipeline' must be specified"),
		)
	}

	if pipeline != "" && pipelineFile != "" {
		return handeErrOutput(
			"CreatePipelineConfig",
			errors.New("Only one of '--pipeline-file' or '--pipeline' can be specified"),
		)
	}

	var pf []byte
	var err error
	if pipelineFile != "" {
		pf, err = ioutil.ReadFile(pipelineFile)
		if err != nil {
			return handeErrOutput("CreatePipelineConfig", err)
		}
	} else {
		pf = []byte(pipeline)
	}
	p := &gocd.Pipeline{}
	err = json.Unmarshal(pf, &p)
	if err != nil {
		return handeErrOutput("CreatePipelineConfig", err)
	}

	pc, r, err := cliAgent(c).PipelineConfigs.Create(context.Background(), group, p)
	if err != nil {
		return handeErrOutput("CreatePipelineConfig", err)
	}
	return handleOutput(pc, r, "CreatePipelineConfig", err)
}

// UpdatePipelineConfigAction handles the interaction between the cli flags and the action handler for
// update-pipeline-config-action
func UpdatePipelineConfigAction(c *cli.Context) error {
	name := c.String("name")
	if name == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--name' is missing"))
	}

	version := c.String("pipeline-version")
	if version == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--pipeline-version' is missing"))
	}

	group := c.String("group")
	if group == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--group' is missing"))
	}

	pipeline := c.String("pipeline")
	pipelineFile := c.String("pipeline-file")
	if pipeline == "" && pipelineFile == "" {
		return handeErrOutput(
			"CreatePipelineConfig",
			errors.New("One of '--pipeline-file' or '--pipeline' must be specified"),
		)
	}

	if pipeline != "" && pipelineFile != "" {
		return handeErrOutput(
			"CreatePipelineConfig",
			errors.New("Only one of '--pipeline-file' or '--pipeline' can be specified"),
		)
	}

	var pf []byte
	var err error
	if pipelineFile != "" {
		pf, err = ioutil.ReadFile(pipelineFile)
		if err != nil {
			return handeErrOutput("CreatePipelineConfig", err)
		}
	} else {
		pf = []byte(pipeline)
	}
	p := &gocd.Pipeline{}
	err = json.Unmarshal(pf, &p)
	if err != nil {
		return handeErrOutput("CreatePipelineConfig", err)
	}

	pc, r, err := cliAgent(c).PipelineConfigs.Update(context.Background(), group, name, version, p)
	if err != nil {
		return handeErrOutput("CreatePipelineConfig", err)
	}
	return handleOutput(pc, r, "CreatePipelineConfig", err)

}

// DeletePipelineConfigAction handles the interaction between the cli flags and the action handler for
// delete-pipeline-config-action
func DeletePipelineConfigAction(c *cli.Context) error {
	name := c.String("name")
	if name == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--name' is missing"))
	}

	deleteResponse, r, err := cliAgent(c).PipelineConfigs.Delete(context.Background(), name)
	if r.HTTP.StatusCode == 406 {
		err = errors.New(deleteResponse)
	}
	return handleOutput(deleteResponse, r, "DeletePipelineTemplate", err)
}

// CreatePipelineConfigCommand handles the interaction between the cli flags and the action handler for create-pipeline-config
func CreatePipelineConfigCommand() *cli.Command {
	return &cli.Command{
		Name:     CreatePipelineConfigCommandName,
		Usage:    CreatePipelineConfigCommandUsage,
		Action:   CreatePipelineConfigAction,
		Category: "Pipeline Configs",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "group"},
			cli.StringFlag{Name: "pipeline"},
			cli.StringFlag{Name: "pipeline-file"},
		},
	}
}

// UpdatePipelineConfigCommand handles the interaction between the cli flags and the action handler for update-pipeline-config
func UpdatePipelineConfigCommand() *cli.Command {
	return &cli.Command{
		Name:     UpdatePipelineConfigCommandName,
		Usage:    UpdatePipelineConfigCommandUsage,
		Action:   UpdatePipelineConfigAction,
		Category: "Pipeline Configs",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "group"},
			cli.StringFlag{Name: "name"},
			cli.StringFlag{Name: "pipeline-version"},
			cli.StringFlag{Name: "pipeline"},
			cli.StringFlag{Name: "pipeline-file"},
		},
	}
}

// DeletePipelineConfigCommand handles the interaction between the cli flags and the action handler for delete-pipeline-config
func DeletePipelineConfigCommand() *cli.Command {
	return &cli.Command{
		Name:     DeletePipelineConfigCommandName,
		Usage:    DeletePipelineConfigCommandUsage,
		Category: "Pipeline Configs",
		Action:   DeletePipelineConfigAction,
		Flags: []cli.Flag{
			cli.StringFlag{Name: "name"},
		},
	}
}
<commit_msg>Fixed bad cli sdk integration<commit_after>package cli

import (
	"context"
	"encoding/json"
	"github.com/drewsonne/go-gocd/gocd"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
	"io/ioutil"
)

// List of command name and descriptions
const (
	CreatePipelineConfigCommandName  = "create-pipeline-config"
	CreatePipelineConfigCommandUsage = "Create Pipeline config"
	UpdatePipelineConfigCommandName  = "update-pipeline-config"
	UpdatePipelineConfigCommandUsage = "Update Pipeline config"
	DeletePipelineConfigCommandName  = "delete-pipeline-config"
	DeletePipelineConfigCommandUsage = "Remove Pipeline. This will not delete the pipeline history, which will be stored in the database"
)

// CreatePipelineConfigAction handles the interaction between the cli flags and the action handler for
// create-pipeline-config-action
func CreatePipelineConfigAction(c *cli.Context) error {
	group := c.String("group")
	if group == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--group' is missing"))
	}

	pipeline := c.String("pipeline")
	pipelineFile := c.String("pipeline-file")
	if pipeline == "" && pipelineFile == "" {
		return handeErrOutput(
			"CreatePipelineConfig",
			errors.New("One of '--pipeline-file' or '--pipeline' must be specified"),
		)
	}

	if pipeline != "" && pipelineFile != "" {
		return handeErrOutput(
			"CreatePipelineConfig",
			errors.New("Only one of '--pipeline-file' or '--pipeline' can be specified"),
		)
	}

	var pf []byte
	var err error
	if pipelineFile != "" {
		pf, err = ioutil.ReadFile(pipelineFile)
		if err != nil {
			return handeErrOutput("CreatePipelineConfig", err)
		}
	} else {
		pf = []byte(pipeline)
	}
	p := &gocd.Pipeline{}
	err = json.Unmarshal(pf, &p)
	if err != nil {
		return handeErrOutput("CreatePipelineConfig", err)
	}

	pc, r, err := cliAgent(c).PipelineConfigs.Create(context.Background(), group, p)
	if err != nil {
		return handeErrOutput("CreatePipelineConfig", err)
	}
	return handleOutput(pc, r, "CreatePipelineConfig", err)
}

// UpdatePipelineConfigAction handles the interaction between the cli flags and the action handler for
// update-pipeline-config-action
func UpdatePipelineConfigAction(c *cli.Context) error {
	name := c.String("name")
	if name == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--name' is missing"))
	}

	version := c.String("pipeline-version")
	if version == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--pipeline-version' is missing"))
	}

	group := c.String("group")
	if group == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--group' is missing"))
	}

	pipeline := c.String("pipeline")
	pipelineFile := c.String("pipeline-file")
	if pipeline == "" && pipelineFile == "" {
		return handeErrOutput(
			"CreatePipelineConfig",
			errors.New("One of '--pipeline-file' or '--pipeline' must be specified"),
		)
	}

	if pipeline != "" && pipelineFile != "" {
		return handeErrOutput(
			"CreatePipelineConfig",
			errors.New("Only one of '--pipeline-file' or '--pipeline' can be specified"),
		)
	}

	var pf []byte
	var err error
	if pipelineFile != "" {
		pf, err = ioutil.ReadFile(pipelineFile)
		if err != nil {
			return handeErrOutput("CreatePipelineConfig", err)
		}
	} else {
		pf = []byte(pipeline)
	}
	p := &gocd.Pipeline{
		Version: version,
	}
	err = json.Unmarshal(pf, &p)
	if err != nil {
		return handeErrOutput("CreatePipelineConfig", err)
	}

	pc, r, err := cliAgent(c).PipelineConfigs.Update(context.Background(), group, name, p)
	if err != nil {
		return handeErrOutput("CreatePipelineConfig", err)
	}
	return handleOutput(pc, r, "CreatePipelineConfig", err)

}

// DeletePipelineConfigAction handles the interaction between the cli flags and the action handler for
// delete-pipeline-config-action
func DeletePipelineConfigAction(c *cli.Context) error {
	name := c.String("name")
	if name == "" {
		return handleOutput(nil, nil, "CreatePipelineConfig", errors.New("'--name' is missing"))
	}

	deleteResponse, r, err := cliAgent(c).PipelineConfigs.Delete(context.Background(), name)
	if r.HTTP.StatusCode == 406 {
		err = errors.New(deleteResponse)
	}
	return handleOutput(deleteResponse, r, "DeletePipelineTemplate", err)
}

// CreatePipelineConfigCommand handles the interaction between the cli flags and the action handler for create-pipeline-config
func CreatePipelineConfigCommand() *cli.Command {
	return &cli.Command{
		Name:     CreatePipelineConfigCommandName,
		Usage:    CreatePipelineConfigCommandUsage,
		Action:   CreatePipelineConfigAction,
		Category: "Pipeline Configs",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "group"},
			cli.StringFlag{Name: "pipeline"},
			cli.StringFlag{Name: "pipeline-file"},
		},
	}
}

// UpdatePipelineConfigCommand handles the interaction between the cli flags and the action handler for update-pipeline-config
func UpdatePipelineConfigCommand() *cli.Command {
	return &cli.Command{
		Name:     UpdatePipelineConfigCommandName,
		Usage:    UpdatePipelineConfigCommandUsage,
		Action:   UpdatePipelineConfigAction,
		Category: "Pipeline Configs",
		Flags: []cli.Flag{
			cli.StringFlag{Name: "group"},
			cli.StringFlag{Name: "name"},
			cli.StringFlag{Name: "pipeline-version"},
			cli.StringFlag{Name: "pipeline"},
			cli.StringFlag{Name: "pipeline-file"},
		},
	}
}

// DeletePipelineConfigCommand handles the interaction between the cli flags and the action handler for delete-pipeline-config
func DeletePipelineConfigCommand() *cli.Command {
	return &cli.Command{
		Name:     DeletePipelineConfigCommandName,
		Usage:    DeletePipelineConfigCommandUsage,
		Category: "Pipeline Configs",
		Action:   DeletePipelineConfigAction,
		Flags: []cli.Flag{
			cli.StringFlag{Name: "name"},
		},
	}
}
<|endoftext|>


<commit_before>package client

import (
	"bytes"
	"crypto/md5"
	"crypto/tls"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/akutz/gofig"
	"github.com/akutz/goof"
	"github.com/akutz/gotil"

	apiclient "github.com/emccode/libstorage/api/client"
	"github.com/emccode/libstorage/api/types"
	"github.com/emccode/libstorage/api/types/context"
	apihttp "github.com/emccode/libstorage/api/types/http"
	"github.com/emccode/libstorage/api/utils"
	apiconfig "github.com/emccode/libstorage/api/utils/config"
	"github.com/emccode/libstorage/api/utils/paths"
	"github.com/emccode/libstorage/cli/executors"

	// load the drivers
	_ "github.com/emccode/libstorage/drivers/os"
)

func init() {
	registerConfig()
}

const (
	clientScope          = "libstorage.client"
	hostKey              = "libstorage.host"
	logEnabledKey        = "libstorage.client.http.logging.enabled"
	logOutKey            = "libstorage.client.http.logging.out"
	logErrKey            = "libstorage.client.http.logging.err"
	logRequestsKey       = "libstorage.client.http.logging.logrequest"
	logResponsesKey      = "libstorage.client.http.logging.logresponse"
	disableKeepAlivesKey = "libstorage.client.http.disableKeepAlives"
	lsxOffline           = "libstorage.client.executor.offline"

	// LSXPathKey is the configuration key for the libStorage executor
	// binary path.
	LSXPathKey = "libstorage.client.executor.path"
)

type lsc struct {
	apiclient.Client
	config             gofig.Config
	svcInfo            apihttp.ServicesMap
	lsxInfo            apihttp.ExecutorsMap
	lsxBinPath         string
	ctx                context.Context
	enableIIDHeader    bool
	enableLclDevHeader bool
}

// New returns a new Client.
func New(config gofig.Config) (Client, error) {

	logFields := log.Fields{}

	if config == nil {
		var err error
		if config, err = apiconfig.NewConfig(); err != nil {
			return nil, err
		}
	}

	addr := config.GetString(hostKey)
	ctx := context.WithContextID(context.Background(), "host", addr)

	proto, lAddr, err := gotil.ParseAddress(addr)
	if err != nil {
		return nil, err
	}

	tlsConfig, err := utils.ParseTLSConfig(
		config.Scope(clientScope), logFields)
	if err != nil {
		return nil, err
	}

	c := &lsc{
		Client: apiclient.Client{
			Host:         getHost(proto, lAddr, tlsConfig),
			Headers:      http.Header{},
			LogRequests:  config.GetBool(logRequestsKey),
			LogResponses: config.GetBool(logResponsesKey),
			Client: &http.Client{
				Transport: &http.Transport{
					Dial: func(string, string) (net.Conn, error) {
						if tlsConfig == nil {
							return net.Dial(proto, lAddr)
						}
						return tls.Dial(proto, lAddr, tlsConfig)
					},
					DisableKeepAlives: config.GetBool(disableKeepAlivesKey),
				},
			},
		},
		config:     config,
		ctx:        ctx,
		lsxBinPath: config.GetString(LSXPathKey),
	}

	if err := c.updateServiceInfo(); err != nil {
		return nil, err
	}

	if !config.GetBool(lsxOffline) {
		if err := c.updateExecutorInfo(); err != nil {
			return nil, err
		}

		if err := c.updateExecutor(); err != nil {
			return nil, err
		}
	}

	if err := c.updateInstanceIDs(); err != nil {
		return nil, err
	}

	if err := c.updateLocalDevices(); err != nil {
		return nil, err
	}

	ctx.Log().WithFields(logFields).Debug("created new libStorage client")

	return c, nil
}

func (c *lsc) API() *apiclient.Client {
	return &c.Client
}

func getHost(proto, lAddr string, tlsConfig *tls.Config) string {
	if tlsConfig != nil && tlsConfig.ServerName != "" {
		return tlsConfig.ServerName
	} else if proto == "unix" {
		return "libstorage-server"
	} else {
		return lAddr
	}
}

func (c *lsc) updateServiceInfo() error {
	c.ctx.Log().Debug("getting service information")
	svcInfo, err := c.Client.Services(c.ctx)
	if err != nil {
		return err
	}
	c.svcInfo = svcInfo
	return nil
}

func (c *lsc) updateExecutorInfo() error {
	c.ctx.Log().Debug("getting executor information")
	lsxInfo, err := c.Client.Executors(c.ctx)
	if err != nil {
		return err
	}
	c.lsxInfo = lsxInfo
	return nil
}

var (
	lsxBinLock = &sync.Mutex{}
)

func (c *lsc) updateExecutor() error {
	lsxi, ok := c.lsxInfo[executors.LSX]
	if !ok {
		return goof.WithField("lsx", executors.LSX, "unknown executor")
	}

	lsxBinLock.Lock()
	defer lsxBinLock.Unlock()

	if !gotil.FileExists(c.lsxBinPath) {
		return c.downloadExecutor()
	}

	checksum, err := c.getExecutorChecksum()
	if err != nil {
		return err
	}

	if lsxi.MD5Checksum != checksum {
		return c.downloadExecutor()
	}

	return nil
}

func (c *lsc) getExecutorChecksum() (string, error) {
	f, err := os.Open(c.lsxBinPath)
	if err != nil {
		return "", err
	}
	defer f.Close()

	h := md5.New()
	buf := make([]byte, 1024)
	for {
		n, err := f.Read(buf)
		if err == io.EOF {
			break
		}
		if err != nil {
			return "", err
		}
		if _, err := h.Write(buf[:n]); err != nil {
			return "", err
		}
	}

	return fmt.Sprintf("%x", h.Sum(nil)), nil
}

func (c *lsc) downloadExecutor() error {
	f, err := os.Create(c.lsxBinPath)
	if err != nil {
		return err
	}
	defer f.Close()

	rdr, err := c.Client.ExecutorGet(c.ctx, executors.LSX)
	if _, err := io.Copy(f, rdr); err != nil {
		return err
	}

	if err := os.Chmod(c.lsxBinPath, 0755); err != nil {
		return err
	}

	return nil
}

type iidHeader struct {
	driverName string
	headerName string
	headerValu string
}

func (c *lsc) updateInstanceIDs() error {
	if !EnableInstanceIDHeaders {
		return nil
	}

	c.ctx.Log().Debug("getting instance IDs")

	cache := map[string]*iidHeader{}

	for service, si := range c.svcInfo {

		if _, ok := cache[si.Driver.Name]; ok {
			continue
		}

		iid, err := c.InstanceID(service)
		if err != nil {
			return err
		}

		var h *iidHeader

		if len(iid.Metadata) == 0 {
			h = &iidHeader{
				headerName: apihttp.InstanceIDHeader,
				headerValu: iid.ID,
			}
		} else {
			jBuf, err := json.Marshal(iid)
			if err != nil {
				return err
			}
			h = &iidHeader{
				headerName: apihttp.InstanceID64Header,
				headerValu: base64.StdEncoding.EncodeToString(jBuf),
			}
		}

		h.driverName = si.Driver.Name
		cache[h.driverName] = h
	}

	for _, h := range cache {
		c.Client.Headers.Add(
			h.headerName,
			fmt.Sprintf("%s=%s", h.driverName, h.headerValu))
	}

	return nil
}

type ldHeader struct {
	driverName string
	headerName string
	headerValu map[string]string
}

func (c *lsc) updateLocalDevices() error {
	if !EnableLocalDevicesHeaders {
		return nil
	}

	c.ctx.Log().Debug("getting local devices")

	cache := map[string]*ldHeader{}

	for service, si := range c.svcInfo {

		if _, ok := cache[si.Driver.Name]; ok {
			continue
		}

		ldm, err := c.LocalDevices(service)
		if err != nil {
			return err
		}

		h := &ldHeader{
			driverName: si.Driver.Name,
			headerName: apihttp.LocalDevicesHeader,
			headerValu: ldm,
		}

		cache[h.driverName] = h
	}

	for _, h := range cache {
		buf := &bytes.Buffer{}

		fmt.Fprintf(buf, "%s=", h.driverName)
		for device, mountPoint := range h.headerValu {
			fmt.Fprintf(buf, "%s=%s, ", device, mountPoint)
		}

		if buf.Len() > (len(h.driverName) + 1) {
			buf.Truncate(buf.Len() - 2)
		}

		c.Client.Headers.Add(h.headerName, buf.String())
	}

	return nil
}

func (c *lsc) getServiceInfo(service string) (*types.ServiceInfo, error) {
	si, ok := c.svcInfo[strings.ToLower(service)]
	if !ok {
		return nil, goof.WithField("name", service, "unknown service")
	}
	return si, nil
}

func registerConfig() {
	r := gofig.NewRegistration("libStorage Client")
	lsxBinPath := fmt.Sprintf("%s/%s", paths.UsrDirPath(), executors.LSX)
	r.Key(gofig.String, "", lsxBinPath, "", LSXPathKey)
	r.Key(gofig.Bool, "", false, "", lsxOffline)
	r.Key(gofig.Bool, "", false, "", logEnabledKey)
	r.Key(gofig.String, "", "", "", logOutKey)
	r.Key(gofig.String, "", "", "", logErrKey)
	r.Key(gofig.Bool, "", false, "", logRequestsKey)
	r.Key(gofig.Bool, "", false, "", logResponsesKey)
	r.Key(gofig.Bool, "", false, "", disableKeepAlivesKey)
	gofig.Register(r)
}
<commit_msg>LSXBin Chmod Text File Busy Fix<commit_after>package client

import (
	"bytes"
	"crypto/md5"
	"crypto/tls"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"strings"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/akutz/gofig"
	"github.com/akutz/goof"
	"github.com/akutz/gotil"

	apiclient "github.com/emccode/libstorage/api/client"
	"github.com/emccode/libstorage/api/types"
	"github.com/emccode/libstorage/api/types/context"
	apihttp "github.com/emccode/libstorage/api/types/http"
	"github.com/emccode/libstorage/api/utils"
	apiconfig "github.com/emccode/libstorage/api/utils/config"
	"github.com/emccode/libstorage/api/utils/paths"
	"github.com/emccode/libstorage/cli/executors"

	// load the drivers
	_ "github.com/emccode/libstorage/drivers/os"
)

func init() {
	registerConfig()
}

const (
	clientScope          = "libstorage.client"
	hostKey              = "libstorage.host"
	logEnabledKey        = "libstorage.client.http.logging.enabled"
	logOutKey            = "libstorage.client.http.logging.out"
	logErrKey            = "libstorage.client.http.logging.err"
	logRequestsKey       = "libstorage.client.http.logging.logrequest"
	logResponsesKey      = "libstorage.client.http.logging.logresponse"
	disableKeepAlivesKey = "libstorage.client.http.disableKeepAlives"
	lsxOffline           = "libstorage.client.executor.offline"

	// LSXPathKey is the configuration key for the libStorage executor
	// binary path.
	LSXPathKey = "libstorage.client.executor.path"
)

type lsc struct {
	apiclient.Client
	config             gofig.Config
	svcInfo            apihttp.ServicesMap
	lsxInfo            apihttp.ExecutorsMap
	lsxBinPath         string
	ctx                context.Context
	enableIIDHeader    bool
	enableLclDevHeader bool
}

// New returns a new Client.
func New(config gofig.Config) (Client, error) {

	logFields := log.Fields{}

	if config == nil {
		var err error
		if config, err = apiconfig.NewConfig(); err != nil {
			return nil, err
		}
	}

	addr := config.GetString(hostKey)
	ctx := context.WithContextID(context.Background(), "host", addr)

	proto, lAddr, err := gotil.ParseAddress(addr)
	if err != nil {
		return nil, err
	}

	tlsConfig, err := utils.ParseTLSConfig(
		config.Scope(clientScope), logFields)
	if err != nil {
		return nil, err
	}

	c := &lsc{
		Client: apiclient.Client{
			Host:         getHost(proto, lAddr, tlsConfig),
			Headers:      http.Header{},
			LogRequests:  config.GetBool(logRequestsKey),
			LogResponses: config.GetBool(logResponsesKey),
			Client: &http.Client{
				Transport: &http.Transport{
					Dial: func(string, string) (net.Conn, error) {
						if tlsConfig == nil {
							return net.Dial(proto, lAddr)
						}
						return tls.Dial(proto, lAddr, tlsConfig)
					},
					DisableKeepAlives: config.GetBool(disableKeepAlivesKey),
				},
			},
		},
		config:     config,
		ctx:        ctx,
		lsxBinPath: config.GetString(LSXPathKey),
	}

	if err := c.updateServiceInfo(); err != nil {
		return nil, err
	}

	if !config.GetBool(lsxOffline) {
		if err := c.updateExecutorInfo(); err != nil {
			return nil, err
		}

		if err := c.updateExecutor(); err != nil {
			return nil, err
		}
	}

	if err := c.updateInstanceIDs(); err != nil {
		return nil, err
	}

	if err := c.updateLocalDevices(); err != nil {
		return nil, err
	}

	ctx.Log().WithFields(logFields).Debug("created new libStorage client")

	return c, nil
}

func (c *lsc) API() *apiclient.Client {
	return &c.Client
}

func getHost(proto, lAddr string, tlsConfig *tls.Config) string {
	if tlsConfig != nil && tlsConfig.ServerName != "" {
		return tlsConfig.ServerName
	} else if proto == "unix" {
		return "libstorage-server"
	} else {
		return lAddr
	}
}

func (c *lsc) updateServiceInfo() error {
	c.ctx.Log().Debug("getting service information")
	svcInfo, err := c.Client.Services(c.ctx)
	if err != nil {
		return err
	}
	c.svcInfo = svcInfo
	return nil
}

func (c *lsc) updateExecutorInfo() error {
	c.ctx.Log().Debug("getting executor information")
	lsxInfo, err := c.Client.Executors(c.ctx)
	if err != nil {
		return err
	}
	c.lsxInfo = lsxInfo
	return nil
}

var (
	lsxBinLock = &sync.Mutex{}
)

func (c *lsc) updateExecutor() error {
	lsxi, ok := c.lsxInfo[executors.LSX]
	if !ok {
		return goof.WithField("lsx", executors.LSX, "unknown executor")
	}

	lsxBinLock.Lock()
	defer lsxBinLock.Unlock()

	if !gotil.FileExists(c.lsxBinPath) {
		return c.downloadExecutor()
	}

	checksum, err := c.getExecutorChecksum()
	if err != nil {
		return err
	}

	if lsxi.MD5Checksum != checksum {
		return c.downloadExecutor()
	}

	return nil
}

func (c *lsc) getExecutorChecksum() (string, error) {
	f, err := os.Open(c.lsxBinPath)
	if err != nil {
		return "", err
	}
	defer f.Close()

	h := md5.New()
	buf := make([]byte, 1024)
	for {
		n, err := f.Read(buf)
		if err == io.EOF {
			break
		}
		if err != nil {
			return "", err
		}
		if _, err := h.Write(buf[:n]); err != nil {
			return "", err
		}
	}

	return fmt.Sprintf("%x", h.Sum(nil)), nil
}

func (c *lsc) downloadExecutor() error {

	if err := func() error {
		f, err := os.Create(c.lsxBinPath)
		if err != nil {
			return err
		}
		defer f.Close()

		rdr, err := c.Client.ExecutorGet(c.ctx, executors.LSX)
		if _, err := io.Copy(f, rdr); err != nil {
			return err
		}

		return nil
	}(); err != nil {
		return err
	}

	if err := os.Chmod(c.lsxBinPath, 0755); err != nil {
		return err
	}

	return nil
}

type iidHeader struct {
	driverName string
	headerName string
	headerValu string
}

func (c *lsc) updateInstanceIDs() error {
	if !EnableInstanceIDHeaders {
		return nil
	}

	c.ctx.Log().Debug("getting instance IDs")

	cache := map[string]*iidHeader{}

	for service, si := range c.svcInfo {

		if _, ok := cache[si.Driver.Name]; ok {
			continue
		}

		iid, err := c.InstanceID(service)
		if err != nil {
			return err
		}

		var h *iidHeader

		if len(iid.Metadata) == 0 {
			h = &iidHeader{
				headerName: apihttp.InstanceIDHeader,
				headerValu: iid.ID,
			}
		} else {
			jBuf, err := json.Marshal(iid)
			if err != nil {
				return err
			}
			h = &iidHeader{
				headerName: apihttp.InstanceID64Header,
				headerValu: base64.StdEncoding.EncodeToString(jBuf),
			}
		}

		h.driverName = si.Driver.Name
		cache[h.driverName] = h
	}

	for _, h := range cache {
		c.Client.Headers.Add(
			h.headerName,
			fmt.Sprintf("%s=%s", h.driverName, h.headerValu))
	}

	return nil
}

type ldHeader struct {
	driverName string
	headerName string
	headerValu map[string]string
}

func (c *lsc) updateLocalDevices() error {
	if !EnableLocalDevicesHeaders {
		return nil
	}

	c.ctx.Log().Debug("getting local devices")

	cache := map[string]*ldHeader{}

	for service, si := range c.svcInfo {

		if _, ok := cache[si.Driver.Name]; ok {
			continue
		}

		ldm, err := c.LocalDevices(service)
		if err != nil {
			return err
		}

		h := &ldHeader{
			driverName: si.Driver.Name,
			headerName: apihttp.LocalDevicesHeader,
			headerValu: ldm,
		}

		cache[h.driverName] = h
	}

	for _, h := range cache {
		buf := &bytes.Buffer{}

		fmt.Fprintf(buf, "%s=", h.driverName)
		for device, mountPoint := range h.headerValu {
			fmt.Fprintf(buf, "%s=%s, ", device, mountPoint)
		}

		if buf.Len() > (len(h.driverName) + 1) {
			buf.Truncate(buf.Len() - 2)
		}

		c.Client.Headers.Add(h.headerName, buf.String())
	}

	return nil
}

func (c *lsc) getServiceInfo(service string) (*types.ServiceInfo, error) {
	si, ok := c.svcInfo[strings.ToLower(service)]
	if !ok {
		return nil, goof.WithField("name", service, "unknown service")
	}
	return si, nil
}

func registerConfig() {
	r := gofig.NewRegistration("libStorage Client")
	lsxBinPath := fmt.Sprintf("%s/%s", paths.UsrDirPath(), executors.LSX)
	r.Key(gofig.String, "", lsxBinPath, "", LSXPathKey)
	r.Key(gofig.Bool, "", false, "", lsxOffline)
	r.Key(gofig.Bool, "", false, "", logEnabledKey)
	r.Key(gofig.String, "", "", "", logOutKey)
	r.Key(gofig.String, "", "", "", logErrKey)
	r.Key(gofig.Bool, "", false, "", logRequestsKey)
	r.Key(gofig.Bool, "", false, "", logResponsesKey)
	r.Key(gofig.Bool, "", false, "", disableKeepAlivesKey)
	gofig.Register(r)
}
<|endoftext|>