<commit_before>package filesys

import (
	"io"
	"log"
	"os"
)

type WrittenIntervalNode struct {
	DataOffset int64
	TempOffset int64
	Size       int64
	Next       *WrittenIntervalNode
}

type WrittenIntervalLinkedList struct {
	tempFile *os.File
	Head     *WrittenIntervalNode
	Tail     *WrittenIntervalNode
}

type WrittenContinuousIntervals struct {
	tempFile   *os.File
	lastOffset int64
	lists      []*WrittenIntervalLinkedList
}

func (list *WrittenIntervalLinkedList) Offset() int64 {
	return list.Head.DataOffset
}
func (list *WrittenIntervalLinkedList) Size() int64 {
	return list.Tail.DataOffset + list.Tail.Size - list.Head.DataOffset
}
func (list *WrittenIntervalLinkedList) addNodeToTail(node *WrittenIntervalNode) {
	// glog.V(4).Infof("add to tail [%d,%d) + [%d,%d) => [%d,%d)", list.Head.Offset, list.Tail.Offset+list.Tail.Size, node.Offset, node.Offset+node.Size, list.Head.Offset, node.Offset+node.Size)
	if list.Tail.TempOffset+list.Tail.Size == node.TempOffset {
		// already connected
		list.Tail.Size += node.Size
	} else {
		list.Tail.Next = node
		list.Tail = node
	}
}
func (list *WrittenIntervalLinkedList) addNodeToHead(node *WrittenIntervalNode) {
	// glog.V(4).Infof("add to head [%d,%d) + [%d,%d) => [%d,%d)", node.Offset, node.Offset+node.Size, list.Head.Offset, list.Tail.Offset+list.Tail.Size, node.Offset, list.Tail.Offset+list.Tail.Size)
	node.Next = list.Head
	list.Head = node
}

func (list *WrittenIntervalLinkedList) ReadData(buf []byte, start, stop int64) {
	t := list.Head
	for {

		nodeStart, nodeStop := max(start, t.DataOffset), min(stop, t.DataOffset+t.Size)
		if nodeStart < nodeStop {
			// glog.V(0).Infof("copying start=%d stop=%d t=[%d,%d) t.data=%d => bufSize=%d nodeStart=%d, nodeStop=%d", start, stop, t.Offset, t.Offset+t.Size, len(t.Data), len(buf), nodeStart, nodeStop)
			list.tempFile.ReadAt(buf[nodeStart-start:nodeStop-start], nodeStart-t.TempOffset)
		}

		if t.Next == nil {
			break
		}
		t = t.Next
	}
}

func (c *WrittenContinuousIntervals) TotalSize() (total int64) {
	for _, list := range c.lists {
		total += list.Size()
	}
	return
}

func (list *WrittenIntervalLinkedList) subList(start, stop int64) *WrittenIntervalLinkedList {
	var nodes []*WrittenIntervalNode
	for t := list.Head; t != nil; t = t.Next {
		nodeStart, nodeStop := max(start, t.DataOffset), min(stop, t.DataOffset+t.Size)
		if nodeStart >= nodeStop {
			// skip non overlapping WrittenIntervalNode
			continue
		}
		nodes = append(nodes, &WrittenIntervalNode{
			TempOffset: t.TempOffset + nodeStart - t.DataOffset,
			DataOffset: nodeStart,
			Size:       nodeStop - nodeStart,
			Next:       nil,
		})
	}
	for i := 1; i < len(nodes); i++ {
		nodes[i-1].Next = nodes[i]
	}
	return &WrittenIntervalLinkedList{
		tempFile: list.tempFile,
		Head:     nodes[0],
		Tail:     nodes[len(nodes)-1],
	}
}

func (c *WrittenContinuousIntervals) debug() {
	log.Printf("++")
	for _, l := range c.lists {
		log.Printf("++++")
		for t := l.Head; ; t = t.Next {
			log.Printf("[%d,%d) => [%d,%d) %d", t.DataOffset, t.DataOffset+t.Size, t.TempOffset, t.TempOffset+t.Size, t.Size)
			if t.Next == nil {
				break
			}
		}
		log.Printf("----")
	}
	log.Printf("--")
}

func (c *WrittenContinuousIntervals) AddInterval(tempOffset int64, dataSize int, dataOffset int64) {

	interval := &WrittenIntervalNode{DataOffset: dataOffset, TempOffset: tempOffset, Size: int64(dataSize)}

	// append to the tail and return
	if len(c.lists) == 1 {
		lastSpan := c.lists[0]
		if lastSpan.Tail.DataOffset+lastSpan.Tail.Size == dataOffset {
			lastSpan.addNodeToTail(interval)
			return
		}
	}

	var newLists []*WrittenIntervalLinkedList
	for _, list := range c.lists {
		// if list is to the left of new interval, add to the new list
		if list.Tail.DataOffset+list.Tail.Size <= interval.DataOffset {
			newLists = append(newLists, list)
		}
		// if list is to the right of new interval, add to the new list
		if interval.DataOffset+interval.Size <= list.Head.DataOffset {
			newLists = append(newLists, list)
		}
		// if new interval overwrite the right part of the list
		if list.Head.DataOffset < interval.DataOffset && interval.DataOffset < list.Tail.DataOffset+list.Tail.Size {
			// create a new list of the left part of existing list
			newLists = append(newLists, list.subList(list.Offset(), interval.DataOffset))
		}
		// if new interval overwrite the left part of the list
		if list.Head.DataOffset < interval.DataOffset+interval.Size && interval.DataOffset+interval.Size < list.Tail.DataOffset+list.Tail.Size {
			// create a new list of the right part of existing list
			newLists = append(newLists, list.subList(interval.DataOffset+interval.Size, list.Tail.DataOffset+list.Tail.Size))
		}
		// skip anything that is fully overwritten by the new interval
	}

	c.lists = newLists
	// add the new interval to the lists, connecting neighbor lists
	var prevList, nextList *WrittenIntervalLinkedList

	for _, list := range c.lists {
		if list.Head.DataOffset == interval.DataOffset+interval.Size {
			nextList = list
			break
		}
	}

	for _, list := range c.lists {
		if list.Head.DataOffset+list.Size() == dataOffset {
			list.addNodeToTail(interval)
			prevList = list
			break
		}
	}

	if prevList != nil && nextList != nil {
		// glog.V(4).Infof("connecting [%d,%d) + [%d,%d) => [%d,%d)", prevList.Head.Offset, prevList.Tail.Offset+prevList.Tail.Size, nextList.Head.Offset, nextList.Tail.Offset+nextList.Tail.Size, prevList.Head.Offset, nextList.Tail.Offset+nextList.Tail.Size)
		prevList.Tail.Next = nextList.Head
		prevList.Tail = nextList.Tail
		c.removeList(nextList)
	} else if nextList != nil {
		// add to head was not done when checking
		nextList.addNodeToHead(interval)
	}
	if prevList == nil && nextList == nil {
		c.lists = append(c.lists, &WrittenIntervalLinkedList{
			tempFile: c.tempFile,
			Head:     interval,
			Tail:     interval,
		})
	}

	return
}

func (c *WrittenContinuousIntervals) RemoveLargestIntervalLinkedList() *WrittenIntervalLinkedList {
	var maxSize int64
	maxIndex := -1
	for k, list := range c.lists {
		if maxSize <= list.Size() {
			maxSize = list.Size()
			maxIndex = k
		}
	}
	if maxSize <= 0 {
		return nil
	}

	t := c.lists[maxIndex]
	t.tempFile = c.tempFile
	c.lists = append(c.lists[0:maxIndex], c.lists[maxIndex+1:]...)
	return t

}

func (c *WrittenContinuousIntervals) removeList(target *WrittenIntervalLinkedList) {
	index := -1
	for k, list := range c.lists {
		if list.Offset() == target.Offset() {
			index = k
		}
	}
	if index < 0 {
		return
	}

	c.lists = append(c.lists[0:index], c.lists[index+1:]...)

}

func (c *WrittenContinuousIntervals) ReadDataAt(data []byte, startOffset int64) (maxStop int64) {
	for _, list := range c.lists {
		start := max(startOffset, list.Offset())
		stop := min(startOffset+int64(len(data)), list.Offset()+list.Size())
		if start < stop {
			list.ReadData(data[start-startOffset:], start, stop)
			maxStop = max(maxStop, stop)
		}
	}
	return
}

func (l *WrittenIntervalLinkedList) ToReader(start int64, stop int64) io.Reader {
	// TODO: optimize this to avoid another loop
	var readers []io.Reader
	for t := l.Head; ; t = t.Next {
		startOffset, stopOffset := max(t.DataOffset, start), min(t.DataOffset+t.Size, stop)
		if startOffset < stopOffset {
			// log.Printf("ToReader read [%d,%d) from [%d,%d) %d", t.DataOffset, t.DataOffset+t.Size, t.TempOffset, t.TempOffset+t.Size, t.Size)
			readers = append(readers, newFileSectionReader(l.tempFile, startOffset-t.DataOffset+t.TempOffset, startOffset, stopOffset-startOffset))
		}
		if t.Next == nil {
			break
		}
	}
	if len(readers) == 1 {
		return readers[0]
	}
	return io.MultiReader(readers...)
}

type FileSectionReader struct {
	file            *os.File
	tempStartOffset int64
	Offset          int64
	dataStart       int64
	dataStop        int64
}

var _ = io.Reader(&FileSectionReader{})

func newFileSectionReader(tempfile *os.File, offset int64, dataOffset int64, size int64) *FileSectionReader {
	return &FileSectionReader{
		file:            tempfile,
		tempStartOffset: offset,
		Offset:          offset,
		dataStart:       dataOffset,
		dataStop:        dataOffset + size,
	}
}

func (f *FileSectionReader) Read(p []byte) (n int, err error) {
	remaining := (f.dataStop - f.dataStart) - (f.Offset - f.tempStartOffset)
	if remaining <= 0 {
		return 0, io.EOF
	}
	dataLen := min(remaining, int64(len(p)))
	// glog.V(4).Infof("reading [%d,%d) from %v [%d,%d)/[%d,%d) %d", f.Offset-f.tempStartOffset+f.dataStart, f.Offset-f.tempStartOffset+f.dataStart+dataLen, f.file.Name(), f.Offset, f.Offset+dataLen, f.tempStartOffset, f.tempStartOffset+f.dataStop-f.dataStart, f.dataStop-f.dataStart)
	n, err = f.file.ReadAt(p[:dataLen], f.Offset)
	if n > 0 {
		f.Offset += int64(n)
	} else {
		err = io.EOF
	}
	return
}
<commit_msg>mount: read file when file is still being written<commit_after>package filesys

import (
	"io"
	"log"
	"os"
)

type WrittenIntervalNode struct {
	DataOffset int64
	TempOffset int64
	Size       int64
	Next       *WrittenIntervalNode
}

type WrittenIntervalLinkedList struct {
	tempFile *os.File
	Head     *WrittenIntervalNode
	Tail     *WrittenIntervalNode
}

type WrittenContinuousIntervals struct {
	tempFile   *os.File
	lastOffset int64
	lists      []*WrittenIntervalLinkedList
}

func (list *WrittenIntervalLinkedList) Offset() int64 {
	return list.Head.DataOffset
}
func (list *WrittenIntervalLinkedList) Size() int64 {
	return list.Tail.DataOffset + list.Tail.Size - list.Head.DataOffset
}
func (list *WrittenIntervalLinkedList) addNodeToTail(node *WrittenIntervalNode) {
	// glog.V(4).Infof("add to tail [%d,%d) + [%d,%d) => [%d,%d)", list.Head.Offset, list.Tail.Offset+list.Tail.Size, node.Offset, node.Offset+node.Size, list.Head.Offset, node.Offset+node.Size)
	if list.Tail.TempOffset+list.Tail.Size == node.TempOffset {
		// already connected
		list.Tail.Size += node.Size
	} else {
		list.Tail.Next = node
		list.Tail = node
	}
}
func (list *WrittenIntervalLinkedList) addNodeToHead(node *WrittenIntervalNode) {
	// glog.V(4).Infof("add to head [%d,%d) + [%d,%d) => [%d,%d)", node.Offset, node.Offset+node.Size, list.Head.Offset, list.Tail.Offset+list.Tail.Size, node.Offset, list.Tail.Offset+list.Tail.Size)
	node.Next = list.Head
	list.Head = node
}

