<commit_before>// tgotop project main.go

package main

import (
	"bytes"
	"fmt"
	//	spew "github.com/davecgh/go-spew/spew"
	ui "github.com/gizak/termui"
	//tm "github.com/nsf/termbox-go"
	"os"
	"os/signal"
	"syscall"
	"text/tabwriter"
	"time"
)

const (
	mult  = 10
	dtick = time.Second / 2 //redrawing interval
	atick = time.Second     //averaging interval
	ptick = atick / mult    //polling interval
)

func main() {
	err := ui.Init()
	if err != nil {
		panic(err)
	}
	defer ui.Close()

	qMess := ui.NewPar(":PRESS q TO QUIT")
	qMess.Height = 3

	gSwap := ui.NewGauge()
	gSwap.Height = 3

	gMem := ui.NewGauge()
	gMem.Height = 3

	gNet := ui.NewList()

	//getting ready to close stuff on command
	evt := ui.EventCh()
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGABRT, syscall.SIGTERM)

	nd := new(netData)
	err = nd.Init(3*mult, ptick)

	if err != nil {
		panic(err)
	}

	gNet.Height = nd.size + 3
	var m memData

	go func() {
		for {
			err := m.Update()
			if err != nil {
				panic(err)
			}

			gMem.Percent = m.memPercent
			gMem.Border.Label = fillfmt("Memory", m.memUse, m.memTotal)

			gSwap.Percent = m.swapPercent
			gSwap.Border.Label = fillfmt("Swap", m.swapUse, m.swapTotal)

			gNet.Items = netf(nd)
			time.Sleep(dtick)
		}
	}()

	ui.Body.AddRows(
		ui.NewRow(
			ui.NewCol(6, 0, gMem, gSwap),
			ui.NewCol(6, 0, gNet)),
		ui.NewRow(ui.NewCol(12, 0, qMess)))

	ui.Body.Align()

	for {
		select {
		case e := <-evt:
			if dealwithevents(e) {
				return
			}
		case <-sig:
			return
		default:
			ui.Render(ui.Body)
		}
	}
}

func fillfmt(s string, u uint64, t uint64) string {
	return fmt.Sprintf("%v used: %v / %v", s, humanBytes(float32(u)), humanBytes(float32(t)))
}

func dealwithevents(e ui.Event) bool {
	if e.Type == ui.EventKey && (e.Ch == 'q' || e.Ch == 'Q') {
		return true
	}
	if e.Type == ui.EventKey && e.Key == ui.KeyCtrlC {
		return true
	}
	if e.Type == ui.EventResize {
		ui.Body.Width = ui.TermWidth()
		ui.Body.Align()
	}
	return false
}

func netf(nd *netData) []string {
	strings := make([]string, 0, nd.size+1)
	var b bytes.Buffer
	tb := tabwriter.NewWriter(&b, 10, 8, 0, ' ', tabwriter.AlignRight)
	fmt.Fprintln(tb, "IFace\t Down\t Up\t")
	for i := 0; i < nd.size; i++ {
		fmt.Fprintf(tb, "%v:\t %s/s\t %s/s\t\n",
			nd.name[i],
			humanBytes(nd.GetD(i, mult)),
			humanBytes(nd.GetU(i, mult)))
	}

	err := tb.Flush()

	if err != nil {
		panic(err)
	}
	for i := 0; i <= nd.size; i++ {
		ts, err := b.ReadString('\n')
		if err != nil {
			panic(err)
		}
		strings = append(strings, ts)
	}
	return strings
}
<commit_msg>Hardlocked screen redraw rate.<commit_after>// tgotop project main.go

package main

import (
	"bytes"
	"fmt"
	//	spew "github.com/davecgh/go-spew/spew"
	ui "github.com/gizak/termui"
	//tm "github.com/nsf/termbox-go"
	"os"
	"os/signal"
	"syscall"
	"text/tabwriter"
	"time"
)

const (
	mult  = 10
	dtick = time.Second / 2 //refreshing interval
	rtick = time.Second /60 //redrawint interval
	atick = time.Second     //averaging interval
	ptick = atick / mult    //polling interval
)

func main() {
	err := ui.Init()
	if err != nil {
		panic(err)
	}
	defer ui.Close()

	qMess := ui.NewPar(":PRESS q TO QUIT")
	qMess.Height = 3

	gSwap := ui.NewGauge()
	gSwap.Height = 3

	gMem := ui.NewGauge()
	gMem.Height = 3

	gNet := ui.NewList()

	//getting ready to close stuff on command
	evt := ui.EventCh()
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGABRT, syscall.SIGTERM)

	nd := new(netData)
	err = nd.Init(3*mult, ptick)

	if err != nil {
		panic(err)
	}

	gNet.Height = nd.size + 3
	var m memData

	go func() {
		for {
			err := m.Update()
			if err != nil {
				panic(err)
			}

			gMem.Percent = m.memPercent
			gMem.Border.Label = fillfmt("Memory", m.memUse, m.memTotal)

			gSwap.Percent = m.swapPercent
			gSwap.Border.Label = fillfmt("Swap", m.swapUse, m.swapTotal)

			gNet.Items = netf(nd)
			time.Sleep(dtick)
		}
	}()

	ui.Body.AddRows(
		ui.NewRow(
			ui.NewCol(6, 0, gMem, gSwap),
			ui.NewCol(6, 0, gNet)),
		ui.NewRow(ui.NewCol(12, 0, qMess)))

	ui.Body.Align()
	tkr := time.Tick(rtick)
	for {
		select {
		case e := <-evt:
			if dealwithevents(e) {
				return
			}
		case <-sig:
			return
		case <- tkr:
			ui.Render(ui.Body)
		}
	}
}

func fillfmt(s string, u uint64, t uint64) string {
	return fmt.Sprintf("%v used: %v / %v", s, humanBytes(float32(u)), humanBytes(float32(t)))
}

func dealwithevents(e ui.Event) bool {
	if e.Type == ui.EventKey && (e.Ch == 'q' || e.Ch == 'Q') {
		return true
	}
	if e.Type == ui.EventKey && e.Key == ui.KeyCtrlC {
		return true
	}
	if e.Type == ui.EventResize {
		ui.Body.Width = ui.TermWidth()
		ui.Body.Align()
	}
	return false
}

func netf(nd *netData) []string {
	strings := make([]string, 0, nd.size+1)
	var b bytes.Buffer
	tb := tabwriter.NewWriter(&b, 10, 8, 0, ' ', tabwriter.AlignRight)
	fmt.Fprintln(tb, "IFace\t Down\t Up\t")
	for i := 0; i < nd.size; i++ {
		fmt.Fprintf(tb, "%v:\t %s/s\t %s/s\t\n",
			nd.name[i],
			humanBytes(nd.GetD(i, mult)),
			humanBytes(nd.GetU(i, mult)))
	}

	err := tb.Flush()

	if err != nil {
		panic(err)
	}
	for i := 0; i <= nd.size; i++ {
		ts, err := b.ReadString('\n')
		if err != nil {
			panic(err)
		}
		strings = append(strings, ts)
	}
	return strings
}
<|endoftext|>


<commit_before><commit_msg>internal/restic: Use errors.New when no formatting is needed<commit_after><|endoftext|>


<commit_before>package app

import (
	"fmt"
)<commit_msg>Update app.go<commit_after>package app

//exodo application
//author: mauricio

import (
	"net/http"
)

func Server(){
	mux  := http.NewServeMux()
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/urfave/cli"
	"github.com/rhaamo/lutrainit/shared/ipc"
)

// CmdReload CLI object
var CmdReload = cli.Command {
	Name: "reload",
	Usage: "Reload init configs",
	Description: "Reload init configs",
	Action: doReload,
	Flags: []cli.Flag{},
}

func doReload(ctx *cli.Context) error {
	res, err := GorpcDispatcherClient.Call("reload", nil)

	resIpc := res.(*ipc.AnswerReload)

	if resIpc.Err {
		println("Reload error:", resIpc.ErrStr)
	} else {
		println("Reload successfull.")
	}

	return err
}<commit_msg>Don't explode if the return is <nil><commit_after>package main

import (
	"github.com/urfave/cli"
	"github.com/rhaamo/lutrainit/shared/ipc"
	"errors"
)

// CmdReload CLI object
var CmdReload = cli.Command {
	Name: "reload",
	Usage: "Reload init configs",
	Description: "Reload init configs",
	Action: doReload,
	Flags: []cli.Flag{},
}

func doReload(ctx *cli.Context) error {
	res, err := GorpcDispatcherClient.Call("reload", nil)

	if err != nil {
		return err
	} else if res == nil {
		return errors.New("result is <nil>")
	}

	resIpc := res.(*ipc.AnswerReload)

	if resIpc.Err {
		println("Reload error:", resIpc.ErrStr)
	} else {
		println("Reload successfull.")
	}

	return err
}<|endoftext|>


<commit_before>package drbuffer

import (
	"fmt"
	"math"
	"unsafe"
)

const META_SECTION_SIZE = 16 // 4 for version 4 for nextWriteFrom 4 for lastReadTo 4 for wrapAt
const MAX_PACKETS_READ_ONE_TIME = 1024
const IS_DEBUG = false

type ringBuffer struct {
	meta          []byte // store pointers
	data          []byte // store packets
	version       *uint32
	nextWriteFrom *uint32
	lastReadTo    *uint32
	wrapAt        *uint32
	nextReadFrom  uint32
	reusablePacketList [][]byte
}

func NewRingBuffer(meta []byte, buffer []byte) *ringBuffer {
	if len(meta) != META_SECTION_SIZE {
		panic(fmt.Sprintf("meta should of size: %s", META_SECTION_SIZE))
	}
	lastReadTo := (*uint32)(unsafe.Pointer(&meta[8]))
	return &ringBuffer{
		meta:       meta,
		data:       buffer,
		version: (*uint32)(unsafe.Pointer(&meta[0])),
		nextWriteFrom: (*uint32)(unsafe.Pointer(&meta[4])),
		lastReadTo: lastReadTo,
		wrapAt: (*uint32)(unsafe.Pointer(&meta[12])),
		nextReadFrom: *lastReadTo,
		reusablePacketList: make([][]byte, MAX_PACKETS_READ_ONE_TIME),
	}
}

type packet []byte

func (p packet) size() uint16 {
	packetSizePtr := (*uint16)(unsafe.Pointer(&p[0]))
	packetSize := *packetSizePtr
	return packetSize
}

func (p packet) write(bytes []byte) {
	if len(bytes) > math.MaxUint16 {
		panic(fmt.Sprintf("packet too large: %s", len(bytes)))
	}
	packetSize := uint16(len(bytes))
	packetSizePtr := (*uint16)(unsafe.Pointer(&p[0]))
	*packetSizePtr = packetSize
	copy(p[2:], bytes)
}

func (p packet) read() packet {
	return p[2 : 2 + p.size()]
}

func (buffer *ringBuffer) PushN(pList [][]byte) {
	writeFrom := *buffer.nextWriteFrom
	for _, p := range pList {
		buffer.PushOne(p)
	}
	writeTo := *buffer.nextWriteFrom
	if IS_DEBUG {
		fmt.Println("write", len(pList), "[", writeFrom, ",", writeTo, ")")
	}
}

func (buffer *ringBuffer) PushOne(p []byte) {
	if len(p) > len(buffer.data) - 2 {
		panic(fmt.Sprintf("packet to push is too large: %s", len(p)))
	}
	writeFrom := *buffer.nextWriteFrom
	writeTo := writeFrom + 2 + uint32(len(p))
	if *buffer.wrapAt != 0 {
		// first lap is immune
		// read pointer in range [writeFrom, writeTo) will be repelled to safe harbour (0)
		buffer.repelReadPointers(writeFrom, writeTo)
	}
	if writeTo > uint32(len(buffer.data)) {
		*buffer.wrapAt = writeFrom
		if IS_DEBUG {
			fmt.Println("wrap at:", writeFrom)
		}
		writeFrom = 0
		writeTo = 2 + uint32(len(p))
		// [writeFrom, writeTo) changed, repel again
		buffer.repelReadPointers(writeFrom, writeTo)
	}
	// write data first before moving nw pointer to ensure the pointing region is valid
	packet(buffer.data[writeFrom:]).write(p)
	*buffer.nextWriteFrom = writeTo
}

func (buffer *ringBuffer) repelReadPointers(writeFrom, writeTo uint32) {
	if writeFrom <= *buffer.lastReadTo && *buffer.lastReadTo <= writeTo {
		// move lastReadTo to avoid overwrite, 0 always point to a valid packet
		// do not allow lastReadTo == writeTo which implies not allow nextReadFrom == writeTo
		// this way, when nextReadFrom == nextWriteTo, the queue is empty
		*buffer.lastReadTo = 0
		*buffer.wrapAt = 0
		buffer.nextReadFrom = 0
	}
	// do not need to check buffer.nextReadFrom as buffer.lastReadTo will always be encountered first
}

