<commit_before>package fuse

import (
	"log"
	"os"
	"strings"
	"syscall"
	"time"
	"unsafe"
)

const (
	// bufSize should be a power of two to minimize lossage in
	// BufferPool.  The minimum is 8k, but it doesn't cost anything to
	// use a much larger buffer.
	bufSize = (1 << 16)
	maxRead = bufSize - PAGESIZE
)

// MountState contains the logic for reading from the FUSE device and
// translating it to RawFileSystem interface calls.
type MountState struct {
	// Empty if unmounted.
	mountPoint string
	fileSystem RawFileSystem

	// I/O with kernel and daemon.
	mountFile *os.File

	// Dump debug info onto stdout.
	Debug bool

	// For efficient reads and writes.
	buffers *BufferPoolImpl

	*LatencyMap

	opts           *MountOptions
	kernelSettings InitIn
}

func (me *MountState) KernelSettings() InitIn {
	return me.kernelSettings
}

func (me *MountState) MountPoint() string {
	return me.mountPoint
}

// Mount filesystem on mountPoint.
func (me *MountState) Mount(mountPoint string, opts *MountOptions) os.Error {
	if opts == nil {
		opts = &MountOptions{
			MaxBackground: _DEFAULT_BACKGROUND_TASKS,
		}
	}
	me.opts = opts

	optStrs := opts.Options
	if opts.AllowOther {
		optStrs = append(optStrs, "allow_other")
	}

	file, mp, err := mount(mountPoint, strings.Join(optStrs, ","))
	if err != nil {
		return err
	}
	initParams := RawFsInit{
		InodeNotify: func(n *NotifyInvalInodeOut) Status {
			return me.writeInodeNotify(n)
		},
		EntryNotify: func(parent uint64, n string) Status {
			return me.writeEntryNotify(parent, n)
		},
	}
	me.fileSystem.Init(&initParams)
	me.mountPoint = mp
	me.mountFile = file
	return nil
}

func (me *MountState) SetRecordStatistics(record bool) {
	if record {
		me.LatencyMap = NewLatencyMap()
	} else {
		me.LatencyMap = nil
	}
}

func (me *MountState) Unmount() os.Error {
	// Todo: flush/release all files/dirs?
	err := unmount(me.mountPoint)
	if err == nil {
		me.mountPoint = ""
		me.mountFile.Close()
		me.mountFile = nil
	}
	return err
}

func NewMountState(fs RawFileSystem) *MountState {
	me := new(MountState)
	me.mountPoint = ""
	me.fileSystem = fs
	me.buffers = NewBufferPool()
	return me
}

func (me *MountState) Latencies() map[string]float64 {
	return me.LatencyMap.Latencies(1e-3)
}

func (me *MountState) OperationCounts() map[string]int {
	return me.LatencyMap.Counts()
}

func (me *MountState) BufferPoolStats() string {
	return me.buffers.String()
}

func (me *MountState) newRequest(oldReq *request) *request {
	if oldReq != nil {
		me.buffers.FreeBuffer(oldReq.flatData)

		*oldReq = request{
			status:   OK,
			inputBuf: oldReq.inputBuf[0:bufSize],
		}
		return oldReq
	}

	return &request{
		status:   OK,
		inputBuf: me.buffers.AllocBuffer(bufSize),
	}
}

func (me *MountState) readRequest(req *request) os.Error {
	n, err := me.mountFile.Read(req.inputBuf)
	// If we start timing before the read, we may take into
	// account waiting for input into the timing.
	if me.LatencyMap != nil {
		req.startNs = time.Nanoseconds()
	}
	req.inputBuf = req.inputBuf[0:n]
	return err
}

func (me *MountState) recordStats(req *request) {
	if me.LatencyMap != nil {
		endNs := time.Nanoseconds()
		dt := endNs - req.startNs

		opname := operationName(req.inHeader.opcode)
		me.LatencyMap.AddMany(
			[]LatencyArg{
				{opname, "", dt},
				{opname + "-write", "", endNs - req.preWriteNs}})
	}
}

// Loop initiates the FUSE loop. Normally, callers should run Loop()
// and wait for it to exit, but tests will want to run this in a
// goroutine.
//
// If threaded is given, each filesystem operation executes in a
// separate goroutine.
func (me *MountState) Loop(threaded bool) {
	// To limit scheduling overhead, we spawn multiple read loops.
	// This means that the request once read does not need to be
	// assigned to another thread, so it avoids a context switch.
	if threaded {
		for i := 0; i < me.opts.MaxBackground-1; i++ {
			go me.loop()
		}
	}
	me.loop()
	me.mountFile.Close()
}

func (me *MountState) loop() {
	var lastReq *request
	for {
		req := me.newRequest(lastReq)
		lastReq = req
		err := me.readRequest(req)
		if err != nil {
			errNo := OsErrorToErrno(err)

			// Retry.
			if errNo == syscall.ENOENT {
				continue
			}

			if errNo == syscall.ENODEV {
				// Unmount.
				break
			}

			log.Printf("Failed to read from fuse conn: %v", err)
			break
		}
		me.handleRequest(req)
	}
}

func (me *MountState) handleRequest(req *request) {
	defer me.recordStats(req)

	req.parse()
	if req.handler == nil {
		req.status = ENOSYS
	}

	if req.status.Ok() && me.Debug {
		log.Println(req.InputDebug())
	}

	if req.status.Ok() && req.handler.Func == nil {
		log.Printf("Unimplemented opcode %v", req.inHeader.opcode)
		req.status = ENOSYS
	}

	if req.status.Ok() {
		req.handler.Func(me, req)
	}

	errNo := me.write(req)
	if errNo != 0 {
		log.Printf("writer: Write/Writev %v failed, err: %v. opcode: %v",
			req.outHeaderBytes, errNo, operationName(req.inHeader.opcode))
	}
}

func (me *MountState) write(req *request) Status {
	// If we try to write OK, nil, we will get
	// error:  writer: Writev [[16 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0]]
	// failed, err: writev: no such file or directory
	if req.inHeader.opcode == _OP_FORGET {
		return OK
	}

	req.serialize()
	if me.Debug {
		log.Println(req.OutputDebug())
	}

	if me.LatencyMap != nil {
		req.preWriteNs = time.Nanoseconds()
	}

	if req.outHeaderBytes == nil {
		return OK
	}

	var err os.Error
	if req.flatData == nil {
		_, err = me.mountFile.Write(req.outHeaderBytes)
	} else {
		_, err = Writev(me.mountFile.Fd(),
			[][]byte{req.outHeaderBytes, req.flatData})
	}

	return OsErrorToErrno(err)
}

func (me *MountState) writeInodeNotify(entry *NotifyInvalInodeOut) Status {
	req := request{
		inHeader: &InHeader{
			opcode: _OP_NOTIFY_INODE,
		},
		handler: operationHandlers[_OP_NOTIFY_INODE],
		status:  NOTIFY_INVAL_INODE,
	}
	req.outData = unsafe.Pointer(entry)
	req.serialize()
	result := me.write(&req)

	if me.Debug {
		log.Println("Response: INODE_NOTIFY", result)
	}
	return result
}

func (me *MountState) writeEntryNotify(parent uint64, name string) Status {
	req := request{
		inHeader: &InHeader{
			opcode: _OP_NOTIFY_ENTRY,
		},
		handler: operationHandlers[_OP_NOTIFY_ENTRY],
		status:  NOTIFY_INVAL_ENTRY,
	}
	entry := &NotifyInvalEntryOut{
		Parent:  parent,
		NameLen: uint32(len(name)),
	}

	// Many versions of FUSE generate stacktraces if the
	// terminating null byte is missing.
	nameBytes := []byte(name + "\000")
	req.outData = unsafe.Pointer(entry)
	req.flatData = nameBytes
	req.serialize()
	result := me.write(&req)

	if me.Debug {
		log.Printf("Response: ENTRY_NOTIFY: %v", result)
	}
	return result
}
<commit_msg>Remove pre-spawned goroutine pool.<commit_after>package fuse

import (
	"log"
	"os"
	"strings"
	"syscall"
	"time"
	"unsafe"
)

const (
	// bufSize should be a power of two to minimize lossage in
	// BufferPool.  The minimum is 8k, but it doesn't cost anything to
	// use a much larger buffer.
	bufSize = (1 << 16)
	maxRead = bufSize - PAGESIZE
)

// MountState contains the logic for reading from the FUSE device and
// translating it to RawFileSystem interface calls.
type MountState struct {
	// Empty if unmounted.
	mountPoint string
	fileSystem RawFileSystem

	// I/O with kernel and daemon.
	mountFile *os.File

	// Dump debug info onto stdout.
	Debug bool

	// For efficient reads and writes.
	buffers *BufferPoolImpl

	*LatencyMap

	opts           *MountOptions
	kernelSettings InitIn
}

func (me *MountState) KernelSettings() InitIn {
	return me.kernelSettings
}

func (me *MountState) MountPoint() string {
	return me.mountPoint
}

// Mount filesystem on mountPoint.
func (me *MountState) Mount(mountPoint string, opts *MountOptions) os.Error {
	if opts == nil {
		opts = &MountOptions{
			MaxBackground: _DEFAULT_BACKGROUND_TASKS,
		}
	}
	me.opts = opts

	optStrs := opts.Options
	if opts.AllowOther {
		optStrs = append(optStrs, "allow_other")
	}

	file, mp, err := mount(mountPoint, strings.Join(optStrs, ","))
	if err != nil {
		return err
	}
	initParams := RawFsInit{
		InodeNotify: func(n *NotifyInvalInodeOut) Status {
			return me.writeInodeNotify(n)
		},
		EntryNotify: func(parent uint64, n string) Status {
			return me.writeEntryNotify(parent, n)
		},
	}
	me.fileSystem.Init(&initParams)
	me.mountPoint = mp
	me.mountFile = file
	return nil
}

func (me *MountState) SetRecordStatistics(record bool) {
	if record {
		me.LatencyMap = NewLatencyMap()
	} else {
		me.LatencyMap = nil
	}
}

func (me *MountState) Unmount() os.Error {
	// Todo: flush/release all files/dirs?
	err := unmount(me.mountPoint)
	if err == nil {
		me.mountPoint = ""
		me.mountFile.Close()
		me.mountFile = nil
	}
	return err
}

func NewMountState(fs RawFileSystem) *MountState {
	me := new(MountState)
	me.mountPoint = ""
	me.fileSystem = fs
	me.buffers = NewBufferPool()
	return me
}

func (me *MountState) Latencies() map[string]float64 {
	return me.LatencyMap.Latencies(1e-3)
}

func (me *MountState) OperationCounts() map[string]int {
	return me.LatencyMap.Counts()
}

func (me *MountState) BufferPoolStats() string {
	return me.buffers.String()
}

func (me *MountState) newRequest() *request {
	return &request{
		status:   OK,
		inputBuf: me.buffers.AllocBuffer(bufSize),
	}
}

func (me *MountState) readRequest(req *request) os.Error {
	n, err := me.mountFile.Read(req.inputBuf)
	// If we start timing before the read, we may take into
	// account waiting for input into the timing.
	if me.LatencyMap != nil {
		req.startNs = time.Nanoseconds()
	}
	req.inputBuf = req.inputBuf[0:n]
	return err
}

func (me *MountState) recordStats(req *request) {
	if me.LatencyMap != nil {
		endNs := time.Nanoseconds()
		dt := endNs - req.startNs

		opname := operationName(req.inHeader.opcode)
		me.LatencyMap.AddMany(
			[]LatencyArg{
				{opname, "", dt},
				{opname + "-write", "", endNs - req.preWriteNs}})
	}
}

// Loop initiates the FUSE loop. Normally, callers should run Loop()
// and wait for it to exit, but tests will want to run this in a
// goroutine.
//
// If threaded is given, each filesystem operation executes in a
// separate goroutine.
func (me *MountState) Loop(unused bool) {
	me.loop()
	me.mountFile.Close()
}

func (me *MountState) loop() {
	for {
		req := me.newRequest()
		err := me.readRequest(req)
		if err != nil {
			errNo := OsErrorToErrno(err)

			// Retry.
			if errNo == syscall.ENOENT {
				continue
			}

			if errNo == syscall.ENODEV {
				// Unmount.
				break
			}

			log.Printf("Failed to read from fuse conn: %v", err)
			break
		}

		// When closely analyzing timings, the context switch
		// generates some delay.  While unfortunate, the
		// alternative is to have a fixed goroutine pool,
		// which will lock up the FS if the daemon has too
		// many blocking calls.
		go func(r *request) {
			me.handleRequest(r)
			me.discardRequest(r)
		}(req)
	}
}