func (list *WrittenIntervalLinkedList) ReadData(buf []byte, start, stop int64) {
	t := list.Head
	for {

		nodeStart, nodeStop := max(start, t.DataOffset), min(stop, t.DataOffset+t.Size)
		if nodeStart < nodeStop {
			// glog.V(4).Infof("copying start=%d stop=%d t=[%d,%d) => bufSize=%d nodeStart=%d, nodeStop=%d", start, stop, t.DataOffset, t.DataOffset+t.Size, len(buf), nodeStart, nodeStop)
			list.tempFile.ReadAt(buf[nodeStart-start:nodeStop-start], t.TempOffset + nodeStart - t.DataOffset)
		}

		if t.Next == nil {
			break
		}
		t = t.Next
	}
}

func (c *WrittenContinuousIntervals) TotalSize() (total int64) {
	for _, list := range c.lists {
		total += list.Size()
	}
	return
}

func (list *WrittenIntervalLinkedList) subList(start, stop int64) *WrittenIntervalLinkedList {
	var nodes []*WrittenIntervalNode
	for t := list.Head; t != nil; t = t.Next {
		nodeStart, nodeStop := max(start, t.DataOffset), min(stop, t.DataOffset+t.Size)
		if nodeStart >= nodeStop {
			// skip non overlapping WrittenIntervalNode
			continue
		}
		nodes = append(nodes, &WrittenIntervalNode{
			TempOffset: t.TempOffset + nodeStart - t.DataOffset,
			DataOffset: nodeStart,
			Size:       nodeStop - nodeStart,
			Next:       nil,
		})
	}
	for i := 1; i < len(nodes); i++ {
		nodes[i-1].Next = nodes[i]
	}
	return &WrittenIntervalLinkedList{
		tempFile: list.tempFile,
		Head:     nodes[0],
		Tail:     nodes[len(nodes)-1],
	}
}

func (c *WrittenContinuousIntervals) debug() {
	log.Printf("++")
	for _, l := range c.lists {
		log.Printf("++++")
		for t := l.Head; ; t = t.Next {
			log.Printf("[%d,%d) => [%d,%d) %d", t.DataOffset, t.DataOffset+t.Size, t.TempOffset, t.TempOffset+t.Size, t.Size)
			if t.Next == nil {
				break
			}
		}
		log.Printf("----")
	}
	log.Printf("--")
}

func (c *WrittenContinuousIntervals) AddInterval(tempOffset int64, dataSize int, dataOffset int64) {

	interval := &WrittenIntervalNode{DataOffset: dataOffset, TempOffset: tempOffset, Size: int64(dataSize)}

	// append to the tail and return
	if len(c.lists) == 1 {
		lastSpan := c.lists[0]
		if lastSpan.Tail.DataOffset+lastSpan.Tail.Size == dataOffset {
			lastSpan.addNodeToTail(interval)
			return
		}
	}

	var newLists []*WrittenIntervalLinkedList
	for _, list := range c.lists {
		// if list is to the left of new interval, add to the new list
		if list.Tail.DataOffset+list.Tail.Size <= interval.DataOffset {
			newLists = append(newLists, list)
		}
		// if list is to the right of new interval, add to the new list
		if interval.DataOffset+interval.Size <= list.Head.DataOffset {
			newLists = append(newLists, list)
		}
		// if new interval overwrite the right part of the list
		if list.Head.DataOffset < interval.DataOffset && interval.DataOffset < list.Tail.DataOffset+list.Tail.Size {
			// create a new list of the left part of existing list
			newLists = append(newLists, list.subList(list.Offset(), interval.DataOffset))
		}
		// if new interval overwrite the left part of the list
		if list.Head.DataOffset < interval.DataOffset+interval.Size && interval.DataOffset+interval.Size < list.Tail.DataOffset+list.Tail.Size {
			// create a new list of the right part of existing list
			newLists = append(newLists, list.subList(interval.DataOffset+interval.Size, list.Tail.DataOffset+list.Tail.Size))
		}
		// skip anything that is fully overwritten by the new interval
	}

	c.lists = newLists
	// add the new interval to the lists, connecting neighbor lists
	var prevList, nextList *WrittenIntervalLinkedList

	for _, list := range c.lists {
		if list.Head.DataOffset == interval.DataOffset+interval.Size {
			nextList = list
			break
		}
	}

	for _, list := range c.lists {
		if list.Head.DataOffset+list.Size() == dataOffset {
			list.addNodeToTail(interval)
			prevList = list
			break
		}
	}

	if prevList != nil && nextList != nil {
		// glog.V(4).Infof("connecting [%d,%d) + [%d,%d) => [%d,%d)", prevList.Head.Offset, prevList.Tail.Offset+prevList.Tail.Size, nextList.Head.Offset, nextList.Tail.Offset+nextList.Tail.Size, prevList.Head.Offset, nextList.Tail.Offset+nextList.Tail.Size)
		prevList.Tail.Next = nextList.Head
		prevList.Tail = nextList.Tail
		c.removeList(nextList)
	} else if nextList != nil {
		// add to head was not done when checking
		nextList.addNodeToHead(interval)
	}
	if prevList == nil && nextList == nil {
		c.lists = append(c.lists, &WrittenIntervalLinkedList{
			tempFile: c.tempFile,
			Head:     interval,
			Tail:     interval,
		})
	}

	return
}

func (c *WrittenContinuousIntervals) RemoveLargestIntervalLinkedList() *WrittenIntervalLinkedList {
	var maxSize int64
	maxIndex := -1
	for k, list := range c.lists {
		if maxSize <= list.Size() {
			maxSize = list.Size()
			maxIndex = k
		}
	}
	if maxSize <= 0 {
		return nil
	}

	t := c.lists[maxIndex]
	t.tempFile = c.tempFile
	c.lists = append(c.lists[0:maxIndex], c.lists[maxIndex+1:]...)
	return t

}

func (c *WrittenContinuousIntervals) removeList(target *WrittenIntervalLinkedList) {
	index := -1
	for k, list := range c.lists {
		if list.Offset() == target.Offset() {
			index = k
		}
	}
	if index < 0 {
		return
	}

	c.lists = append(c.lists[0:index], c.lists[index+1:]...)

}

func (c *WrittenContinuousIntervals) ReadDataAt(data []byte, startOffset int64) (maxStop int64) {
	for _, list := range c.lists {
		start := max(startOffset, list.Offset())
		stop := min(startOffset+int64(len(data)), list.Offset()+list.Size())
		if start < stop {
			list.ReadData(data[start-startOffset:], start, stop)
			maxStop = max(maxStop, stop)
		}
	}
	return
}

func (l *WrittenIntervalLinkedList) ToReader(start int64, stop int64) io.Reader {
	// TODO: optimize this to avoid another loop
	var readers []io.Reader
	for t := l.Head; ; t = t.Next {
		startOffset, stopOffset := max(t.DataOffset, start), min(t.DataOffset+t.Size, stop)
		if startOffset < stopOffset {
			// glog.V(4).Infof("ToReader read [%d,%d) from [%d,%d) %d", t.DataOffset, t.DataOffset+t.Size, t.TempOffset, t.TempOffset+t.Size, t.Size)
			readers = append(readers, newFileSectionReader(l.tempFile, startOffset-t.DataOffset+t.TempOffset, startOffset, stopOffset-startOffset))
		}
		if t.Next == nil {
			break
		}
	}
	if len(readers) == 1 {
		return readers[0]
	}
	return io.MultiReader(readers...)
}

type FileSectionReader struct {
	file            *os.File
	tempStartOffset int64
	Offset          int64
	dataStart       int64
	dataStop        int64
}

var _ = io.Reader(&FileSectionReader{})

func newFileSectionReader(tempfile *os.File, offset int64, dataOffset int64, size int64) *FileSectionReader {
	return &FileSectionReader{
		file:            tempfile,
		tempStartOffset: offset,
		Offset:          offset,
		dataStart:       dataOffset,
		dataStop:        dataOffset + size,
	}
}

func (f *FileSectionReader) Read(p []byte) (n int, err error) {
	remaining := (f.dataStop - f.dataStart) - (f.Offset - f.tempStartOffset)
	if remaining <= 0 {
		return 0, io.EOF
	}
	dataLen := min(remaining, int64(len(p)))
	// glog.V(4).Infof("reading [%d,%d) from %v [%d,%d)/[%d,%d) %d", f.Offset-f.tempStartOffset+f.dataStart, f.Offset-f.tempStartOffset+f.dataStart+dataLen, f.file.Name(), f.Offset, f.Offset+dataLen, f.tempStartOffset, f.tempStartOffset+f.dataStop-f.dataStart, f.dataStop-f.dataStart)
	n, err = f.file.ReadAt(p[:dataLen], f.Offset)
	if n > 0 {
		f.Offset += int64(n)
	} else {
		err = io.EOF
	}
	return
}
<|endoftext|>


<commit_before>package hg

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"time"
	"fmt"
)

var _ = Describe("Hg", func() {
	repo := Repository{
		Path: "/path/to/repo",
		Branch: "a_branch",
		IncludePaths: []string{
			"/path/1",
			"/path/2",
			"/path/3",
		},
		ExcludePaths: []string{
			"/path/4",
			"/path/5",
			"/path/6",
		},
	}
	emptyRepo := Repository{}
	Context("When making revset query fragments", func() {
		It("joins all given paths", func() {
			Expect(unionOfPaths(repo.IncludePaths)).To(Equal("file('re:/path/1')|file('re:/path/2')|file('re:/path/3')"))
		})

		It("produces the correct include fragment", func() {
			Expect(repo.makeIncludeQueryFragment()).To(Equal("file('re:/path/1')|file('re:/path/2')|file('re:/path/3')"))
			Expect(emptyRepo.makeIncludeQueryFragment()).To(Equal("all()"))
		})

		It("produces the correct exclude fragment", func() {
			Expect(repo.makeExcludeQueryFragment()).To(Equal("file('re:/path/4')|file('re:/path/5')|file('re:/path/6')"))
			Expect(emptyRepo.makeExcludeQueryFragment()).To(Equal("not all()"))
		})

	})

	Context("When getting metadata on a commit", func() {
		logResponse := `[
			{
				"rev": 16,
				"node": "f47d10f40bf7a96c2d853c6c6025ba35b6a9c499",
				"branch": "default",
				"phase": "draft",
				"user": "Jane Doe <jdoe@example.com>",
				"date": [1457968493, -32400],
				"desc": "foo",
				"bookmarks": [],
				"tags": ["tip"],
				"parents": ["4484191cd2e41c174ecc2604af06aeb2a21c247f"]
			}
		]`
		var metadata []CommitProperty
		var err error

		BeforeEach(func() {
			metadata, err = parseMetadata([]byte(logResponse))
		})

		It("extracts all expected fields", func() {
			Expect(err).To(BeNil())
			Expect(metadata).To(HaveLen(5))
		})

		It("extracts commit id, author and message", func() {
			Expect(err).To(BeNil())
			Expect(metadata[0].Name).To(Equal("commit"))
			Expect(metadata[0].Value).To(Equal("f47d10f40bf7a96c2d853c6c6025ba35b6a9c499"))

			Expect(metadata[1].Name).To(Equal("author"))
			Expect(metadata[1].Value).To(Equal("Jane Doe <jdoe@example.com>"))

			Expect(metadata[3].Name).To(Equal("message"))
			Expect(metadata[3].Value).To(Equal("foo"))
			Expect(metadata[3].Type).To(Equal("message"))
		})

		It("parses the date correctly", func() {
			// [1457968493, -32400] -> 2016-03-15 00:14:53 +0900
			// note the sign on the offset
			parsedTime, err := parseHgTime([]int64{1457968493, -32400})

			Expect(err).To(BeNil())

			fmt.Println(parsedTime)
			year, month, day := parsedTime.Date()
			Expect(year).To(Equal(2016))
			Expect(month).To(Equal(time.Month(3)))
			Expect(day).To(Equal(15))

			hour, min, second := parsedTime.Clock()
			Expect(hour).To(Equal(0))
			Expect(min).To(Equal(14))
			Expect(second).To(Equal(53))

			_, offset := parsedTime.Zone()
			Expect(offset).To(Equal(32400))
		})

		It("parses the date and formats it in the expected ISO 8601 format", func() {
			Expect(err).To(BeNil())
			Expect(metadata[2].Name).To(Equal("author_date"))
			Expect(metadata[2].Value).To(Equal("2016-03-15 00:14:53 +0900"))
			Expect(metadata[2].Type).To(Equal("time"))
		})

		It("lists all tags of the commit", func() {
			Expect(err).To(BeNil())
			Expect(metadata[4].Name).To(Equal("tags"))
			Expect(metadata[4].Value).To(Equal("tip"))
		})
	})
})
<commit_msg>hg_test: remove debug print statement<commit_after>package hg

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"time"
)