func (buffer *ringBuffer) PopN(maxPacketsCount int) [][]byte {
	if maxPacketsCount > MAX_PACKETS_READ_ONE_TIME {
		maxPacketsCount = MAX_PACKETS_READ_ONE_TIME
	}
	*buffer.lastReadTo = buffer.nextReadFrom
	if buffer.nextReadFrom == *buffer.nextWriteFrom {
		return buffer.reusablePacketList[:0]
	}
	if buffer.nextReadFrom > *buffer.nextWriteFrom {
		// write is in the next lap now, we finish the first lap at wrapAt
		packetsCount, readTo := buffer.readRegion(buffer.nextReadFrom, *buffer.wrapAt, 0, maxPacketsCount)
		if packetsCount >= maxPacketsCount {
			buffer.nextReadFrom = readTo
			return buffer.reusablePacketList[:packetsCount]
		} else {
			// catch up the second lap
			packetsCount, readTo = buffer.readRegion(0, *buffer.nextWriteFrom, packetsCount, maxPacketsCount)
			buffer.nextReadFrom = readTo
			return buffer.reusablePacketList[:packetsCount]
		}
	} else {
		// we are at the same lap
		packetsCount, readTo := buffer.readRegion(buffer.nextReadFrom, *buffer.nextWriteFrom, 0, maxPacketsCount)
		buffer.nextReadFrom = readTo
		return buffer.reusablePacketList[:packetsCount]
	}
}

func (buffer *ringBuffer) readRegion(readFrom, readTo uint32, packetsCount int, maxPacketsCount int) (int, uint32) {
	if IS_DEBUG {
		fmt.Println("read [", readFrom, ",", readTo, ")")
	}
	pos := readFrom
	for ; pos < readTo && packetsCount < maxPacketsCount; {
		if IS_DEBUG {
			fmt.Println("read packet of size: ", packet(buffer.data[pos:]).size())
		}
		p := packet(buffer.data[pos:]).read()
		buffer.reusablePacketList[packetsCount] = p
		pos = pos + 2 + uint32(len(p))
		packetsCount += 1
	}
	return packetsCount, pos
}

func (buffer *ringBuffer) PopOne() []byte {
	packets := buffer.PopN(1)
	if len(packets) > 0 {
		return packets[0]
	} else {
		return nil
	}
}
<commit_msg>meta is not needed<commit_after>package drbuffer

import (
	"fmt"
	"math"
	"unsafe"
)

const META_SECTION_SIZE = 16 // 4 for version 4 for nextWriteFrom 4 for lastReadTo 4 for wrapAt
const MAX_PACKETS_READ_ONE_TIME = 1024
const IS_DEBUG = false

type ringBuffer struct {
	data          []byte // store packets
	version       *uint32
	nextWriteFrom *uint32
	lastReadTo    *uint32
	wrapAt        *uint32
	nextReadFrom  uint32
	reusablePacketList [][]byte
}

func NewRingBuffer(meta []byte, buffer []byte) *ringBuffer {
	if len(meta) != META_SECTION_SIZE {
		panic(fmt.Sprintf("meta should of size: %s", META_SECTION_SIZE))
	}
	lastReadTo := (*uint32)(unsafe.Pointer(&meta[8]))
	return &ringBuffer{
		data:       buffer,
		version: (*uint32)(unsafe.Pointer(&meta[0])),
		nextWriteFrom: (*uint32)(unsafe.Pointer(&meta[4])),
		lastReadTo: lastReadTo,
		wrapAt: (*uint32)(unsafe.Pointer(&meta[12])),
		nextReadFrom: *lastReadTo,
		reusablePacketList: make([][]byte, MAX_PACKETS_READ_ONE_TIME),
	}
}

type packet []byte

func (p packet) size() uint16 {
	packetSizePtr := (*uint16)(unsafe.Pointer(&p[0]))
	packetSize := *packetSizePtr
	return packetSize
}

func (p packet) write(bytes []byte) {
	if len(bytes) > math.MaxUint16 {
		panic(fmt.Sprintf("packet too large: %s", len(bytes)))
	}
	packetSize := uint16(len(bytes))
	packetSizePtr := (*uint16)(unsafe.Pointer(&p[0]))
	*packetSizePtr = packetSize
	copy(p[2:], bytes)
}

func (p packet) read() packet {
	return p[2 : 2 + p.size()]
}

func (buffer *ringBuffer) PushN(pList [][]byte) {
	writeFrom := *buffer.nextWriteFrom
	for _, p := range pList {
		buffer.PushOne(p)
	}
	writeTo := *buffer.nextWriteFrom
	if IS_DEBUG {
		fmt.Println("write", len(pList), "[", writeFrom, ",", writeTo, ")")
	}
}

func (buffer *ringBuffer) PushOne(p []byte) {
	if len(p) > len(buffer.data) - 2 {
		panic(fmt.Sprintf("packet to push is too large: %s", len(p)))
	}
	writeFrom := *buffer.nextWriteFrom
	writeTo := writeFrom + 2 + uint32(len(p))
	if *buffer.wrapAt != 0 {
		// first lap is immune
		// read pointer in range [writeFrom, writeTo) will be repelled to safe harbour (0)
		buffer.repelReadPointers(writeFrom, writeTo)
	}
	if writeTo > uint32(len(buffer.data)) {
		*buffer.wrapAt = writeFrom
		if IS_DEBUG {
			fmt.Println("wrap at:", writeFrom)
		}
		writeFrom = 0
		writeTo = 2 + uint32(len(p))
		// [writeFrom, writeTo) changed, repel again
		buffer.repelReadPointers(writeFrom, writeTo)
	}
	// write data first before moving nw pointer to ensure the pointing region is valid
	packet(buffer.data[writeFrom:]).write(p)
	*buffer.nextWriteFrom = writeTo
}

func (buffer *ringBuffer) repelReadPointers(writeFrom, writeTo uint32) {
	if writeFrom <= *buffer.lastReadTo && *buffer.lastReadTo <= writeTo {
		// move lastReadTo to avoid overwrite, 0 always point to a valid packet
		// do not allow lastReadTo == writeTo which implies not allow nextReadFrom == writeTo
		// this way, when nextReadFrom == nextWriteTo, the queue is empty
		*buffer.lastReadTo = 0
		*buffer.wrapAt = 0
		buffer.nextReadFrom = 0
	}
	// do not need to check buffer.nextReadFrom as buffer.lastReadTo will always be encountered first
}

func (buffer *ringBuffer) PopN(maxPacketsCount int) [][]byte {
	if maxPacketsCount > MAX_PACKETS_READ_ONE_TIME {
		maxPacketsCount = MAX_PACKETS_READ_ONE_TIME
	}
	*buffer.lastReadTo = buffer.nextReadFrom
	if buffer.nextReadFrom == *buffer.nextWriteFrom {
		return buffer.reusablePacketList[:0]
	}
	if buffer.nextReadFrom > *buffer.nextWriteFrom {
		// write is in the next lap now, we finish the first lap at wrapAt
		packetsCount, readTo := buffer.readRegion(buffer.nextReadFrom, *buffer.wrapAt, 0, maxPacketsCount)
		if packetsCount >= maxPacketsCount {
			buffer.nextReadFrom = readTo
			return buffer.reusablePacketList[:packetsCount]
		} else {
			// catch up the second lap
			packetsCount, readTo = buffer.readRegion(0, *buffer.nextWriteFrom, packetsCount, maxPacketsCount)
			buffer.nextReadFrom = readTo
			return buffer.reusablePacketList[:packetsCount]
		}
	} else {
		// we are at the same lap
		packetsCount, readTo := buffer.readRegion(buffer.nextReadFrom, *buffer.nextWriteFrom, 0, maxPacketsCount)
		buffer.nextReadFrom = readTo
		return buffer.reusablePacketList[:packetsCount]
	}
}

func (buffer *ringBuffer) readRegion(readFrom, readTo uint32, packetsCount int, maxPacketsCount int) (int, uint32) {
	if IS_DEBUG {
		fmt.Println("read [", readFrom, ",", readTo, ")")
	}
	pos := readFrom
	for ; pos < readTo && packetsCount < maxPacketsCount; {
		if IS_DEBUG {
			fmt.Println("read packet of size: ", packet(buffer.data[pos:]).size())
		}
		p := packet(buffer.data[pos:]).read()
		buffer.reusablePacketList[packetsCount] = p
		pos = pos + 2 + uint32(len(p))
		packetsCount += 1
	}
	return packetsCount, pos
}

func (buffer *ringBuffer) PopOne() []byte {
	packets := buffer.PopN(1)
	if len(packets) > 0 {
		return packets[0]
	} else {
		return nil
	}
}
<|endoftext|>


<commit_before>package core

import "fmt"

type domain struct {
	app           *app
	name          string
	joined        bool
	subscriptions map[uint]*boundEndpoint
	registrations map[uint]*boundEndpoint
}

type boundEndpoint struct {
	callback      uint
	endpoint      string
	expectedTypes []interface{}
}

func (d domain) Subdomain(name string) Domain {
	return d.app.NewDomain(d.name + "." + name)
}

// Accepts a connection that has just been opened. This method should only
// be called once, to initialize the fabric
func (c domain) Join(conn Connection) error {
	if c.joined {
		return fmt.Errorf("Domain %s is already joined", c.name)
	}

	c.app.Connection = conn

	// Should we hard close on conn.Close()? The App may be interested in knowing about the close
	if err := c.app.SendNow(&hello{Realm: c.name, Details: map[string]interface{}{}}); err != nil {
		c.app.Close("ERR: could not send a hello message")
		return err
	}

	if msg, err := c.app.getMessageTimeout(); err != nil {
		c.app.Close(err.Error())
		return err
	} else if _, ok := msg.(*welcome); !ok {
		c.app.SendNow(&abort{Details: map[string]interface{}{}, Reason: "Error- unexpected_message_type"})
		c.app.Close("Error- unexpected_message_type")
		return fmt.Errorf(formatUnexpectedMessage(msg, wELCOME.String()))
	}

	// This is super dumb, and the reason its in here was fixed. Please revert
	go c.app.receiveLoop()
	go c.app.sendLoop()

	// old contents of app.join
	for _, x := range c.app.domains {
		if !x.joined {
			x.joined = true
			// x.Delegate.OnJoin(x.name)
			// Invoke the onjoin method for the domain!
		}
	}

	Info("Domain joined")
	return nil
}

func (c *domain) Leave() error {
	if dems, ok := removeDomain(c.app.domains, c); !ok {
		return fmt.Errorf("WARN: couldn't find %s to remove!", c)
	} else {
		c.app.domains = dems
	}

	if err := c.app.Send(&goodbye{
		Details: map[string]interface{}{},
		Reason:  ErrCloseRealm,
	}); err != nil {
		return fmt.Errorf("Error leaving fabric: %v", err)
	}

	// if no domains remain, terminate the connection
	if len(c.app.domains) == 0 {
		c.app.Close("Closing: no domains connected")
	}

	return nil
}

/////////////////////////////////////////////
// Message Patterns
/////////////////////////////////////////////

func (c domain) Subscribe(endpoint string, requestId uint, types []interface{}) error {
	endpoint = makeEndpoint(c.name, endpoint)
	sub := &subscribe{Request: NewID(), Options: make(map[string]interface{}), Name: endpoint}

	if msg, err := c.app.requestListenType(sub, "*core.subscribed"); err != nil {
		return err
	} else {
		subbed := msg.(*subscribed)
		Info("Subscribed: %s", endpoint)
		c.subscriptions[subbed.Subscription] = &boundEndpoint{requestId, endpoint, types}
		return nil
	}
}

func (c domain) Register(endpoint string, requestId uint, types []interface{}) error {
	endpoint = makeEndpoint(c.name, endpoint)
	register := &register{Request: NewID(), Options: make(map[string]interface{}), Name: endpoint}

	if msg, err := c.app.requestListenType(register, "*core.registered"); err != nil {
		return err
	} else {
		Info("Registered: %s", endpoint)
		reg := msg.(*registered)
		c.registrations[reg.Registration] = &boundEndpoint{requestId, endpoint, types}
		return nil
	}
}

func (c domain) Publish(endpoint string, requestId uint, args []interface{}) error {
	return c.app.Send(&publish{
		Request:   NewID(),
		Options:   make(map[string]interface{}),
		Name:      makeEndpoint(c.name, endpoint),
		Arguments: args,
	})
}

func (c domain) Call(endpoint string, requestId uint, args []interface{}) error {
	endpoint = makeEndpoint(c.name, endpoint)
	call := &call{Request: NewID(), Name: endpoint, Options: make(map[string]interface{}), Arguments: args}

	if msg, err := c.app.requestListenType(call, "*core.result"); err != nil {
		return err
	} else {
		c.app.CallbackSend(requestId, msg.(*result).Arguments...)
		return nil
	}
}

func (c domain) Yield(request uint, args []interface{}) {
	// Big todo here
	m := &yield{
		Request:   request,
		Options:   make(map[string]interface{}),
		Arguments: args,
	}

	// if err != nil {
	//     m = &errorMessage{
	//         Type:      iNVOCATION,
	//         Request:   request,
	//         Details:   make(map[string]interface{}),
	//         Arguments: args,
	//         Error:     "Not Implemented",
	//     }
	// }

	if err := c.app.Send(m); err != nil {
		Warn("Could not send yield")
	} else {
		Info("Yield: %s", m)
	}
}

// This isn't going to work on the callback chain... no request id passed in
func (c domain) Unsubscribe(endpoint string) error {
	endpoint = makeEndpoint(c.name, endpoint)

	if id, _, ok := bindingForEndpoint(c.subscriptions, endpoint); !ok {
		return fmt.Errorf("domain %s is not registered with this client.", endpoint)
	} else {
		sub := &unsubscribe{Request: NewID(), Subscription: id}

		if _, err := c.app.requestListenType(sub, "*core.unsubscribed"); err != nil {
			return err
		} else {
			Info("Unsubscribed: %s", endpoint)
			delete(c.subscriptions, id)
			return nil
		}
	}
}