func (me *MountState) discardRequest(req *request) {
	me.buffers.FreeBuffer(req.flatData)
	me.buffers.FreeBuffer(req.inputBuf)
}

func (me *MountState) handleRequest(req *request) {
	defer me.recordStats(req)

	req.parse()
	if req.handler == nil {
		req.status = ENOSYS
	}

	if req.status.Ok() && me.Debug {
		log.Println(req.InputDebug())
	}

	if req.status.Ok() && req.handler.Func == nil {
		log.Printf("Unimplemented opcode %v", req.inHeader.opcode)
		req.status = ENOSYS
	}

	if req.status.Ok() {
		req.handler.Func(me, req)
	}

	errNo := me.write(req)
	if errNo != 0 {
		log.Printf("writer: Write/Writev %v failed, err: %v. opcode: %v",
			req.outHeaderBytes, errNo, operationName(req.inHeader.opcode))
	}
}

func (me *MountState) write(req *request) Status {
	// If we try to write OK, nil, we will get
	// error:  writer: Writev [[16 0 0 0 0 0 0 0 17 0 0 0 0 0 0 0]]
	// failed, err: writev: no such file or directory
	if req.inHeader.opcode == _OP_FORGET {
		return OK
	}

	req.serialize()
	if me.Debug {
		log.Println(req.OutputDebug())
	}

	if me.LatencyMap != nil {
		req.preWriteNs = time.Nanoseconds()
	}

	if req.outHeaderBytes == nil {
		return OK
	}

	var err os.Error
	if req.flatData == nil {
		_, err = me.mountFile.Write(req.outHeaderBytes)
	} else {
		_, err = Writev(me.mountFile.Fd(),
			[][]byte{req.outHeaderBytes, req.flatData})
	}

	return OsErrorToErrno(err)
}

func (me *MountState) writeInodeNotify(entry *NotifyInvalInodeOut) Status {
	req := request{
		inHeader: &InHeader{
			opcode: _OP_NOTIFY_INODE,
		},
		handler: operationHandlers[_OP_NOTIFY_INODE],
		status:  NOTIFY_INVAL_INODE,
	}
	req.outData = unsafe.Pointer(entry)
	req.serialize()
	result := me.write(&req)

	if me.Debug {
		log.Println("Response: INODE_NOTIFY", result)
	}
	return result
}

func (me *MountState) writeEntryNotify(parent uint64, name string) Status {
	req := request{
		inHeader: &InHeader{
			opcode: _OP_NOTIFY_ENTRY,
		},
		handler: operationHandlers[_OP_NOTIFY_ENTRY],
		status:  NOTIFY_INVAL_ENTRY,
	}
	entry := &NotifyInvalEntryOut{
		Parent:  parent,
		NameLen: uint32(len(name)),
	}

	// Many versions of FUSE generate stacktraces if the
	// terminating null byte is missing.
	nameBytes := []byte(name + "\000")
	req.outData = unsafe.Pointer(entry)
	req.flatData = nameBytes
	req.serialize()
	result := me.write(&req)

	if me.Debug {
		log.Printf("Response: ENTRY_NOTIFY: %v", result)
	}
	return result
}
<|endoftext|>


<commit_before>package nodefs

import (
	"log"

	"github.com/hanwen/go-fuse/fuse"
)

type connectorDir struct {
	node       Node
	stream     []fuse.DirEntry
	lastOffset uint64
	rawFS      fuse.RawFileSystem
}

func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
	if d.stream == nil {
		return fuse.OK
	}
	// rewinddir() should be as if reopening directory.
	// TODO - test this.
	if d.lastOffset > 0 && input.Offset == 0 {
		d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
		if !code.Ok() {
			return code
		}
	}

	if input.Offset > uint64(len(d.stream)) {
		// This shouldn't happen, but let's not crash.
		return fuse.EINVAL
	}

	todo := d.stream[input.Offset:]
	for _, e := range todo {
		if e.Name == "" {
			log.Printf("got emtpy directory entry, mode %o.", e.Mode)
			continue
		}
		ok, off := out.AddDirEntry(e)
		d.lastOffset = off
		if !ok {
			break
		}
	}
	return fuse.OK
}

func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
	if d.stream == nil {
		return fuse.OK
	}

	// rewinddir() should be as if reopening directory.
	if d.lastOffset > 0 && input.Offset == 0 {
		d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
		if !code.Ok() {
			return code
		}
	}

	if input.Offset > uint64(len(d.stream)) {
		// This shouldn't happen, but let's not crash.
		return fuse.EINVAL
	}
	todo := d.stream[input.Offset:]
	for _, e := range todo {
		if e.Name == "" {
			log.Printf("got empty directory entry, mode %o.", e.Mode)
			continue
		}

		if e.Name == "." || e.Name == ".." {
			continue
		}

		// we have to be sure entry will fit if we try to add
		// it, or we'll mess up the lookup counts.
		entryDest, off := out.AddDirLookupEntry(e)
		if entryDest == nil {
			break
		}
		entryDest.Ino = uint64(fuse.FUSE_UNKNOWN_INO)

		// We ignore the return value
		code := d.rawFS.Lookup(&input.InHeader, e.Name, entryDest)
		if !code.Ok() {
			// if something went wrong, clear out the entry.
			*entryDest = fuse.EntryOut{}
		}
		d.lastOffset = off
	}
	return fuse.OK

}

type rawDir interface {
	ReadDir(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
	ReadDirPlus(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
}
<commit_msg>ReadDirPlus: Do not drop "." and ".."<commit_after>package nodefs

import (
	"log"

	"github.com/hanwen/go-fuse/fuse"
)

type connectorDir struct {
	node       Node
	stream     []fuse.DirEntry
	lastOffset uint64
	rawFS      fuse.RawFileSystem
}

func (d *connectorDir) ReadDir(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
	if d.stream == nil {
		return fuse.OK
	}
	// rewinddir() should be as if reopening directory.
	// TODO - test this.
	if d.lastOffset > 0 && input.Offset == 0 {
		d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
		if !code.Ok() {
			return code
		}
	}

	if input.Offset > uint64(len(d.stream)) {
		// This shouldn't happen, but let's not crash.
		return fuse.EINVAL
	}

	todo := d.stream[input.Offset:]
	for _, e := range todo {
		if e.Name == "" {
			log.Printf("got emtpy directory entry, mode %o.", e.Mode)
			continue
		}
		ok, off := out.AddDirEntry(e)
		d.lastOffset = off
		if !ok {
			break
		}
	}
	return fuse.OK
}

func (d *connectorDir) ReadDirPlus(input *fuse.ReadIn, out *fuse.DirEntryList) (code fuse.Status) {
	if d.stream == nil {
		return fuse.OK
	}

	// rewinddir() should be as if reopening directory.
	if d.lastOffset > 0 && input.Offset == 0 {
		d.stream, code = d.node.OpenDir((*fuse.Context)(&input.Context))
		if !code.Ok() {
			return code
		}
	}

	if input.Offset > uint64(len(d.stream)) {
		// This shouldn't happen, but let's not crash.
		return fuse.EINVAL
	}
	todo := d.stream[input.Offset:]
	for _, e := range todo {
		if e.Name == "" {
			log.Printf("got empty directory entry, mode %o.", e.Mode)
			continue
		}

		// we have to be sure entry will fit if we try to add
		// it, or we'll mess up the lookup counts.
		entryDest, off := out.AddDirLookupEntry(e)
		if entryDest == nil {
			break
		}
		entryDest.Ino = uint64(fuse.FUSE_UNKNOWN_INO)

		// No need to fill attributes for . and ..
		if e.Name == "." || e.Name == ".." {
			continue
		}

		code := d.rawFS.Lookup(&input.InHeader, e.Name, entryDest)
		if !code.Ok() {
			// if something went wrong, clear out the entry.
			*entryDest = fuse.EntryOut{}
		}
		d.lastOffset = off
	}
	return fuse.OK

}

type rawDir interface {
	ReadDir(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
	ReadDirPlus(out *fuse.DirEntryList, input *fuse.ReadIn, c *fuse.Context) fuse.Status
}
<|endoftext|>


<commit_before>package dockerignore

import (
	"bufio"
	"fmt"
	"io"
	"path/filepath"
	"strings"
)

// ReadAll reads a .dockerignore file and returns the list of file patterns
// to ignore. Note this will trim whitespace from each line as well
// as use GO's "clean" func to get the shortest/cleanest path for each.
func ReadAll(reader io.ReadCloser) ([]string, error) {
	if reader == nil {
		return nil, nil
	}
	defer reader.Close()
	scanner := bufio.NewScanner(reader)
	var excludes []string

	for scanner.Scan() {
		pattern := strings.TrimSpace(scanner.Text())
		if pattern == "" {
			continue
		}
		pattern = filepath.Clean(pattern)
		excludes = append(excludes, pattern)
	}
	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("Error reading .dockerignore: %v", err)
	}
	return excludes, nil
}
<commit_msg>Fix ReadAll to run on Windows.<commit_after>package dockerignore

import (
	"bufio"
	"fmt"
	"io"
	"path/filepath"
	"strings"
)

// ReadAll reads a .dockerignore file and returns the list of file patterns
// to ignore. Note this will trim whitespace from each line as well
// as use GO's "clean" func to get the shortest/cleanest path for each.
func ReadAll(reader io.ReadCloser) ([]string, error) {
	if reader == nil {
		return nil, nil
	}
	defer reader.Close()
	scanner := bufio.NewScanner(reader)
	var excludes []string

	for scanner.Scan() {
		pattern := strings.TrimSpace(scanner.Text())
		if pattern == "" {
			continue
		}
		pattern = filepath.Clean(pattern)
		pattern = filepath.ToSlash(pattern)
		excludes = append(excludes, pattern)
	}
	if err := scanner.Err(); err != nil {
		return nil, fmt.Errorf("Error reading .dockerignore: %v", err)
	}
	return excludes, nil
}
<|endoftext|>


<commit_before>package common

import (
	"bytes"
	"fmt"
	"github.com/going/toolkit/xmlpath"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"time"
)

type Parallels9Driver struct {
	// This is the path to the "prlctl" application.
	PrlctlPath string
}

func (d *Parallels9Driver) Import(name, srcPath, dstDir string) error {

	err := d.Prlctl("register", srcPath, "--preserve-uuid")
	if err != nil {
		return err
	}

	srcId, err := getVmId(srcPath)
	if err != nil {
		return err
	}

	srcMac, err := getFirtsMacAddress(srcPath)
	if err != nil {
		return err
	}

	err = d.Prlctl("clone", srcId, "--name", name, "--dst", dstDir)
	if err != nil {
		return err
	}

	err = d.Prlctl("unregister", srcId)
	if err != nil {
		return err
	}

	err = d.Prlctl("set", name, "--device-set", "net0", "--mac", srcMac)
	return nil
}

func getVmId(path string) (string, error) {
	return getConfigValueFromXpath(path, "/ParallelsVirtualMachine/Identification/VmUuid")
}

func getFirtsMacAddress(path string) (string, error) {
	return getConfigValueFromXpath(path, "/ParallelsVirtualMachine/Hardware/NetworkAdapter[@id='0']/MAC")
}

func getConfigValueFromXpath(path, xpath string) (string, error) {
	file, err := os.Open(path + "/config.pvs")
	if err != nil {
		return "", err
	}
	xpathComp := xmlpath.MustCompile(xpath)
	root, err := xmlpath.Parse(file)
	if err != nil {
		return "", err
	}
	value, _ := xpathComp.String(root)
	return value, nil
}

func (d *Parallels9Driver) IsRunning(name string) (bool, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.PrlctlPath, "list", name, "--no-header", "--output", "status")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return false, err
	}

	log.Printf("Checking VM state: %s\n", strings.TrimSpace(stdout.String()))

	for _, line := range strings.Split(stdout.String(), "\n") {
		if line == "running" {
			return true, nil
		}

		if line == "suspended" {
			return true, nil
		}
		if line == "paused" {
			return true, nil
		}
		if line == "stopping" {
			return true, nil
		}
	}

	return false, nil
}

func (d *Parallels9Driver) Stop(name string) error {
	if err := d.Prlctl("stop", name); err != nil {
		return err
	}

	// We sleep here for a little bit to let the session "unlock"
	time.Sleep(2 * time.Second)

	return nil
}