var _ = Describe("Hg", func() {
	repo := Repository{
		Path: "/path/to/repo",
		Branch: "a_branch",
		IncludePaths: []string{
			"/path/1",
			"/path/2",
			"/path/3",
		},
		ExcludePaths: []string{
			"/path/4",
			"/path/5",
			"/path/6",
		},
	}
	emptyRepo := Repository{}
	Context("When making revset query fragments", func() {
		It("joins all given paths", func() {
			Expect(unionOfPaths(repo.IncludePaths)).To(Equal("file('re:/path/1')|file('re:/path/2')|file('re:/path/3')"))
		})

		It("produces the correct include fragment", func() {
			Expect(repo.makeIncludeQueryFragment()).To(Equal("file('re:/path/1')|file('re:/path/2')|file('re:/path/3')"))
			Expect(emptyRepo.makeIncludeQueryFragment()).To(Equal("all()"))
		})

		It("produces the correct exclude fragment", func() {
			Expect(repo.makeExcludeQueryFragment()).To(Equal("file('re:/path/4')|file('re:/path/5')|file('re:/path/6')"))
			Expect(emptyRepo.makeExcludeQueryFragment()).To(Equal("not all()"))
		})

	})

	Context("When getting metadata on a commit", func() {
		logResponse := `[
			{
				"rev": 16,
				"node": "f47d10f40bf7a96c2d853c6c6025ba35b6a9c499",
				"branch": "default",
				"phase": "draft",
				"user": "Jane Doe <jdoe@example.com>",
				"date": [1457968493, -32400],
				"desc": "foo",
				"bookmarks": [],
				"tags": ["tip"],
				"parents": ["4484191cd2e41c174ecc2604af06aeb2a21c247f"]
			}
		]`
		var metadata []CommitProperty
		var err error

		BeforeEach(func() {
			metadata, err = parseMetadata([]byte(logResponse))
		})

		It("extracts all expected fields", func() {
			Expect(err).To(BeNil())
			Expect(metadata).To(HaveLen(5))
		})

		It("extracts commit id, author and message", func() {
			Expect(err).To(BeNil())
			Expect(metadata[0].Name).To(Equal("commit"))
			Expect(metadata[0].Value).To(Equal("f47d10f40bf7a96c2d853c6c6025ba35b6a9c499"))

			Expect(metadata[1].Name).To(Equal("author"))
			Expect(metadata[1].Value).To(Equal("Jane Doe <jdoe@example.com>"))

			Expect(metadata[3].Name).To(Equal("message"))
			Expect(metadata[3].Value).To(Equal("foo"))
			Expect(metadata[3].Type).To(Equal("message"))
		})

		It("parses the date correctly", func() {
			// [1457968493, -32400] -> 2016-03-15 00:14:53 +0900
			// note the sign on the offset
			parsedTime, err := parseHgTime([]int64{1457968493, -32400})

			Expect(err).To(BeNil())

			year, month, day := parsedTime.Date()
			Expect(year).To(Equal(2016))
			Expect(month).To(Equal(time.Month(3)))
			Expect(day).To(Equal(15))

			hour, min, second := parsedTime.Clock()
			Expect(hour).To(Equal(0))
			Expect(min).To(Equal(14))
			Expect(second).To(Equal(53))

			_, offset := parsedTime.Zone()
			Expect(offset).To(Equal(32400))
		})

		It("parses the date and formats it in the expected ISO 8601 format", func() {
			Expect(err).To(BeNil())
			Expect(metadata[2].Name).To(Equal("author_date"))
			Expect(metadata[2].Value).To(Equal("2016-03-15 00:14:53 +0900"))
			Expect(metadata[2].Type).To(Equal("time"))
		})

		It("lists all tags of the commit", func() {
			Expect(err).To(BeNil())
			Expect(metadata[4].Name).To(Equal("tags"))
			Expect(metadata[4].Value).To(Equal("tip"))
		})
	})
})
<|endoftext|>


<commit_before>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

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

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

package main

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"

	"github.com/nickvanw/ircx"
	"github.com/sorcix/irc"
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
)

func getURL(s ircx.Sender, message *irc.Message, word string) {
	if url, err := url.Parse(word); err == nil && strings.HasPrefix(url.Scheme, "http") {
		resp, err := http.Head(url.String())
		if err == nil {
			resp.Body.Close()
			if resp.StatusCode == 200 && strings.Contains(resp.Header.Get("content-type"), "text/html") && resp.ContentLength < 1024*1024 {
				resp2, err2 := http.Get(url.String())
				if err2 == nil {
					defer resp2.Body.Close()
					if resp.StatusCode == 200 && strings.Contains(resp.Header.Get("content-type"), "text/html") {
						z := html.NewTokenizer(resp2.Body)
						for {
							tt := z.Next()
							if tt == html.ErrorToken {
								return
							}
							if tt == html.StartTagToken && z.Token().DataAtom == atom.Title {
								tt = z.Next()
								if tt == html.TextToken {
									p := message.Params
									if p[0] == config.General.Name {
										p = []string{message.Prefix.Name}
									}

									title := fmt.Sprintf("Title: %s", z.Token().Data)

									log.Println("Sending HTML", title)
									s.Send(&irc.Message{
										Command:  irc.PRIVMSG,
										Params:   p,
										Trailing: title,
									})
								}
								return
							}

						}
					}
				}
			}
		}
	}
}

func GetTitle(s ircx.Sender, message *irc.Message) {
	words := strings.Split(message.Trailing, " ")
	for _, word := range words {
		go getURL(s, message, word)
	}
}
<commit_msg>Clean up title text and use constants for return codes<commit_after>/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

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

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

package main

import (
	"fmt"
	"log"
	"net/http"
	"net/url"
	"strings"

	"github.com/nickvanw/ircx"
	"github.com/sorcix/irc"
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
)

func getURL(s ircx.Sender, message *irc.Message, word string) {
	if url, err := url.Parse(word); err == nil && strings.HasPrefix(url.Scheme, "http") {
		resp, err := http.Head(url.String())
		if err == nil {
			resp.Body.Close()
			if resp.StatusCode == http.StatusOK && strings.Contains(resp.Header.Get("content-type"), "text/html") && resp.ContentLength < 1024*1024 {
				resp2, err2 := http.Get(url.String())
				if err2 == nil {
					defer resp2.Body.Close()
					if resp.StatusCode == http.StatusOK && strings.Contains(resp.Header.Get("content-type"), "text/html") {
						z := html.NewTokenizer(resp2.Body)
						for {
							tt := z.Next()
							if tt == html.ErrorToken {
								return
							}
							if tt == html.StartTagToken && z.Token().DataAtom == atom.Title {
								tt = z.Next()
								if tt == html.TextToken {
									p := message.Params
									if p[0] == config.General.Name {
										p = []string{message.Prefix.Name}
									}

									title := fmt.Sprintf("Title: %s", strings.TrimSpace(strings.Replace(z.Token().Data, "\n", "", -1)))

									log.Println("Sending HTML", title)
									s.Send(&irc.Message{
										Command:  irc.PRIVMSG,
										Params:   p,
										Trailing: title,
									})
								}
								return
							}

						}
					}
				}
			}
		}
	}
}

func GetTitle(s ircx.Sender, message *irc.Message) {
	words := strings.Split(message.Trailing, " ")
	for _, word := range words {
		go getURL(s, message, word)
	}
}
<|endoftext|>


<commit_before>package http

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"regexp"
	"strings"

	"github.com/Tecsisa/foulkon/api"
	"github.com/Tecsisa/foulkon/foulkon"
	"github.com/julienschmidt/httprouter"
	"github.com/satori/go.uuid"
)

const (
	// Proxy error codes
	INVALID_DEST_HOST_URL = "InvalidDestinationHostURL"
	HOST_UNREACHABLE      = "HostUnreachableError"
	INTERNAL_SERVER_ERROR = "InternalServerError"
	FORBIDDEN_ERROR       = "ForbiddenError"
)

var rUrnParam, _ = regexp.Compile(`\{(\w+)\}`)

func (h *ProxyHandler) HandleRequest(resource foulkon.APIResource) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		requestID := uuid.NewV4().String()
		w.Header().Set(REQUEST_ID_HEADER, requestID)
		// Retrieve parameters to replace in URN
		parameters := getUrnParameters(resource.Urn)
		urn := resource.Urn
		for _, p := range parameters {
			urn = strings.Replace(urn, p[0], ps.ByName(p[1]), -1)
		}
		if workerRequestID, err := h.checkAuthorization(r, urn, resource.Action); err == nil {
			destURL, err := url.Parse(resource.Host)
			if err != nil {
				h.TransactionErrorLog(r, requestID, workerRequestID, fmt.Sprintf("Error creating destination host URL: %v", err.Error()))
				h.RespondInternalServerError(w, getErrorMessage(INVALID_DEST_HOST_URL, "Invalid destination host"))
				return
			}
			r.URL.Host = destURL.Host
			r.URL.Scheme = destURL.Scheme
			// Clean request URI because net/http send method force this
			r.RequestURI = ""
			// Retrieve requested resource
			res, err := h.client.Do(r)
			if err != nil {
				h.TransactionErrorLog(r, requestID, workerRequestID, fmt.Sprintf("Error calling to destination host resource: %v", err.Error()))
				h.RespondInternalServerError(w, getErrorMessage(HOST_UNREACHABLE, "Error calling destination resource"))
				return
			}

			// Copy the response cookies
			for _, cookie := range res.Cookies() {
				http.SetCookie(w, cookie)
			}
			// Copy the response headers from the target server to the proxy response
			for key, values := range res.Header {
				for _, v := range values {
					w.Header().Add(key, v)
				}
			}

			buffer := new(bytes.Buffer)
			if _, err := buffer.ReadFrom(res.Body); err != nil {
				h.TransactionErrorLog(r, requestID, workerRequestID, fmt.Sprintf("Error reading response from destination: %v", err.Error()))
				h.RespondInternalServerError(w, getErrorMessage(INTERNAL_SERVER_ERROR, "Error reading response from destination"))
				return
			}
			w.Write(buffer.Bytes())
			h.TransactionLog(r, requestID, workerRequestID, "Request accepted")
		} else {
			h.TransactionErrorLog(r, requestID, workerRequestID, fmt.Sprintf("Error in authorization: %v", err.Error()))
			apiError := err.(*api.Error)
			switch apiError.Code {
			case FORBIDDEN_ERROR:
				h.RespondForbidden(w, getErrorMessage(FORBIDDEN_ERROR, ""))
			case api.INVALID_PARAMETER_ERROR, api.REGEX_NO_MATCH:
				h.RespondBadRequest(w, getErrorMessage(api.INVALID_PARAMETER_ERROR, "Bad request"))
			default:
				h.RespondInternalServerError(w, getErrorMessage(INTERNAL_SERVER_ERROR, "Internal server error. Contact the administrator"))
			}
			return
		}
	}
}