// Same as above -- won't work on the callbacks
func (c domain) Unregister(endpoint string) error {
	endpoint = makeEndpoint(c.name, endpoint)

	if id, _, ok := bindingForEndpoint(c.registrations, endpoint); !ok {
		return fmt.Errorf("domain %s is not registered with this domain.", endpoint)
	} else {
		unregister := &unregister{Request: NewID(), Registration: id}

		if _, err := c.app.requestListenType(unregister, "*core.unregistered"); err != nil {
			return err
		} else {
			Info("Unregistered: %s", endpoint)
			delete(c.registrations, id)
			return nil
		}
	}
}

// This blocks on the invoke. Does the goroutine block waiting for the response?
func (c domain) handleInvocation(msg *invocation, binding *boundEndpoint) {
	Debug("Processing invocation: %s", msg)

	if err := softCumin(binding.expectedTypes, msg.Arguments); err == nil {
		// Debug("Cuminciation succeeded.")
		// c.Delegate.Invoke(binding.callback, msg.Arguments)
		c.app.CallbackSend(binding.callback, msg.Arguments...)
		// c.app.up <- Callback{binding.callback, msg.Arguments}
	} else {
		// Debug("Cuminication failed.")

		tosend := &errorMessage{
			Type:      iNVOCATION,
			Request:   msg.Request,
			Details:   make(map[string]interface{}),
			Arguments: msg.Arguments,
			Error:     err.Error(),
		}

		if err := c.app.Send(tosend); err != nil {
			Warn("error sending message:", err)
		}
	}
}

func (c *domain) handlePublish(msg *event, binding *boundEndpoint) {
	Debug("Processing publish: %s", msg)

	if e := softCumin(binding.expectedTypes, msg.Arguments); e == nil {
		// Debug("Cuminciation succeeded.")
		// c.Delegate.Invoke(binding.callback, msg.Arguments)
		// c.app.up <- Callback{binding.callback, msg.Arguments}
		c.app.CallbackSend(binding.callback, msg.Arguments...)
	} else {
		// Debug("Cuminication failed.")
		tosend := &errorMessage{Type: pUBLISH, Request: msg.Subscription, Details: make(map[string]interface{}), Arguments: make([]interface{}, 0), Error: e.Error()}

		if err := c.app.Send(tosend); err != nil {
			Warn("error sending message:", err)
		}
	}
}
<commit_msg>better handling of functions<commit_after>package core

import "fmt"

type domain struct {
	app           *app
	name          string
	joined        bool
	subscriptions map[uint]*boundEndpoint
	registrations map[uint]*boundEndpoint
}

type boundEndpoint struct {
	callback      uint
	endpoint      string
	expectedTypes []interface{}
}

func (d domain) Subdomain(name string) Domain {
	return d.app.NewDomain(d.name + "." + name)
}

// Accepts a connection that has just been opened. This method should only
// be called once, to initialize the fabric
func (c domain) Join(conn Connection) error {
	if c.joined {
		return fmt.Errorf("Domain %s is already joined", c.name)
	}

	c.app.Connection = conn

	// Should we hard close on conn.Close()? The App may be interested in knowing about the close
	if err := c.app.SendNow(&hello{Realm: c.name, Details: map[string]interface{}{}}); err != nil {
		c.app.Close("ERR: could not send a hello message")
		return err
	}

	if msg, err := c.app.getMessageTimeout(); err != nil {
		c.app.Close(err.Error())
		return err
	} else if _, ok := msg.(*welcome); !ok {
		c.app.SendNow(&abort{Details: map[string]interface{}{}, Reason: "Error- unexpected_message_type"})
		c.app.Close("Error- unexpected_message_type")
		return fmt.Errorf(formatUnexpectedMessage(msg, wELCOME.String()))
	}

	// This is super dumb, and the reason its in here was fixed. Please revert
	go c.app.receiveLoop()
	go c.app.sendLoop()

	// old contents of app.join
	for _, x := range c.app.domains {
		if !x.joined {
			x.joined = true
			// x.Delegate.OnJoin(x.name)
			// Invoke the onjoin method for the domain!
		}
	}

	Info("Domain joined")
	return nil
}

func (c *domain) Leave() error {
	if dems, ok := removeDomain(c.app.domains, c); !ok {
		return fmt.Errorf("WARN: couldn't find %s to remove!", c)
	} else {
		c.app.domains = dems
	}

	if err := c.app.Send(&goodbye{
		Details: map[string]interface{}{},
		Reason:  ErrCloseRealm,
	}); err != nil {
		return fmt.Errorf("Error leaving fabric: %v", err)
	}

	// if no domains remain, terminate the connection
	if len(c.app.domains) == 0 {
		c.app.Close("Closing: no domains connected")
	}

	return nil
}

/////////////////////////////////////////////
// Message Patterns
/////////////////////////////////////////////

func (c domain) Subscribe(endpoint string, requestId uint, types []interface{}) error {
	endpoint = makeEndpoint(c.name, endpoint)
	sub := &subscribe{Request: NewID(), Options: make(map[string]interface{}), Name: endpoint}

	if msg, err := c.app.requestListenType(sub, "*core.subscribed"); err != nil {
		return err
	} else {
		subbed := msg.(*subscribed)
		Info("Subscribed: %s", endpoint)
		c.subscriptions[subbed.Subscription] = &boundEndpoint{requestId, endpoint, types}
		return nil
	}
}

func (c domain) Register(endpoint string, requestId uint, types []interface{}) error {
	endpoint = makeEndpoint(c.name, endpoint)
	register := &register{Request: requestId, Options: make(map[string]interface{}), Name: endpoint}

	if msg, err := c.app.requestListenType(register, "*core.registered"); err != nil {
		return err
	} else {
		Info("Registered: %s", endpoint)
		reg := msg.(*registered)
		c.registrations[reg.Registration] = &boundEndpoint{requestId, endpoint, types}
		return nil
	}
}

func (c domain) Publish(endpoint string, requestId uint, args []interface{}) error {
	return c.app.Send(&publish{
		Request:   NewID(),
		Options:   make(map[string]interface{}),
		Name:      makeEndpoint(c.name, endpoint),
		Arguments: args,
	})
}

func (c domain) Call(endpoint string, requestId uint, args []interface{}) error {
	endpoint = makeEndpoint(c.name, endpoint)
	call := &call{Request: NewID(), Name: endpoint, Options: make(map[string]interface{}), Arguments: args}

	if msg, err := c.app.requestListenType(call, "*core.result"); err != nil {
		return err
	} else {
		c.app.CallbackSend(requestId, msg.(*result).Arguments...)
		return nil
	}
}

func (c domain) Yield(request uint, args []interface{}) {
	// Big todo here
	m := &yield{
		Request:   request,
		Options:   make(map[string]interface{}),
		Arguments: args,
	}

	// if err != nil {
	//     m = &errorMessage{
	//         Type:      iNVOCATION,
	//         Request:   request,
	//         Details:   make(map[string]interface{}),
	//         Arguments: args,
	//         Error:     "Not Implemented",
	//     }
	// }

	if err := c.app.Send(m); err != nil {
		Warn("Could not send yield")
	} else {
		Info("Yield: %s", m)
	}
}

// This isn't going to work on the callback chain... no request id passed in
func (c domain) Unsubscribe(endpoint string) error {
	endpoint = makeEndpoint(c.name, endpoint)

	if id, _, ok := bindingForEndpoint(c.subscriptions, endpoint); !ok {
		return fmt.Errorf("domain %s is not registered with this client.", endpoint)
	} else {
		sub := &unsubscribe{Request: NewID(), Subscription: id}

		if _, err := c.app.requestListenType(sub, "*core.unsubscribed"); err != nil {
			return err
		} else {
			Info("Unsubscribed: %s", endpoint)
			delete(c.subscriptions, id)
			return nil
		}
	}
}

// Same as above -- won't work on the callbacks
func (c domain) Unregister(endpoint string) error {
	endpoint = makeEndpoint(c.name, endpoint)

	if id, _, ok := bindingForEndpoint(c.registrations, endpoint); !ok {
		return fmt.Errorf("domain %s is not registered with this domain.", endpoint)
	} else {
		unregister := &unregister{Request: NewID(), Registration: id}

		if _, err := c.app.requestListenType(unregister, "*core.unregistered"); err != nil {
			return err
		} else {
			Info("Unregistered: %s", endpoint)
			delete(c.registrations, id)
			return nil
		}
	}
}

// This blocks on the invoke. Does the goroutine block waiting for the response?
func (c domain) handleInvocation(msg *invocation, binding *boundEndpoint) {
	Debug("Processing invocation: %s", msg)

	if err := softCumin(binding.expectedTypes, msg.Arguments); err == nil {
		// Debug("Cuminciation succeeded.")
		// c.Delegate.Invoke(binding.callback, msg.Arguments)
		c.app.CallbackSend(binding.callback, msg.Arguments...)
		// c.app.up <- Callback{binding.callback, msg.Arguments}
	} else {
		// Debug("Cuminication failed.")

		tosend := &errorMessage{
			Type:      iNVOCATION,
			Request:   msg.Request,
			Details:   make(map[string]interface{}),
			Arguments: msg.Arguments,
			Error:     err.Error(),
		}

		if err := c.app.Send(tosend); err != nil {
			Warn("error sending message:", err)
		}
	}
}