func (d *Parallels9Driver) Prlctl(args ...string) error {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing prlctl: %#v", args)
	cmd := exec.Command(d.PrlctlPath, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("prlctl error: %s", stderrString)
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func (d *Parallels9Driver) Verify() error {
	version, _ := d.Version()
	if !strings.HasPrefix(version, "9.") {
		return fmt.Errorf("The packer-parallels builder plugin only supports Parallels Desktop v. 9. You have: %s!\n", version)
	}
	return nil
}

func (d *Parallels9Driver) Version() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.PrlctlPath, "--version")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	versionOutput := strings.TrimSpace(stdout.String())
	re := regexp.MustCompile("prlctl version ([0-9\\.]+)")
	verMatch := re.FindAllStringSubmatch(versionOutput, 1)

	if len(verMatch) != 1 {
		return "", fmt.Errorf("prlctl version not found!\n")
	}

	version := verMatch[0][1]
	log.Printf("prlctl version: %s\n", version)
	return version, nil
}

func (d *Parallels9Driver) SendKeyScanCodes(vmName string, codes ...string) error {
	var stdout, stderr bytes.Buffer

	args := prepend(vmName, codes)
	cmd := exec.Command("prltype", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("prltype error: %s", stderrString)
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func prepend(head string, tail []string) []string {
	tmp := make([]string, len(tail)+1)
	for i := 0; i < len(tail); i++ {
		tmp[i+1] = tail[i]
	}
	tmp[0] = head
	return tmp
}

func (d *Parallels9Driver) Mac(vmName string) (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.PrlctlPath, "list", "-i", vmName)
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		log.Printf("MAC address for NIC: nic0 on Virtual Machine: %s not found!\n", vmName)
		return "", err
	}

	stdoutString := strings.TrimSpace(stdout.String())
	re := regexp.MustCompile("net0.* mac=([0-9A-F]{12}) card=.*")
	macMatch := re.FindAllStringSubmatch(stdoutString, 1)

	if len(macMatch) != 1 {
		return "", fmt.Errorf("MAC address for NIC: nic0 on Virtual Machine: %s not found!\n", vmName)
	}

	mac := macMatch[0][1]
	log.Printf("Found MAC address for NIC: net0 - %s\n", mac)
	return mac, nil
}

// Finds the IP address of a VM connected that uses DHCP by its MAC address
func (d *Parallels9Driver) IpAddress(mac string) (string, error) {
	var stdout bytes.Buffer
	dhcp_lease_file := "/Library/Preferences/Parallels/parallels_dhcp_leases"

	if len(mac) != 12 {
		return "", fmt.Errorf("Not a valid MAC address: %s. It should be exactly 12 digits.", mac)
	}

	cmd := exec.Command("grep", "-i", mac, dhcp_lease_file)
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	stdoutString := strings.TrimSpace(stdout.String())
	re := regexp.MustCompile("(.*)=.*")
	ipMatch := re.FindAllStringSubmatch(stdoutString, 1)

	if len(ipMatch) != 1 {
		return "", fmt.Errorf("IP lease not found for MAC address %s in: %s\n", mac, dhcp_lease_file)
	}

	ip := ipMatch[0][1]
	log.Printf("Found IP lease: %s for MAC address %s\n", ip, mac)
	return ip, nil
}
<commit_msg>parallels: Support for Parallels Desktop 10<commit_after>package common

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"os/exec"
	"regexp"
	"strings"
	"time"

	"github.com/going/toolkit/xmlpath"
)

// Driver supporting Parallels Desktop for Mac v. 9 & 10
type Parallels9Driver struct {
	// This is the path to the "prlctl" application.
	PrlctlPath string
}

func (d *Parallels9Driver) Import(name, srcPath, dstDir string) error {

	err := d.Prlctl("register", srcPath, "--preserve-uuid")
	if err != nil {
		return err
	}

	srcId, err := getVmId(srcPath)
	if err != nil {
		return err
	}

	srcMac, err := getFirtsMacAddress(srcPath)
	if err != nil {
		return err
	}

	err = d.Prlctl("clone", srcId, "--name", name, "--dst", dstDir)
	if err != nil {
		return err
	}

	err = d.Prlctl("unregister", srcId)
	if err != nil {
		return err
	}

	err = d.Prlctl("set", name, "--device-set", "net0", "--mac", srcMac)
	return nil
}

func getVmId(path string) (string, error) {
	return getConfigValueFromXpath(path, "/ParallelsVirtualMachine/Identification/VmUuid")
}

func getFirtsMacAddress(path string) (string, error) {
	return getConfigValueFromXpath(path, "/ParallelsVirtualMachine/Hardware/NetworkAdapter[@id='0']/MAC")
}

func getConfigValueFromXpath(path, xpath string) (string, error) {
	file, err := os.Open(path + "/config.pvs")
	if err != nil {
		return "", err
	}
	xpathComp := xmlpath.MustCompile(xpath)
	root, err := xmlpath.Parse(file)
	if err != nil {
		return "", err
	}
	value, _ := xpathComp.String(root)
	return value, nil
}

func (d *Parallels9Driver) IsRunning(name string) (bool, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.PrlctlPath, "list", name, "--no-header", "--output", "status")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return false, err
	}

	log.Printf("Checking VM state: %s\n", strings.TrimSpace(stdout.String()))

	for _, line := range strings.Split(stdout.String(), "\n") {
		if line == "running" {
			return true, nil
		}

		if line == "suspended" {
			return true, nil
		}
		if line == "paused" {
			return true, nil
		}
		if line == "stopping" {
			return true, nil
		}
	}

	return false, nil
}

func (d *Parallels9Driver) Stop(name string) error {
	if err := d.Prlctl("stop", name); err != nil {
		return err
	}

	// We sleep here for a little bit to let the session "unlock"
	time.Sleep(2 * time.Second)

	return nil
}

func (d *Parallels9Driver) Prlctl(args ...string) error {
	var stdout, stderr bytes.Buffer

	log.Printf("Executing prlctl: %#v", args)
	cmd := exec.Command(d.PrlctlPath, args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("prlctl error: %s", stderrString)
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func (d *Parallels9Driver) Verify() error {
	version, _ := d.Version()
	if !(strings.HasPrefix(version, "9.") || strings.HasPrefix(version, "10.")) {
		return fmt.Errorf("The packer-parallels builder plugin only supports Parallels Desktop v. 9 & 10. You have: %s!\n", version)
	}
	return nil
}

func (d *Parallels9Driver) Version() (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.PrlctlPath, "--version")
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	versionOutput := strings.TrimSpace(stdout.String())
	re := regexp.MustCompile("prlctl version ([0-9\\.]+)")
	verMatch := re.FindAllStringSubmatch(versionOutput, 1)

	if len(verMatch) != 1 {
		return "", fmt.Errorf("prlctl version not found!\n")
	}

	version := verMatch[0][1]
	log.Printf("prlctl version: %s\n", version)
	return version, nil
}

func (d *Parallels9Driver) SendKeyScanCodes(vmName string, codes ...string) error {
	var stdout, stderr bytes.Buffer

	args := prepend(vmName, codes)
	cmd := exec.Command("prltype", args...)
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	err := cmd.Run()

	stdoutString := strings.TrimSpace(stdout.String())
	stderrString := strings.TrimSpace(stderr.String())

	if _, ok := err.(*exec.ExitError); ok {
		err = fmt.Errorf("prltype error: %s", stderrString)
	}

	log.Printf("stdout: %s", stdoutString)
	log.Printf("stderr: %s", stderrString)

	return err
}

func prepend(head string, tail []string) []string {
	tmp := make([]string, len(tail)+1)
	for i := 0; i < len(tail); i++ {
		tmp[i+1] = tail[i]
	}
	tmp[0] = head
	return tmp
}

func (d *Parallels9Driver) Mac(vmName string) (string, error) {
	var stdout bytes.Buffer

	cmd := exec.Command(d.PrlctlPath, "list", "-i", vmName)
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		log.Printf("MAC address for NIC: nic0 on Virtual Machine: %s not found!\n", vmName)
		return "", err
	}

	stdoutString := strings.TrimSpace(stdout.String())
	re := regexp.MustCompile("net0.* mac=([0-9A-F]{12}) card=.*")
	macMatch := re.FindAllStringSubmatch(stdoutString, 1)

	if len(macMatch) != 1 {
		return "", fmt.Errorf("MAC address for NIC: nic0 on Virtual Machine: %s not found!\n", vmName)
	}

	mac := macMatch[0][1]
	log.Printf("Found MAC address for NIC: net0 - %s\n", mac)
	return mac, nil
}

// Finds the IP address of a VM connected that uses DHCP by its MAC address
func (d *Parallels9Driver) IpAddress(mac string) (string, error) {
	var stdout bytes.Buffer
	dhcp_lease_file := "/Library/Preferences/Parallels/parallels_dhcp_leases"

	if len(mac) != 12 {
		return "", fmt.Errorf("Not a valid MAC address: %s. It should be exactly 12 digits.", mac)
	}

	cmd := exec.Command("grep", "-i", mac, dhcp_lease_file)
	cmd.Stdout = &stdout
	if err := cmd.Run(); err != nil {
		return "", err
	}

	stdoutString := strings.TrimSpace(stdout.String())
	re := regexp.MustCompile("(.*)=.*")
	ipMatch := re.FindAllStringSubmatch(stdoutString, 1)

	if len(ipMatch) != 1 {
		return "", fmt.Errorf("IP lease not found for MAC address %s in: %s\n", mac, dhcp_lease_file)
	}

	ip := ipMatch[0][1]
	log.Printf("Found IP lease: %s for MAC address %s\n", ip, mac)
	return ip, nil
}
<|endoftext|>


<commit_before>package vmx

import (
	"context"
	"fmt"
	"log"
	"path/filepath"
	"regexp"

	vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

// StepCloneVMX takes a VMX file and clones the VM into the output directory.
type StepCloneVMX struct {
	OutputDir string
	Path      string
	VMName    string
}

type vmxAdapter struct {
	diskPathKeyRe string
}

var (
	// The VMX file stores the path to a configured disk, and information
	// about that disks attachment to a virtual adapter/controller, as a
	// key/value pair.
	// For a virtual disk attached to bus ID 3 of the virtual machines
	// first SCSI adapter the key/value pair would look something like:
	// scsi0:3.fileName = "relative/path/to/scsiDisk.vmdk"
	// The supported adapter types and configuration maximums for each type
	// vary according to the VMware platform type and version, and the
	// Virtual Machine Hardware version used. See the 'Virtual Machine
	// Maximums' section within VMware's 'Configuration Maximums'
	// documentation for each platform:
	// https://kb.vmware.com/s/article/1003497
	// Information about the supported Virtual Machine Hardware versions:
	// https://kb.vmware.com/s/article/1003746
	// The following regexp's are used to match all possible disk attachment
	// points that may be found in the VMX file across all VMware
	// platforms/versions and Virtual Machine Hardware versions
	scsiAdapter = vmxAdapter{
		diskPathKeyRe: `(?i)^scsi[[:digit:]]:[[:digit:]]{1,2}\.fileName`,
	}
	sataAdapter = vmxAdapter{
		diskPathKeyRe: `(?i)^sata[[:digit:]]:[[:digit:]]{1,2}\.fileName`,
	}
	nvmeAdapter = vmxAdapter{
		diskPathKeyRe: `(?i)^nvme[[:digit:]]:[[:digit:]]{1,2}\.fileName`,
	}
	ideAdapter = vmxAdapter{
		diskPathKeyRe: `(?i)^ide[[:digit:]]:[[:digit:]]\.fileName`,
	}
)

func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
	driver := state.Get("driver").(vmwcommon.Driver)
	ui := state.Get("ui").(packer.Ui)

	// Set the path we want for the new .vmx file and clone
	vmxPath := filepath.Join(s.OutputDir, s.VMName+".vmx")
	ui.Say("Cloning source VM...")
	log.Printf("Cloning from: %s", s.Path)
	log.Printf("Cloning to: %s", vmxPath)
	if err := driver.Clone(vmxPath, s.Path); err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	// Read in the machine configuration from the cloned VMX file
	//
	// * The main driver needs the path to the vmx (set above) and the
	// network type so that it can work out things like IP's and MAC
	// addresses
	// * The disk compaction step needs the paths to all attached disks
	vmxData, err := vmwcommon.ReadVMX(vmxPath)
	if err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	// Search across all adapter types to get the filenames of attached disks
	allDiskAdapters := []vmxAdapter{
		scsiAdapter,
		sataAdapter,
		nvmeAdapter,
		ideAdapter,
	}
	var diskFilenames []string
	for _, adapter := range allDiskAdapters {
		diskFilenames = append(diskFilenames, getAttachedDisks(adapter, vmxData)...)
	}

	// Write out the relative, host filesystem paths to the disks
	var diskFullPaths []string
	for _, diskFilename := range diskFilenames {
		log.Printf("Found attached disk with filename: %s", diskFilename)
		diskFullPaths = append(diskFullPaths, filepath.Join(s.OutputDir, diskFilename))
	}

	if len(diskFullPaths) == 0 {
		state.Put("error", fmt.Errorf("Could not enumerate disk info from the vmx file"))
		return multistep.ActionHalt
	}

	// Determine the network type by reading out of the .vmx
	var networkType string
	if _, ok := vmxData["ethernet0.connectiontype"]; ok {
		networkType = vmxData["ethernet0.connectiontype"]
		log.Printf("Discovered the network type: %s", networkType)
	}
	if networkType == "" {
		networkType = "nat"
		log.Printf("Defaulting to network type: %s", networkType)
	}

	// Stash all required information in our state bag
	state.Put("vmx_path", vmxPath)
	state.Put("disk_full_paths", diskFullPaths)
	state.Put("vmnetwork", networkType)

	return multistep.ActionContinue
}