func (h *ProxyHandler) checkAuthorization(r *http.Request, urn string, action string) (string, error) {
	workerRequestID := "None"
	if !isFullUrn(urn) {
		return workerRequestID,
			getErrorMessage(api.INVALID_PARAMETER_ERROR, fmt.Sprintf("Urn %v is a prefix, it would be a full urn resource", urn))
	}
	if err := api.AreValidResources([]string{urn}); err != nil {
		return workerRequestID, err
	}
	if err := api.AreValidActions([]string{action}); err != nil {
		return workerRequestID, err
	}

	body, err := json.Marshal(AuthorizeResourcesRequest{
		Action:    action,
		Resources: []string{urn},
	})
	if err != nil {
		return workerRequestID, getErrorMessage(api.UNKNOWN_API_ERROR, err.Error())
	}

	req, err := http.NewRequest(http.MethodPost, h.proxy.WorkerHost+RESOURCE_URL, bytes.NewBuffer(body))
	if err != nil {
		return workerRequestID, getErrorMessage(api.UNKNOWN_API_ERROR, err.Error())
	}
	// Add all headers from original request
	req.Header = r.Header
	// Call worker to retrieve authorization
	res, err := h.client.Do(req)
	if err != nil {
		return workerRequestID, getErrorMessage(HOST_UNREACHABLE, err.Error())
	}

	workerRequestID = res.Header.Get(REQUEST_ID_HEADER)

	switch res.StatusCode {
	case http.StatusUnauthorized:
		return workerRequestID, getErrorMessage(FORBIDDEN_ERROR, "Unauthenticated user")
	case http.StatusForbidden:
		return workerRequestID, getErrorMessage(FORBIDDEN_ERROR, fmt.Sprintf("Restricted access to urn %v", urn))
	case http.StatusOK:
		authzResponse := AuthorizeResourcesResponse{}
		err = json.NewDecoder(res.Body).Decode(&authzResponse)
		if err != nil {
			return workerRequestID, getErrorMessage(api.UNKNOWN_API_ERROR, fmt.Sprintf("Error parsing foulkon response %v", err.Error()))
		}

		// Check urns allowed to find target urn
		allowed := false
		for _, allowedRes := range authzResponse.ResourcesAllowed {
			if allowedRes == urn {
				allowed = true
				break
			}
		}

		if !allowed {
			return workerRequestID,
				getErrorMessage(FORBIDDEN_ERROR, fmt.Sprintf("No access for urn %v received from server", urn))
		}

		return workerRequestID, nil
	default:
		return workerRequestID,
			getErrorMessage(INTERNAL_SERVER_ERROR, fmt.Sprintf("There was a problem retrieving authorization, status code %v", res.StatusCode))
	}
}

// Check parameters in URN to replace with URI parameters
func getUrnParameters(urn string) [][]string {
	match := rUrnParam.FindAllStringSubmatch(urn, -1)
	if match != nil && len(match) > 0 {
		return match
	}
	return nil
}

func isFullUrn(resource string) bool {
	return !strings.ContainsAny(resource, "*")
}

func getErrorMessage(errorCode string, message string) *api.Error {
	if message == "" {
		return &api.Error{
			Code:    errorCode,
			Message: "Forbidden resource. If you need access, contact the administrator",
		}
	}
	return &api.Error{
		Code:    errorCode,
		Message: message,
	}
}
<commit_msg>Fix proxy response code (closes #14)<commit_after>package http

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"regexp"
	"strings"

	"github.com/Tecsisa/foulkon/api"
	"github.com/Tecsisa/foulkon/foulkon"
	"github.com/julienschmidt/httprouter"
	"github.com/satori/go.uuid"
)

const (
	// Proxy error codes
	INVALID_DEST_HOST_URL = "InvalidDestinationHostURL"
	HOST_UNREACHABLE      = "HostUnreachableError"
	INTERNAL_SERVER_ERROR = "InternalServerError"
	FORBIDDEN_ERROR       = "ForbiddenError"
)

var rUrnParam, _ = regexp.Compile(`\{(\w+)\}`)

func (h *ProxyHandler) HandleRequest(resource foulkon.APIResource) httprouter.Handle {
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
		requestID := uuid.NewV4().String()
		w.Header().Set(REQUEST_ID_HEADER, requestID)
		// Retrieve parameters to replace in URN
		parameters := getUrnParameters(resource.Urn)
		urn := resource.Urn
		for _, p := range parameters {
			urn = strings.Replace(urn, p[0], ps.ByName(p[1]), -1)
		}
		if workerRequestID, err := h.checkAuthorization(r, urn, resource.Action); err == nil {
			destURL, err := url.Parse(resource.Host)
			if err != nil {
				h.TransactionErrorLog(r, requestID, workerRequestID, fmt.Sprintf("Error creating destination host URL: %v", err.Error()))
				h.RespondInternalServerError(w, getErrorMessage(INVALID_DEST_HOST_URL, "Invalid destination host"))
				return
			}
			r.URL.Host = destURL.Host
			r.URL.Scheme = destURL.Scheme
			// Clean request URI because net/http send method force this
			r.RequestURI = ""
			// Retrieve requested resource
			res, err := h.client.Do(r)
			if err != nil {
				h.TransactionErrorLog(r, requestID, workerRequestID, fmt.Sprintf("Error calling to destination host resource: %v", err.Error()))
				h.RespondInternalServerError(w, getErrorMessage(HOST_UNREACHABLE, "Error calling destination resource"))
				return
			}

			// Copy the response cookies
			for _, cookie := range res.Cookies() {
				http.SetCookie(w, cookie)
			}
			// Copy the response headers from the target server to the proxy response
			for key, values := range res.Header {
				for _, v := range values {
					w.Header().Add(key, v)
				}
			}

			buffer := new(bytes.Buffer)
			if _, err := buffer.ReadFrom(res.Body); err != nil {
				h.TransactionErrorLog(r, requestID, workerRequestID, fmt.Sprintf("Error reading response from destination: %v", err.Error()))
				h.RespondInternalServerError(w, getErrorMessage(INTERNAL_SERVER_ERROR, "Error reading response from destination"))
				return
			}
			w.WriteHeader(res.StatusCode)
			w.Write(buffer.Bytes())
			h.TransactionLog(r, requestID, workerRequestID, "Request accepted")
		} else {
			h.TransactionErrorLog(r, requestID, workerRequestID, fmt.Sprintf("Error in authorization: %v", err.Error()))
			apiError := err.(*api.Error)
			switch apiError.Code {
			case FORBIDDEN_ERROR:
				h.RespondForbidden(w, getErrorMessage(FORBIDDEN_ERROR, ""))
			case api.INVALID_PARAMETER_ERROR, api.REGEX_NO_MATCH:
				h.RespondBadRequest(w, getErrorMessage(api.INVALID_PARAMETER_ERROR, "Bad request"))
			default:
				h.RespondInternalServerError(w, getErrorMessage(INTERNAL_SERVER_ERROR, "Internal server error. Contact the administrator"))
			}
			return
		}
	}
}

func (h *ProxyHandler) checkAuthorization(r *http.Request, urn string, action string) (string, error) {
	workerRequestID := "None"
	if !isFullUrn(urn) {
		return workerRequestID,
			getErrorMessage(api.INVALID_PARAMETER_ERROR, fmt.Sprintf("Urn %v is a prefix, it would be a full urn resource", urn))
	}
	if err := api.AreValidResources([]string{urn}); err != nil {
		return workerRequestID, err
	}
	if err := api.AreValidActions([]string{action}); err != nil {
		return workerRequestID, err
	}

	body, err := json.Marshal(AuthorizeResourcesRequest{
		Action:    action,
		Resources: []string{urn},
	})
	if err != nil {
		return workerRequestID, getErrorMessage(api.UNKNOWN_API_ERROR, err.Error())
	}

	req, err := http.NewRequest(http.MethodPost, h.proxy.WorkerHost+RESOURCE_URL, bytes.NewBuffer(body))
	if err != nil {
		return workerRequestID, getErrorMessage(api.UNKNOWN_API_ERROR, err.Error())
	}
	// Add all headers from original request
	req.Header = r.Header
	// Call worker to retrieve authorization
	res, err := h.client.Do(req)
	if err != nil {
		return workerRequestID, getErrorMessage(HOST_UNREACHABLE, err.Error())
	}

	workerRequestID = res.Header.Get(REQUEST_ID_HEADER)

	switch res.StatusCode {
	case http.StatusUnauthorized:
		return workerRequestID, getErrorMessage(FORBIDDEN_ERROR, "Unauthenticated user")
	case http.StatusForbidden:
		return workerRequestID, getErrorMessage(FORBIDDEN_ERROR, fmt.Sprintf("Restricted access to urn %v", urn))
	case http.StatusOK:
		authzResponse := AuthorizeResourcesResponse{}
		err = json.NewDecoder(res.Body).Decode(&authzResponse)
		if err != nil {
			return workerRequestID, getErrorMessage(api.UNKNOWN_API_ERROR, fmt.Sprintf("Error parsing foulkon response %v", err.Error()))
		}

		// Check urns allowed to find target urn
		allowed := false
		for _, allowedRes := range authzResponse.ResourcesAllowed {
			if allowedRes == urn {
				allowed = true
				break
			}
		}

		if !allowed {
			return workerRequestID,
				getErrorMessage(FORBIDDEN_ERROR, fmt.Sprintf("No access for urn %v received from server", urn))
		}

		return workerRequestID, nil
	default:
		return workerRequestID,
			getErrorMessage(INTERNAL_SERVER_ERROR, fmt.Sprintf("There was a problem retrieving authorization, status code %v", res.StatusCode))
	}
}

// Check parameters in URN to replace with URI parameters
func getUrnParameters(urn string) [][]string {
	match := rUrnParam.FindAllStringSubmatch(urn, -1)
	if match != nil && len(match) > 0 {
		return match
	}
	return nil
}

func isFullUrn(resource string) bool {
	return !strings.ContainsAny(resource, "*")
}

func getErrorMessage(errorCode string, message string) *api.Error {
	if message == "" {
		return &api.Error{
			Code:    errorCode,
			Message: "Forbidden resource. If you need access, contact the administrator",
		}
	}
	return &api.Error{
		Code:    errorCode,
		Message: message,
	}
}
<|endoftext|>


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

import (
	"os"
	log "github.com/Sirupsen/logrus"
	"github.com/megamsys/megdc/packages/megam"
	"github.com/megamsys/megdc/packages/config"
	"github.com/megamsys/megdc/packages/one"
	"github.com/megamsys/megdc/packages/onehost"
	"github.com/megamsys/megdc/packages/ceph"
	"github.com/megamsys/megdc/packages/mesos"
	"github.com/megamsys/libgo/cmd"
)

// These variables are populated via the Go linker.
var (
	version string = "0.9"
	commit  string = "01"
	branch  string = "master"
	header  string = "Supported-Megdc"
	date    string
)

func init() {
	// Only log the debug or above
  log.SetLevel(log.DebugLevel)  // level is configurable via cli option.
	// Output to stderr instead of stdout, could also be a file.
  log.SetOutput(os.Stdout)
}

// Only log debug level when the -v flag is passed.
func cmdRegistry(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version+"  "+date, nil, func(modelvl int) {
		if modelvl >= 1 {
			log.SetLevel(log.DebugLevel)
		}
	})
	m.Register(&megam.VerticeInstall{})
	m.Register(&megam.Megamremove{})
	m.Register(&megam.Megamreport{})
	m.Register(&config.VerticeConf{})
	m.Register(&one.Oneinstall{})
	m.Register(&one.Oneremove{})
	m.Register(&onehost.Onehostinstall{})
	m.Register(&onehost.Onehostremove{})
	m.Register(&ceph.Cephremove{})
	m.Register(&ceph.Cephdatastore{})
	m.Register(&onehost.Createnetwork{})
	m.Register(&onehost.Sshpass{})
	m.Register(&ceph.Cephinstall{})
	m.Register(&ceph.Cephgateway{})
	m.Register(&mesos.MesosMasterInstall{})
	m.Register(&mesos.MesosSlaveInstall{})
	return m
}