func (c *domain) handlePublish(msg *event, binding *boundEndpoint) {
	Debug("Processing publish: %s", msg)

	if e := softCumin(binding.expectedTypes, msg.Arguments); e == nil {
		// Debug("Cuminciation succeeded.")
		// c.Delegate.Invoke(binding.callback, msg.Arguments)
		// c.app.up <- Callback{binding.callback, msg.Arguments}
		c.app.CallbackSend(binding.callback, msg.Arguments...)
	} else {
		// Debug("Cuminication failed.")
		tosend := &errorMessage{Type: pUBLISH, Request: msg.Subscription, Details: make(map[string]interface{}), Arguments: make([]interface{}, 0), Error: e.Error()}

		if err := c.app.Send(tosend); err != nil {
			Warn("error sending message:", err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"io"
	"log"
	"strings"
)

// JSONIn provides methods of the Input interface
type JSONIn struct {
	reader   *json.Decoder
	firstRow []string
	header   []string
	ajson    []interface{}
	count    int
}

// JSONOut provides methods of the Output interface
type JSONOut struct {
	writer  *json.Encoder
	results []map[string]string
}

func (trdsql *TRDSQL) jsonInputNew(r io.Reader) (Input, error) {
	jr := &JSONIn{}
	jr.reader = json.NewDecoder(r)
	return jr, nil
}

// FirstRead is read input to determine column of table
func (jr *JSONIn) FirstRead() ([]string, error) {
	var top interface{}
	err := jr.reader.Decode(&top)
	if err != nil {
		return nil, err
	}
	jr.header, jr.firstRow = jr.topLevel(top)
	debug.Printf("Column Name: [%v]", strings.Join(jr.header, ","))
	return jr.header, err
}

func (jr *JSONIn) topLevel(top interface{}) ([]string, []string) {
	switch top.(type) {
	case []interface{}:
		jr.ajson = top.([]interface{})
		val := jr.ajson[0]
		return jr.secondLevel(top, val)
	case map[string]interface{}:
		// {"a":"b"} object
		jr.ajson = nil
		return jr.objectFirstRow(top.(map[string]interface{}))
	default:
		log.Printf("Not a table format")
	}
	return nil, nil
}

// Analyze second when top is array
func (jr *JSONIn) secondLevel(top interface{}, second interface{}) ([]string, []string) {
	switch second.(type) {
	case map[string]interface{}:
		// [{}]
		return jr.objectFirstRow(second.(map[string]interface{}))
	case []interface{}:
		// [[]]
		return jr.etcFirstRow(second)
	default:
		// ["a","b"]
		jr.ajson = nil
		return jr.etcFirstRow(top)
	}
}

func (jr *JSONIn) objectFirstRow(obj map[string]interface{}) ([]string, []string) {
	// {"a":"b"} object
	var header []string
	var firstRow []string
	for k, v := range obj {
		header = append(header, k)
		firstRow = append(firstRow, jsonString(v))
	}
	return header, firstRow
}

func (jr *JSONIn) etcFirstRow(val interface{}) ([]string, []string) {
	// ex. array array
	// [["a"],
	//  ["b"]]
	var header []string
	var firstRow []string
	header = append(header, "c1")
	firstRow = append(firstRow, jsonString(val))
	return header, firstRow
}

func jsonString(val interface{}) string {
	switch val.(type) {
	case map[string]interface{}, []interface{}:
		str, err := json.Marshal(val)
		if err != nil {
			log.Println("ERROR:", err)
		}
		return valString(str)
	default:
		return valString(val)
	}
}

// FirstRowRead is read the first row
func (jr *JSONIn) FirstRowRead(list []interface{}) []interface{} {
	for i := range jr.header {
		list[i] = jr.firstRow[i]
	}
	return list
}

// RowRead is read 2row or later
func (jr *JSONIn) RowRead(list []interface{}) ([]interface{}, error) {
	if jr.ajson != nil {
		// [] array
		jr.count++
		if jr.count >= len(jr.ajson) {
			var top interface{}
			err := jr.reader.Decode(&top)
			if err != nil {
				return nil, err
			}
			_, jr.firstRow = jr.topLevel(top)
			jr.count = 0
		}
		list = jr.rowParse(list, jr.ajson[jr.count])
	} else {
		// {} object
		var data interface{}
		err := jr.reader.Decode(&data)
		if err != nil {
			return nil, err
		}
		list = jr.rowParse(list, data)
	}
	return list, nil
}

func (jr *JSONIn) rowParse(list []interface{}, jsonRow interface{}) []interface{} {
	switch jsonRow.(type) {
	case map[string]interface{}:
		dmap := jsonRow.(map[string]interface{})
		for i := range jr.header {
			list[i] = jsonString(dmap[jr.header[i]])
		}
	default:
		list[0] = jsonString(jsonRow)
	}
	return list
}

func (trdsql *TRDSQL) jsonOutNew() Output {
	js := &JSONOut{}
	js.writer = json.NewEncoder(trdsql.outStream)
	js.writer.SetIndent("", "  ")
	return js
}

// First is preparation
func (js *JSONOut) First(columns []string) error {
	js.results = make([]map[string]string, 0)
	return nil
}

// RowWrite is Addition to array
func (js *JSONOut) RowWrite(values []interface{}, columns []string) error {
	m := make(map[string]string, len(columns))
	for i, col := range values {
		m[columns[i]] = valString(col)
	}
	js.results = append(js.results, m)
	return nil
}

// Last is Actual output
func (js *JSONOut) Last() error {
	return js.writer.Encode(js.results)
}
<commit_msg>Need initialization<commit_after>package main

import (
	"encoding/json"
	"io"
	"log"
	"strings"
)

// JSONIn provides methods of the Input interface
type JSONIn struct {
	reader   *json.Decoder
	firstRow []string
	header   []string
	ajson    []interface{}
	count    int
}

// JSONOut provides methods of the Output interface
type JSONOut struct {
	writer  *json.Encoder
	results []map[string]string
}

func (trdsql *TRDSQL) jsonInputNew(r io.Reader) (Input, error) {
	jr := &JSONIn{}
	jr.reader = json.NewDecoder(r)
	return jr, nil
}

// FirstRead is read input to determine column of table
func (jr *JSONIn) FirstRead() ([]string, error) {
	var top interface{}
	err := jr.reader.Decode(&top)
	if err != nil {
		return nil, err
	}
	jr.header, jr.firstRow = jr.topLevel(top)
	debug.Printf("Column Name: [%v]", strings.Join(jr.header, ","))
	return jr.header, err
}

func (jr *JSONIn) topLevel(top interface{}) ([]string, []string) {
	switch top.(type) {
	case []interface{}:
		jr.ajson = top.([]interface{})
		val := jr.ajson[0]
		return jr.secondLevel(top, val)
	case map[string]interface{}:
		// {"a":"b"} object
		jr.ajson = nil
		return jr.objectFirstRow(top.(map[string]interface{}))
	default:
		log.Printf("Not a table format")
	}
	return nil, nil
}

// Analyze second when top is array
func (jr *JSONIn) secondLevel(top interface{}, second interface{}) ([]string, []string) {
	switch second.(type) {
	case map[string]interface{}:
		// [{}]
		return jr.objectFirstRow(second.(map[string]interface{}))
	case []interface{}:
		// [[]]
		return jr.etcFirstRow(second)
	default:
		// ["a","b"]
		jr.ajson = nil
		return jr.etcFirstRow(top)
	}
}

func (jr *JSONIn) objectFirstRow(obj map[string]interface{}) ([]string, []string) {
	// {"a":"b"} object
	var header []string
	var firstRow []string
	for k, v := range obj {
		header = append(header, k)
		firstRow = append(firstRow, jsonString(v))
	}
	return header, firstRow
}

func (jr *JSONIn) etcFirstRow(val interface{}) ([]string, []string) {
	// ex. array array
	// [["a"],
	//  ["b"]]
	var header []string
	var firstRow []string
	header = append(header, "c1")
	firstRow = append(firstRow, jsonString(val))
	return header, firstRow
}

func jsonString(val interface{}) string {
	switch val.(type) {
	case map[string]interface{}, []interface{}:
		str, err := json.Marshal(val)
		if err != nil {
			log.Println("ERROR:", err)
		}
		return valString(str)
	default:
		return valString(val)
	}
}

// FirstRowRead is read the first row
func (jr *JSONIn) FirstRowRead(list []interface{}) []interface{} {
	for i := range jr.header {
		list[i] = jr.firstRow[i]
	}
	return list
}

// RowRead is read 2row or later
func (jr *JSONIn) RowRead(list []interface{}) ([]interface{}, error) {
	if jr.ajson != nil {
		// [] array
		jr.count++
		if jr.count >= len(jr.ajson) {
			var top interface{}
			err := jr.reader.Decode(&top)
			if err != nil {
				return nil, err
			}
			_, jr.firstRow = jr.topLevel(top)
			jr.count = 0
		}
		list = jr.rowParse(list, jr.ajson[jr.count])
	} else {
		// {} object
		var data interface{}
		err := jr.reader.Decode(&data)
		if err != nil {
			return nil, err
		}
		list = jr.rowParse(list, data)
	}
	return list, nil
}

func (jr *JSONIn) rowParse(list []interface{}, jsonRow interface{}) []interface{} {
	switch jsonRow.(type) {
	case map[string]interface{}:
		dmap := jsonRow.(map[string]interface{})
		for i := range jr.header {
			list[i] = jsonString(dmap[jr.header[i]])
		}
	default:
		for i := range jr.header {
			list[i] = nil
		}
		list[0] = jsonString(jsonRow)
	}
	return list
}

func (trdsql *TRDSQL) jsonOutNew() Output {
	js := &JSONOut{}
	js.writer = json.NewEncoder(trdsql.outStream)
	js.writer.SetIndent("", "  ")
	return js
}

// First is preparation
func (js *JSONOut) First(columns []string) error {
	js.results = make([]map[string]string, 0)
	return nil
}

// RowWrite is Addition to array
func (js *JSONOut) RowWrite(values []interface{}, columns []string) error {
	m := make(map[string]string, len(columns))
	for i, col := range values {
		m[columns[i]] = valString(col)
	}
	js.results = append(js.results, m)
	return nil
}

// Last is Actual output
func (js *JSONOut) Last() error {
	return js.writer.Encode(js.results)
}
<|endoftext|>


<commit_before>package main

import (
	"strconv"
	"unicode"
	"unicode/utf8"

	"github.com/mattn/go-runewidth"
	term "github.com/nsf/termbox-go"
)

func SetCell(l, o int, r rune, fg, bg term.Attribute) {
	term.SetCell(o, l, r, fg, bg)
}

func clearScreen(ar *Area) {
	for l := ar.min.l; l < ar.max.l; l++ {
		for o := ar.min.o; o < ar.max.o; o++ {
			SetCell(l, o, ' ', term.ColorDefault, term.ColorDefault)
		}
	}
}

func resizeScreen(ar *Area, win *Window, w, h int) {
	min := ar.min
	*ar = Area{min, Point{min.l + h, min.o + w}}
	win.size = ar.Size()
}

// draw text inside of window at mainarea.
func drawScreen(ar *Area, w *Window, t *Text, sel *Selection, c *Cursor) {
	multiLineComment := false
	for l, ln := range t.lines {
		if l < w.min.l || l >= w.Max().l {
			continue
		}

		inStr := false
		inStrStarter := ' '
		inStrFinished := false
		commented := false
		oldR := ' '
		oldOldR := ' '
		var oldBg term.Attribute

		eoc := 0
		if ln.data != "" {
			// ++
			for _, r := range ln.data {
				if r == '\t' {
					eoc += t.tabWidth
				} else {
					eoc += runewidth.RuneWidth(r)
				}
			}
			// --
			remain := ln.data
			for {
				if remain == "" {
					break
				}
				r, rlen := utf8.DecodeLastRuneInString(remain)
				remain = remain[:len(remain)-rlen]
				if !unicode.IsSpace(r) {
					break
				}
				if r == '\t' {
					eoc -= t.tabWidth
				} else {
					eoc -= runewidth.RuneWidth(r)
				}
			}
		}

		// draw
		o := 0
		for _, r := range ln.data {
			if o >= w.Max().o {
				break
			}

			bg := term.ColorDefault
			if o >= eoc {
				bg = term.ColorYellow
			}
			if sel.on && sel.Contains(Point{l, o}) {
				bg = term.ColorGreen
			}
			if r == '/' && oldR == '/' && oldOldR != '\\' {
				if !inStr {
					commented = true
					SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o-1, '/', term.ColorMagenta, oldBg) // hacky way to color the first '/' cell.
				}
			} else if r == '*' && oldR == '/' && oldOldR != '\\' {
				if !inStr {
					multiLineComment = true
					SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o-1, '/', term.ColorMagenta, oldBg) // hacky way to color the first '/' cell.
				}
			} else if r == '/' && oldR == '*' && oldOldR != '\\' {
				if !inStr {
					multiLineComment = false
					SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o, '/', term.ColorMagenta, oldBg) // hacky way to color the last '/' cell.
					continue
				}
			}
			if inStrFinished {
				inStr = false
				inStrStarter = ' '
			}
			if r == '\'' || r == '"' {
				if !(oldR == '\\' && oldOldR != '\\') {
					if !inStr {
						inStr = true
						inStrStarter = r
						inStrFinished = false
					} else if inStrStarter == r {
						inStrFinished = true
					}
				}
			}

			fg := term.ColorWhite
			if commented || multiLineComment {
				fg = term.ColorMagenta
			} else if inStr {
				if inStrStarter == '\'' {
					fg = term.ColorYellow
				} else {
					fg = term.ColorRed
				}
			} else {
				_, err := strconv.Atoi(string(r))
				if err == nil {
					fg = term.ColorCyan
				}
			}

			if r == '\t' {
				for i := 0; i < t.tabWidth; i++ {
					if o >= w.min.o {
						SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o, rune(' '), fg, bg)
					}
					o += 1
				}
			} else {
				if o >= w.min.o {
					SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o, rune(r), fg, bg)
				}
				o += runewidth.RuneWidth(r)
			}

			oldOldR = oldR
			oldR = r
			oldBg = bg
		}
	}
}

func printStatus(status string) {
	termw, termh := term.Size()
	statusLine := termh - 1
	// clear
	for i := 0; i < termw; i++ {
		SetCell(statusLine, i, ' ', term.ColorBlack, term.ColorWhite)
	}
	// draw
	o := 0
	for _, r := range status {
		SetCell(statusLine, o, r, term.ColorBlack, term.ColorWhite)
		o += runewidth.RuneWidth(r)
	}
}

func printErrorStatus(err string) {
	termw, termh := term.Size()
	statusLine := termh - 1
	// clear
	for i := 0; i < termw; i++ {
		SetCell(statusLine, i, ' ', term.ColorBlack, term.ColorRed)
	}
	// draw
	o := 0
	for _, r := range err {
		SetCell(statusLine, o, r, term.ColorBlack, term.ColorRed)
		o += runewidth.RuneWidth(r)
	}
}
<commit_msg>draw: add \n to line ending<commit_after>package main

import (
	"strconv"
	"unicode"
	"unicode/utf8"

	"github.com/mattn/go-runewidth"
	term "github.com/nsf/termbox-go"
)

func SetCell(l, o int, r rune, fg, bg term.Attribute) {
	term.SetCell(o, l, r, fg, bg)
}

func clearScreen(ar *Area) {
	for l := ar.min.l; l < ar.max.l; l++ {
		for o := ar.min.o; o < ar.max.o; o++ {
			SetCell(l, o, ' ', term.ColorDefault, term.ColorDefault)
		}
	}
}

func resizeScreen(ar *Area, win *Window, w, h int) {
	min := ar.min
	*ar = Area{min, Point{min.l + h, min.o + w}}
	win.size = ar.Size()
}

// draw text inside of window at mainarea.
func drawScreen(ar *Area, w *Window, t *Text, sel *Selection, c *Cursor) {
	multiLineComment := false
	for l, ln := range t.lines {
		if l < w.min.l || l >= w.Max().l {
			continue
		}

		inStr := false
		inStrStarter := ' '
		inStrFinished := false
		commented := false
		oldR := ' '
		oldOldR := ' '
		var oldBg term.Attribute

		eoc := 0
		if ln.data != "" {
			// ++
			for _, r := range ln.data {
				if r == '\t' {
					eoc += t.tabWidth
				} else {
					eoc += runewidth.RuneWidth(r)
				}
			}
			// --
			remain := ln.data
			for {
				if remain == "" {
					break
				}
				r, rlen := utf8.DecodeLastRuneInString(remain)
				remain = remain[:len(remain)-rlen]
				if !unicode.IsSpace(r) {
					break
				}
				if r == '\t' {
					eoc -= t.tabWidth
				} else {
					eoc -= runewidth.RuneWidth(r)
				}
			}
		}

		// draw
		o := 0
		for _, r := range ln.data {
			if o >= w.Max().o {
				break
			}

			bg := term.ColorDefault
			if o >= eoc {
				bg = term.ColorYellow
			}
			if sel.on && sel.Contains(Point{l, o}) {
				bg = term.ColorGreen
			}
			if r == '/' && oldR == '/' && oldOldR != '\\' {
				if !inStr {
					commented = true
					SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o-1, '/', term.ColorMagenta, oldBg) // hacky way to color the first '/' cell.
				}
			} else if r == '*' && oldR == '/' && oldOldR != '\\' {
				if !inStr {
					multiLineComment = true
					SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o-1, '/', term.ColorMagenta, oldBg) // hacky way to color the first '/' cell.
				}
			} else if r == '/' && oldR == '*' && oldOldR != '\\' {
				if !inStr {
					multiLineComment = false
					SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o, '/', term.ColorMagenta, oldBg) // hacky way to color the last '/' cell.
					continue
				}
			}
			if inStrFinished {
				inStr = false
				inStrStarter = ' '
			}
			if r == '\'' || r == '"' {
				if !(oldR == '\\' && oldOldR != '\\') {
					if !inStr {
						inStr = true
						inStrStarter = r
						inStrFinished = false
					} else if inStrStarter == r {
						inStrFinished = true
					}
				}
			}

			fg := term.ColorWhite
			if commented || multiLineComment {
				fg = term.ColorMagenta
			} else if inStr {
				if inStrStarter == '\'' {
					fg = term.ColorYellow
				} else {
					fg = term.ColorRed
				}
			} else {
				_, err := strconv.Atoi(string(r))
				if err == nil {
					fg = term.ColorCyan
				}
			}

			if r == '\t' {
				for i := 0; i < t.tabWidth; i++ {
					if o >= w.min.o {
						SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o, rune(' '), fg, bg)
					}
					o += 1
				}
			} else {
				if o >= w.min.o {
					SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o, rune(r), fg, bg)
				}
				o += runewidth.RuneWidth(r)
			}

			oldOldR = oldR
			oldR = r
			oldBg = bg
		}
		SetCell(l-w.min.l+ar.min.l, o-w.min.o+ar.min.o, '\n', term.ColorDefault, term.ColorDefault)
	}
}