func (s *StepCloneVMX) Cleanup(state multistep.StateBag) {
}

func getAttachedDisks(a vmxAdapter, data map[string]string) (attachedDisks []string) {
	pathKeyRe := regexp.MustCompile(a.diskPathKeyRe)
	for k, v := range data {
		match := pathKeyRe.FindString(k)
		if match != "" && filepath.Ext(v) == ".vmdk" {
			attachedDisks = append(attachedDisks, v)
		}
	}
	return
}
<commit_msg>Further simplify enumeration of attached disks for VMware VMX builder<commit_after>package vmx

import (
	"context"
	"fmt"
	"log"
	"path/filepath"
	"regexp"

	vmwcommon "github.com/hashicorp/packer/builder/vmware/common"
	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

// StepCloneVMX takes a VMX file and clones the VM into the output directory.
type StepCloneVMX struct {
	OutputDir string
	Path      string
	VMName    string
}

func (s *StepCloneVMX) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
	driver := state.Get("driver").(vmwcommon.Driver)
	ui := state.Get("ui").(packer.Ui)

	// Set the path we want for the new .vmx file and clone
	vmxPath := filepath.Join(s.OutputDir, s.VMName+".vmx")
	ui.Say("Cloning source VM...")
	log.Printf("Cloning from: %s", s.Path)
	log.Printf("Cloning to: %s", vmxPath)
	if err := driver.Clone(vmxPath, s.Path); err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	// Read in the machine configuration from the cloned VMX file
	//
	// * The main driver needs the path to the vmx (set above) and the
	// network type so that it can work out things like IP's and MAC
	// addresses
	// * The disk compaction step needs the paths to all attached disks
	vmxData, err := vmwcommon.ReadVMX(vmxPath)
	if err != nil {
		state.Put("error", err)
		return multistep.ActionHalt
	}

	var diskFilenames []string
	// The VMX file stores the path to a configured disk, and information
	// about that disks attachment to a virtual adapter/controller, as a
	// key/value pair.
	// For a virtual disk attached to bus ID 3 of the virtual machines
	// first SCSI adapter the key/value pair would look something like:
	// scsi0:3.fileName = "relative/path/to/scsiDisk.vmdk"
	// The supported adapter types and configuration maximums for each type
	// vary according to the VMware platform type and version, and the
	// Virtual Machine Hardware version used. See the 'Virtual Machine
	// Maximums' section within VMware's 'Configuration Maximums'
	// documentation for each platform:
	// https://kb.vmware.com/s/article/1003497
	// Information about the supported Virtual Machine Hardware versions:
	// https://kb.vmware.com/s/article/1003746
	// The following regexp is used to match all possible disk attachment
	// points that may be found in the VMX file across all VMware
	// platforms/versions and Virtual Machine Hardware versions
	diskPathKeyRe := regexp.MustCompile(`(?i)^(scsi|sata|ide|nvme)[[:digit:]]:[[:digit:]]{1,2}\.fileName`)
	for k, v := range vmxData {
		match := diskPathKeyRe.FindString(k)
		if match != "" && filepath.Ext(v) == ".vmdk" {
			diskFilenames = append(diskFilenames, v)
		}
	}

	// Write out the relative, host filesystem paths to the disks
	var diskFullPaths []string
	for _, diskFilename := range diskFilenames {
		log.Printf("Found attached disk with filename: %s", diskFilename)
		diskFullPaths = append(diskFullPaths, filepath.Join(s.OutputDir, diskFilename))
	}

	if len(diskFullPaths) == 0 {
		state.Put("error", fmt.Errorf("Could not enumerate disk info from the vmx file"))
		return multistep.ActionHalt
	}

	// Determine the network type by reading out of the .vmx
	var networkType string
	if _, ok := vmxData["ethernet0.connectiontype"]; ok {
		networkType = vmxData["ethernet0.connectiontype"]
		log.Printf("Discovered the network type: %s", networkType)
	}
	if networkType == "" {
		networkType = "nat"
		log.Printf("Defaulting to network type: %s", networkType)
	}

	// Stash all required information in our state bag
	state.Put("vmx_path", vmxPath)
	state.Put("disk_full_paths", diskFullPaths)
	state.Put("vmnetwork", networkType)

	return multistep.ActionContinue
}

func (s *StepCloneVMX) Cleanup(state multistep.StateBag) {
}
<|endoftext|>


<commit_before>package cloudformation

import (
	"fmt"

	"github.com/hashicorp/go-multierror"
	"github.com/remind101/empire"
	"golang.org/x/net/context"
)

// envClient mocks the Empire interface we use.
type envClient interface {
	AppsFind(empire.AppsQuery) (*empire.App, error)
	Set(context.Context, empire.SetOpts) (*empire.Config, error)
}

type Variable struct {
	Name  *string
	Value *string
}

// EnvironmentProperties represents the properties for the
// Custom::EmpireAppEnvironment
type EnvironmentProperties struct {
	AppId     *string
	Variables []Variable
}

// EnvironmentResource is a Provisioner that manages environmental variables
// within an Empire application.
type EnvironmentResource struct {
	empire envClient
}

func (p *EnvironmentResource) Properties() interface{} {
	return &EnvironmentProperties{}
}

type VariableError struct {
	index int
	err   string
}

func (v *VariableError) Error() string {
	return fmt.Sprintf("invalid variable [%d]: %s", v.index, v.err)
}

func (p *EnvironmentResource) Provision(req Request) (id string, data interface{}, err error) {
	ctx := context.Background()
	user := NewUser()
	properties := req.ResourceProperties.(*EnvironmentProperties)

	switch req.RequestType {
	case Create:
		if *properties.AppId == "" {
			return "", nil, fmt.Errorf("missing parameter: AppId")
		}
		id = *properties.AppId
	default:
		id = req.PhysicalResourceId
	}

	app, err := p.empire.AppsFind(empire.AppsQuery{
		ID: &id,
	})
	if err != nil {
		return id, nil, err
	}

	if err := p.setEnvironment(ctx, user, app, req); err != nil {
		return id, nil, err
	}
	return
}

func (p *EnvironmentResource) setEnvironment(ctx context.Context, user *empire.User, app *empire.App, req Request) error {
	vars, err := varsFromRequest(req)
	if err != nil {
		return err
	}

	var action string
	switch req.RequestType {
	case Create:
		action = "Setting"
	case Update:
		action = "Updating"
	case Delete:
		action = "Unsetting"
	}

	_, err = p.empire.Set(ctx, empire.SetOpts{
		User:    user,
		App:     app,
		Vars:    vars,
		Message: fmt.Sprintf("%s variables via Cloudformation", action),
	})

	return err
}

func isValid(index int, variable *Variable) error {
	var err error
	if variable.Name == nil || *variable.Name == "" {
		err = &VariableError{index, "key 'Name' is required"}
	}
	return err
}

func varsFromRequest(req Request) (empire.Vars, error) {
	vars := make(empire.Vars)
	var errors *multierror.Error

	properties := req.ResourceProperties.(*EnvironmentProperties)
	oldProperties := req.OldResourceProperties.(*EnvironmentProperties)

	for i, v := range properties.Variables {
		err := isValid(i, &v)
		if err != nil {
			errors = multierror.Append(errors, err)
			continue
		}

		var val *string
		// If we're deleting the resource, we want to unset the variable
		if req.RequestType != Delete {
			val = v.Value
		}
		vars[empire.Variable(*v.Name)] = val
	}

	if req.RequestType == Update {
		for i, v := range oldProperties.Variables {
			err := isValid(i, &v)
			if err != nil {
				errors = multierror.Append(errors, err)
				continue
			}

			if _, ok := vars[empire.Variable(*v.Name)]; !ok {
				vars[empire.Variable(*v.Name)] = nil
			}
		}
	}

	return vars, errors.ErrorOrNil()
}
<commit_msg>Remove unnecessary whitespace<commit_after>package cloudformation

import (
	"fmt"

	"github.com/hashicorp/go-multierror"
	"github.com/remind101/empire"
	"golang.org/x/net/context"
)

// envClient mocks the Empire interface we use.
type envClient interface {
	AppsFind(empire.AppsQuery) (*empire.App, error)
	Set(context.Context, empire.SetOpts) (*empire.Config, error)
}

type Variable struct {
	Name  *string
	Value *string
}

// EnvironmentProperties represents the properties for the
// Custom::EmpireAppEnvironment
type EnvironmentProperties struct {
	AppId     *string
	Variables []Variable
}

// EnvironmentResource is a Provisioner that manages environmental variables
// within an Empire application.
type EnvironmentResource struct {
	empire envClient
}

func (p *EnvironmentResource) Properties() interface{} {
	return &EnvironmentProperties{}
}

type VariableError struct {
	index int
	err   string
}

func (v *VariableError) Error() string {
	return fmt.Sprintf("invalid variable [%d]: %s", v.index, v.err)
}

func (p *EnvironmentResource) Provision(req Request) (id string, data interface{}, err error) {
	ctx := context.Background()
	user := NewUser()
	properties := req.ResourceProperties.(*EnvironmentProperties)

	switch req.RequestType {
	case Create:
		if *properties.AppId == "" {
			return "", nil, fmt.Errorf("missing parameter: AppId")
		}
		id = *properties.AppId
	default:
		id = req.PhysicalResourceId
	}

	app, err := p.empire.AppsFind(empire.AppsQuery{
		ID: &id,
	})
	if err != nil {
		return id, nil, err
	}

	if err := p.setEnvironment(ctx, user, app, req); err != nil {
		return id, nil, err
	}
	return
}

func (p *EnvironmentResource) setEnvironment(ctx context.Context, user *empire.User, app *empire.App, req Request) error {
	vars, err := varsFromRequest(req)
	if err != nil {
		return err
	}

	var action string
	switch req.RequestType {
	case Create:
		action = "Setting"
	case Update:
		action = "Updating"
	case Delete:
		action = "Unsetting"
	}

	_, err = p.empire.Set(ctx, empire.SetOpts{
		User:    user,
		App:     app,
		Vars:    vars,
		Message: fmt.Sprintf("%s variables via Cloudformation", action),
	})
	return err
}

func isValid(index int, variable *Variable) error {
	var err error
	if variable.Name == nil || *variable.Name == "" {
		err = &VariableError{index, "key 'Name' is required"}
	}
	return err
}

func varsFromRequest(req Request) (empire.Vars, error) {
	vars := make(empire.Vars)
	var errors *multierror.Error

	properties := req.ResourceProperties.(*EnvironmentProperties)
	oldProperties := req.OldResourceProperties.(*EnvironmentProperties)

	for i, v := range properties.Variables {
		err := isValid(i, &v)
		if err != nil {
			errors = multierror.Append(errors, err)
			continue
		}

		var val *string
		// If we're deleting the resource, we want to unset the variable
		if req.RequestType != Delete {
			val = v.Value
		}
		vars[empire.Variable(*v.Name)] = val
	}

	if req.RequestType == Update {
		for i, v := range oldProperties.Variables {
			err := isValid(i, &v)
			if err != nil {
				errors = multierror.Append(errors, err)
				continue
			}

			if _, ok := vars[empire.Variable(*v.Name)]; !ok {
				vars[empire.Variable(*v.Name)] = nil
			}
		}
	}
	return vars, errors.ErrorOrNil()
}
<|endoftext|>


<commit_before>package mockserver_test

import (
	"context"
	"encoding/json"
	"log"
	"net/http/httptest"
	"os"

	"github.com/lestrrat/go-slack"
	"github.com/lestrrat/go-slack/server"
	"github.com/lestrrat/go-slack/server/mockserver"
)

const token = "AbCdEfG"