//Run the commands from cli.
func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := cmdRegistry(name)
	manager.Run(os.Args[1:])
}
<commit_msg>config command hide<commit_after>/*
** Copyright [2013-2015] [Megam Systems]
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
 */
package main

import (
	"os"
	log "github.com/Sirupsen/logrus"
	"github.com/megamsys/megdc/packages/megam"
	"github.com/megamsys/megdc/packages/config"
	"github.com/megamsys/megdc/packages/one"
	"github.com/megamsys/megdc/packages/onehost"
	"github.com/megamsys/megdc/packages/ceph"
	"github.com/megamsys/megdc/packages/mesos"
	"github.com/megamsys/libgo/cmd"
)

// These variables are populated via the Go linker.
var (
	version string = "0.9"
	commit  string = "01"
	branch  string = "master"
	header  string = "Supported-Megdc"
	date    string
)

func init() {
	// Only log the debug or above
  log.SetLevel(log.DebugLevel)  // level is configurable via cli option.
	// Output to stderr instead of stdout, could also be a file.
  log.SetOutput(os.Stdout)
}

// Only log debug level when the -v flag is passed.
func cmdRegistry(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version+"  "+date, nil, func(modelvl int) {
		if modelvl >= 1 {
			log.SetLevel(log.DebugLevel)
		}
	})
	m.Register(&megam.VerticeInstall{})
	m.Register(&megam.Megamremove{})
	m.Register(&megam.Megamreport{})
	//m.Register(&config.VerticeConf{})
	m.Register(&one.Oneinstall{})
	m.Register(&one.Oneremove{})
	m.Register(&onehost.Onehostinstall{})
	m.Register(&onehost.Onehostremove{})
	m.Register(&ceph.Cephremove{})
	m.Register(&ceph.Cephdatastore{})
	m.Register(&onehost.Createnetwork{})
	m.Register(&onehost.Sshpass{})
	m.Register(&ceph.Cephinstall{})
	m.Register(&ceph.Cephgateway{})
	m.Register(&mesos.MesosMasterInstall{})
	m.Register(&mesos.MesosSlaveInstall{})
	return m
}

//Run the commands from cli.
func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := cmdRegistry(name)
	manager.Run(os.Args[1:])
}
<|endoftext|>


<commit_before><commit_msg>panic: add reference to _TracebackMaxFrames<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package main

import (
	"bytes"
	"context"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"github.com/pkg/diff"
	"golang.org/x/crypto/ssh/terminal"
	"mvdan.cc/editorconfig"

	"mvdan.cc/sh/v3/fileutil"
	"mvdan.cc/sh/v3/syntax"
)

var (
	showVersion = flag.Bool("version", false, "")

	list    = flag.Bool("l", false, "")
	write   = flag.Bool("w", false, "")
	simple  = flag.Bool("s", false, "")
	minify  = flag.Bool("mn", false, "")
	find    = flag.Bool("f", false, "")
	diffOut = flag.Bool("d", false, "")

	// useEditorConfig will be false if any parser or printer flags were used.
	useEditorConfig = true

	langStr = flag.String("ln", "", "")
	posix   = flag.Bool("p", false, "")

	indent      = flag.Uint("i", 0, "")
	binNext     = flag.Bool("bn", false, "")
	caseIndent  = flag.Bool("ci", false, "")
	spaceRedirs = flag.Bool("sr", false, "")
	keepPadding = flag.Bool("kp", false, "")

	toJSON = flag.Bool("tojson", false, "")

	parser            *syntax.Parser
	printer           *syntax.Printer
	readBuf, writeBuf bytes.Buffer

	copyBuf = make([]byte, 32*1024)

	in    io.Reader = os.Stdin
	out   io.Writer = os.Stdout
	color bool

	version = "v3.0.0-beta1"
)

func main() {
	os.Exit(main1())
}

func main1() int {
	flag.Usage = func() {
		fmt.Fprint(os.Stderr, `usage: shfmt [flags] [path ...]

If no arguments are given, standard input will be used. If a given path
is a directory, it will be recursively searched for shell files - both
by filename extension and by shebang.

  -version  show version and exit

  -l        list files whose formatting differs from shfmt's
  -w        write result to file instead of stdout
  -d        error with a diff when the formatting differs
  -s        simplify the code
  -mn       minify the code to reduce its size (implies -s)

Parser options:

  -ln str   language variant to parse (bash/posix/mksh, default "bash")
  -p        shorthand for -ln=posix

Printer options:

  -i uint   indent: 0 for tabs (default), >0 for number of spaces
  -bn       binary ops like && and | may start a line
  -ci       switch cases will be indented
  -sr       redirect operators will be followed by a space
  -kp       keep column alignment paddings

Utilities:

  -f        recursively find all shell files and print the paths
  -tojson   print syntax tree to stdout as a typed JSON
`)
	}
	flag.Parse()

	if *showVersion {
		fmt.Println(version)
		return 0
	}
	if *posix && *langStr != "" {
		fmt.Fprintf(os.Stderr, "-p and -ln=lang cannot coexist\n")
		return 1
	}
	if *minify {
		*simple = true
	}
	if os.Getenv("SHFMT_NO_EDITORCONFIG") == "true" {
		useEditorConfig = false
	}
	flag.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "ln", "p", "i", "bn", "ci", "sr", "kp":
			useEditorConfig = false
		}
	})
	parser = syntax.NewParser(syntax.KeepComments(true))
	printer = syntax.NewPrinter(syntax.Minify(*minify))

	lang := syntax.LangBash
	if !useEditorConfig {
		switch *langStr {
		case "bash", "":
		case "posix":
			lang = syntax.LangPOSIX
		case "mksh":
			lang = syntax.LangMirBSDKorn
		default:
			fmt.Fprintf(os.Stderr, "unknown shell language: %s\n", *langStr)
			return 1
		}
		if *posix {
			lang = syntax.LangPOSIX
		}
		syntax.Variant(lang)(parser)

		syntax.Indent(*indent)(printer)
		syntax.BinaryNextLine(*binNext)(printer)
		syntax.SwitchCaseIndent(*caseIndent)(printer)
		syntax.SpaceRedirects(*spaceRedirs)(printer)
		syntax.KeepPadding(*keepPadding)(printer)
	}

	if os.Getenv("FORCE_COLOR") == "true" {
		// Undocumented way to force color; used in the tests.
		color = true
	} else if os.Getenv("TERM") == "dumb" {
		// Equivalent to forcing color to be turned off.
	} else if f, ok := out.(*os.File); ok && terminal.IsTerminal(int(f.Fd())) {
		color = true
	}
	if flag.NArg() == 0 {
		if err := formatStdin(); err != nil {
			if err != errChangedWithDiff {
				fmt.Fprintln(os.Stderr, err)
			}
			return 1
		}
		return 0
	}
	if *toJSON {
		fmt.Fprintln(os.Stderr, "-tojson can only be used with stdin/out")
		return 1
	}
	status := 0
	for _, path := range flag.Args() {
		walk(path, func(err error) {
			if err != errChangedWithDiff {
				fmt.Fprintln(os.Stderr, err)
			}
			status = 1
		})
	}
	return status
}

var errChangedWithDiff = fmt.Errorf("")

func formatStdin() error {
	if *write {
		return fmt.Errorf("-w cannot be used on standard input")
	}
	src, err := ioutil.ReadAll(in)
	if err != nil {
		return err
	}
	return formatBytes(src, "<standard input>")
}

var vcsDir = regexp.MustCompile(`^\.(git|svn|hg)$`)

func walk(path string, onError func(error)) {
	info, err := os.Stat(path)
	if err != nil {
		onError(err)
		return
	}
	if !info.IsDir() {
		if err := formatPath(path, false); err != nil {
			onError(err)
		}
		return
	}
	filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() && vcsDir.MatchString(info.Name()) {
			return filepath.SkipDir
		}
		if err != nil {
			onError(err)
			return nil
		}
		conf := fileutil.CouldBeScript(info)
		if conf == fileutil.ConfNotScript {
			return nil
		}
		err = formatPath(path, conf == fileutil.ConfIfShebang)
		if err != nil && !os.IsNotExist(err) {
			onError(err)
		}
		return nil
	})
}

var query = editorconfig.Query{
	FileCache:   make(map[string]*editorconfig.File),
	RegexpCache: make(map[string]*regexp.Regexp),
}

func propsOptions(props editorconfig.Section) {
	lang := syntax.LangBash
	switch props.Get("shell_variant") {
	case "posix":
		lang = syntax.LangPOSIX
	case "mksh":
		lang = syntax.LangMirBSDKorn
	}
	syntax.Variant(lang)(parser)

	size := uint(0)
	if props.Get("indent_style") == "space" {
		size = 8
		if n := props.IndentSize(); n > 0 {
			size = uint(n)
		}
	}
	syntax.Indent(size)(printer)

	syntax.BinaryNextLine(props.Get("binary_next_line") == "true")(printer)
	syntax.SwitchCaseIndent(props.Get("switch_case_indent") == "true")(printer)
	syntax.SpaceRedirects(props.Get("space_redirects") == "true")(printer)
	syntax.KeepPadding(props.Get("keep_padding") == "true")(printer)
}

func formatPath(path string, checkShebang bool) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	readBuf.Reset()
	if checkShebang {
		n, err := f.Read(copyBuf[:32])
		if err != nil {
			return err
		}
		if !fileutil.HasShebang(copyBuf[:n]) {
			return nil
		}
		readBuf.Write(copyBuf[:n])
	}
	if *find {
		fmt.Fprintln(out, path)
		return nil
	}
	if _, err := io.CopyBuffer(&readBuf, f, copyBuf); err != nil {
		return err
	}
	f.Close()
	return formatBytes(readBuf.Bytes(), path)
}

func formatBytes(src []byte, path string) error {
	if useEditorConfig {
		props, err := query.Find(path)
		if err != nil {
			return err
		}
		propsOptions(props)
	}
	prog, err := parser.Parse(bytes.NewReader(src), path)
	if err != nil {
		return err
	}
	if *simple {
		syntax.Simplify(prog)
	}
	if *toJSON {
		// must be standard input; fine to return
		return writeJSON(out, prog, true)
	}
	writeBuf.Reset()
	printer.Print(&writeBuf, prog)
	res := writeBuf.Bytes()
	if !bytes.Equal(src, res) {
		if *list {
			if _, err := fmt.Fprintln(out, path); err != nil {
				return err
			}
		}
		if *write {
			f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0)
			if err != nil {
				return err
			}
			if _, err := f.Write(res); err != nil {
				return err
			}
			if err := f.Close(); err != nil {
				return err
			}
		}
		if *diffOut {
			if err := diffBytes(src, res, path); err != nil {
				return fmt.Errorf("computing diff: %s", err)
			}
			return errChangedWithDiff
		}
	}
	if !*list && !*write && !*diffOut {
		if _, err := out.Write(res); err != nil {
			return err
		}
	}
	return nil
}

func diffBytes(b1, b2 []byte, path string) error {
	a := bytes.Split(b1, []byte("\n"))
	b := bytes.Split(b2, []byte("\n"))
	ab := diff.Bytes(a, b)
	e := diff.Myers(context.Background(), ab)
	opts := []diff.WriteOpt{diff.Names(path+".orig", path)}
	if color {
		opts = append(opts, diff.TerminalColor())
	}
	if _, err := e.WriteUnified(out, ab, opts...); err != nil {
		return err
	}
	return nil
}
<commit_msg>all: bump to v3.0.0<commit_after>// Copyright (c) 2016, Daniel Martí <mvdan@mvdan.cc>
// See LICENSE for licensing information

package main

import (
	"bytes"
	"context"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"

	"github.com/pkg/diff"
	"golang.org/x/crypto/ssh/terminal"
	"mvdan.cc/editorconfig"

	"mvdan.cc/sh/v3/fileutil"
	"mvdan.cc/sh/v3/syntax"
)