func printStatus(status string) {
	termw, termh := term.Size()
	statusLine := termh - 1
	// clear
	for i := 0; i < termw; i++ {
		SetCell(statusLine, i, ' ', term.ColorBlack, term.ColorWhite)
	}
	// draw
	o := 0
	for _, r := range status {
		SetCell(statusLine, o, r, term.ColorBlack, term.ColorWhite)
		o += runewidth.RuneWidth(r)
	}
}

func printErrorStatus(err string) {
	termw, termh := term.Size()
	statusLine := termh - 1
	// clear
	for i := 0; i < termw; i++ {
		SetCell(statusLine, i, ' ', term.ColorBlack, term.ColorRed)
	}
	// draw
	o := 0
	for _, r := range err {
		SetCell(statusLine, o, r, term.ColorBlack, term.ColorRed)
		o += runewidth.RuneWidth(r)
	}
}
<|endoftext|>


<commit_before><commit_msg>speed: add XChaCha20-Poly1305-Go<commit_after><|endoftext|>


<commit_before><commit_msg>Dewire if/else in user updateUsername.<commit_after><|endoftext|>


<commit_before>// Copyright 2012 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 main

func init() {
	addTestCases(frameTests, frame)
}

var frameTests = []testCase{
	{
		Name: "frame.0",
		In: `package main

import (
	"image"

	"github.com/as/frame"
	"github.com/as/frame/font"
)

func main() {
	img := image.NewRGBA(image.Rect(0, 0, 100, 100))
	frame.New(img.Bounds(), font.NewGoMono(11), img, frame.Mono, frame.FrElastic)
}
`,
		Out: `package main

import (
	"image"

	"github.com/as/font"
	"github.com/as/frame"
)

func main() {
	img := image.NewRGBA(image.Rect(0, 0, 100, 100))
	frame.New(img, img.Bounds(), &frame.Config{Font: font.NewGoMono(11), Color: frame.Mono, Flag: frame.FrElastic})
}
`,
	},
}
<commit_msg>frame: framefix: update test to have a correct comparison<commit_after>// Copyright 2012 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 main

func init() {
	addTestCases(frameTests, frame)
}

var frameTests = []testCase{
	{
		Name: "frame.0",
		In: `package main

import (
	"image"

	"github.com/as/frame"
	"github.com/as/frame/font"
)

func main() {
	img := image.NewRGBA(image.Rect(0, 0, 100, 100))
	frame.New(img.Bounds(), font.NewGoMono(11), img, frame.Mono, frame.FrElastic)
}
`,
		Out: `package main

import (
	"image"

	"github.com/as/font"
	"github.com/as/frame"
)

func main() {
	img := image.NewRGBA(image.Rect(0, 0, 100, 100))
	frame.New(img, img.Bounds(), &frame.Config{Face: font.NewGoMono(11), Color: frame.Mono, Flag: frame.FrElastic})
}
`,
	},
}
<|endoftext|>


<commit_before>// Copyright 2018 The Go Cloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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
// limtations under the License.

// Package runtimevar provides an interface for reading runtime variables and
// ability to detect changes and get updates on those variables.
package runtimevar // import "gocloud.dev/runtimevar"

import (
	"bytes"
	"context"
	"encoding/gob"
	"encoding/json"
	"reflect"
	"time"

	"gocloud.dev/runtimevar/driver"
)

// Snapshot contains a variable and metadata about it.
type Snapshot struct {
	// Value is an object containing a runtime variable  The type of
	// this object is set by the driver and it should always be the same type for the same Variable
	// object. A driver implementation can provide the ability to configure the object type and a
	// decoding scheme where variables are stored as bytes in the backend service.  Clients
	// should not mutate this object as it can be accessed by multiple goroutines.
	Value interface{}

	// UpdateTime is the time when the last changed was detected.
	UpdateTime time.Time
}

// Variable provides the ability to read runtime variables with its blocking Watch method.
type Variable struct {
	watcher  driver.Watcher
	nextCall time.Time
	prev     driver.State
}

// New constructs a Variable object given a driver.Watcher implementation.
func New(w driver.Watcher) *Variable {
	return &Variable{watcher: w}
}

// Watch blocks until there are variable changes, the Context's Done channel
// closes or a new error occurs.
//
// If the variable changes, the method returns a Snapshot object containing the
// updated value.
//
// If method returns an error, the returned Snapshot object is a zero value and cannot be used.
//
// The first call to this method should return the current variable unless there are errors in
// retrieving the value.
//
// Users should not call this method from multiple goroutines as implementations may not guarantee
// safety in data access.  It is typical to use only one goroutine calling this method in a loop.
//
// To stop this function from blocking, caller can passed in Context object constructed via
// WithCancel and call the cancel function.
func (c *Variable) Watch(ctx context.Context) (Snapshot, error) {
	for {
		wait := c.nextCall.Sub(time.Now())
		if wait > 0 {
			select {
			case <-ctx.Done():
				return Snapshot{}, ctx.Err()
			case <-time.After(wait):
				// Continue.
			}
		}

		cur, wait := c.watcher.WatchVariable(ctx, c.prev)
		c.nextCall = time.Now().Add(wait)
		if cur == nil {
			// No change.
			continue
		}
		// Something new to return!
		c.prev = cur
		v, err := cur.Value()
		if err != nil {
			return Snapshot{}, wrapError(err)
		}
		return Snapshot{Value: v, UpdateTime: cur.UpdateTime()}, nil
	}
}

// Close cleans up any resources used by the Variable object.
func (c *Variable) Close() error {
	err := c.watcher.Close()
	return wrapError(err)
}

// wrappedError is used to wrap all errors returned by drivers so that users
// are not given access to provider-specific errors.
type wrappedError struct {
	err error
}

func wrapError(err error) error {
	if err == nil {
		return nil
	}
	return &wrappedError{err: err}
}

func (w *wrappedError) Error() string {
	return "runtimevar: " + w.err.Error()
}

// Decode is a function type for unmarshaling/decoding bytes into given object.
type Decode func([]byte, interface{}) error

// Decoder is a helper for decoding bytes into a particular Go type object.  The Variable objects
// produced by a particular driver.Watcher should always contain the same type for Variable.Value
// field.  A driver.Watcher can use/construct a Decoder object with an associated type (Type) and
// decoding function (Func) for decoding retrieved bytes into Variable.Value.
type Decoder struct {
	typ reflect.Type
	// Func is a Decode function.
	fn Decode
}

// NewDecoder constructs a Decoder for given object that uses the given Decode function.
func NewDecoder(obj interface{}, fn Decode) *Decoder {
	return &Decoder{
		typ: reflect.TypeOf(obj),
		fn:  fn,
	}
}

// Decode decodes given bytes into an object of type Type using Func.
func (d *Decoder) Decode(b []byte) (interface{}, error) {
	nv := reflect.New(d.typ).Interface()
	if err := d.fn(b, nv); err != nil {
		return nil, err
	}
	ptr := reflect.ValueOf(nv)
	return ptr.Elem().Interface(), nil
}

// Simple Decoder objects.
var (
	StringDecoder = NewDecoder("", stringDecode)

	BytesDecoder = NewDecoder([]byte{}, bytesDecode)
)

// Decode functions.
var (
	JSONDecode = json.Unmarshal
)

// GobDecode gob decodes bytes into given object.
func GobDecode(data []byte, obj interface{}) error {
	return gob.NewDecoder(bytes.NewBuffer(data)).Decode(obj)
}

func stringDecode(b []byte, obj interface{}) error {
	v := obj.(*string)
	*v = string(b)
	return nil
}

func bytesDecode(b []byte, obj interface{}) error {
	v := obj.(*[]byte)
	*v = b[:]
	return nil
}
<commit_msg>runtimevar/doc: refresh documentation for Decoder-related stuff (#1010)<commit_after>// Copyright 2018 The Go Cloud Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://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
// limtations under the License.

// Package runtimevar provides an interface for reading runtime variables and
// ability to detect changes and get updates on those variables.
package runtimevar // import "gocloud.dev/runtimevar"

import (
	"bytes"
	"context"
	"encoding/gob"
	"encoding/json"
	"reflect"
	"time"

	"gocloud.dev/runtimevar/driver"
)

// Snapshot contains a variable and metadata about it.
type Snapshot struct {
	// Value is an object containing a runtime variable  The type of
	// this object is set by the driver and it should always be the same type for the same Variable
	// object. A driver implementation can provide the ability to configure the object type and a
	// decoding scheme where variables are stored as bytes in the backend service.  Clients
	// should not mutate this object as it can be accessed by multiple goroutines.
	Value interface{}

	// UpdateTime is the time when the last changed was detected.
	UpdateTime time.Time
}

// Variable provides the ability to read runtime variables with its blocking Watch method.
type Variable struct {
	watcher  driver.Watcher
	nextCall time.Time
	prev     driver.State
}

// New constructs a Variable object given a driver.Watcher implementation.
func New(w driver.Watcher) *Variable {
	return &Variable{watcher: w}
}

// Watch blocks until there are variable changes, the Context's Done channel
// closes or a new error occurs.
//
// If the variable changes, the method returns a Snapshot object containing the
// updated value.
//
// If method returns an error, the returned Snapshot object is a zero value and cannot be used.
//
// The first call to this method should return the current variable unless there are errors in
// retrieving the value.
//
// Users should not call this method from multiple goroutines as implementations may not guarantee
// safety in data access.  It is typical to use only one goroutine calling this method in a loop.
//
// To stop this function from blocking, caller can passed in Context object constructed via
// WithCancel and call the cancel function.
func (c *Variable) Watch(ctx context.Context) (Snapshot, error) {
	for {
		wait := c.nextCall.Sub(time.Now())
		if wait > 0 {
			select {
			case <-ctx.Done():
				return Snapshot{}, ctx.Err()
			case <-time.After(wait):
				// Continue.
			}
		}

		cur, wait := c.watcher.WatchVariable(ctx, c.prev)
		c.nextCall = time.Now().Add(wait)
		if cur == nil {
			// No change.
			continue
		}
		// Something new to return!
		c.prev = cur
		v, err := cur.Value()
		if err != nil {
			return Snapshot{}, wrapError(err)
		}
		return Snapshot{Value: v, UpdateTime: cur.UpdateTime()}, nil
	}
}

// Close cleans up any resources used by the Variable object.
func (c *Variable) Close() error {
	err := c.watcher.Close()
	return wrapError(err)
}

// wrappedError is used to wrap all errors returned by drivers so that users
// are not given access to provider-specific errors.
type wrappedError struct {
	err error
}

func wrapError(err error) error {
	if err == nil {
		return nil
	}
	return &wrappedError{err: err}
}

func (w *wrappedError) Error() string {
	return "runtimevar: " + w.err.Error()
}

// Decode is a function type for unmarshaling/decoding a slice of bytes into
// an arbitrary type. Decode functions are used when creating a Decoder via
// NewDecoder. This package provides common Decode functions including
// GobDecode and JSONDecode.
type Decode func([]byte, interface{}) error

// Decoder decodes a slice of bytes into a particular Go object.
//
// This package provides some common Decoders that you can use directly,
// including StringDecoder and BytesDecoder. You can also NewDecoder to
// construct other Decoders.
type Decoder struct {
	typ reflect.Type
	fn Decode
}

// NewDecoder returns a Decoder that uses fn to decode a slice of bytes into
// an object of type obj.
//
// This package provides some common Decode functions, including JSONDecode
// and GobDecode, which can be passed to this function to create Decoders for
// JSON and gob values.
func NewDecoder(obj interface{}, fn Decode) *Decoder {
	return &Decoder{
		typ: reflect.TypeOf(obj),
		fn:  fn,
	}
}

// Decode decodes b into a new instance of the target type.
func (d *Decoder) Decode(b []byte) (interface{}, error) {
	nv := reflect.New(d.typ).Interface()
	if err := d.fn(b, nv); err != nil {
		return nil, err
	}
	ptr := reflect.ValueOf(nv)
	return ptr.Elem().Interface(), nil
}

var (
	// StringDecoder decodes into strings.
	StringDecoder = NewDecoder("", stringDecode)

	// BytesDecoder copies the slice of bytes.
	BytesDecoder = NewDecoder([]byte{}, bytesDecode)

	// JSONDecode can be passed to NewDecoder when decoding JSON (https://golang.org/pkg/encoding/json/).
	JSONDecode = json.Unmarshal
)

// GobDecode can be passed to NewDecoder when decoding gobs (https://golang.org/pkg/encoding/gob/).
func GobDecode(data []byte, obj interface{}) error {
	return gob.NewDecoder(bytes.NewBuffer(data)).Decode(obj)
}

func stringDecode(b []byte, obj interface{}) error {
	v := obj.(*string)
	*v = string(b)
	return nil
}

func bytesDecode(b []byte, obj interface{}) error {
	v := obj.(*[]byte)
	*v = b[:]
	return nil
}
<|endoftext|>


<commit_before>// +build linux

package main

import (
	"fmt"
	"strconv"
	"strings"
	"syscall"

	"github.com/urfave/cli"
)

var signalMap = map[string]syscall.Signal{
	"ABRT":   syscall.SIGABRT,
	"ALRM":   syscall.SIGALRM,
	"BUS":    syscall.SIGBUS,
	"CHLD":   syscall.SIGCHLD,
	"CLD":    syscall.SIGCLD,
	"CONT":   syscall.SIGCONT,
	"FPE":    syscall.SIGFPE,
	"HUP":    syscall.SIGHUP,
	"ILL":    syscall.SIGILL,
	"INT":    syscall.SIGINT,
	"IO":     syscall.SIGIO,
	"IOT":    syscall.SIGIOT,
	"KILL":   syscall.SIGKILL,
	"PIPE":   syscall.SIGPIPE,
	"POLL":   syscall.SIGPOLL,
	"PROF":   syscall.SIGPROF,
	"PWR":    syscall.SIGPWR,
	"QUIT":   syscall.SIGQUIT,
	"SEGV":   syscall.SIGSEGV,
	"STKFLT": syscall.SIGSTKFLT,
	"STOP":   syscall.SIGSTOP,
	"SYS":    syscall.SIGSYS,
	"TERM":   syscall.SIGTERM,
	"TRAP":   syscall.SIGTRAP,
	"TSTP":   syscall.SIGTSTP,
	"TTIN":   syscall.SIGTTIN,
	"TTOU":   syscall.SIGTTOU,
	"UNUSED": syscall.SIGUNUSED,
	"URG":    syscall.SIGURG,
	"USR1":   syscall.SIGUSR1,
	"USR2":   syscall.SIGUSR2,
	"VTALRM": syscall.SIGVTALRM,
	"WINCH":  syscall.SIGWINCH,
	"XCPU":   syscall.SIGXCPU,
	"XFSZ":   syscall.SIGXFSZ,
}

var killCommand = cli.Command{
	Name:  "kill",
	Usage: "kill sends the specified signal (default: SIGTERM) to the container's init process",
	ArgsUsage: `<container-id> <signal>

Where "<container-id>" is the name for the instance of the container and
"<signal>" is the signal to be sent to the init process.

EXAMPLE:
For example, if the container id is "ubuntu01" the following will send a "KILL"
signal to the init process of the "ubuntu01" container:

       # runc kill ubuntu01 KILL`,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "all, a",
			Usage: "send the specified signal to all processes inside the container",
		},
	},
	Action: func(context *cli.Context) error {
		if err := checkArgs(context, 2, exactArgs); err != nil {
			return err
		}
		container, err := getContainer(context)
		if err != nil {
			return err
		}

		sigstr := context.Args().Get(1)
		if sigstr == "" {
			sigstr = "SIGTERM"
		}

		signal, err := parseSignal(sigstr)
		if err != nil {
			return err
		}
		if err := container.Signal(signal, context.Bool("all")); err != nil {
			return err
		}
		return nil
	},
}