func ExampleMockServer() {
	h := mockserver.New(token)
	s := server.New()
	h.InstallHandlers(s)
	ts := httptest.NewServer(s)
	defer ts.Close()

	cl := slack.New(token, slack.WithAPIEndpoint(ts.URL))

	channel, err := cl.Channels().Info("jedi").Do(context.Background())
	if err != nil {
		log.Printf(`expected channels.info to succeed: %s`, err)
		return
	}

	json.NewEncoder(os.Stdout).Encode(channel)
	// OUTPUT:
	// {"id":"123456789ABCDEFG","created":233431200,"is_open":false,"creator":"yoda","is_archived":false,"is_group":false,"is_mpim":false,"members":["obiwan","lukeskywalker"],"name":"jedis","name_normalized":"jedis","num_members":2,"previous_names":null,"purpose":{"value":"There is no emotion, there is peace.\nThere is no ignorance, there is knowledge.\nThere is no passion, there is serenity.\nThere is no chaos, there is harmony.\nThere is no death, there is the Force.","creator":"yoda","last_set":233431200},"topic":{"value":"Jedi meetup and drinks next Tuesday","creator":"yoda","last_set":233431200},"is_channel":false,"is_general":false,"is_member":false,"is_org_shared":false,"is_shared":false}
}
<commit_msg>Fix eample<commit_after>package mockserver_test

import (
	"context"
	"encoding/json"
	"log"
	"net/http/httptest"
	"os"

	"github.com/lestrrat/go-slack"
	"github.com/lestrrat/go-slack/server"
	"github.com/lestrrat/go-slack/server/mockserver"
)

const token = "AbCdEfG"

func ExampleMockServer() {
	h := mockserver.New(token)
	s := server.New()
	h.InstallHandlers(s)
	ts := httptest.NewServer(s)
	defer ts.Close()

	cl := slack.New(token, slack.WithAPIEndpoint(ts.URL))

	channel, err := cl.Channels().Info("jedi").Do(context.Background())
	if err != nil {
		log.Printf(`expected channels.info to succeed: %s`, err)
		return
	}

	buf, _ := json.MarshalIndent(channel, "", "  ")
	os.Stdout.Write(buf)
	// OUTPUT:
	//{
	//   "id": "123456789ABCDEFG",
	//   "created": 233431200,
	//   "is_open": false,
	//   "creator": "yoda",
	//   "is_archived": false,
	//   "is_group": false,
	//   "is_mpim": false,
	//   "members": [
	//     "obiwan",
	//     "lukeskywalker"
	//   ],
	//   "name": "jedis",
	//   "name_normalized": "jedis",
	//   "num_members": 2,
	//   "previous_names": null,
	//   "purpose": {
	//     "value": "There is no emotion, there is peace.\nThere is no ignorance, there is knowledge.\nThere is no passion, there is serenity.\nThere is no chaos, there is harmony.\nThere is no death, there is the Force.",
	//     "creator": "yoda",
	//     "last_set": 233431200
	//   },
	//   "topic": {
	//     "value": "Jedi meetup and drinks next Tuesday",
	//     "creator": "yoda",
	//     "last_set": 233431200
	//   },
	//   "is_channel": true,
	//   "is_general": false,
	//   "is_member": true,
	//   "is_org_shared": false,
	//   "is_shared": false
	//}
}
<|endoftext|>


<commit_before>package mail

import (
	"fmt"

	"github.com/fragmenta/view"
	"github.com/sendgrid/sendgrid-go"
)

// The Mail service secret key/password (must be set before first sending)
var secret string

// The default sender
var from string

// Setup sets the user and secret for use in sending mail (possibly later we should have a config etc)
func Setup(s string, f string) {
	secret = s
	from = f
}

// Send sends mail
func Send(recipients []string, subject string, template string, context map[string]interface{}) error {

	// For now  ensure that we don't send to more than 1 recipient while we debug emails
	if len(recipients) > 1 {
		return fmt.Errorf("mail.send: #error bad recipients for debug %v", recipients)
	}

	if recipients[0] != "kennygrant@gmail.com" {
		return fmt.Errorf("mail.send: #error bad recipients for debug %v", recipients)
	}

	// Send via sendgrid
	sg := sendgrid.NewSendGridClientWithApiKey(secret)

	message := sendgrid.NewMail()
	message.SetFrom(from)
	message.AddTos(recipients)
	message.SetSubject(subject)

	// Load the template, and substitute using context
	// We should possibly set layout from caller too?
	view := view.NewWithPath("", nil)
	view.Template(template)
	view.Context(context)

	html, err := view.RenderToString()
	if err != nil {
		return err
	}
	message.SetHTML(html)

	// For debug, print message
	fmt.Printf("#info sending MAIL to:%s", recipients)

	return sg.Send(message)
}

// SendOne sends email to ONE recipient only
func SendOne(recipient string, subject string, template string, context map[string]interface{}) error {
	return Send([]string{recipient}, subject, template, context)
}
<commit_msg>Fixed mail to compile with new sendgrid API - fixes #15<commit_after>package mail

import (
	"fmt"

	"github.com/fragmenta/view"
	"github.com/sendgrid/sendgrid-go"
	"github.com/sendgrid/sendgrid-go/helpers/mail"
)

// The Mail service secret key/password (must be set before first sending)
var secret string

// The default sender
var from string

// Setup sets the user and secret for use in sending mail
func Setup(s string, f string) {
	secret = s
	from = f
}

// Send sends mail (using sendgrid API v3)
func Send(recipients []string, subject string, template string, context map[string]interface{}) error {

	// For now  ensure that we don't send to more than 1 recipient while we debug emails
	if len(recipients) > 1 {
		return fmt.Errorf("mail.send: #error bad recipients for debug %v", recipients)
	}

	if recipients[0] != "kennygrant@gmail.com" {
		return fmt.Errorf("mail.send: #error bad recipients for debug %v", recipients)
	}

	// Send via sendgrid
	// Apparently this API will probably break again without warning !
	// consider vendoring

	// Load the template, and substitute using context
	// We should possibly set layout from caller too?
	view := view.NewWithPath("", nil)
	view.Template(template)
	view.Context(context)

	html, err := view.RenderToString()
	if err != nil {
		return err
	}

	// Create a sendgrid message with v3
	sendgridContent := mail.NewContent("text/html", html)
	var sendgridRecipients []*mail.Email
	for _, r := range recipients {
		sendgridRecipients = append(sendgridRecipients, mail.NewEmail("", r))
	}

	message := mail.NewV3Mail()
	message.Subject = subject
	message.From = mail.NewEmail("", from)
	p := mail.NewPersonalization()
	p.AddTos(sendgridRecipients...)
	message.AddPersonalizations(p)
	message.AddContent(sendgridContent)

	request := sendgrid.GetRequest(secret, "/v3/mail/send", "https://api.sendgrid.com")
	request.Method = "POST"
	request.Body = mail.GetRequestBody(message)
	_, err = sendgrid.API(request)

	// For debug, print message
	fmt.Printf("#info sending MAIL to:%s", recipients)

	return err
}

// SendOne sends email to ONE recipient only
func SendOne(recipient string, subject string, template string, context map[string]interface{}) error {
	return Send([]string{recipient}, subject, template, context)
}
<|endoftext|>


<commit_before>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http

import (
	"io"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"

	"golang_org/x/net/lex/httplex"
)

// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1

// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(233431200, 0)

// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.

// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
	name string
}

func (k *contextKey) String() string { return "net/http context value " + k.name }

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
	if hasPort(host) {
		return strings.TrimSuffix(host, ":")
	}
	return host
}

func isNotToken(r rune) bool {
	return !httplex.IsTokenRune(r)
}

func isASCII(s string) bool {
	for i := 0; i < len(s); i++ {
		if s[i] >= utf8.RuneSelf {
			return false
		}
	}
	return true
}

func hexEscapeNonASCII(s string) string {
	newLen := 0
	for i := 0; i < len(s); i++ {
		if s[i] >= utf8.RuneSelf {
			newLen += 3
		} else {
			newLen++
		}
	}
	if newLen == len(s) {
		return s
	}
	b := make([]byte, 0, newLen)
	for i := 0; i < len(s); i++ {
		if s[i] >= utf8.RuneSelf {
			b = append(b, '%')
			b = strconv.AppendInt(b, int64(s[i]), 16)
		} else {
			b = append(b, s[i])
		}
	}
	return string(b)
}

// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}

type noBody struct{}

func (noBody) Read([]byte) (int, error)         { return 0, io.EOF }
func (noBody) Close() error                     { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }

var (
	// verify that an io.Copy from NoBody won't require a buffer:
	_ io.WriterTo   = NoBody
	_ io.ReadCloser = NoBody
)
<commit_msg>net/http: add an interface for server push<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http

import (
	"io"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"

	"golang_org/x/net/lex/httplex"
)

// maxInt64 is the effective "infinite" value for the Server and
// Transport's byte-limiting readers.
const maxInt64 = 1<<63 - 1

// aLongTimeAgo is a non-zero time, far in the past, used for
// immediate cancelation of network operations.
var aLongTimeAgo = time.Unix(233431200, 0)

// TODO(bradfitz): move common stuff here. The other files have accumulated
// generic http stuff in random places.

// contextKey is a value for use with context.WithValue. It's used as
// a pointer so it fits in an interface{} without allocation.
type contextKey struct {
	name string
}

func (k *contextKey) String() string { return "net/http context value " + k.name }

// Given a string of the form "host", "host:port", or "[ipv6::address]:port",
// return true if the string includes a port.
func hasPort(s string) bool { return strings.LastIndex(s, ":") > strings.LastIndex(s, "]") }

// removeEmptyPort strips the empty port in ":port" to ""
// as mandated by RFC 3986 Section 6.2.3.
func removeEmptyPort(host string) string {
	if hasPort(host) {
		return strings.TrimSuffix(host, ":")
	}
	return host
}

func isNotToken(r rune) bool {
	return !httplex.IsTokenRune(r)
}

func isASCII(s string) bool {
	for i := 0; i < len(s); i++ {
		if s[i] >= utf8.RuneSelf {
			return false
		}
	}
	return true
}

func hexEscapeNonASCII(s string) string {
	newLen := 0
	for i := 0; i < len(s); i++ {
		if s[i] >= utf8.RuneSelf {
			newLen += 3
		} else {
			newLen++
		}
	}
	if newLen == len(s) {
		return s
	}
	b := make([]byte, 0, newLen)
	for i := 0; i < len(s); i++ {
		if s[i] >= utf8.RuneSelf {
			b = append(b, '%')
			b = strconv.AppendInt(b, int64(s[i]), 16)
		} else {
			b = append(b, s[i])
		}
	}
	return string(b)
}

// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
var NoBody = noBody{}

type noBody struct{}

func (noBody) Read([]byte) (int, error)         { return 0, io.EOF }
func (noBody) Close() error                     { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }

var (
	// verify that an io.Copy from NoBody won't require a buffer:
	_ io.WriterTo   = NoBody
	_ io.ReadCloser = NoBody
)

// PushOptions describes options for Pusher.Push.
type PushOptions struct {
	// Method specifies the HTTP method for the promised request.
	// If set, it must be "GET" or "HEAD". Empty means "GET".
	Method string

	// Header specifies additional promised request headers. This cannot
	// include HTTP/2 pseudo header fields like ":path" and ":scheme",
	// which will be added automatically.
	Header Header
}

// Pusher is the interface implemented by ResponseWriters that support
// HTTP/2 server push. For more background, see
// https://tools.ietf.org/html/rfc7540#section-8.2.
type Pusher interface {
	// Push initiates an HTTP/2 server push. This constructs a synthetic
	// request using the given target and options, serializes that request
	// into a PUSH_PROMISE frame, then dispatches that request using the
	// server's request handler. If opts is nil, default options are used.
	//
	// The target must either be an absolute path (like "/path") or an absolute
	// URL that contains a valid host and the same scheme as the parent request.
	// If the target is a path, it will inherit the scheme and host of the
	// parent request.
	//
	// The HTTP/2 spec disallows recursive pushes and cross-authority pushes.
	// Push may or may not detect these invalid pushes; however, invalid
	// pushes will be detected and canceled by conforming clients.
	//
	// Handlers that wish to push URL X should call Push before sending any
	// data that may trigger a request for URL X. This avoids a race where the
	// client issues requests for X before receiving the PUSH_PROMISE for X.
	//
	// Push returns ErrNotSupported if the client has disabled push or if push
	// is not supported on the underlying connection.
	Push(target string, opts *PushOptions) error
}
<|endoftext|>


<commit_before>// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package x509_test

import (
	"crypto/tls"
	"crypto/x509"
	"internal/testenv"
	"testing"
	"time"
)