var (
	showVersion = flag.Bool("version", false, "")

	list    = flag.Bool("l", false, "")
	write   = flag.Bool("w", false, "")
	simple  = flag.Bool("s", false, "")
	minify  = flag.Bool("mn", false, "")
	find    = flag.Bool("f", false, "")
	diffOut = flag.Bool("d", false, "")

	// useEditorConfig will be false if any parser or printer flags were used.
	useEditorConfig = true

	langStr = flag.String("ln", "", "")
	posix   = flag.Bool("p", false, "")

	indent      = flag.Uint("i", 0, "")
	binNext     = flag.Bool("bn", false, "")
	caseIndent  = flag.Bool("ci", false, "")
	spaceRedirs = flag.Bool("sr", false, "")
	keepPadding = flag.Bool("kp", false, "")

	toJSON = flag.Bool("tojson", false, "")

	parser            *syntax.Parser
	printer           *syntax.Printer
	readBuf, writeBuf bytes.Buffer

	copyBuf = make([]byte, 32*1024)

	in    io.Reader = os.Stdin
	out   io.Writer = os.Stdout
	color bool

	version = "v3.0.0"
)

func main() {
	os.Exit(main1())
}

func main1() int {
	flag.Usage = func() {
		fmt.Fprint(os.Stderr, `usage: shfmt [flags] [path ...]

If no arguments are given, standard input will be used. If a given path
is a directory, it will be recursively searched for shell files - both
by filename extension and by shebang.

  -version  show version and exit

  -l        list files whose formatting differs from shfmt's
  -w        write result to file instead of stdout
  -d        error with a diff when the formatting differs
  -s        simplify the code
  -mn       minify the code to reduce its size (implies -s)

Parser options:

  -ln str   language variant to parse (bash/posix/mksh, default "bash")
  -p        shorthand for -ln=posix

Printer options:

  -i uint   indent: 0 for tabs (default), >0 for number of spaces
  -bn       binary ops like && and | may start a line
  -ci       switch cases will be indented
  -sr       redirect operators will be followed by a space
  -kp       keep column alignment paddings

Utilities:

  -f        recursively find all shell files and print the paths
  -tojson   print syntax tree to stdout as a typed JSON
`)
	}
	flag.Parse()

	if *showVersion {
		fmt.Println(version)
		return 0
	}
	if *posix && *langStr != "" {
		fmt.Fprintf(os.Stderr, "-p and -ln=lang cannot coexist\n")
		return 1
	}
	if *minify {
		*simple = true
	}
	if os.Getenv("SHFMT_NO_EDITORCONFIG") == "true" {
		useEditorConfig = false
	}
	flag.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "ln", "p", "i", "bn", "ci", "sr", "kp":
			useEditorConfig = false
		}
	})
	parser = syntax.NewParser(syntax.KeepComments(true))
	printer = syntax.NewPrinter(syntax.Minify(*minify))

	lang := syntax.LangBash
	if !useEditorConfig {
		switch *langStr {
		case "bash", "":
		case "posix":
			lang = syntax.LangPOSIX
		case "mksh":
			lang = syntax.LangMirBSDKorn
		default:
			fmt.Fprintf(os.Stderr, "unknown shell language: %s\n", *langStr)
			return 1
		}
		if *posix {
			lang = syntax.LangPOSIX
		}
		syntax.Variant(lang)(parser)

		syntax.Indent(*indent)(printer)
		syntax.BinaryNextLine(*binNext)(printer)
		syntax.SwitchCaseIndent(*caseIndent)(printer)
		syntax.SpaceRedirects(*spaceRedirs)(printer)
		syntax.KeepPadding(*keepPadding)(printer)
	}

	if os.Getenv("FORCE_COLOR") == "true" {
		// Undocumented way to force color; used in the tests.
		color = true
	} else if os.Getenv("TERM") == "dumb" {
		// Equivalent to forcing color to be turned off.
	} else if f, ok := out.(*os.File); ok && terminal.IsTerminal(int(f.Fd())) {
		color = true
	}
	if flag.NArg() == 0 {
		if err := formatStdin(); err != nil {
			if err != errChangedWithDiff {
				fmt.Fprintln(os.Stderr, err)
			}
			return 1
		}
		return 0
	}
	if *toJSON {
		fmt.Fprintln(os.Stderr, "-tojson can only be used with stdin/out")
		return 1
	}
	status := 0
	for _, path := range flag.Args() {
		walk(path, func(err error) {
			if err != errChangedWithDiff {
				fmt.Fprintln(os.Stderr, err)
			}
			status = 1
		})
	}
	return status
}

var errChangedWithDiff = fmt.Errorf("")

func formatStdin() error {
	if *write {
		return fmt.Errorf("-w cannot be used on standard input")
	}
	src, err := ioutil.ReadAll(in)
	if err != nil {
		return err
	}
	return formatBytes(src, "<standard input>")
}

var vcsDir = regexp.MustCompile(`^\.(git|svn|hg)$`)

func walk(path string, onError func(error)) {
	info, err := os.Stat(path)
	if err != nil {
		onError(err)
		return
	}
	if !info.IsDir() {
		if err := formatPath(path, false); err != nil {
			onError(err)
		}
		return
	}
	filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() && vcsDir.MatchString(info.Name()) {
			return filepath.SkipDir
		}
		if err != nil {
			onError(err)
			return nil
		}
		conf := fileutil.CouldBeScript(info)
		if conf == fileutil.ConfNotScript {
			return nil
		}
		err = formatPath(path, conf == fileutil.ConfIfShebang)
		if err != nil && !os.IsNotExist(err) {
			onError(err)
		}
		return nil
	})
}

var query = editorconfig.Query{
	FileCache:   make(map[string]*editorconfig.File),
	RegexpCache: make(map[string]*regexp.Regexp),
}

func propsOptions(props editorconfig.Section) {
	lang := syntax.LangBash
	switch props.Get("shell_variant") {
	case "posix":
		lang = syntax.LangPOSIX
	case "mksh":
		lang = syntax.LangMirBSDKorn
	}
	syntax.Variant(lang)(parser)

	size := uint(0)
	if props.Get("indent_style") == "space" {
		size = 8
		if n := props.IndentSize(); n > 0 {
			size = uint(n)
		}
	}
	syntax.Indent(size)(printer)

	syntax.BinaryNextLine(props.Get("binary_next_line") == "true")(printer)
	syntax.SwitchCaseIndent(props.Get("switch_case_indent") == "true")(printer)
	syntax.SpaceRedirects(props.Get("space_redirects") == "true")(printer)
	syntax.KeepPadding(props.Get("keep_padding") == "true")(printer)
}

func formatPath(path string, checkShebang bool) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	readBuf.Reset()
	if checkShebang {
		n, err := f.Read(copyBuf[:32])
		if err != nil {
			return err
		}
		if !fileutil.HasShebang(copyBuf[:n]) {
			return nil
		}
		readBuf.Write(copyBuf[:n])
	}
	if *find {
		fmt.Fprintln(out, path)
		return nil
	}
	if _, err := io.CopyBuffer(&readBuf, f, copyBuf); err != nil {
		return err
	}
	f.Close()
	return formatBytes(readBuf.Bytes(), path)
}

func formatBytes(src []byte, path string) error {
	if useEditorConfig {
		props, err := query.Find(path)
		if err != nil {
			return err
		}
		propsOptions(props)
	}
	prog, err := parser.Parse(bytes.NewReader(src), path)
	if err != nil {
		return err
	}
	if *simple {
		syntax.Simplify(prog)
	}
	if *toJSON {
		// must be standard input; fine to return
		return writeJSON(out, prog, true)
	}
	writeBuf.Reset()
	printer.Print(&writeBuf, prog)
	res := writeBuf.Bytes()
	if !bytes.Equal(src, res) {
		if *list {
			if _, err := fmt.Fprintln(out, path); err != nil {
				return err
			}
		}
		if *write {
			f, err := os.OpenFile(path, os.O_WRONLY|os.O_TRUNC, 0)
			if err != nil {
				return err
			}
			if _, err := f.Write(res); err != nil {
				return err
			}
			if err := f.Close(); err != nil {
				return err
			}
		}
		if *diffOut {
			if err := diffBytes(src, res, path); err != nil {
				return fmt.Errorf("computing diff: %s", err)
			}
			return errChangedWithDiff
		}
	}
	if !*list && !*write && !*diffOut {
		if _, err := out.Write(res); err != nil {
			return err
		}
	}
	return nil
}

func diffBytes(b1, b2 []byte, path string) error {
	a := bytes.Split(b1, []byte("\n"))
	b := bytes.Split(b2, []byte("\n"))
	ab := diff.Bytes(a, b)
	e := diff.Myers(context.Background(), ab)
	opts := []diff.WriteOpt{diff.Names(path+".orig", path)}
	if color {
		opts = append(opts, diff.TerminalColor())
	}
	if _, err := e.WriteUnified(out, ab, opts...); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package file

/*
The File builder creates an artifact from a file. Because it does not require
any virtualization or network resources, it's very fast and useful for testing.
*/

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"

	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

const BuilderId = "packer.file"

type Builder struct {
	config *Config
	runner multistep.Runner
}

func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
	c, warnings, errs := NewConfig(raws...)
	if errs != nil {
		return warnings, errs
	}
	b.config = c

	return warnings, nil
}

// Run is where the actual build should take place. It takes a Build and a Ui.
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	artifact := new(FileArtifact)

	if b.config.Source != "" {
		source, err := os.Open(b.config.Source)
		defer source.Close()
		if err != nil {
			return nil, err
		}

		// Create will truncate an existing file
		target, err := os.Create(b.config.Target)
		defer target.Close()
		if err != nil {
			return nil, err
		}

		ui.Say(fmt.Sprintf("Copying %s to %s", source.Name(), target.Name()))
		bytes, err := io.Copy(target, source)
		if err != nil {
			return nil, err
		}
		ui.Say(fmt.Sprintf("Copied %d bytes", bytes))
		artifact.filename = target.Name()
	} else {
		// We're going to write Contents; if it's empty we'll just create an
		// empty file.
		err := ioutil.WriteFile(b.config.Target, []byte(b.config.Content), 0600)
		if err != nil {
			return nil, err
		}
		artifact.filename = b.config.Target
	}

	if hook != nil {
		if err := hook.Run(ctx, packer.HookProvision, ui, new(packer.MockCommunicator), nil); err != nil {
			return nil, err
		}
	}

	return artifact, nil
}
<commit_msg>builder/file: defer close after testing for errors<commit_after>package file

/*
The File builder creates an artifact from a file. Because it does not require
any virtualization or network resources, it's very fast and useful for testing.
*/

import (
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"os"

	"github.com/hashicorp/packer/helper/multistep"
	"github.com/hashicorp/packer/packer"
)

const BuilderId = "packer.file"

type Builder struct {
	config *Config
	runner multistep.Runner
}

func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
	c, warnings, errs := NewConfig(raws...)
	if errs != nil {
		return warnings, errs
	}
	b.config = c

	return warnings, nil
}

// Run is where the actual build should take place. It takes a Build and a Ui.
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
	artifact := new(FileArtifact)

	if b.config.Source != "" {
		source, err := os.Open(b.config.Source)
		if err != nil {
			return nil, err
		}
		defer source.Close()

		// Create will truncate an existing file
		target, err := os.Create(b.config.Target)
		if err != nil {
			return nil, err
		}
		defer target.Close()

		ui.Say(fmt.Sprintf("Copying %s to %s", source.Name(), target.Name()))
		bytes, err := io.Copy(target, source)
		if err != nil {
			return nil, err
		}
		ui.Say(fmt.Sprintf("Copied %d bytes", bytes))
		artifact.filename = target.Name()
	} else {
		// We're going to write Contents; if it's empty we'll just create an
		// empty file.
		err := ioutil.WriteFile(b.config.Target, []byte(b.config.Content), 0600)
		if err != nil {
			return nil, err
		}
		artifact.filename = b.config.Target
	}

	if hook != nil {
		if err := hook.Run(ctx, packer.HookProvision, ui, new(packer.MockCommunicator), nil); err != nil {
			return nil, err
		}
	}

	return artifact, nil
}
<|endoftext|>