func parseSignal(rawSignal string) (syscall.Signal, error) {
	s, err := strconv.Atoi(rawSignal)
	if err == nil {
		sig := syscall.Signal(s)
		for _, msig := range signalMap {
			if sig == msig {
				return sig, nil
			}
		}
		return -1, fmt.Errorf("unknown signal %q", rawSignal)
	}
	signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
	if !ok {
		return -1, fmt.Errorf("unknown signal %q", rawSignal)
	}
	return signal, nil
}
<commit_msg>kill: make second argument optional<commit_after>// +build linux

package main

import (
	"fmt"
	"strconv"
	"strings"
	"syscall"

	"github.com/urfave/cli"
)

var signalMap = map[string]syscall.Signal{
	"ABRT":   syscall.SIGABRT,
	"ALRM":   syscall.SIGALRM,
	"BUS":    syscall.SIGBUS,
	"CHLD":   syscall.SIGCHLD,
	"CLD":    syscall.SIGCLD,
	"CONT":   syscall.SIGCONT,
	"FPE":    syscall.SIGFPE,
	"HUP":    syscall.SIGHUP,
	"ILL":    syscall.SIGILL,
	"INT":    syscall.SIGINT,
	"IO":     syscall.SIGIO,
	"IOT":    syscall.SIGIOT,
	"KILL":   syscall.SIGKILL,
	"PIPE":   syscall.SIGPIPE,
	"POLL":   syscall.SIGPOLL,
	"PROF":   syscall.SIGPROF,
	"PWR":    syscall.SIGPWR,
	"QUIT":   syscall.SIGQUIT,
	"SEGV":   syscall.SIGSEGV,
	"STKFLT": syscall.SIGSTKFLT,
	"STOP":   syscall.SIGSTOP,
	"SYS":    syscall.SIGSYS,
	"TERM":   syscall.SIGTERM,
	"TRAP":   syscall.SIGTRAP,
	"TSTP":   syscall.SIGTSTP,
	"TTIN":   syscall.SIGTTIN,
	"TTOU":   syscall.SIGTTOU,
	"UNUSED": syscall.SIGUNUSED,
	"URG":    syscall.SIGURG,
	"USR1":   syscall.SIGUSR1,
	"USR2":   syscall.SIGUSR2,
	"VTALRM": syscall.SIGVTALRM,
	"WINCH":  syscall.SIGWINCH,
	"XCPU":   syscall.SIGXCPU,
	"XFSZ":   syscall.SIGXFSZ,
}

var killCommand = cli.Command{
	Name:  "kill",
	Usage: "kill sends the specified signal (default: SIGTERM) to the container's init process",
	ArgsUsage: `<container-id> [signal]

Where "<container-id>" is the name for the instance of the container and
"[signal]" is the signal to be sent to the init process.

EXAMPLE:
For example, if the container id is "ubuntu01" the following will send a "KILL"
signal to the init process of the "ubuntu01" container:

       # runc kill ubuntu01 KILL`,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "all, a",
			Usage: "send the specified signal to all processes inside the container",
		},
	},
	Action: func(context *cli.Context) error {
		if err := checkArgs(context, 1, minArgs); err != nil {
			return err
		}
		container, err := getContainer(context)
		if err != nil {
			return err
		}

		sigstr := context.Args().Get(1)
		if sigstr == "" {
			sigstr = "SIGTERM"
		}

		signal, err := parseSignal(sigstr)
		if err != nil {
			return err
		}
		if err := container.Signal(signal, context.Bool("all")); err != nil {
			return err
		}
		return nil
	},
}

func parseSignal(rawSignal string) (syscall.Signal, error) {
	s, err := strconv.Atoi(rawSignal)
	if err == nil {
		sig := syscall.Signal(s)
		for _, msig := range signalMap {
			if sig == msig {
				return sig, nil
			}
		}
		return -1, fmt.Errorf("unknown signal %q", rawSignal)
	}
	signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
	if !ok {
		return -1, fmt.Errorf("unknown signal %q", rawSignal)
	}
	return signal, nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"syscall"
	"unsafe"
)

type Termios struct {
	Iflag  uint32
	Oflag  uint32
	Cflag  uint32
	Lflag  uint32
	Cc     [20]byte
	Ispeed uint32
	Ospeed uint32
}

func TcSetAttr(fd uintptr, termios *Termios) error {
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TCSETS), uintptr(unsafe.Pointer(termios))); err != 0 {
		return err
	}
	return nil
}

func TcGetAttr(fd uintptr) (*Termios, error) {
	var termios = &Termios{}
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, syscall.TCGETS, uintptr(unsafe.Pointer(termios))); err != 0 {
		return nil, err
	}
	return termios, nil
}

func enableRawMode() {
	raw, _ := TcGetAttr(os.Stdin.Fd())
	raw.Lflag &^= syscall.ECHO
	_ = TcSetAttr(os.Stdin.Fd(), raw)
}

func main() {
	enableRawMode()
	buffer := make([]byte, 1)
	for cc, err := os.Stdin.Read(buffer); buffer[0] != 'q' && err == nil && cc == 1; cc, err = os.Stdin.Read(buffer) {
		// blank
	}
	os.Exit(0)
}
<commit_msg>Step 6 - enable and disable tty echo<commit_after>package main

import (
	"fmt"
	"os"
	"syscall"
	"unsafe"
)

type Termios struct {
	Iflag  uint32
	Oflag  uint32
	Cflag  uint32
	Lflag  uint32
	Cc     [20]byte
	Ispeed uint32
	Ospeed uint32
}

var origTermios *Termios

func TcSetAttr(fd uintptr, termios *Termios) error {
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TCSETS+1), uintptr(unsafe.Pointer(termios))); err != 0 {
		return err
	}
	return nil
}

func TcGetAttr(fd uintptr) (*Termios, error) {
	var termios = &Termios{}
	if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, syscall.TCGETS, uintptr(unsafe.Pointer(termios))); err != 0 {
		return nil, err
	}
	return termios, nil
}

func enableRawMode() {
	origTermios, _ = TcGetAttr(os.Stdin.Fd())
	var raw Termios
	raw = *origTermios
	raw.Lflag &^= syscall.ECHO
	if e := TcSetAttr(os.Stdin.Fd(), &raw); e != nil {
		fmt.Fprintf(os.Stderr, "Problem enabling raw mode: %s\n", e)
	}
}

func disableRawMode() {
fmt.Fprintf(os.Stderr, "Enter disableRawmode\n")
	if e := TcSetAttr(os.Stdin.Fd(), origTermios); e != nil {
		fmt.Fprintf(os.Stderr, "Problem disabling raw mode: %s\n", e)
	}
}

func main() {
	enableRawMode()
	defer disableRawMode()
	buffer := make([]byte, 1)
	for cc, err := os.Stdin.Read(buffer); buffer[0] != 'q' && err == nil && cc == 1; cc, err = os.Stdin.Read(buffer) {
		// blank
	}
}
<|endoftext|>


<commit_before>package main

/*
 * Driver implementation
 * ---------------------
 */

import (
	"errors"
	"fmt"
	"net"
	"os"

	stdlog "log"

	"github.com/docker/machine/libmachine/drivers"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcnflag"
	"github.com/docker/machine/libmachine/state"
	"github.com/tintoy/docker-machine-driver-terraform/terraform"
)

// Driver is the Docker Machine driver for Terraform.
type Driver struct {
	*drivers.BaseDriver

	// The source path (or URL) of the Terraform configuration.
	ConfigSource string

	// The path of the directory containing the imported Terraform configuration.
	ConfigDir string

	// Additional variables for the Terraform configuration
	ConfigVariables terraform.ConfigVariables

	// An optional file containing the JSON that represents additional variables for the Terraform configuration
	AdditionalVariablesFile string

	// Refresh the configuration after applying it
	RefreshAfterApply bool

	// The full path to the Terraform executable.
	TerraformExecutablePath string

	// The path to the SSH private key file to use for authentication.
	//
	// If not specified, a new key-pair will be generated.
	SSHKey string

	// The terraform executor.
	terraformer *terraform.Terraformer
}

// GetCreateFlags registers the "machine create" flags recognized by this driver, including
// their help text and defaults.
func (driver *Driver) GetCreateFlags() []mcnflag.Flag {
	return []mcnflag.Flag{
		mcnflag.StringFlag{
			Name:  "terraform-config",
			Usage: "The path (or URL) of the Terraform configuration",
			Value: "",
		},
		mcnflag.StringFlag{
			Name:  "terraform-additional-variables",
			Usage: "An optional file containing the JSON that represents additional variables for the Terraform configuration",
			Value: "",
		},
		mcnflag.BoolFlag{
			Name:  "terraform-refresh",
			Usage: "Refresh the configuration after applying it",
		},
		mcnflag.StringFlag{
			EnvVar: "TERRAFORM_SSH_USER",
			Name:   "terraform-ssh-user",
			Usage:  "The SSH username to use. Default: root",
			Value:  "root",
		},
		mcnflag.StringFlag{
			EnvVar: "TERRAFORM_SSH_KEY",
			Name:   "terraform-ssh-key",
			Usage:  "The SSH key file to use",
			Value:  "",
		},
		mcnflag.IntFlag{
			EnvVar: "TERRAFORM_SSH_PORT",
			Name:   "terraform-ssh-port",
			Usage:  "The SSH port. Default: 22",
			Value:  22,
		},
	}
}

// DriverName returns the name of the driver
func (driver *Driver) DriverName() string {
	return "terraform"
}

// SetConfigFromFlags assigns and verifies the command-line arguments presented to the driver.
func (driver *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
	log.Debugf("docker-machine-driver-terraform %s", DriverVersion)

	// Enable ALL logging if MACHINE_DEBUG is set
	if os.Getenv("MACHINE_DEBUG") != "" {
		stdlog.SetOutput(os.Stderr)
	}

	driver.ConfigSource = flags.String("terraform-config")
	driver.ConfigVariables = make(map[string]interface{})
	driver.AdditionalVariablesFile = flags.String("terraform-additional-variables")
	driver.RefreshAfterApply = flags.Bool("terraform-refresh")

	driver.SSHPort = flags.Int("terraform-ssh-port")
	driver.SSHUser = flags.String("terraform-ssh-user")
	driver.SSHKey = flags.String("terraform-ssh-key")

	// Validation
	if driver.ConfigSource == "" {
		return errors.New("Required argument: --terraform-config")
	}

	return nil
}