func TestPlatformVerifier(t *testing.T) {
	if !testenv.HasExternalNetwork() {
		t.Skip()
	}

	getChain := func(host string) []*x509.Certificate {
		t.Helper()
		c, err := tls.Dial("tcp", host+":443", &tls.Config{InsecureSkipVerify: true})
		if err != nil {
			t.Fatalf("tls connection failed: %s", err)
		}
		return c.ConnectionState().PeerCertificates
	}

	tests := []struct {
		name        string
		host        string
		verifyName  string
		verifyTime  time.Time
		expectedErr string
	}{
		{
			// whatever google.com serves should, hopefully, be trusted
			name: "valid chain",
			host: "google.com",
		},
		{
			name:        "expired leaf",
			host:        "expired.badssl.com",
			expectedErr: "x509: certificate has expired or is not yet valid: ",
		},
		{
			name:        "wrong host for leaf",
			host:        "wrong.host.badssl.com",
			verifyName:  "wrong.host.badssl.com",
			expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com",
		},
		{
			name:        "self-signed leaf",
			host:        "self-signed.badssl.com",
			expectedErr: "x509: certificate signed by unknown authority",
		},
		{
			name:        "untrusted root",
			host:        "untrusted-root.badssl.com",
			expectedErr: "x509: certificate signed by unknown authority",
		},
		{
			name:        "expired leaf (custom time)",
			host:        "google.com",
			verifyTime:  time.Time{}.Add(time.Hour),
			expectedErr: "x509: certificate has expired or is not yet valid: ",
		},
		{
			name:       "valid chain (custom time)",
			host:       "google.com",
			verifyTime: time.Now(),
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			chain := getChain(tc.host)
			var opts x509.VerifyOptions
			if len(chain) > 1 {
				opts.Intermediates = x509.NewCertPool()
				for _, c := range chain[1:] {
					opts.Intermediates.AddCert(c)
				}
			}
			if tc.verifyName != "" {
				opts.DNSName = tc.verifyName
			}
			if !tc.verifyTime.IsZero() {
				opts.CurrentTime = tc.verifyTime
			}

			_, err := chain[0].Verify(opts)
			if err != nil && tc.expectedErr == "" {
				t.Errorf("unexpected verification error: %s", err)
			} else if err != nil && err.Error() != tc.expectedErr {
				t.Errorf("unexpected verification error: got %q, want %q", err.Error(), tc.expectedErr)
			} else if err == nil && tc.expectedErr != "" {
				t.Errorf("unexpected verification success: want %q", tc.expectedErr)
			}
		})
	}
}
<commit_msg>[release-branch.go1.18] crypto/x509: skip WSATRY_AGAIN errors when dialing badssl.com subdomains<commit_after>// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package x509_test

import (
	"crypto/tls"
	"crypto/x509"
	"errors"
	"internal/testenv"
	"net"
	"strings"
	"syscall"
	"testing"
	"time"
)

func TestPlatformVerifier(t *testing.T) {
	if !testenv.HasExternalNetwork() {
		t.Skip()
	}

	getChain := func(t *testing.T, host string) []*x509.Certificate {
		t.Helper()
		c, err := tls.Dial("tcp", host+":443", &tls.Config{InsecureSkipVerify: true})
		if err != nil {
			// From https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2,
			// matching the error string observed in https://go.dev/issue/52094.
			const WSATRY_AGAIN syscall.Errno = 11002
			var errDNS *net.DNSError
			if strings.HasSuffix(host, ".badssl.com") && errors.As(err, &errDNS) && strings.HasSuffix(errDNS.Err, WSATRY_AGAIN.Error()) {
				t.Log(err)
				testenv.SkipFlaky(t, 52094)
			}

			t.Fatalf("tls connection failed: %s", err)
		}
		return c.ConnectionState().PeerCertificates
	}

	tests := []struct {
		name        string
		host        string
		verifyName  string
		verifyTime  time.Time
		expectedErr string
	}{
		{
			// whatever google.com serves should, hopefully, be trusted
			name: "valid chain",
			host: "google.com",
		},
		{
			name:        "expired leaf",
			host:        "expired.badssl.com",
			expectedErr: "x509: certificate has expired or is not yet valid: ",
		},
		{
			name:        "wrong host for leaf",
			host:        "wrong.host.badssl.com",
			verifyName:  "wrong.host.badssl.com",
			expectedErr: "x509: certificate is valid for *.badssl.com, badssl.com, not wrong.host.badssl.com",
		},
		{
			name:        "self-signed leaf",
			host:        "self-signed.badssl.com",
			expectedErr: "x509: certificate signed by unknown authority",
		},
		{
			name:        "untrusted root",
			host:        "untrusted-root.badssl.com",
			expectedErr: "x509: certificate signed by unknown authority",
		},
		{
			name:        "expired leaf (custom time)",
			host:        "google.com",
			verifyTime:  time.Time{}.Add(time.Hour),
			expectedErr: "x509: certificate has expired or is not yet valid: ",
		},
		{
			name:       "valid chain (custom time)",
			host:       "google.com",
			verifyTime: time.Now(),
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			chain := getChain(t, tc.host)
			var opts x509.VerifyOptions
			if len(chain) > 1 {
				opts.Intermediates = x509.NewCertPool()
				for _, c := range chain[1:] {
					opts.Intermediates.AddCert(c)
				}
			}
			if tc.verifyName != "" {
				opts.DNSName = tc.verifyName
			}
			if !tc.verifyTime.IsZero() {
				opts.CurrentTime = tc.verifyTime
			}

			_, err := chain[0].Verify(opts)
			if err != nil && tc.expectedErr == "" {
				t.Errorf("unexpected verification error: %s", err)
			} else if err != nil && err.Error() != tc.expectedErr {
				t.Errorf("unexpected verification error: got %q, want %q", err.Error(), tc.expectedErr)
			} else if err == nil && tc.expectedErr != "" {
				t.Errorf("unexpected verification success: want %q", tc.expectedErr)
			}
		})
	}
}
<|endoftext|>


<commit_before>package main

import (
	"llvm.org/llvm/bindings/go/llvm"
	"fmt"
	"os"
	"io/ioutil"
)

func main() {
	context := llvm.GlobalContext()
	builder := context.NewBuilder()
	mainModule := context.NewModule("mainModule")

	putsFuncType := llvm.FunctionType(llvm.Int32Type(), []llvm.Type{llvm.PointerType(llvm.Int8Type(), 0)}, false)
	putsFunc := llvm.AddFunction(mainModule, "puts", putsFuncType)

	mainFuncType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{}, false)
	mainFunc := llvm.AddFunction(mainModule, "main", mainFuncType)

	body := llvm.AddBasicBlock(mainFunc, "entry")
	builder.SetInsertPoint(body, mainFunc)

	hello := builder.CreateGlobalStringPtr("Hello, Grainlang!", "hello")
	builder.SetInsertPoint(body, body.FirstInstruction())
	builder.CreateCall(putsFunc, []llvm.Value{hello}, "puts2")
	builder.CreateRetVoid()

	mainModule.Dump()

	var err error
	var target llvm.Target

	llvm.LinkInMCJIT()

	err = llvm.InitializeNativeTarget()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Native target initialization error:")
		fmt.Fprintln(os.Stderr, err)
		os.Exit(-1)
	}

	err = llvm.InitializeNativeAsmPrinter()
	if err != nil {
		fmt.Fprintln(os.Stderr, "ASM printer initialization error:")
		fmt.Fprintln(os.Stderr, err)
		os.Exit(-1)
	}

	target, err = llvm.GetTargetFromTriple(llvm.DefaultTargetTriple())
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get target:")
		fmt.Fprintln(os.Stderr, err)
		os.Exit(-1)
	}

	fmt.Println("Initialize: TargetTriple = " + llvm.DefaultTargetTriple())
	fmt.Println("Initialize: TargetDescription = " + target.Description())

	machine := target.CreateTargetMachine(llvm.DefaultTargetTriple(),
		"", "",
		llvm.CodeGenLevelNone,
		llvm.RelocDefault,
		llvm.CodeModelSmall)
	buffer, err := machine.EmitToMemoryBuffer(mainModule, llvm.ObjectFile)
	ioutil.WriteFile("hello.o", buffer.Bytes(), 0644)
}
<commit_msg>Create executable file.<commit_after>package main

import (
	"llvm.org/llvm/bindings/go/llvm"
	"fmt"
	"os"
	"io/ioutil"
	"os/exec"
)

func main() {
	context := llvm.GlobalContext()
	builder := context.NewBuilder()
	mainModule := context.NewModule("mainModule")

	putsFuncType := llvm.FunctionType(llvm.Int32Type(), []llvm.Type{llvm.PointerType(llvm.Int8Type(), 0)}, false)
	putsFunc := llvm.AddFunction(mainModule, "puts", putsFuncType)

	mainFuncType := llvm.FunctionType(llvm.VoidType(), []llvm.Type{}, false)
	mainFunc := llvm.AddFunction(mainModule, "main", mainFuncType)

	body := llvm.AddBasicBlock(mainFunc, "entry")
	builder.SetInsertPoint(body, mainFunc)

	hello := builder.CreateGlobalStringPtr("Hello, Grainlang!", "hello")
	builder.SetInsertPoint(body, body.FirstInstruction())
	builder.CreateCall(putsFunc, []llvm.Value{hello}, "puts2")
	builder.CreateRetVoid()

	mainModule.Dump()

	var err error
	var target llvm.Target

	llvm.LinkInMCJIT()

	err = llvm.InitializeNativeTarget()
	if err != nil {
		fmt.Fprintln(os.Stderr, "Native target initialization error:")
		fmt.Fprintln(os.Stderr, err)
		os.Exit(-1)
	}

	err = llvm.InitializeNativeAsmPrinter()
	if err != nil {
		fmt.Fprintln(os.Stderr, "ASM printer initialization error:")
		fmt.Fprintln(os.Stderr, err)
		os.Exit(-1)
	}

	target, err = llvm.GetTargetFromTriple(llvm.DefaultTargetTriple())
	if err != nil {
		fmt.Fprintln(os.Stderr, "Cannot get target:")
		fmt.Fprintln(os.Stderr, err)
		os.Exit(-1)
	}

	fmt.Println("Initialize: TargetTriple = " + llvm.DefaultTargetTriple())
	fmt.Println("Initialize: TargetDescription = " + target.Description())

	machine := target.CreateTargetMachine(llvm.DefaultTargetTriple(),
		"", "",
		llvm.CodeGenLevelNone,
		llvm.RelocDefault,
		llvm.CodeModelSmall)
	buffer, err := machine.EmitToMemoryBuffer(mainModule, llvm.ObjectFile)
	objectFileName := "hello.o"
	ioutil.WriteFile(objectFileName, buffer.Bytes(), 0644)
	cmd := exec.Command("clang", objectFileName, "-o", "hello")
	cmd.Run()
	os.Remove(objectFileName)
}
<|endoftext|>


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

package memstore

import (
	"context"

	"github.com/cayleygraph/cayley/graph"
	"github.com/cayleygraph/cayley/graph/iterator"
)

var _ graph.Iterator = (*AllIterator)(nil)

type AllIterator struct {
	uid  uint64
	tags graph.Tagger

	qs    *QuadStore
	all   []*primitive
	maxid int64 // id of last observed insert (prim id)
	nodes bool

	i    int // index into qs.all
	cur  *primitive
	done bool
}

func newAllIterator(qs *QuadStore, nodes bool, maxid int64) *AllIterator {
	return &AllIterator{
		uid: iterator.NextUID(),
		qs:  qs, all: qs.cloneAll(), nodes: nodes,
		i: -1, maxid: maxid,
	}
}

func (it *AllIterator) Clone() graph.Iterator {
	it2 := newAllIterator(it.qs, it.nodes, it.maxid)
	it2.tags.CopyFrom(it)
	return it2
}

func (it *AllIterator) Reset() {
	it.i = -1
	it.cur = nil
	it.done = false
}

func (it *AllIterator) ok(p *primitive) bool {
	if p.ID > it.maxid {
		return false
	} else if it.nodes && p.Value != nil {
		return true
	} else if !it.nodes && !p.Quad.Zero() {
		return true
	}
	return false
}

func (it *AllIterator) Next(ctx context.Context) bool {
	it.cur = nil
	if it.done {
		return false
	}
	all := it.all
	if it.i >= len(all) {
		it.done = true
		return false
	}
	it.i++
	for ; it.i < len(all); it.i++ {
		p := all[it.i]
		if p.ID > it.maxid {
			break
		}
		if it.ok(p) {
			it.cur = p
			return true
		}
	}
	it.done = true
	return false
}

func (it *AllIterator) Contains(ctx context.Context, v graph.Value) bool {
	it.cur = nil
	if it.done {
		return false
	}
	id, ok := asID(v)
	if !ok {
		return false
	}
	p := it.qs.prim[id]
	if p.ID > it.maxid {
		return false
	}
	if !it.ok(p) {
		return false
	}
	it.cur = p
	return true
}
func (it *AllIterator) Result() graph.Value {
	if it.cur == nil {
		return nil
	}
	if !it.cur.Quad.Zero() {
		return qprim{p: it.cur}
	}
	return bnode(it.cur.ID)
}