<commit_before>package main

import "fmt"

type tile struct {
	xCoord int
	yCoord int

	heat			int
	fireLevel int

	wall bool
	door bool

	occupied bool
	personID int

	outOfBounds bool

	neighborNorth *tile
	neighborEast  *tile
	neighborSouth *tile
	neighborWest  *tile
}

/*
func FireSpread(thisTile tile){
	if thisTile.heat > 9 {
		thisTile.fireLevel = 1
	}
	if thisTile.heat > 19 {
		thisTile.fireLevel = 2
	}
	if thisTile.heat > 29 {
		thisTile.fireLevel = 3
	}

	tile.neighborNorth.heat += fireLevel
	tile.neighborEast.heat	+= fireLevel
	tile.neighborWest.heat	+= fireLevel
	tile.neighborSouth.heat += fireLevel

	/*
	tile.neighborNorth.heat += heat/10
	tile.neighborEast.heat += heat/10
	tile.neighborWest.heat += heat/10
	tile.neighborSouth.heat += heat/10
	*/
//}

func assignNeighbor(thisTile *tile, x int, y int, maxX int, maxY int, tileMap [][]tile) {

	if x > 0 {
		//thisTile.neighborWest = &tileMap[x-1][y]
		thisTile.neighborNorth = &tileMap[x-1][y]
	}

	if y > 0 {
		//thisTile.neighborNorth = &tileMap[x][y-1]
		thisTile.neighborWest = &tileMap[x][y-1]
	}

	if x < maxX-1 {
		//thisTile.neighborEast = &tileMap[x+1][y]
		thisTile.neighborSouth = &tileMap[x+1][y]
	}

	if y < maxY-1 {
		//thisTile.neighborSouth = &tileMap[x][y+1]
		thisTile.neighborEast = &tileMap[x][y+1]
	}
}

func makeNewTile(thisPoint int, x int, y int) tile{

	//makes a basic floor tile with no nothin on it
	newTile := tile{x, y, 0, 0, false, false, false, 0, false, nil, nil, nil, nil}

	if thisPoint == 0 {
		//make normal floor
		//helt normalt flour

		//append to tilemap
	} else if thisPoint == 1 {
		//wall
		newTile.wall = true
	} else if thisPoint == 2 {
		//door
		newTile.door = true
	} else if thisPoint == 3 {
		//out of bounds
		newTile.outOfBounds = true
	}

	return newTile
}

func TileConvert(inMap [][]int) [][]tile{
	mapXSize := len(inMap)
	mapYSize := len(inMap[0])

	//Initiates a slice of tile slices (2D tile slice)
	tileMap := make([][]tile, mapXSize)

	for x:= 0; x < mapXSize; x++{
		//initiates slice of tiles
		tileMap[x] = make([]tile, mapYSize)

		for y:= 0; y < mapYSize; y++{
			//constructs a new tile
			newTile := makeNewTile(inMap[x][y], x, y)

			//inserts tile into 2d slice
			tileMap[x][y] = newTile

		}
	}

	//Assigns 4 neighbors to each tile
	for x:= 0; x < mapXSize; x++{
		for y:= 0; y < mapYSize; y++{
			assignNeighbor(&(tileMap[x][y]), x, y, mapXSize, mapYSize, tileMap)
		}
	}

	return tileMap
}

func printTile(thisTile tile) {
	if thisTile.wall {
		fmt.Print("[vägg] ")
	} else if thisTile.door {
		fmt.Print("[dörr] ")
	} else if thisTile.outOfBounds {
		fmt.Print("[ute] ")
	} else {
		fmt.Print("[golv] ")
	}
}

func printTileMap(inMap [][]tile) {
	mapXSize := len(inMap)
	mapYSize := len(inMap[0])

	for x:= 0; x < mapXSize; x++{
		for y:= 0; y < mapYSize; y++{
			printTile(inMap[x][y])
		}
    fmt.Print("\n")
	}
}
func printNeighbors(atile tile) {
		if atile.neighborNorth != nil {
			fmt.Print("North: ")
			printTile(*(atile.neighborNorth))
			fmt.Print("\n")
		} else {
			fmt.Print("North: nil\n")
		}
		if atile.neighborWest != nil {
			fmt.Print("West: ")
			printTile(*(atile.neighborWest))
			fmt.Print("\n")
		} else {
			fmt.Print("West: nil\n")
		}
		if atile.neighborEast != nil {
			fmt.Print("East: ")
			printTile(*(atile.neighborEast))
			fmt.Print("\n")
		} else {
			fmt.Print("East: nil\n")
		}
		if atile.neighborSouth != nil {
			fmt.Print("South: ")
			printTile(*(atile.neighborSouth))
			fmt.Print("\n")
		} else {
			fmt.Print("South: nil\n")
		}
}

func main() {
	testMatrix := [][]int{
		{0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0},
		{1, 1, 0, 1, 1},
		{0, 0, 0, 3, 3},
		{2, 0, 0, 3, 3}}

		amap := TileConvert(testMatrix)
		//tileConvert(testMatrix)
		printTileMap(amap)
		fmt.Print("\n")
		printNeighbors(amap[4][4])

}
<commit_msg>can now print fireLevel<commit_after>package main

import "fmt"

type tile struct {
	xCoord int
	yCoord int

	heat			int
	fireLevel int

	wall bool
	door bool

	occupied bool
	personID int

	outOfBounds bool

	neighborNorth *tile
	neighborEast  *tile
	neighborSouth *tile
	neighborWest  *tile
}

func FireSpread(thisTile tile){
	if thisTile.heat > 9 {
		thisTile.fireLevel = 1
	}
	if thisTile.heat > 19 {
		thisTile.fireLevel = 2
	}
	if thisTile.heat > 29 {
		thisTile.fireLevel = 3
	}

	(thisTile.neighborNorth.heat) += thisTile.fireLevel
	(thisTile.neighborEast.heat)	+= thisTile.fireLevel
	(thisTile.neighborWest.heat)	+= thisTile.fireLevel
	(thisTile.neighborSouth.heat) += thisTile.fireLevel
}

func assignNeighbor(thisTile *tile, x int, y int, maxX int, maxY int, tileMap [][]tile) {

	if x > 0 {
		//thisTile.neighborWest = &tileMap[x-1][y]
		thisTile.neighborNorth = &tileMap[x-1][y]
	}

	if y > 0 {
		//thisTile.neighborNorth = &tileMap[x][y-1]
		thisTile.neighborWest = &tileMap[x][y-1]
	}

	if x < maxX-1 {
		//thisTile.neighborEast = &tileMap[x+1][y]
		thisTile.neighborSouth = &tileMap[x+1][y]
	}

	if y < maxY-1 {
		//thisTile.neighborSouth = &tileMap[x][y+1]
		thisTile.neighborEast = &tileMap[x][y+1]
	}
}

func makeNewTile(thisPoint int, x int, y int) tile{

	//makes a basic floor tile with no nothin on it
	newTile := tile{x, y, 0, 0, false, false, false, 0, false, nil, nil, nil, nil}

	if thisPoint == 0 {
		//make normal floor
		//helt normalt flour

		//append to tilemap
	} else if thisPoint == 1 {
		//wall
		newTile.wall = true
	} else if thisPoint == 2 {
		//door
		newTile.door = true
	} else if thisPoint == 3 {
		//out of bounds
		newTile.outOfBounds = true
	}

	return newTile
}

func TileConvert(inMap [][]int) [][]tile{
	mapXSize := len(inMap)
	mapYSize := len(inMap[0])

	//Initiates a slice of tile slices (2D tile slice)
	tileMap := make([][]tile, mapXSize)

	for x:= 0; x < mapXSize; x++{
		//initiates slice of tiles
		tileMap[x] = make([]tile, mapYSize)

		for y:= 0; y < mapYSize; y++{
			//constructs a new tile
			newTile := makeNewTile(inMap[x][y], x, y)

			//inserts tile into 2d slice
			tileMap[x][y] = newTile

		}
	}

	//Assigns 4 neighbors to each tile
	for x:= 0; x < mapXSize; x++{
		for y:= 0; y < mapYSize; y++{
			assignNeighbor(&(tileMap[x][y]), x, y, mapXSize, mapYSize, tileMap)
		}
	}

	return tileMap
}

func printTile(thisTile tile) {
	if thisTile.wall {
		fmt.Print("[vägg(")
	} else if thisTile.door {
		fmt.Print("[dörr(")
	} else if thisTile.outOfBounds {
		fmt.Print("[ute(")
	} else {
		fmt.Print("[golv(")
	}
		fmt.Print(thisTile.fireLevel)

		fmt.Print(")] ")
}

func printTileMap(inMap [][]tile) {
	mapXSize := len(inMap)
	mapYSize := len(inMap[0])

	for x:= 0; x < mapXSize; x++{
		for y:= 0; y < mapYSize; y++{
			printTile(inMap[x][y])
		}
    fmt.Print("\n")
	}
}
func printNeighbors(atile tile) {
		if atile.neighborNorth != nil {
			fmt.Print("North: ")
			printTile(*(atile.neighborNorth))
			fmt.Print("\n")
		} else {
			fmt.Print("North: nil\n")
		}
		if atile.neighborWest != nil {
			fmt.Print("West: ")
			printTile(*(atile.neighborWest))
			fmt.Print("\n")
		} else {
			fmt.Print("West: nil\n")
		}
		if atile.neighborEast != nil {
			fmt.Print("East: ")
			printTile(*(atile.neighborEast))
			fmt.Print("\n")
		} else {
			fmt.Print("East: nil\n")
		}
		if atile.neighborSouth != nil {
			fmt.Print("South: ")
			printTile(*(atile.neighborSouth))
			fmt.Print("\n")
		} else {
			fmt.Print("South: nil\n")
		}
}

func main() {
	testMatrix := [][]int{
		{0, 0, 0, 0, 0},
		{0, 0, 0, 0, 0},
		{1, 1, 0, 1, 1},
		{0, 0, 0, 3, 3},
		{2, 0, 0, 3, 3}}

		amap := TileConvert(testMatrix)
		//tileConvert(testMatrix)
		printTileMap(amap)
		fmt.Print("\n")
		printNeighbors(amap[4][4])
}
<|endoftext|>


<commit_before>package accesstoken

import (
	"context"
	"os"
	"strings"
	"testing"

	dbm "github.com/tendermint/tmlibs/db"

	"github.com/bytom/errors"
)

func TestCreate(t *testing.T) {
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)
	ctx := context.Background()

	cases := []struct {
		id, typ string
		want    error
	}{
		{"a", "client", nil},
		{"b", "network", nil},
		{"", "client", ErrBadID},
		{"bad:id", "client", ErrBadID},
		{"a", "network", ErrDuplicateID}, // this aborts the transaction, so no tests can follow
	}

	for _, c := range cases {
		_, err := cs.Create(ctx, c.id, c.typ)
		if errors.Root(err) != c.want {
			t.Errorf("Create(%s, %s) error = %s want %s", c.id, c.typ, err, c.want)
		}
	}
}

func TestList(t *testing.T) {
	ctx := context.Background()
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)

	mustCreateToken(ctx, t, cs, "ab", "test")
	mustCreateToken(ctx, t, cs, "bc", "test")
	mustCreateToken(ctx, t, cs, "cd", "test")

	cases := struct {
		want []string
	}{
		want: []string{"ab", "bc", "cd"},
	}

	got, err := cs.List(ctx)
	if err != nil {
		t.Errorf("List errored: get list error")
	}
	for i, v := range got {
		if m := strings.Compare(v.ID, cases.want[i]); m != 0 {
			t.Errorf("List errored: %s %s", v.ID, cases.want[i])
		}
		continue
	}
}