// PreCreateCheck validates the configuration before making any changes.
func (driver *Driver) PreCreateCheck() error {
	if driver.ConfigSource == "" {
		return errors.New("The source for Terraform configuration has not been specified")
	}

	log.Infof("Auto-detecting client's public (external) IP address...")
	clientIP, err := getClientPublicIPv4Address()
	if err != nil {
		return err
	}

	log.Infof("Will create machine '%s' using Terraform configuration from '%s'.",
		driver.MachineName,
		driver.ConfigSource,
	)

	log.Infof("Resolving Terraform configuration...")
	err = driver.resolveConfigDir()
	if err != nil {
		return err
	}
	err = driver.importConfig()
	if err != nil {
		return err
	}

	if driver.SSHKey != "" {
		log.Infof("Importing SSH key '%s'...", driver.SSHKey)
		err = driver.importSSHKey()
		if err != nil {
			return err
		}
	} else {
		log.Infof("Generating new SSH key...")
		err = driver.generateSSHKey()
		if err != nil {
			return err
		}
	}

	log.Infof("Customising terraform configuration...")
	driver.ConfigVariables["dm_client_ip"] = clientIP
	driver.ConfigVariables["dm_machine_name"] = driver.MachineName
	driver.ConfigVariables["dm_ssh_private_key_file"] = driver.SSHKeyPath
	driver.ConfigVariables["dm_ssh_public_key_file"] = driver.SSHKeyPath + ".pub"
	driver.ConfigVariables["dm_ssh_user"] = driver.SSHUser
	driver.ConfigVariables["dm_ssh_port"] = driver.SSHPort
	err = driver.readAdditionalVariables()
	if err != nil {
		return err
	}
	err = driver.writeVariables()
	if err != nil {
		return err
	}

	return nil
}

// Create a new Docker Machine instance on CloudControl.
func (driver *Driver) Create() error {
	log.Infof("Applying terraform configuration...")

	terraformer, err := driver.getTerraformer()
	if err != nil {
		return err
	}

	success, err := terraformer.Apply(true /* withVariablesFile */)
	if err != nil {
		return err
	}
	if !success {
		return errors.New("Failed to apply Terraform configuration")
	}

	outputs, err := terraformer.Output()
	if err != nil {
		return err
	}
	if !success {
		return fmt.Errorf("Failed to obtain Terraform outputs")
	}

	output, ok := outputs["dm_machine_ip"]
	if !ok {
		return fmt.Errorf("Configuration does not declare required output 'dm_machine_ip'")
	}
	driver.IPAddress = output.Value.(string)

	log.Infof("Deployed host has IP '%s'.", driver.IPAddress)

	return nil
}

// GetState retrieves the status of the target Docker Machine instance in CloudControl.
func (driver *Driver) GetState() (state.State, error) {
	return state.Running, nil
}

// GetURL returns docker daemon URL on the target machine
func (driver *Driver) GetURL() (string, error) {
	if driver.IPAddress == "" {
		return "", nil
	}

	url := fmt.Sprintf("tcp://%s", net.JoinHostPort(driver.IPAddress, "2376"))

	return url, nil
}

// Remove deletes the target machine.
func (driver *Driver) Remove() error {
	log.Infof("Destroying terraform configuration...")

	terraformer, err := driver.getTerraformer()
	if err != nil {
		return err
	}

	success, err := terraformer.Destroy(true /* withVariablesFile */)
	if err != nil {
		return err
	}
	if !success {
		return errors.New("Failed to destroy Terraform configuration")
	}

	return nil
}

// Start the target machine.
func (driver *Driver) Start() error {
	return errors.New("The Terraform driver does not support Start.")
}

// Stop the target machine (gracefully).
func (driver *Driver) Stop() error {
	return errors.New("The Terraform driver does not support Stop.")
}

// Restart the target machine.
func (driver *Driver) Restart() error {
	// TODO: Check machine has been created.

	_, err := drivers.RunSSHCommandFromDriver(driver, "sudo shutdown -r now")

	return err
}

// Kill the target machine (hard shutdown).
func (driver *Driver) Kill() error {
	return errors.New("The Terraform driver does not support Kill.")
}

// GetSSHHostname returns the hostname for SSH
func (driver *Driver) GetSSHHostname() (string, error) {
	// TODO: Check machine has been created.

	return driver.IPAddress, nil
}

// GetSSHKeyPath returns the ssh key path
func (driver *Driver) GetSSHKeyPath() string {
	return driver.SSHKeyPath
}
<commit_msg>Capture change to SSH user (if any) after terraform apply.<commit_after>package main

/*
 * Driver implementation
 * ---------------------
 */

import (
	"errors"
	"fmt"
	"net"
	"os"

	stdlog "log"

	"github.com/docker/machine/libmachine/drivers"
	"github.com/docker/machine/libmachine/log"
	"github.com/docker/machine/libmachine/mcnflag"
	"github.com/docker/machine/libmachine/state"
	"github.com/tintoy/docker-machine-driver-terraform/terraform"
)

// Driver is the Docker Machine driver for Terraform.
type Driver struct {
	*drivers.BaseDriver

	// The source path (or URL) of the Terraform configuration.
	ConfigSource string

	// The path of the directory containing the imported Terraform configuration.
	ConfigDir string

	// Additional variables for the Terraform configuration
	ConfigVariables terraform.ConfigVariables

	// An optional file containing the JSON that represents additional variables for the Terraform configuration
	AdditionalVariablesFile string

	// Refresh the configuration after applying it
	RefreshAfterApply bool

	// The full path to the Terraform executable.
	TerraformExecutablePath string

	// The path to the SSH private key file to use for authentication.
	//
	// If not specified, a new key-pair will be generated.
	SSHKey string

	// The terraform executor.
	terraformer *terraform.Terraformer
}

// GetCreateFlags registers the "machine create" flags recognized by this driver, including
// their help text and defaults.
func (driver *Driver) GetCreateFlags() []mcnflag.Flag {
	return []mcnflag.Flag{
		mcnflag.StringFlag{
			Name:  "terraform-config",
			Usage: "The path (or URL) of the Terraform configuration",
			Value: "",
		},
		mcnflag.StringFlag{
			Name:  "terraform-additional-variables",
			Usage: "An optional file containing the JSON that represents additional variables for the Terraform configuration",
			Value: "",
		},
		mcnflag.BoolFlag{
			Name:  "terraform-refresh",
			Usage: "Refresh the configuration after applying it",
		},
		mcnflag.StringFlag{
			EnvVar: "TERRAFORM_SSH_USER",
			Name:   "terraform-ssh-user",
			Usage:  "The SSH username to use. Default: root",
			Value:  "root",
		},
		mcnflag.StringFlag{
			EnvVar: "TERRAFORM_SSH_KEY",
			Name:   "terraform-ssh-key",
			Usage:  "The SSH key file to use",
			Value:  "",
		},
		mcnflag.IntFlag{
			EnvVar: "TERRAFORM_SSH_PORT",
			Name:   "terraform-ssh-port",
			Usage:  "The SSH port. Default: 22",
			Value:  22,
		},
	}
}

// DriverName returns the name of the driver
func (driver *Driver) DriverName() string {
	return "terraform"
}

// SetConfigFromFlags assigns and verifies the command-line arguments presented to the driver.
func (driver *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
	log.Debugf("docker-machine-driver-terraform %s", DriverVersion)

	// Enable ALL logging if MACHINE_DEBUG is set
	if os.Getenv("MACHINE_DEBUG") != "" {
		stdlog.SetOutput(os.Stderr)
	}

	driver.ConfigSource = flags.String("terraform-config")
	driver.ConfigVariables = make(map[string]interface{})
	driver.AdditionalVariablesFile = flags.String("terraform-additional-variables")
	driver.RefreshAfterApply = flags.Bool("terraform-refresh")

	driver.SSHPort = flags.Int("terraform-ssh-port")
	driver.SSHUser = flags.String("terraform-ssh-user")
	driver.SSHKey = flags.String("terraform-ssh-key")

	// Validation
	if driver.ConfigSource == "" {
		return errors.New("Required argument: --terraform-config")
	}

	return nil
}

// PreCreateCheck validates the configuration before making any changes.
func (driver *Driver) PreCreateCheck() error {
	if driver.ConfigSource == "" {
		return errors.New("The source for Terraform configuration has not been specified")
	}

	log.Infof("Auto-detecting client's public (external) IP address...")
	clientIP, err := getClientPublicIPv4Address()
	if err != nil {
		return err
	}

	log.Infof("Will create machine '%s' using Terraform configuration from '%s'.",
		driver.MachineName,
		driver.ConfigSource,
	)

	log.Infof("Resolving Terraform configuration...")
	err = driver.resolveConfigDir()
	if err != nil {
		return err
	}
	err = driver.importConfig()
	if err != nil {
		return err
	}

	if driver.SSHKey != "" {
		log.Infof("Importing SSH key '%s'...", driver.SSHKey)
		err = driver.importSSHKey()
		if err != nil {
			return err
		}
	} else {
		log.Infof("Generating new SSH key...")
		err = driver.generateSSHKey()
		if err != nil {
			return err
		}
	}

	log.Infof("Customising terraform configuration...")
	driver.ConfigVariables["dm_client_ip"] = clientIP
	driver.ConfigVariables["dm_machine_name"] = driver.MachineName
	driver.ConfigVariables["dm_ssh_private_key_file"] = driver.SSHKeyPath
	driver.ConfigVariables["dm_ssh_public_key_file"] = driver.SSHKeyPath + ".pub"
	driver.ConfigVariables["dm_ssh_user"] = driver.SSHUser
	driver.ConfigVariables["dm_ssh_port"] = driver.SSHPort
	err = driver.readAdditionalVariables()
	if err != nil {
		return err
	}
	err = driver.writeVariables()
	if err != nil {
		return err
	}

	return nil
}

// Create a new Docker Machine instance on CloudControl.
func (driver *Driver) Create() error {
	log.Infof("Applying terraform configuration...")

	terraformer, err := driver.getTerraformer()
	if err != nil {
		return err
	}

	success, err := terraformer.Apply(true /* withVariablesFile */)
	if err != nil {
		return err
	}
	if !success {
		return errors.New("Failed to apply Terraform configuration")
	}

	outputs, err := terraformer.Output()
	if err != nil {
		return err
	}
	if !success {
		return fmt.Errorf("Failed to obtain Terraform outputs")
	}

	output, ok := outputs["dm_machine_ip"]
	if !ok {
		return fmt.Errorf("Configuration does not declare required output 'dm_machine_ip'")
	}
	driver.IPAddress = output.Value.(string)

	output, ok = outputs["dm_ssh_user"]
	if ok {
		driver.SSHUser = output.Value.(string)
	}

	log.Infof("Deployed host has IP '%s'.", driver.IPAddress)
	log.Infof("Deployed host has SSH user '%s'.", driver.SSHUser)

	return nil
}

// GetState retrieves the status of the target Docker Machine instance in CloudControl.
func (driver *Driver) GetState() (state.State, error) {
	return state.Running, nil
}

// GetURL returns docker daemon URL on the target machine
func (driver *Driver) GetURL() (string, error) {
	if driver.IPAddress == "" {
		return "", nil
	}

	url := fmt.Sprintf("tcp://%s", net.JoinHostPort(driver.IPAddress, "2376"))

	return url, nil
}

// Remove deletes the target machine.
func (driver *Driver) Remove() error {
	log.Infof("Destroying terraform configuration...")

	terraformer, err := driver.getTerraformer()
	if err != nil {
		return err
	}

	success, err := terraformer.Destroy(true /* withVariablesFile */)
	if err != nil {
		return err
	}
	if !success {
		return errors.New("Failed to destroy Terraform configuration")
	}

	return nil
}

// Start the target machine.
func (driver *Driver) Start() error {
	return errors.New("The Terraform driver does not support Start.")
}

// Stop the target machine (gracefully).
func (driver *Driver) Stop() error {
	return errors.New("The Terraform driver does not support Stop.")
}

// Restart the target machine.
func (driver *Driver) Restart() error {
	// TODO: Check machine has been created.

	_, err := drivers.RunSSHCommandFromDriver(driver, "sudo shutdown -r now")

	return err
}

// Kill the target machine (hard shutdown).
func (driver *Driver) Kill() error {
	return errors.New("The Terraform driver does not support Kill.")
}

// GetSSHHostname returns the hostname for SSH
func (driver *Driver) GetSSHHostname() (string, error) {
	// TODO: Check machine has been created.

	return driver.IPAddress, nil
}

// GetSSHKeyPath returns the ssh key path
func (driver *Driver) GetSSHKeyPath() string {
	return driver.SSHKeyPath
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/sha1"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/dickeyxxx/golock"
	"github.com/franela/goreq"
	"github.com/heroku/heroku-cli/gode"
	"github.com/kardianos/osext"
	"github.com/ulikunitz/xz"
)

var updateTopic = &Topic{
	Name:        "update",
	Description: "update heroku-cli",
}

var updateCmd = &Command{
	Topic:            "update",
	Hidden:           true,
	Description:      "updates heroku-cli",
	DisableAnalytics: true,
	Args:             []Arg{{Name: "channel", Optional: true}},
	Flags:            []Flag{{Name: "background", Hidden: true}},
	Run: func(ctx *Context) {
		channel := ctx.Args.(map[string]string)["channel"]
		if channel == "" {
			channel = Channel
		}
		t := "foreground"
		if ctx.Flags["background"] == true {
			t = "background"
		}
		Update(channel, t)
	},
}