func (it *AllIterator) Err() error { return nil }
func (it *AllIterator) Close() error {
	it.done = true
	it.all = nil
	return nil
}
func (it *AllIterator) Tagger() *graph.Tagger {
	return &it.tags
}

func (it *AllIterator) TagResults(dst map[string]graph.Value) {
	it.tags.TagResult(dst, it.Result())
}

func (it *AllIterator) SubIterators() []graph.Iterator   { return nil }
func (it *AllIterator) Optimize() (graph.Iterator, bool) { return it, false }

func (it *AllIterator) UID() uint64 {
	return it.uid
}
func (it *AllIterator) Type() graph.Type { return graph.All }
func (it *AllIterator) String() string {
	return "MemStoreAll"
}
func (it *AllIterator) NextPath(ctx context.Context) bool { return false }

func (it *AllIterator) Size() (int64, bool) {
	// TODO: use maxid?
	return int64(len(it.qs.all)), true
}
func (it *AllIterator) Stats() graph.IteratorStats {
	st := graph.IteratorStats{NextCost: 1, ContainsCost: 1}
	st.Size, st.ExactSize = it.Size()
	return st
}
<commit_msg>memstore: use correct size for all iterator<commit_after>// Copyright 2014 The Cayley Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package memstore

import (
	"context"

	"github.com/cayleygraph/cayley/graph"
	"github.com/cayleygraph/cayley/graph/iterator"
)

var _ graph.Iterator = (*AllIterator)(nil)

type AllIterator struct {
	uid  uint64
	tags graph.Tagger

	qs    *QuadStore
	all   []*primitive
	maxid int64 // id of last observed insert (prim id)
	nodes bool

	i    int // index into qs.all
	cur  *primitive
	done bool
}

func newAllIterator(qs *QuadStore, nodes bool, maxid int64) *AllIterator {
	return &AllIterator{
		uid: iterator.NextUID(),
		qs:  qs, all: qs.cloneAll(), nodes: nodes,
		i: -1, maxid: maxid,
	}
}

func (it *AllIterator) Clone() graph.Iterator {
	it2 := newAllIterator(it.qs, it.nodes, it.maxid)
	it2.tags.CopyFrom(it)
	return it2
}

func (it *AllIterator) Reset() {
	it.i = -1
	it.cur = nil
	it.done = false
}

func (it *AllIterator) ok(p *primitive) bool {
	if p.ID > it.maxid {
		return false
	} else if it.nodes && p.Value != nil {
		return true
	} else if !it.nodes && !p.Quad.Zero() {
		return true
	}
	return false
}

func (it *AllIterator) Next(ctx context.Context) bool {
	it.cur = nil
	if it.done {
		return false
	}
	all := it.all
	if it.i >= len(all) {
		it.done = true
		return false
	}
	it.i++
	for ; it.i < len(all); it.i++ {
		p := all[it.i]
		if p.ID > it.maxid {
			break
		}
		if it.ok(p) {
			it.cur = p
			return true
		}
	}
	it.done = true
	return false
}

func (it *AllIterator) Contains(ctx context.Context, v graph.Value) bool {
	it.cur = nil
	if it.done {
		return false
	}
	id, ok := asID(v)
	if !ok {
		return false
	}
	p := it.qs.prim[id]
	if p.ID > it.maxid {
		return false
	}
	if !it.ok(p) {
		return false
	}
	it.cur = p
	return true
}
func (it *AllIterator) Result() graph.Value {
	if it.cur == nil {
		return nil
	}
	if !it.cur.Quad.Zero() {
		return qprim{p: it.cur}
	}
	return bnode(it.cur.ID)
}

func (it *AllIterator) Err() error { return nil }
func (it *AllIterator) Close() error {
	it.done = true
	it.all = nil
	return nil
}
func (it *AllIterator) Tagger() *graph.Tagger {
	return &it.tags
}

func (it *AllIterator) TagResults(dst map[string]graph.Value) {
	it.tags.TagResult(dst, it.Result())
}

func (it *AllIterator) SubIterators() []graph.Iterator   { return nil }
func (it *AllIterator) Optimize() (graph.Iterator, bool) { return it, false }

func (it *AllIterator) UID() uint64 {
	return it.uid
}
func (it *AllIterator) Type() graph.Type { return graph.All }
func (it *AllIterator) String() string {
	return "MemStoreAll"
}
func (it *AllIterator) NextPath(ctx context.Context) bool { return false }

func (it *AllIterator) Size() (int64, bool) {
	// TODO: use maxid?
	return int64(len(it.all)), true
}
func (it *AllIterator) Stats() graph.IteratorStats {
	st := graph.IteratorStats{NextCost: 1, ContainsCost: 1}
	st.Size, st.ExactSize = it.Size()
	return st
}
<|endoftext|>


<commit_before>/*
   Copyright (C) 2014  Salsita s.r.o.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program. If not, see {http://www.gnu.org/licenses/}.
*/

package pivotal

import (
	"fmt"
	"net/http"
	"net/url"
	"time"
)

const (
	StoryTypeFeature = "feature"
	StoryTypeBug     = "bug"
	StoryTypeChore   = "chore"
	StoryTypeRelease = "release"
)

const (
	StoryStateUnscheduled = "unscheduled"
	StoryStatePlanned     = "planned"
	StoryStateUnstarted   = "unstarted"
	StoryStateStarted     = "started"
	StoryStateFinished    = "finished"
	StoryStateDelivered   = "delivered"
	StoryStateAccepted    = "accepted"
	StoryStateRejected    = "rejected"
)

type Story struct {
	Id            int        `json:"id,omitempty"`
	ProjectId     int        `json:"project_id,omitempty"`
	Name          string     `json:"name,omitempty"`
	Description   string     `json:"description,omitempty"`
	Type          string     `json:"story_type,omitempty"`
	State         string     `json:"current_state,omitempty"`
	Estimate      float64    `json:"estimate,omitempty"`
	AcceptedAt    *time.Time `json:"accepted_at,omitempty"`
	Deadline      *time.Time `json:"deadline,omitempty"`
	RequestedById int        `json:"requested_by_id,omitempty"`
	OwnerIds      []int      `json:"owner_ids,omitempty"`
	LabelIds      []int      `json:"label_ids,omitempty"`
	Labels        []*Label   `json:"labels,omitempty"`
	TaskIds       []int      `json:"task_ids,omitempty"`
	Tasks         []int      `json:"tasks,omitempty"`
	FollowerIds   []int      `json:"follower_ids,omitempty"`
	CommentIds    []int      `json:"comment_ids,omitempty"`
	CreatedAt     *time.Time `json:"created_at,omitempty"`
	UpdatedAt     *time.Time `json:"updated_at,omitempty"`
	IntegrationId int        `json:"integration_id,omitempty"`
	ExternalId    string     `json:"external_id,omitempty"`
	URL           string     `json:"url,omitempty"`
	Kind          string     `json:"kind,omitempty"`
}

type Label struct {
	Id        int        `json:"id,omitempty"`
	ProjectId int        `json:"project_id,omitempty"`
	Name      string     `json:"name,omitempty"`
	CreatedAt *time.Time `json:"created_at,omitempty"`
	UpdatedAt *time.Time `json:"updated_at,omitempty"`
	Kind      string     `json:"kind,omitempty"`
}

type Task struct {
	Id          int        `json:"id,omitempty"`
	StoryId     int        `json:"story_id,omitempty"`
	Description string     `json:"description,omitempty"`
	Position    int        `json:"position,omitempty"`
	Complete    bool       `json:"complete,omitempty"`
	CreatedAt   *time.Time `json:"created_at,omitempty"`
	UpdatedAt   *time.Time `json:"updated_at,omitempty"`
}

type Person struct {
	Id                         int        `json:"id"`
	Name                       string     `json:"name"`
	Initials                   string     `json:"initials"`
	Username                   string     `json:"username"`
	TimeZone                   *TimeZone  `json:"time_zone"`
	Email                      string     `json:"email"`
	Kind					   string     `json:"kind"`
}

type StoryService struct {
	client *Client
}

func newStoryService(client *Client) *StoryService {
	return &StoryService{client}
}

func (service *StoryService) List(projectId int, filter string) ([]*Story, *http.Response, error) {
	u := fmt.Sprintf("projects/%v/stories", projectId)
	if filter != "" {
		u += "?filter=" + url.QueryEscape(filter)
	}

	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var stories []*Story
	resp, err := service.client.Do(req, &stories)
	if err != nil {
		return nil, resp, err
	}

	return stories, resp, err
}

func (service *StoryService) Get(projectId, storyId int) (*Story, *http.Response, error) {
	u := fmt.Sprintf("projects/%v/stories/%v", projectId, storyId)
	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var story Story
	resp, err := service.client.Do(req, &story)
	if err != nil {
		return nil, resp, err
	}

	return &story, resp, err
}

func (service *StoryService) Update(projectId, storyId int, story *Story) (*Story, *http.Response, error) {
	u := fmt.Sprintf("projects/%v/stories/%v", projectId, storyId)
	req, err := service.client.NewRequest("PUT", u, story)
	if err != nil {
		return nil, nil, err
	}

	var bodyStory Story
	resp, err := service.client.Do(req, &bodyStory)
	if err != nil {
		return nil, resp, err
	}

	return &bodyStory, resp, err

}

func (service *StoryService) ListTasks(projectId, storyId int) ([]*Task, *http.Response, error) {
	u := fmt.Sprintf("projects/%v/stories/%v/tasks", projectId, storyId)
	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var tasks []*Task
	resp, err := service.client.Do(req, &tasks)
	if err != nil {
		return nil, resp, err
	}

	return tasks, resp, err
}

func (service *StoryService) AddTask(projectId, storyId int, task *Task) (*http.Response, error) {
	if task.Description == "" {
		return nil, &ErrFieldNotSet{"description"}
	}

	u := fmt.Sprintf("projects/%v/stories/%v/tasks", projectId, storyId)
	req, err := service.client.NewRequest("POST", u, task)
	if err != nil {
		return nil, err
	}

	return service.client.Do(req, nil)
}

func (service *StoryService) ListOwners(projectId, storyId int) ([]*Person, *http.Response, error) {
	u := fmt.Sprintf("projects/%d/stories/%d/owners", projectId, storyId)
	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var owners []*Person
	resp, err := service.client.Do(req, &owners)
	if err != nil {
		return nil, resp, err
	}

	return owners, resp, err
}
<commit_msg>Fix spacing, add omitempty to struct definitions<commit_after>/*
   Copyright (C) 2014  Salsita s.r.o.

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program. If not, see {http://www.gnu.org/licenses/}.
*/

package pivotal

import (
	"fmt"
	"net/http"
	"net/url"
	"time"
)

const (
	StoryTypeFeature = "feature"
	StoryTypeBug     = "bug"
	StoryTypeChore   = "chore"
	StoryTypeRelease = "release"
)

const (
	StoryStateUnscheduled = "unscheduled"
	StoryStatePlanned     = "planned"
	StoryStateUnstarted   = "unstarted"
	StoryStateStarted     = "started"
	StoryStateFinished    = "finished"
	StoryStateDelivered   = "delivered"
	StoryStateAccepted    = "accepted"
	StoryStateRejected    = "rejected"
)

type Story struct {
	Id            int        `json:"id,omitempty"`
	ProjectId     int        `json:"project_id,omitempty"`
	Name          string     `json:"name,omitempty"`
	Description   string     `json:"description,omitempty"`
	Type          string     `json:"story_type,omitempty"`
	State         string     `json:"current_state,omitempty"`
	Estimate      float64    `json:"estimate,omitempty"`
	AcceptedAt    *time.Time `json:"accepted_at,omitempty"`
	Deadline      *time.Time `json:"deadline,omitempty"`
	RequestedById int        `json:"requested_by_id,omitempty"`
	OwnerIds      []int      `json:"owner_ids,omitempty"`
	LabelIds      []int      `json:"label_ids,omitempty"`
	Labels        []*Label   `json:"labels,omitempty"`
	TaskIds       []int      `json:"task_ids,omitempty"`
	Tasks         []int      `json:"tasks,omitempty"`
	FollowerIds   []int      `json:"follower_ids,omitempty"`
	CommentIds    []int      `json:"comment_ids,omitempty"`
	CreatedAt     *time.Time `json:"created_at,omitempty"`
	UpdatedAt     *time.Time `json:"updated_at,omitempty"`
	IntegrationId int        `json:"integration_id,omitempty"`
	ExternalId    string     `json:"external_id,omitempty"`
	URL           string     `json:"url,omitempty"`
	Kind          string     `json:"kind,omitempty"`
}