func TestCheck(t *testing.T) {
	ctx := context.Background()
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)

	token := mustCreateToken(ctx, t, cs, "x", "client")
	tokenParts := strings.Split(*token, ":")

	valid, err := cs.Check(ctx, tokenParts[0], tokenParts[1])
	if err != nil {
		t.Fatal(err)
	}
	if !valid {
		t.Fatal("expected token and secret to be valid")
	}

	valid, err = cs.Check(ctx, "x", "badsecret")
	if err != nil {
		t.Fatal(err)
	}
	if valid {
		t.Fatal("expected bad secret to not be valid")
	}
}

func TestDelete(t *testing.T) {
	ctx := context.Background()
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)

	const id = "Y"
	mustCreateToken(ctx, t, cs, id, "client")

	err := cs.Delete(ctx, id)
	if err != nil {
		t.Fatal(err)
	}

	value := cs.DB.Get([]byte(id))
	if len(value) > 0 {
		t.Fatal("delete fail")
	}
}

func TestDeleteWithInvalidId(t *testing.T) {
	ctx := context.Background()
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)

	err := cs.Delete(ctx, "@")
	if errors.Root(err) != ErrBadID {
		t.Errorf("Deletion with invalid id success, while it should not")
	}
}

func mustCreateToken(ctx context.Context, t *testing.T, cs *CredentialStore, id, typ string) *string {
	token, err := cs.Create(ctx, id, typ)
	if err != nil {
		t.Fatal(err)
	}
	return token
}
<commit_msg>improve accesstoken list test<commit_after>package accesstoken

import (
	"context"
	"os"
	"strings"
	"testing"

	dbm "github.com/tendermint/tmlibs/db"

	"github.com/bytom/errors"
)

func TestCreate(t *testing.T) {
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)
	ctx := context.Background()

	cases := []struct {
		id, typ string
		want    error
	}{
		{"a", "client", nil},
		{"b", "network", nil},
		{"", "client", ErrBadID},
		{"bad:id", "client", ErrBadID},
		{"a", "network", ErrDuplicateID}, // this aborts the transaction, so no tests can follow
	}

	for _, c := range cases {
		_, err := cs.Create(ctx, c.id, c.typ)
		if errors.Root(err) != c.want {
			t.Errorf("Create(%s, %s) error = %s want %s", c.id, c.typ, err, c.want)
		}
	}
}

func TestList(t *testing.T) {
	ctx := context.Background()
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)

	tokenMap := make(map[string]*string)
	tokenMap["ab"] = mustCreateToken(ctx, t, cs, "ab", "test")
	tokenMap["bc"] = mustCreateToken(ctx, t, cs, "bc", "test")
	tokenMap["cd"] = mustCreateToken(ctx, t, cs, "cd", "test")

	got, err := cs.List(ctx)
	if err != nil {
		t.Errorf("List errored: get list error")
	}

	if len(got) != len(tokenMap) {
		t.Error("List errored: get invalid length")
	}
	for _, v := range got {
		if m := strings.Compare(v.Token, *tokenMap[v.ID]); m != 0 {
			t.Errorf("List error: ID: %s, expected token: %s, DB token: %s", v.ID, *tokenMap[v.ID], v.Token)
		}
		continue
	}
}

func TestCheck(t *testing.T) {
	ctx := context.Background()
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)

	token := mustCreateToken(ctx, t, cs, "x", "client")
	tokenParts := strings.Split(*token, ":")

	valid, err := cs.Check(ctx, tokenParts[0], tokenParts[1])
	if err != nil {
		t.Fatal(err)
	}
	if !valid {
		t.Fatal("expected token and secret to be valid")
	}

	valid, err = cs.Check(ctx, "x", "badsecret")
	if err != nil {
		t.Fatal(err)
	}
	if valid {
		t.Fatal("expected bad secret to not be valid")
	}
}

func TestDelete(t *testing.T) {
	ctx := context.Background()
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)

	const id = "Y"
	mustCreateToken(ctx, t, cs, id, "client")

	err := cs.Delete(ctx, id)
	if err != nil {
		t.Fatal(err)
	}

	value := cs.DB.Get([]byte(id))
	if len(value) > 0 {
		t.Fatal("delete fail")
	}
}

func TestDeleteWithInvalidId(t *testing.T) {
	ctx := context.Background()
	testDB := dbm.NewDB("testdb", "leveldb", "temp")
	defer os.RemoveAll("temp")
	cs := NewStore(testDB)

	err := cs.Delete(ctx, "@")
	if errors.Root(err) != ErrBadID {
		t.Errorf("Deletion with invalid id success, while it should not")
	}
}

func mustCreateToken(ctx context.Context, t *testing.T, cs *CredentialStore, id, typ string) *string {
	token, err := cs.Create(ctx, id, typ)
	if err != nil {
		t.Fatal(err)
	}
	return token
}
<|endoftext|>


<commit_before>package httptoo

import (
	"context"
	"net/http"
)

var closeNotifyContextKey = new(struct{})

func RequestWithCloseNotify(r *http.Request, w http.ResponseWriter) *http.Request {
	if r.Context().Value(closeNotifyContextKey) != nil {
		return r
	}
	v := make(chan struct{})
	r = r.WithContext(context.WithValue(r.Context(), closeNotifyContextKey, v))
	cn := w.(http.CloseNotifier).CloseNotify()
	go func() {
		select {
		case <-cn:
			close(v)
		case <-r.Context().Done():
		}
	}()
	return r
}

func RequestCloseNotifyValue(r *http.Request) <-chan struct{} {
	return r.Context().Value(closeNotifyContextKey).(chan struct{})
}
<commit_msg>Remove CloseNotify hacks, as of Go 1.8 Request.Context.Done suffices<commit_after><|endoftext|>


<commit_before>package main

import (
	"fmt"

	"stash.ovh.net/sailabove/sailgo/Godeps/_workspace/src/github.com/spf13/cobra"
)

func init() {
	cmdApplication.AddCommand(cmdApplicationList)
	cmdApplication.AddCommand(cmdApplicationInspect)

	cmdApplicationDomain.AddCommand(cmdApplicationDomainList)
	cmdApplication.AddCommand(cmdApplicationDomain)

	// TODO domain list, attach, detach
}

var cmdApplication = &cobra.Command{
	Use:     "me",
	Short:   "Application commands : sailgo application --help",
	Long:    `Application commands : sailgo application <command>`,
	Aliases: []string{"a", "app", "apps", "applications"},
}

var cmdApplicationList = &cobra.Command{
	Use:     "list",
	Short:   "List granted apps : sailgo application list",
	Aliases: []string{"ls", "ps"},
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println(getWantJSON("/applications"))
	},
}

var cmdApplicationInspect = &cobra.Command{
	Use:   "inspect",
	Short: "Details of an app : sailgo application inspect <applicationName>",
	Long: `Details of an app : sailgo application inspect <applicationName>
	\"example : sailgo application inspect myApp"
	`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 || args[0] == "" {
			fmt.Println("Invalid usage. Please see sailgo application inspect --help")
		} else {
			fmt.Println(getWantJSON(fmt.Sprintf("/applications/%s", args[0])))
		}
	},
}

var cmdApplicationDomain = &cobra.Command{
	Use:     "domain",
	Short:   "Application Domain commands : sailgo application domain --help",
	Long:    `Application Domain commands : sailgo application domain <command>`,
	Aliases: []string{"domains"},
}

var cmdApplicationDomainList = &cobra.Command{
	Use:     "list",
	Short:   "List domains and routes on the HTTP load balancer : sailgo application domain list <applicationName>",
	Aliases: []string{"ls", "ps"},
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 || args[0] == "" {
			fmt.Println("Invalid usage. Please see sailgo application domain list --help")
		} else {
			// cmdApplicationDomainList TODO ? Tab view with headers ['DOMAIN', 'SERVICE', 'METHOD', 'PATTERN']
			fmt.Println(getWantJSON(fmt.Sprintf("/applications/%s/attached-domains", args[0])))
		}
	},
}

var cmdApplicationDomainAttach = &cobra.Command{
	Use:     "attach",
	Short:   "Attach a domain on the HTTP load balancer : sailgo application domain attach <applicationName> <domainName>",
	Aliases: []string{"add"},
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 2 {
			fmt.Println("Invalid usage. Please see sailgo application domain attach --help")
		} else {
			fmt.Println(postWantJSON(fmt.Sprintf("/applications/%s/attached-domains/%s", args[0], args[1])))
		}
	},
}

var cmdApplicationDomainDetach = &cobra.Command{
	Use:     "detach",
	Short:   "Detach a domain from the HTTP load balancer : sailgo application domain detach <applicationName> <domainName>",
	Aliases: []string{"add"},
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 2 {
			fmt.Println("Invalid usage. Please see sailgo application domain attach --help")
		} else {
			fmt.Println(deleteWantJSON(fmt.Sprintf("/applications/%s/attached-domains/%s", args[0], args[1])))
		}
	},
}
<commit_msg>feat : sail app domain detach / attach<commit_after>package main

import (
	"fmt"

	"stash.ovh.net/sailabove/sailgo/Godeps/_workspace/src/github.com/spf13/cobra"
)

func init() {
	cmdApplication.AddCommand(cmdApplicationList)
	cmdApplication.AddCommand(cmdApplicationInspect)

	cmdApplicationDomain.AddCommand(cmdApplicationDomainList)
	cmdApplicationDomain.AddCommand(cmdApplicationDomainAttach)
	cmdApplicationDomain.AddCommand(cmdApplicationDomainDetach)
	cmdApplication.AddCommand(cmdApplicationDomain)
}

var cmdApplication = &cobra.Command{
	Use:     "me",
	Short:   "Application commands : sailgo application --help",
	Long:    `Application commands : sailgo application <command>`,
	Aliases: []string{"a", "app", "apps", "applications"},
}

var cmdApplicationList = &cobra.Command{
	Use:     "list",
	Short:   "List granted apps : sailgo application list",
	Aliases: []string{"ls", "ps"},
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println(getWantJSON("/applications"))
	},
}

var cmdApplicationInspect = &cobra.Command{
	Use:   "inspect",
	Short: "Details of an app : sailgo application inspect <applicationName>",
	Long: `Details of an app : sailgo application inspect <applicationName>
	\"example : sailgo application inspect myApp"
	`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 || args[0] == "" {
			fmt.Println("Invalid usage. Please see sailgo application inspect --help")
		} else {
			fmt.Println(getWantJSON(fmt.Sprintf("/applications/%s", args[0])))
		}
	},
}

var cmdApplicationDomain = &cobra.Command{
	Use:     "domain",
	Short:   "Application Domain commands : sailgo application domain --help",
	Long:    `Application Domain commands : sailgo application domain <command>`,
	Aliases: []string{"domains"},
}

var cmdApplicationDomainList = &cobra.Command{
	Use:     "list",
	Short:   "List domains and routes on the HTTP load balancer : sailgo application domain list <applicationName>",
	Aliases: []string{"ls", "ps"},
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 || args[0] == "" {
			fmt.Println("Invalid usage. Please see sailgo application domain list --help")
		} else {
			// cmdApplicationDomainList TODO ? Tab view with headers ['DOMAIN', 'SERVICE', 'METHOD', 'PATTERN']
			fmt.Println(getWantJSON(fmt.Sprintf("/applications/%s/attached-domains", args[0])))
		}
	},
}

var cmdApplicationDomainAttach = &cobra.Command{
	Use:     "attach",
	Short:   "Attach a domain on the HTTP load balancer : sailgo application domain attach <applicationName> <domainName>",
	Aliases: []string{"add"},
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 2 {
			fmt.Println("Invalid usage. Please see sailgo application domain attach --help")
		} else {
			fmt.Println(postWantJSON(fmt.Sprintf("/applications/%s/attached-domains/%s", args[0], args[1])))
		}
	},
}

var cmdApplicationDomainDetach = &cobra.Command{
	Use:     "detach",
	Short:   "Detach a domain from the HTTP load balancer : sailgo application domain detach <applicationName> <domainName>",
	Aliases: []string{"add"},
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) != 2 {
			fmt.Println("Invalid usage. Please see sailgo application domain attach --help")
		} else {
			fmt.Println(deleteWantJSON(fmt.Sprintf("/applications/%s/attached-domains/%s", args[0], args[1])))
		}
	},
}
<|endoftext|>