var binPath string
var updateLockPath = filepath.Join(AppDir(), "updating.lock")
var autoupdateFile = filepath.Join(AppDir(), "autoupdate")
var tmpPath = filepath.Join(AppDir(), "tmp")

func init() {
	binPath, _ = osext.Executable()
}

// Update updates the CLI and plugins
func Update(channel string, t string) {
	if !IsUpdateNeeded(t) {
		return
	}
	touchAutoupdateFile()
	updateCLI(channel)
	SetupNode()
	updatePlugins()
	truncateErrorLog()
	cleanTmpDir()
}

func updatePlugins() {
	action("heroku-cli: Updating plugins", "", func() {
		plugins := PluginNamesNotSymlinked()
		if len(plugins) == 0 {
			return
		}
		packages, err := gode.OutdatedPackages(plugins...)
		PrintError(err)
		if len(packages) > 0 {
			for name, version := range packages {
				lockPlugin(name)
				PrintError(gode.InstallPackages(name + "@" + version))
				plugin, err := ParsePlugin(name)
				PrintError(err)
				AddPluginsToCache(plugin)
				unlockPlugin(name)
			}
			Errf(" done. Updated %d %s.\n", len(packages), plural("package", len(packages)))
		} else {
			Errln(" no plugins to update.")
		}
	})
}

func updateCLI(channel string) {
	if channel == "?" {
		// do not update dev version
		return
	}
	manifest, err := getUpdateManifest(channel)
	if err != nil {
		Warn("Error updating CLI")
		PrintError(err)
		return
	}
	if manifest.Version == Version && manifest.Channel == Channel {
		return
	}
	locked, err := golock.IsLocked(updateLockPath)
	LogIfError(err)
	if locked {
		Warn("Update in progress")
		return
	}
	LogIfError(golock.Lock(updateLockPath))
	unlock := func() {
		golock.Unlock(updateLockPath)
	}
	defer unlock()
	msg := fmt.Sprintf("heroku-cli: Updating to %s", manifest.Version)
	if manifest.Channel != "master" {
		msg = fmt.Sprintf("%s (%s)", msg, manifest.Channel)
	}
	action(msg, "done", func() {
		build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
		// on windows we can't remove an existing file or remove the running binary
		// so we download the file to binName.new
		// move the running binary to binName.old (deleting any existing file first)
		// rename the downloaded file to binName
		tmpBinPathNew := binPath + ".new"
		tmpBinPathOld := binPath + ".old"
		if err := downloadBin(tmpBinPathNew, build.URL); err != nil {
			panic(err)
		}
		if fileSha1(tmpBinPathNew) != build.Sha1 {
			panic("SHA mismatch")
		}
		os.Remove(tmpBinPathOld)
		os.Rename(binPath, tmpBinPathOld)
		if err := os.Rename(tmpBinPathNew, binPath); err != nil {
			panic(err)
		}
		os.Remove(tmpBinPathOld)
		unlock()
		clearAutoupdateFile() // force full update
	})
	reexec() // reexec to finish updating with new code
}

// IsUpdateNeeded checks if an update is available
func IsUpdateNeeded(t string) bool {
	f, err := os.Stat(autoupdateFile)
	if err != nil {
		return true
	}
	if t == "background" {
		return time.Since(f.ModTime()) > 4*time.Hour
	} else if t == "block" {
		return time.Since(f.ModTime()) > 2160*time.Hour // 90 days
	}
	return true
}

func touchAutoupdateFile() {
	out, err := os.OpenFile(autoupdateFile, os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		panic(err)
	}
	out.WriteString(time.Now().String())
	out.Close()
}

// forces a full update on the next run
func clearAutoupdateFile() {
	PrintError(os.Remove(autoupdateFile))
}

type manifest struct {
	Channel, Version string
	Builds           map[string]map[string]struct {
		URL, Sha1 string
	}
}

func getUpdateManifest(channel string) (*manifest, error) {
	res, err := goreq.Request{
		Uri:       "https://cli-assets.heroku.com/" + channel + "/manifest.json",
		ShowDebug: debugging,
	}.Do()
	if err != nil {
		return nil, err
	}
	var m manifest
	res.Body.FromJsonTo(&m)
	return &m, nil
}

func downloadBin(path, url string) error {
	out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return err
	}
	defer out.Close()
	res, err := goreq.Request{
		Uri:       url + ".xz",
		ShowDebug: debugging,
	}.Do()
	if err != nil {
		return err
	}
	if res.StatusCode != 200 {
		b, _ := res.Body.ToString()
		return errors.New(b)
	}
	defer res.Body.Close()
	uncompressed, err := xz.NewReader(res.Body)
	if err != nil {
		return err
	}
	_, err = io.Copy(out, uncompressed)
	return err
}

func fileSha1(path string) string {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", sha1.Sum(data))
}

// TriggerBackgroundUpdate will trigger an update to the client in the background
func TriggerBackgroundUpdate() {
	wg.Add(1)
	go func() {
		wg.Done()
		if IsUpdateNeeded("background") {
			exec.Command(binPath, "update", "--background").Start()
		}
	}()
}

// restarts the CLI with the same arguments
func reexec() {
	Debugln("reexecing new CLI...")
	cmd := exec.Command(binPath, os.Args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	Exit(getExitCode(cmd.Run()))
}

func truncateErrorLog() {
	Debugln("truncating error log...")
	body, err := ioutil.ReadFile(ErrLogPath)
	if err != nil {
		PrintError(err)
		return
	}
	lines := strings.Split(string(body), "\n")
	lines = lines[maxint(len(lines)-1000, 0) : len(lines)-1]
	err = ioutil.WriteFile(ErrLogPath, []byte(strings.Join(lines, "\n")+"\n"), 0644)
	PrintError(err)
}

func maxint(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func cleanTmpDir() {
	Debugln("cleaning up tmp dirs...")
	dirs, err := ioutil.ReadDir(tmpPath)
	if err != nil {
		PrintError(err)
		return
	}
	for _, dir := range dirs {
		if time.Since(dir.ModTime()) > 24*time.Hour {
			path := filepath.Join(tmpPath, dir.Name())
			Debugln("deleting " + path)
			PrintError(os.RemoveAll(path))
		}
	}
}
<commit_msg>ensure builtins are installed<commit_after>package main

import (
	"crypto/sha1"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	"github.com/dickeyxxx/golock"
	"github.com/franela/goreq"
	"github.com/heroku/heroku-cli/gode"
	"github.com/kardianos/osext"
	"github.com/ulikunitz/xz"
)

var updateTopic = &Topic{
	Name:        "update",
	Description: "update heroku-cli",
}

var updateCmd = &Command{
	Topic:            "update",
	Hidden:           true,
	Description:      "updates heroku-cli",
	DisableAnalytics: true,
	Args:             []Arg{{Name: "channel", Optional: true}},
	Flags:            []Flag{{Name: "background", Hidden: true}},
	Run: func(ctx *Context) {
		channel := ctx.Args.(map[string]string)["channel"]
		if channel == "" {
			channel = Channel
		}
		t := "foreground"
		if ctx.Flags["background"] == true {
			t = "background"
		}
		Update(channel, t)
	},
}

var binPath string
var updateLockPath = filepath.Join(AppDir(), "updating.lock")
var autoupdateFile = filepath.Join(AppDir(), "autoupdate")
var tmpPath = filepath.Join(AppDir(), "tmp")

func init() {
	binPath, _ = osext.Executable()
}

// Update updates the CLI and plugins
func Update(channel string, t string) {
	if !IsUpdateNeeded(t) {
		return
	}
	touchAutoupdateFile()
	updateCLI(channel)
	SetupNode()
	SetupBuiltinPlugins()
	updatePlugins()
	truncateErrorLog()
	cleanTmpDir()
}

func updatePlugins() {
	action("heroku-cli: Updating plugins", "", func() {
		plugins := PluginNamesNotSymlinked()
		if len(plugins) == 0 {
			return
		}
		packages, err := gode.OutdatedPackages(plugins...)
		PrintError(err)
		if len(packages) > 0 {
			for name, version := range packages {
				lockPlugin(name)
				PrintError(gode.InstallPackages(name + "@" + version))
				plugin, err := ParsePlugin(name)
				PrintError(err)
				AddPluginsToCache(plugin)
				unlockPlugin(name)
			}
			Errf(" done. Updated %d %s.\n", len(packages), plural("package", len(packages)))
		} else {
			Errln(" no plugins to update.")
		}
	})
}

func updateCLI(channel string) {
	if channel == "?" {
		// do not update dev version
		return
	}
	manifest, err := getUpdateManifest(channel)
	if err != nil {
		Warn("Error updating CLI")
		PrintError(err)
		return
	}
	if manifest.Version == Version && manifest.Channel == Channel {
		return
	}
	locked, err := golock.IsLocked(updateLockPath)
	LogIfError(err)
	if locked {
		Warn("Update in progress")
		return
	}
	LogIfError(golock.Lock(updateLockPath))
	unlock := func() {
		golock.Unlock(updateLockPath)
	}
	defer unlock()
	msg := fmt.Sprintf("heroku-cli: Updating to %s", manifest.Version)
	if manifest.Channel != "master" {
		msg = fmt.Sprintf("%s (%s)", msg, manifest.Channel)
	}
	action(msg, "done", func() {
		build := manifest.Builds[runtime.GOOS][runtime.GOARCH]
		// on windows we can't remove an existing file or remove the running binary
		// so we download the file to binName.new
		// move the running binary to binName.old (deleting any existing file first)
		// rename the downloaded file to binName
		tmpBinPathNew := binPath + ".new"
		tmpBinPathOld := binPath + ".old"
		if err := downloadBin(tmpBinPathNew, build.URL); err != nil {
			panic(err)
		}
		if fileSha1(tmpBinPathNew) != build.Sha1 {
			panic("SHA mismatch")
		}
		os.Remove(tmpBinPathOld)
		os.Rename(binPath, tmpBinPathOld)
		if err := os.Rename(tmpBinPathNew, binPath); err != nil {
			panic(err)
		}
		os.Remove(tmpBinPathOld)
		unlock()
		clearAutoupdateFile() // force full update
	})
	reexec() // reexec to finish updating with new code
}

// IsUpdateNeeded checks if an update is available
func IsUpdateNeeded(t string) bool {
	f, err := os.Stat(autoupdateFile)
	if err != nil {
		return true
	}
	if t == "background" {
		return time.Since(f.ModTime()) > 4*time.Hour
	} else if t == "block" {
		return time.Since(f.ModTime()) > 2160*time.Hour // 90 days
	}
	return true
}

func touchAutoupdateFile() {
	out, err := os.OpenFile(autoupdateFile, os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		panic(err)
	}
	out.WriteString(time.Now().String())
	out.Close()
}

// forces a full update on the next run
func clearAutoupdateFile() {
	PrintError(os.Remove(autoupdateFile))
}

type manifest struct {
	Channel, Version string
	Builds           map[string]map[string]struct {
		URL, Sha1 string
	}
}

func getUpdateManifest(channel string) (*manifest, error) {
	res, err := goreq.Request{
		Uri:       "https://cli-assets.heroku.com/" + channel + "/manifest.json",
		ShowDebug: debugging,
	}.Do()
	if err != nil {
		return nil, err
	}
	var m manifest
	res.Body.FromJsonTo(&m)
	return &m, nil
}

func downloadBin(path, url string) error {
	out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
	if err != nil {
		return err
	}
	defer out.Close()
	res, err := goreq.Request{
		Uri:       url + ".xz",
		ShowDebug: debugging,
	}.Do()
	if err != nil {
		return err
	}
	if res.StatusCode != 200 {
		b, _ := res.Body.ToString()
		return errors.New(b)
	}
	defer res.Body.Close()
	uncompressed, err := xz.NewReader(res.Body)
	if err != nil {
		return err
	}
	_, err = io.Copy(out, uncompressed)
	return err
}

func fileSha1(path string) string {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		panic(err)
	}
	return fmt.Sprintf("%x", sha1.Sum(data))
}

// TriggerBackgroundUpdate will trigger an update to the client in the background
func TriggerBackgroundUpdate() {
	wg.Add(1)
	go func() {
		wg.Done()
		if IsUpdateNeeded("background") {
			exec.Command(binPath, "update", "--background").Start()
		}
	}()
}

// restarts the CLI with the same arguments
func reexec() {
	Debugln("reexecing new CLI...")
	cmd := exec.Command(binPath, os.Args[1:]...)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	Exit(getExitCode(cmd.Run()))
}

func truncateErrorLog() {
	Debugln("truncating error log...")
	body, err := ioutil.ReadFile(ErrLogPath)
	if err != nil {
		PrintError(err)
		return
	}
	lines := strings.Split(string(body), "\n")
	lines = lines[maxint(len(lines)-1000, 0) : len(lines)-1]
	err = ioutil.WriteFile(ErrLogPath, []byte(strings.Join(lines, "\n")+"\n"), 0644)
	PrintError(err)
}

func maxint(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func cleanTmpDir() {
	Debugln("cleaning up tmp dirs...")
	dirs, err := ioutil.ReadDir(tmpPath)
	if err != nil {
		PrintError(err)
		return
	}
	for _, dir := range dirs {
		if time.Since(dir.ModTime()) > 24*time.Hour {
			path := filepath.Join(tmpPath, dir.Name())
			Debugln("deleting " + path)
			PrintError(os.RemoveAll(path))
		}
	}
}
<|endoftext|>