type Label struct {
	Id        int        `json:"id,omitempty"`
	ProjectId int        `json:"project_id,omitempty"`
	Name      string     `json:"name,omitempty"`
	CreatedAt *time.Time `json:"created_at,omitempty"`
	UpdatedAt *time.Time `json:"updated_at,omitempty"`
	Kind      string     `json:"kind,omitempty"`
}

type Task struct {
	Id          int        `json:"id,omitempty"`
	StoryId     int        `json:"story_id,omitempty"`
	Description string     `json:"description,omitempty"`
	Position    int        `json:"position,omitempty"`
	Complete    bool       `json:"complete,omitempty"`
	CreatedAt   *time.Time `json:"created_at,omitempty"`
	UpdatedAt   *time.Time `json:"updated_at,omitempty"`
}

type Person struct {
	Id                         int        `json:"id,omitempty"`
	Name                       string     `json:"name,omitempty"`
	Initials                   string     `json:"initials,omitempty"`
	Username                   string     `json:"username,omitempty"`
	TimeZone                   *TimeZone  `json:"time_zone,omitempty"`
	Email                      string     `json:"email,omitempty"`
	Kind                       string     `json:"kind,omitempty"`
}

type StoryService struct {
	client *Client
}

func newStoryService(client *Client) *StoryService {
	return &StoryService{client}
}

func (service *StoryService) List(projectId int, filter string) ([]*Story, *http.Response, error) {
	u := fmt.Sprintf("projects/%v/stories", projectId)
	if filter != "" {
		u += "?filter=" + url.QueryEscape(filter)
	}

	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var stories []*Story
	resp, err := service.client.Do(req, &stories)
	if err != nil {
		return nil, resp, err
	}

	return stories, resp, err
}

func (service *StoryService) Get(projectId, storyId int) (*Story, *http.Response, error) {
	u := fmt.Sprintf("projects/%v/stories/%v", projectId, storyId)
	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var story Story
	resp, err := service.client.Do(req, &story)
	if err != nil {
		return nil, resp, err
	}

	return &story, resp, err
}

func (service *StoryService) Update(projectId, storyId int, story *Story) (*Story, *http.Response, error) {
	u := fmt.Sprintf("projects/%v/stories/%v", projectId, storyId)
	req, err := service.client.NewRequest("PUT", u, story)
	if err != nil {
		return nil, nil, err
	}

	var bodyStory Story
	resp, err := service.client.Do(req, &bodyStory)
	if err != nil {
		return nil, resp, err
	}

	return &bodyStory, resp, err

}

func (service *StoryService) ListTasks(projectId, storyId int) ([]*Task, *http.Response, error) {
	u := fmt.Sprintf("projects/%v/stories/%v/tasks", projectId, storyId)
	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var tasks []*Task
	resp, err := service.client.Do(req, &tasks)
	if err != nil {
		return nil, resp, err
	}

	return tasks, resp, err
}

func (service *StoryService) AddTask(projectId, storyId int, task *Task) (*http.Response, error) {
	if task.Description == "" {
		return nil, &ErrFieldNotSet{"description"}
	}

	u := fmt.Sprintf("projects/%v/stories/%v/tasks", projectId, storyId)
	req, err := service.client.NewRequest("POST", u, task)
	if err != nil {
		return nil, err
	}

	return service.client.Do(req, nil)
}

func (service *StoryService) ListOwners(projectId, storyId int) ([]*Person, *http.Response, error) {
	u := fmt.Sprintf("projects/%d/stories/%d/owners", projectId, storyId)
	req, err := service.client.NewRequest("GET", u, nil)
	if err != nil {
		return nil, nil, err
	}

	var owners []*Person
	resp, err := service.client.Do(req, &owners)
	if err != nil {
		return nil, resp, err
	}

	return owners, resp, err
}
<|endoftext|>


<commit_before>package middleware

import (
	"github.com/DeedleFake/Go-PhysicsFS/physfs"
	"github.com/fzzy/radix/redis"
	"github.com/gin-gonic/gin"
	"github.com/pmylund/go-cache"
	"github.com/vifino/carbon/modules/glue"
	"github.com/vifino/carbon/modules/helpers"
	"github.com/vifino/carbon/modules/static"
	"github.com/vifino/contrib/gzip"
	"github.com/vifino/golua/lua"
	"github.com/vifino/luar"
	"time"
	"net"
	"fmt"
	"bufio"
)

func Bind(L *lua.State) {
	BindMiddleware(L)
	BindRedis(L)
	BindPhysFS(L)
	BindOther(L)
	BindNet(L)
	BindConversions(L)
	BindComs(L)
}

func BindMiddleware(L *lua.State) {
	luar.Register(L, "mw", luar.Map{
		"Lua": Lua,
		"ExtRoute": (func(plan map[string]interface{}) func(*gin.Context) {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(func(*gin.Context))
			}
			return ExtRoute(newplan)
		}),
		"VHOST": (func(plan map[string]interface{}) func(*gin.Context) {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(func(*gin.Context))
			}
			return VHOST(newplan)
		}),
		"Logger":   gin.Logger,
		"Recovery": gin.Recovery,
		"GZip": func() func(*gin.Context) {
			return gzip.Gzip(gzip.DefaultCompression)
		},
		"DLR_NS":    DLR_NS,
		"DLR_RUS":   DLR_RUS,
		"DLRWS_RUS": DLRWS_RUS,
		"Echo":      EchoHTML,
		"EchoText":  Echo,
	})
	L.DoString(glue.RouteGlue())
}
func BindPhysFS(L *lua.State) {
	luar.Register(L, "fs", luar.Map{ // PhysFS
		"mount":       physfs.Mount,
		"exits":       physfs.Exists,
		"getFS":       physfs.FileSystem,
		"mkdir":       physfs.Mkdir,
		"umount":      physfs.RemoveFromSearchPath,
		"delete":      physfs.Delete,
		"setWriteDir": physfs.SetWriteDir,
		"getWriteDir": physfs.GetWriteDir,
	})
}
func BindRedis(L *lua.State) {
	luar.Register(L, "redis", luar.Map{
		"connectTimeout": (func(host string, timeout int) (*redis.Client, error) {
			return redis.DialTimeout("tcp", host, time.Duration(timeout)*time.Second)
		}),
		"connect": (func(host string) (*redis.Client, error) {
			return redis.Dial("tcp", host)
		}),
	})
}
func BindOther(L *lua.State) {
	luar.Register(L, "", luar.Map{
		"unixtime": (func() int {
			return int(time.Now().UnixNano())
		}),
		"_syntaxhlfunc": helpers.SyntaxHL,
	})
}
func BindComs(L *lua.State) {
	luar.Register(L, "com", luar.Map{
		"create": (func() chan interface{} {
			return make(chan interface{})
		}),
		"createBuffered": (func(buffer int) chan interface{} {
			return make(chan interface{}, buffer)
		}),
		"receive": (func(c chan interface{}) interface{} {
			return <-c
		}),
		"send": (func(c chan interface{}, val interface{}) {
			c <- val
		}),
	})
}
func BindNet(L *lua.State) {
	luar.Register(L, "net", luar.Map{
		"dial": net.Dial,
		"write": (func(con *net.Conn, str string) {
			fmt.Fprintf(con, str)
		}),
		"readline": (func(conn *net.Conn) (string, error) {
			return bufio.NewReader(conn).ReadString('\n')
		}),
	})
}
func BindConversions(L *lua.State) {
	luar.Register(L, "convert", luar.Map{
		"stringtocharslice": (func(x string) []byte {
			return []byte(x)
		}),
		"charslicetostring": (func(x []byte) string {
			return string(x)
		}),
	})
}
func BindContext(L *lua.State, context *gin.Context) {
	luar.Register(L, "", luar.Map{
		"context":    context,
		"req":        context.Request,
		"_paramfunc": context.Param,
		"_formfunc":  context.PostForm,
		"_queryfunc": context.Query,
	})
}
func BindStatic(L *lua.State, cfe *cache.Cache) {
	luar.Register(L, "static", luar.Map{
		"serve": (func(prefix string) func(*gin.Context) {
			return staticServe.ServeCached(prefix, staticServe.PhysFS("", true, true), cfe)
		}),
	})
}
<commit_msg>More fixes! Yay!<commit_after>package middleware

import (
	"github.com/DeedleFake/Go-PhysicsFS/physfs"
	"github.com/fzzy/radix/redis"
	"github.com/gin-gonic/gin"
	"github.com/pmylund/go-cache"
	"github.com/vifino/carbon/modules/glue"
	"github.com/vifino/carbon/modules/helpers"
	"github.com/vifino/carbon/modules/static"
	"github.com/vifino/contrib/gzip"
	"github.com/vifino/golua/lua"
	"github.com/vifino/luar"
	"time"
	"net"
	"fmt"
	"bufio"
)

func Bind(L *lua.State) {
	BindMiddleware(L)
	BindRedis(L)
	BindPhysFS(L)
	BindOther(L)
	BindNet(L)
	BindConversions(L)
	BindComs(L)
}

func BindMiddleware(L *lua.State) {
	luar.Register(L, "mw", luar.Map{
		"Lua": Lua,
		"ExtRoute": (func(plan map[string]interface{}) func(*gin.Context) {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(func(*gin.Context))
			}
			return ExtRoute(newplan)
		}),
		"VHOST": (func(plan map[string]interface{}) func(*gin.Context) {
			newplan := make(Plan, len(plan))
			for k, v := range plan {
				newplan[k] = v.(func(*gin.Context))
			}
			return VHOST(newplan)
		}),
		"Logger":   gin.Logger,
		"Recovery": gin.Recovery,
		"GZip": func() func(*gin.Context) {
			return gzip.Gzip(gzip.DefaultCompression)
		},
		"DLR_NS":    DLR_NS,
		"DLR_RUS":   DLR_RUS,
		"DLRWS_RUS": DLRWS_RUS,
		"Echo":      EchoHTML,
		"EchoText":  Echo,
	})
	L.DoString(glue.RouteGlue())
}
func BindPhysFS(L *lua.State) {
	luar.Register(L, "fs", luar.Map{ // PhysFS
		"mount":       physfs.Mount,
		"exits":       physfs.Exists,
		"getFS":       physfs.FileSystem,
		"mkdir":       physfs.Mkdir,
		"umount":      physfs.RemoveFromSearchPath,
		"delete":      physfs.Delete,
		"setWriteDir": physfs.SetWriteDir,
		"getWriteDir": physfs.GetWriteDir,
	})
}
func BindRedis(L *lua.State) {
	luar.Register(L, "redis", luar.Map{
		"connectTimeout": (func(host string, timeout int) (*redis.Client, error) {
			return redis.DialTimeout("tcp", host, time.Duration(timeout)*time.Second)
		}),
		"connect": (func(host string) (*redis.Client, error) {
			return redis.Dial("tcp", host)
		}),
	})
}
func BindOther(L *lua.State) {
	luar.Register(L, "", luar.Map{
		"unixtime": (func() int {
			return int(time.Now().UnixNano())
		}),
		"_syntaxhlfunc": helpers.SyntaxHL,
	})
}
func BindComs(L *lua.State) {
	luar.Register(L, "com", luar.Map{
		"create": (func() chan interface{} {
			return make(chan interface{})
		}),
		"createBuffered": (func(buffer int) chan interface{} {
			return make(chan interface{}, buffer)
		}),
		"receive": (func(c chan interface{}) interface{} {
			return <-c
		}),
		"send": (func(c chan interface{}, val interface{}) {
			c <- val
		}),
	})
}
func BindNet(L *lua.State) {
	luar.Register(L, "net", luar.Map{
		"dial": net.Dial,
		"write": (func(con net.Conn, str string) {
			fmt.Fprintf(con, str)
		}),
		"readline": (func(conn *net.Conn) (string, error) {
			return bufio.NewReader(conn).ReadString('\n')
		}),
	})
}
func BindConversions(L *lua.State) {
	luar.Register(L, "convert", luar.Map{
		"stringtocharslice": (func(x string) []byte {
			return []byte(x)
		}),
		"charslicetostring": (func(x []byte) string {
			return string(x)
		}),
	})
}
func BindContext(L *lua.State, context *gin.Context) {
	luar.Register(L, "", luar.Map{
		"context":    context,
		"req":        context.Request,
		"_paramfunc": context.Param,
		"_formfunc":  context.PostForm,
		"_queryfunc": context.Query,
	})
}
func BindStatic(L *lua.State, cfe *cache.Cache) {
	luar.Register(L, "static", luar.Map{
		"serve": (func(prefix string) func(*gin.Context) {
			return staticServe.ServeCached(prefix, staticServe.PhysFS("", true, true), cfe)
		}),
	})
}
<|endoftext|>