<commit_before>package main

import (
	"flag"
	"image"
	"log"
	"rtsengine"
	"time"
)

/*
 Main entry point for the go rtsengine.

*/

type flags struct {
	port    *int
	host    *string
	verbose *bool
	quiet   *bool
	width   *int
	height  *int
}

func main() {

	var cargs flags

	cargs.port = flag.Int("port", 8080, "port of rts server")
	cargs.host = flag.String("host", "localhost", "hostname of rts server")
	cargs.verbose = flag.Bool("verbose", false, "Emit excessive progress reporting during rts server execution .")
	cargs.quiet = flag.Bool("quiet", false, "Silent testing.")
	cargs.width = flag.Int("width", 1000, "Width of the world.")
	cargs.height = flag.Int("height", 1000, "Height of the world.")

	// Command line arguments parsinmg
	flag.Parse()

	if !*cargs.quiet {
		log.Print("GO RTS Engine starting")
	}

	game, err := rtsengine.NewGame("Game test", 10000, 1, 0, 50, 50, *cargs.width, *cargs.height)
	if err != nil {
		log.Print(err)
		return
	}
	start := time.Now()
	pathList, err := game.FindPath(&image.Point{10, 10}, &image.Point{45, 45})
	elapsed := time.Since(start)

	if err != nil {
		log.Print(err)
		return
	}

	for e := pathList.Front(); e != nil; e = e.Next() {
		square := e.Value.(*rtsengine.Square)
		fence := rtsengine.Fence{}
		fence.Initialize()
		_ = game.OurWorld.Grid.Set(&square.Locus, &fence)
	}

	//game.OurWorld.Print()

	for e := pathList.Front(); e != nil; e = e.Next() {
		square := e.Value.(*rtsengine.Square)
		square.Print()
		game.ItemPool.Free(square)
	}

	game.ItemPool.PrintAllocatedSquares()

	log.Printf("\n\nPathfinding  took %s\n\n", elapsed)

	err = game.AcceptNetConnections()
	if err != nil {
		log.Print(err)
		return
	}

	game.Start()

	//time.Sleep(time.Second * 60)
	select {} // wait forever without eating CPU.
	//game.Stop()
}
<commit_msg>Removed printf's<commit_after>package main

import (
	"flag"
	"image"
	"log"
	"rtsengine"
	"time"
)

/*
 Main entry point for the go rtsengine.

*/

type flags struct {
	port    *int
	host    *string
	verbose *bool
	quiet   *bool
	width   *int
	height  *int
}

func main() {

	var cargs flags

	cargs.port = flag.Int("port", 8080, "port of rts server")
	cargs.host = flag.String("host", "localhost", "hostname of rts server")
	cargs.verbose = flag.Bool("verbose", false, "Emit excessive progress reporting during rts server execution .")
	cargs.quiet = flag.Bool("quiet", false, "Silent testing.")
	cargs.width = flag.Int("width", 1000, "Width of the world.")
	cargs.height = flag.Int("height", 1000, "Height of the world.")

	// Command line arguments parsinmg
	flag.Parse()

	if !*cargs.quiet {
		log.Print("GO RTS Engine starting")
	}

	game, err := rtsengine.NewGame("Game test", 10000, 1, 0, 50, 50, *cargs.width, *cargs.height)
	if err != nil {
		log.Print(err)
		return
	}
	start := time.Now()
	pathList, err := game.FindPath(&image.Point{10, 10}, &image.Point{45, 45})
	elapsed := time.Since(start)

	if err != nil {
		log.Print(err)
		return
	}

	for e := pathList.Front(); e != nil; e = e.Next() {
		square := e.Value.(*rtsengine.Square)
		fence := rtsengine.Fence{}
		fence.Initialize()
		_ = game.OurWorld.Grid.Set(&square.Locus, &fence)
	}

	//game.OurWorld.Print()

	for e := pathList.Front(); e != nil; e = e.Next() {
		square := e.Value.(*rtsengine.Square)
		//square.Print()
		game.ItemPool.Free(square)
	}

	game.ItemPool.PrintAllocatedSquares()

	log.Printf("\n\nPathfinding  took %s\n\n", elapsed)

	err = game.AcceptNetConnections()
	if err != nil {
		log.Print(err)
		return
	}

	game.Start()

	//time.Sleep(time.Second * 60)
	select {} // wait forever without eating CPU.
	//game.Stop()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
)

func waitForExit() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	<-c
	os.Exit(0)
}

func main() {
	pid := os.Getpid()
	parentpid := os.Getppid()
	fmt.Printf("Parent: %d pid: %d ", pid, parentpid)

	proc, err := os.FindProcess(pid)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Process: %d\n", proc.Pid)

	go func() {
		r, w, err := os.Pipe()
		if err != nil {
			panic(err)
		}
		defer r.Close()
		cmdToRun := "/bin/sleep"
		args := []string{"sleep", "30"}
		procAttr := new(os.ProcAttr)
		procAttr.Files = []*os.File{nil, w, os.Stderr}
		process, err := os.StartProcess(cmdToRun, args, procAttr)
		if err != nil {
			fmt.Printf("ERROR Unable to run %s: %s\n", cmdToRun, err.Error())
			return
		}
		fmt.Printf("%s running as pid %d\n", cmdToRun, process.Pid)

		processState, err := process.Wait()

		if err != nil {
			panic(err)
		}

		err = process.Release()

		if err != nil {
			panic(err)
		}

		fmt.Println("Did the child process exited? : ", processState.Exited())
		fmt.Println("So the child pid is? : ", processState.Pid())
		fmt.Println("Exited successfully? : ", processState.Success())

		fmt.Println("Exited system CPU time ? : ", processState.SystemTime())
		fmt.Println("Exited user CPU time ? : ", processState.UserTime())

		// just to be sure, let's kill again
		err = process.Signal(syscall.SIGKILL)

		if err != nil {
			fmt.Println(err) // see what the serial killer has to say
			return
		}
		w.Close()
	}()

	waitForExit()
}
<commit_msg>	modified:   main.go<commit_after>package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"
)

func waitForExit() {
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	<-c
	os.Exit(0)
}

func main() {
	pid := os.Getpid()
	parentpid := os.Getppid()
	fmt.Printf("Parent: %d pid: %d ", pid, parentpid)

	proc, err := os.FindProcess(pid)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Process: %d\n", proc.Pid)

	go func() {
		r, w, err := os.Pipe()
		if err != nil {
			panic(err)
		}
		defer r.Close()
		cmdToRun := "/bin/sleep"
		args := []string{"name-of-the-cmd", "30"}
		procAttr := new(os.ProcAttr)
		procAttr.Files = []*os.File{nil, w, os.Stderr}
		process, err := os.StartProcess(cmdToRun, args, procAttr)
		if err != nil {
			fmt.Printf("ERROR Unable to run %s: %s\n", cmdToRun, err.Error())
			return
		}
		fmt.Printf("%s running as pid %d\n", cmdToRun, process.Pid)

		processState, err := process.Wait()

		if err != nil {
			panic(err)
		}

		err = process.Release()

		if err != nil {
			panic(err)
		}

		fmt.Println("Did the child process exited? : ", processState.Exited())
		fmt.Println("So the child pid is? : ", processState.Pid())
		fmt.Println("Exited successfully? : ", processState.Success())

		fmt.Println("Exited system CPU time ? : ", processState.SystemTime())
		fmt.Println("Exited user CPU time ? : ", processState.UserTime())

		// just to be sure, let's kill again
		err = process.Signal(syscall.SIGKILL)

		if err != nil {
			fmt.Println(err) // see what the serial killer has to say
			return
		}
		w.Close()
	}()

	waitForExit()
}
<|endoftext|>


<commit_before>package golzmq

import "fmt"

/* Structure to sustain ZMQ Proxy configuration */
type ZmqProxyConfig struct {
	DestinationIP    string
	DestinationPorts []int
	SourceIP         string
	SourcePorts      []int
}

/* Create a Proxy connection for given ZmqProxyConfig */
func ZmqProxySocket(proxy ZmqProxyConfig) {
	chan_source := make(chan []byte, 5)
	chan_destination := make(chan []byte, 5)

	go proxyDestination(proxy.DestinationIP, proxy.DestinationPorts, chan_source, chan_destination)
	go proxySource(proxy.SourceIP, proxy.SourcePorts, chan_source, chan_destination)
}

/* Create a ZMQ Proxy Reader from source of Proxy */
func proxyDestination(ip string, ports []int, chan_source chan []byte, chan_destination chan []byte) error {
	socket := ZmqRequestSocket(ip, ports)

	for {
		request := <-chan_destination
		reply, err_request := ZmqRequestByte(socket, request)
		if err_request != nil {
			fmt.Println("ERROR:", err_request)
			return err_request
		}
		chan_source <- reply
	}
}

/* Create a ZMQ Proxy Reader from source of Proxy */
func proxySource(ip string, ports []int, chan_source chan []byte, chan_destination chan []byte) error {
	socket := ZmqReplySocket(ip, ports)

	reply_handler := func(request []byte) []byte {
		chan_destination <- request
		reply := <-chan_source
		return reply
	}

	for {
		err_reply := ZmqReplyByte(socket, reply_handler)
		if err_reply != nil {
			fmt.Println("ERROR:", err_reply)
			return err_reply
		}
	}
	return nil
}
<commit_msg>[golzmq] gofmt and golint -ified proxy.go<commit_after>package golzmq

import "fmt"

/*
ZmqProxyConfig is structure to sustain ZMQ Proxy configuration.
*/
type ZmqProxyConfig struct {
	DestinationIP    string
	DestinationPorts []int
	SourceIP         string
	SourcePorts      []int
}

/*
ZmqProxySocket creates a Proxy connection for given ZmqProxyConfig.
*/
func ZmqProxySocket(proxy ZmqProxyConfig) {
	chanSource := make(chan []byte, 5)
	chanDestination := make(chan []byte, 5)

	go proxyDestination(proxy.DestinationIP, proxy.DestinationPorts, chanSource, chanDestination)
	go proxySource(proxy.SourceIP, proxy.SourcePorts, chanSource, chanDestination)
}

/*
proxyDestination creates a ZMQ Proxy Reader from source of Proxy.
*/
func proxyDestination(ip string, ports []int, chanSource chan []byte, chanDestination chan []byte) error {
	socket := ZmqRequestSocket(ip, ports)

	for {
		request := <-chanDestination
		reply, errRequest := ZmqRequestByte(socket, request)
		if errRequest != nil {
			fmt.Println("ERROR:", errRequest)
			return errRequest
		}
		chanSource <- reply
	}
}

/*
proxySource creates a ZMQ Proxy Reader from source of Proxy.
*/
func proxySource(ip string, ports []int, chanSource chan []byte, chanDestination chan []byte) error {
	socket := ZmqReplySocket(ip, ports)

	replyHandler := func(request []byte) []byte {
		chanDestination <- request
		reply := <-chanSource
		return reply
	}

	for {
		errReply := ZmqReplyByte(socket, replyHandler)
		if errReply != nil {
			fmt.Println("ERROR:", errReply)
			return errReply
		}
	}
}
<|endoftext|>


<commit_before>package gpg

import (
	"log"
	"os"
	"testing"
)

const asciiKeyFile = "../test-keys/new-MacGPG2/TEST gpg-validation-server (For Testing Only) test-gpg-validation@server.local (0x87144E5E) pub-sec.asc"
const binaryKeyFile = "../test-keys/new-MacGPG2/TEST gpg-validation-server (For Testing Only) test-gpg-validation@server.local (0x87144E5E) pub-sec.asc.gpg"
const expectedIdentity = "TEST gpg-validation-server (For Testing Only) <test-gpg-validation@server.local>"

func TestReadEntity(t *testing.T) {
	keyFile, err := os.Open(binaryKeyFile)
	if err != nil {
		log.Fatal("Could not open test key file: ", err)
	}

	entity, err := ReadEntity(keyFile, 0, false)
	if err != nil {
		t.Error("Failed to read entity:", err)
	}

    _, ok := entity.Identities[expectedIdentity]
    if ! ok {
        t.Error("Could not find identity:", expectedIdentity)
    }
}

func TestReadEntityArmored(t *testing.T) {
	keyFile, err := os.Open(asciiKeyFile)
	if err != nil {
		log.Fatal("Could not open test key file: ", err)
	}

	entity, err := ReadEntity(keyFile, 0, true)
	if err != nil {
		t.Error("Failed to read entity:", err)
	}

    _, ok := entity.Identities[expectedIdentity]
    if ! ok {
        t.Error("Could not find identity:", expectedIdentity)
    }
}<commit_msg>go-fmt..<commit_after>package gpg

import (
	"log"
	"os"
	"testing"
)

const asciiKeyFile = "../test-keys/new-MacGPG2/TEST gpg-validation-server (For Testing Only) test-gpg-validation@server.local (0x87144E5E) pub-sec.asc"
const binaryKeyFile = "../test-keys/new-MacGPG2/TEST gpg-validation-server (For Testing Only) test-gpg-validation@server.local (0x87144E5E) pub-sec.asc.gpg"
const expectedIdentity = "TEST gpg-validation-server (For Testing Only) <test-gpg-validation@server.local>"

func TestReadEntity(t *testing.T) {
	keyFile, err := os.Open(binaryKeyFile)
	if err != nil {
		log.Fatal("Could not open test key file: ", err)
	}

	entity, err := ReadEntity(keyFile, 0, false)
	if err != nil {
		t.Error("Failed to read entity:", err)
	}

	_, ok := entity.Identities[expectedIdentity]
	if !ok {
		t.Error("Could not find identity:", expectedIdentity)
	}
}

func TestReadEntityArmored(t *testing.T) {
	keyFile, err := os.Open(asciiKeyFile)
	if err != nil {
		log.Fatal("Could not open test key file: ", err)
	}

	entity, err := ReadEntity(keyFile, 0, true)
	if err != nil {
		t.Error("Failed to read entity:", err)
	}

	_, ok := entity.Identities[expectedIdentity]
	if !ok {
		t.Error("Could not find identity:", expectedIdentity)
	}
}
<|endoftext|>


<commit_before>// Copyright 2009 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.

// HTTP file system request handler

package http

import (
	"fmt"
	"io"
	"mime"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"utf8"
)

// Heuristic: b is text if it is valid UTF-8 and doesn't
// contain any unprintable ASCII or Unicode characters.
func isText(b []byte) bool {
	for len(b) > 0 && utf8.FullRune(b) {
		rune, size := utf8.DecodeRune(b)
		if size == 1 && rune == utf8.RuneError {
			// decoding error
			return false
		}
		if 0x7F <= rune && rune <= 0x9F {
			return false
		}
		if rune < ' ' {
			switch rune {
			case '\n', '\r', '\t':
				// okay
			default:
				// binary garbage
				return false
			}
		}
		b = b[size:]
	}
	return true
}

func dirList(w ResponseWriter, f *os.File) {
	fmt.Fprintf(w, "
\n")
	for {
		dirs, err := f.Readdir(100)
		if err != nil || len(dirs) == 0 {
			break
		}
		for _, d := range dirs {
			name := d.Name
			if d.IsDirectory() {
				name += "/"
			}
			// TODO htmlescape
			fmt.Fprintf(w, "%s\n", name, name)
		}
	}
	fmt.Fprintf(w, "
\n")
}

func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
	const indexPage = "/index.html"

	// redirect .../index.html to .../
	if strings.HasSuffix(r.URL.Path, indexPage) {
		Redirect(w, r, r.URL.Path[0:len(r.URL.Path)-len(indexPage)+1], StatusMovedPermanently)
		return
	}

	f, err := os.Open(name, os.O_RDONLY, 0)
	if err != nil {
		// TODO expose actual error?
		NotFound(w, r)
		return
	}
	defer f.Close()

	d, err1 := f.Stat()
	if err1 != nil {
		// TODO expose actual error?
		NotFound(w, r)
		return
	}

	if redirect {
		// redirect to canonical path: / at end of directory url
		// r.URL.Path always begins with /
		url := r.URL.Path
		if d.IsDirectory() {
			if url[len(url)-1] != '/' {
				Redirect(w, r, url+"/", StatusMovedPermanently)
				return
			}
		} else {
			if url[len(url)-1] == '/' {
				Redirect(w, r, url[0:len(url)-1], StatusMovedPermanently)
				return
			}
		}
	}

	if t, _ := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); t != nil && d.Mtime_ns/1e9 <= t.Seconds() {
		w.WriteHeader(StatusNotModified)
		return
	}
	w.SetHeader("Last-Modified", time.SecondsToUTC(d.Mtime_ns/1e9).Format(TimeFormat))

	// use contents of index.html for directory, if present
	if d.IsDirectory() {
		index := name + indexPage
		ff, err := os.Open(index, os.O_RDONLY, 0)
		if err == nil {
			defer ff.Close()
			dd, err := ff.Stat()
			if err == nil {
				name = index
				d = dd
				f = ff
			}
		}
	}

	if d.IsDirectory() {
		dirList(w, f)
		return
	}

	// serve file
	size := d.Size
	code := StatusOK

	// use extension to find content type.
	ext := filepath.Ext(name)
	if ctype := mime.TypeByExtension(ext); ctype != "" {
		w.SetHeader("Content-Type", ctype)
	} else {
		// read first chunk to decide between utf-8 text and binary
		var buf [1024]byte
		n, _ := io.ReadFull(f, buf[:])
		b := buf[:n]
		if isText(b) {
			w.SetHeader("Content-Type", "text-plain; charset=utf-8")
		} else {
			w.SetHeader("Content-Type", "application/octet-stream") // generic binary
		}
		f.Seek(0, 0) // rewind to output whole file
	}

	// handle Content-Range header.
	// TODO(adg): handle multiple ranges
	ranges, err := parseRange(r.Header.Get("Range"), size)
	if err != nil || len(ranges) > 1 {
		Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
		return
	}
	if len(ranges) == 1 {
		ra := ranges[0]
		if _, err := f.Seek(ra.start, 0); err != nil {
			Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
			return
		}
		size = ra.length
		code = StatusPartialContent
		w.SetHeader("Content-Range", fmt.Sprintf("bytes %d-%d/%d", ra.start, ra.start+ra.length-1, d.Size))
	}

	w.SetHeader("Accept-Ranges", "bytes")
	w.SetHeader("Content-Length", strconv.Itoa64(size))

	w.WriteHeader(code)

	if r.Method != "HEAD" {
		io.Copyn(w, f, size)
	}
}

// ServeFile replies to the request with the contents of the named file or directory.
func ServeFile(w ResponseWriter, r *Request, name string) {
	serveFile(w, r, name, false)
}

type fileHandler struct {
	root   string
	prefix string
}

// FileServer returns a handler that serves HTTP requests
// with the contents of the file system rooted at root.
// It strips prefix from the incoming requests before
// looking up the file name in the file system.
func FileServer(root, prefix string) Handler { return &fileHandler{root, prefix} }

func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
	path := r.URL.Path
	if !strings.HasPrefix(path, f.prefix) {
		NotFound(w, r)
		return
	}
	path = path[len(f.prefix):]
	serveFile(w, r, f.root+"/"+path, true)
}

// httpRange specifies the byte range to be sent to the client.
type httpRange struct {
	start, length int64
}

// parseRange parses a Range header string as per RFC 2616.
func parseRange(s string, size int64) ([]httpRange, os.Error) {
	if s == "" {
		return nil, nil // header not present
	}
	const b = "bytes="
	if !strings.HasPrefix(s, b) {
		return nil, os.NewError("invalid range")
	}
	var ranges []httpRange
	for _, ra := range strings.Split(s[len(b):], ",", -1) {
		i := strings.Index(ra, "-")
		if i < 0 {
			return nil, os.NewError("invalid range")
		}
		start, end := ra[:i], ra[i+1:]
		var r httpRange
		if start == "" {
			// If no start is specified, end specifies the
			// range start relative to the end of the file.
			i, err := strconv.Atoi64(end)
			if err != nil {
				return nil, os.NewError("invalid range")
			}
			if i > size {
				i = size
			}
			r.start = size - i
			r.length = size - r.start
		} else {
			i, err := strconv.Atoi64(start)
			if err != nil || i > size || i < 0 {
				return nil, os.NewError("invalid range")
			}
			r.start = i
			if end == "" {
				// If no end is specified, range extends to end of the file.
				r.length = size - r.start
			} else {
				i, err := strconv.Atoi64(end)
				if err != nil || r.start > i {
					return nil, os.NewError("invalid range")
				}
				if i >= size {
					i = size - 1
				}
				r.length = i - r.start + 1
			}
		}
		ranges = append(ranges, r)
	}
	return ranges, nil
}
<commit_msg>http.FileServer now converting paths.<commit_after>// Copyright 2009 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.

// HTTP file system request handler

package http

import (
	"fmt"
	"io"
	"mime"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
	"utf8"
)

// Heuristic: b is text if it is valid UTF-8 and doesn't
// contain any unprintable ASCII or Unicode characters.
func isText(b []byte) bool {
	for len(b) > 0 && utf8.FullRune(b) {
		rune, size := utf8.DecodeRune(b)
		if size == 1 && rune == utf8.RuneError {
			// decoding error
			return false
		}
		if 0x7F <= rune && rune <= 0x9F {
			return false
		}
		if rune < ' ' {
			switch rune {
			case '\n', '\r', '\t':
				// okay
			default:
				// binary garbage
				return false
			}
		}
		b = b[size:]
	}
	return true
}

func dirList(w ResponseWriter, f *os.File) {
	fmt.Fprintf(w, "
\n")
	for {
		dirs, err := f.Readdir(100)
		if err != nil || len(dirs) == 0 {
			break
		}
		for _, d := range dirs {
			name := d.Name
			if d.IsDirectory() {
				name += "/"
			}
			// TODO htmlescape
			fmt.Fprintf(w, "%s\n", name, name)
		}
	}
	fmt.Fprintf(w, "
\n")
}

func serveFile(w ResponseWriter, r *Request, name string, redirect bool) {
	const indexPage = "/index.html"

	// redirect .../index.html to .../
	if strings.HasSuffix(r.URL.Path, indexPage) {
		Redirect(w, r, r.URL.Path[0:len(r.URL.Path)-len(indexPage)+1], StatusMovedPermanently)
		return
	}

	f, err := os.Open(name, os.O_RDONLY, 0)
	if err != nil {
		// TODO expose actual error?
		NotFound(w, r)
		return
	}
	defer f.Close()

	d, err1 := f.Stat()
	if err1 != nil {
		// TODO expose actual error?
		NotFound(w, r)
		return
	}

	if redirect {
		// redirect to canonical path: / at end of directory url
		// r.URL.Path always begins with /
		url := r.URL.Path
		if d.IsDirectory() {
			if url[len(url)-1] != '/' {
				Redirect(w, r, url+"/", StatusMovedPermanently)
				return
			}
		} else {
			if url[len(url)-1] == '/' {
				Redirect(w, r, url[0:len(url)-1], StatusMovedPermanently)
				return
			}
		}
	}

	if t, _ := time.Parse(TimeFormat, r.Header.Get("If-Modified-Since")); t != nil && d.Mtime_ns/1e9 <= t.Seconds() {
		w.WriteHeader(StatusNotModified)
		return
	}
	w.SetHeader("Last-Modified", time.SecondsToUTC(d.Mtime_ns/1e9).Format(TimeFormat))

	// use contents of index.html for directory, if present
	if d.IsDirectory() {
		index := name + filepath.FromSlash(indexPage)
		ff, err := os.Open(index, os.O_RDONLY, 0)
		if err == nil {
			defer ff.Close()
			dd, err := ff.Stat()
			if err == nil {
				name = index
				d = dd
				f = ff
			}
		}
	}

	if d.IsDirectory() {
		dirList(w, f)
		return
	}

	// serve file
	size := d.Size
	code := StatusOK

	// use extension to find content type.
	ext := filepath.Ext(name)
	if ctype := mime.TypeByExtension(ext); ctype != "" {
		w.SetHeader("Content-Type", ctype)
	} else {
		// read first chunk to decide between utf-8 text and binary
		var buf [1024]byte
		n, _ := io.ReadFull(f, buf[:])
		b := buf[:n]
		if isText(b) {
			w.SetHeader("Content-Type", "text-plain; charset=utf-8")
		} else {
			w.SetHeader("Content-Type", "application/octet-stream") // generic binary
		}
		f.Seek(0, 0) // rewind to output whole file
	}

	// handle Content-Range header.
	// TODO(adg): handle multiple ranges
	ranges, err := parseRange(r.Header.Get("Range"), size)
	if err != nil || len(ranges) > 1 {
		Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
		return
	}
	if len(ranges) == 1 {
		ra := ranges[0]
		if _, err := f.Seek(ra.start, 0); err != nil {
			Error(w, err.String(), StatusRequestedRangeNotSatisfiable)
			return
		}
		size = ra.length
		code = StatusPartialContent
		w.SetHeader("Content-Range", fmt.Sprintf("bytes %d-%d/%d", ra.start, ra.start+ra.length-1, d.Size))
	}

	w.SetHeader("Accept-Ranges", "bytes")
	w.SetHeader("Content-Length", strconv.Itoa64(size))

	w.WriteHeader(code)

	if r.Method != "HEAD" {
		io.Copyn(w, f, size)
	}
}

// ServeFile replies to the request with the contents of the named file or directory.
func ServeFile(w ResponseWriter, r *Request, name string) {
	serveFile(w, r, name, false)
}

type fileHandler struct {
	root   string
	prefix string
}

// FileServer returns a handler that serves HTTP requests
// with the contents of the file system rooted at root.
// It strips prefix from the incoming requests before
// looking up the file name in the file system.
func FileServer(root, prefix string) Handler { return &fileHandler{root, prefix} }

func (f *fileHandler) ServeHTTP(w ResponseWriter, r *Request) {
	path := r.URL.Path
	if !strings.HasPrefix(path, f.prefix) {
		NotFound(w, r)
		return
	}
	path = path[len(f.prefix):]
	serveFile(w, r, filepath.Join(f.root, filepath.FromSlash(path)), true)
}

// httpRange specifies the byte range to be sent to the client.
type httpRange struct {
	start, length int64
}

// parseRange parses a Range header string as per RFC 2616.
func parseRange(s string, size int64) ([]httpRange, os.Error) {
	if s == "" {
		return nil, nil // header not present
	}
	const b = "bytes="
	if !strings.HasPrefix(s, b) {
		return nil, os.NewError("invalid range")
	}
	var ranges []httpRange
	for _, ra := range strings.Split(s[len(b):], ",", -1) {
		i := strings.Index(ra, "-")
		if i < 0 {
			return nil, os.NewError("invalid range")
		}
		start, end := ra[:i], ra[i+1:]
		var r httpRange
		if start == "" {
			// If no start is specified, end specifies the
			// range start relative to the end of the file.
			i, err := strconv.Atoi64(end)
			if err != nil {
				return nil, os.NewError("invalid range")
			}
			if i > size {
				i = size
			}
			r.start = size - i
			r.length = size - r.start
		} else {
			i, err := strconv.Atoi64(start)
			if err != nil || i > size || i < 0 {
				return nil, os.NewError("invalid range")
			}
			r.start = i
			if end == "" {
				// If no end is specified, range extends to end of the file.
				r.length = size - r.start
			} else {
				i, err := strconv.Atoi64(end)
				if err != nil || r.start > i {
					return nil, os.NewError("invalid range")
				}
				if i >= size {
					i = size - 1
				}
				r.length = i - r.start + 1
			}
		}
		ranges = append(ranges, r)
	}
	return ranges, nil
}
<|endoftext|>


<commit_before>package panicwrap

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"testing"
	"time"
)

func helperProcess(s ...string) *exec.Cmd {
	cs := []string{"-test.run=TestHelperProcess", "--"}
	cs = append(cs, s...)
	env := []string{
		"GO_WANT_HELPER_PROCESS=1",
	}

	cmd := exec.Command(os.Args[0], cs...)
	cmd.Env = append(env, os.Environ()...)
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd
}

// This is executed by `helperProcess` in a separate process in order to
// provider a proper sub-process environment to test some of our functionality.
func TestHelperProcess(*testing.T) {
	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
		return
	}

	// Find the arguments to our helper, which are the arguments past
	// the "--" in the command line.
	args := os.Args
	for len(args) > 0 {
		if args[0] == "--" {
			args = args[1:]
			break
		}

		args = args[1:]
	}

	if len(args) == 0 {
		fmt.Fprintf(os.Stderr, "No command\n")
		os.Exit(2)
	}

	panicHandler := func(s string) {
		fmt.Fprintf(os.Stdout, "wrapped: %d", len(s))
		os.Exit(0)
	}

	cmd, args := args[0], args[1:]
	switch cmd {
	case "no-panic-ordered-output":
		exitStatus, err := BasicWrap(panicHandler)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			for i := 0; i < 1000; i++ {
				os.Stdout.Write([]byte("a"))
				os.Stderr.Write([]byte("b"))
			}
			os.Exit(0)
		}

		os.Exit(exitStatus)
	case "no-panic-output":
		fmt.Fprint(os.Stdout, "i am output")
		fmt.Fprint(os.Stderr, "stderr out")
		os.Exit(0)
	case "panic-boundary":
		exitStatus, err := BasicWrap(panicHandler)

		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			// Simulate a panic but on two boundaries...
			fmt.Fprint(os.Stderr, "pan")
			os.Stderr.Sync()
			time.Sleep(100 * time.Millisecond)
			fmt.Fprint(os.Stderr, "ic: oh crap")
			os.Exit(2)
		}

		os.Exit(exitStatus)
	case "panic-long":
		exitStatus, err := BasicWrap(panicHandler)

		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			// Make a fake panic by faking the header and adding a
			// bunch of garbage.
			fmt.Fprint(os.Stderr, "panic: foo\n\n")
			for i := 0; i < 1024; i++ {
				fmt.Fprint(os.Stderr, "foobarbaz")
			}

			// Sleep so that it dumps the previous data
			//time.Sleep(1 * time.Millisecond)
			time.Sleep(500 * time.Millisecond)

			// Make a real panic
			panic("I AM REAL!")
		}

		os.Exit(exitStatus)
	case "stack exhaustion":
		exitStatus, err := BasicWrap(panicHandler)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			var f func(a [1000]int64)
			f = func(a [1000]int64) {
				f(a)
			}
			f([1000]int64{})
		}

	case "nil goroutine":
		exitStatus, err := BasicWrap(panicHandler)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			var f func()
			go f()
		}

		os.Exit(exitStatus)
	case "concurrent map write":
		exitStatus, err := BasicWrap(panicHandler)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			m := map[string]int{}

			go func() {
				for {
					m["x"] = 1
				}
			}()
			for {
				_ = m["x"]
			}
		}

		os.Exit(exitStatus)
	case "panic":
		hidePanic := false
		if args[0] == "hide" {
			hidePanic = true
		}

		config := &WrapConfig{
			Handler:   panicHandler,
			HidePanic: hidePanic,
		}

		exitStatus, err := Wrap(config)

		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			panic("uh oh")
		}

		os.Exit(exitStatus)
	case "wrapped":
		child := false
		if len(args) > 0 && args[0] == "child" {
			child = true
		}
		config := &WrapConfig{
			Handler: panicHandler,
		}

		exitStatus, err := Wrap(config)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			if child {
				fmt.Printf("%v", Wrapped(config))
			}
			os.Exit(0)
		}

		if !child {
			fmt.Printf("%v", Wrapped(config))
		}
		os.Exit(exitStatus)
	case "panic-monitor":

		config := &WrapConfig{
			Handler: panicHandler,
			HidePanic: true,
			Monitor: true,
		}

		exitStatus, err := Wrap(config)

		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus != -1 {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		panic("uh oh")

	default:
		fmt.Fprintf(os.Stderr, "Unknown command: %q\n", cmd)
		os.Exit(2)
	}
}

func TestPanicWrap_Output(t *testing.T) {
	stderr := new(bytes.Buffer)
	stdout := new(bytes.Buffer)

	p := helperProcess("no-panic-output")
	p.Stdout = stdout
	p.Stderr = stderr
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "i am output") {
		t.Fatalf("didn't forward: %#v", stdout.String())
	}

	if !strings.Contains(stderr.String(), "stderr out") {
		t.Fatalf("didn't forward: %#v", stderr.String())
	}
}

/*
TODO(mitchellh): This property would be nice to gain.
func TestPanicWrap_Output_Order(t *testing.T) {
	output := new(bytes.Buffer)

	p := helperProcess("no-panic-ordered-output")
	p.Stdout = output
	p.Stderr = output
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	expectedBuf := new(bytes.Buffer)
	for i := 0; i < 1000; i++ {
		expectedBuf.WriteString("ab")
	}

	actual := strings.TrimSpace(output.String())
	expected := strings.TrimSpace(expectedBuf.String())

	if actual != expected {
		t.Fatalf("bad: %#v", actual)
	}
}
*/

func TestPanicWrap_panicHide(t *testing.T) {
	stdout := new(bytes.Buffer)
	stderr := new(bytes.Buffer)

	p := helperProcess("panic", "hide")
	p.Stdout = stdout
	p.Stderr = stderr
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}

	if strings.Contains(stderr.String(), "panic:") {
		t.Fatalf("shouldn't have panic: %#v", stderr.String())
	}
}

func TestPanicWrap_panicShow(t *testing.T) {
	stdout := new(bytes.Buffer)
	stderr := new(bytes.Buffer)

	p := helperProcess("panic", "show")
	p.Stdout = stdout
	p.Stderr = stderr
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}

	if !strings.Contains(stderr.String(), "panic:") {
		t.Fatalf("should have panic: %#v", stderr.String())
	}
}

func TestPanicWrap_panicLong(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("panic-long")
	p.Stdout = stdout
	p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestPanicWrap_nilGoroutine(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("nil goroutine")
	p.Stdout = stdout
	p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestPanicWrap_stackExhaustion(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("stack exhaustion")
	p.Stdout = stdout
	p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestPanicWrap_concurrentMapWrite(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("concurrent map write")
	p.Stdout = stdout
	p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestPanicWrap_panicBoundary(t *testing.T) {
	// TODO(mitchellh): panics are currently lost on boundaries
	t.SkipNow()

	stdout := new(bytes.Buffer)

	p := helperProcess("panic-boundary")
	p.Stdout = stdout
	//p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped: 1015") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestWrapped(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("wrapped", "child")
	p.Stdout = stdout
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "true") {
		t.Fatalf("bad: %#v", stdout.String())
	}
}

func TestWrapped_parent(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("wrapped")
	p.Stdout = stdout
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "false") {
		t.Fatalf("bad: %#v", stdout.String())
	}
}
<commit_msg>test: update to run on arm64 linux<commit_after>package panicwrap

import (
	"bytes"
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"testing"
	"time"
)

func helperProcess(s ...string) *exec.Cmd {
	cs := []string{"-test.run=TestHelperProcess", "--"}
	cs = append(cs, s...)
	env := []string{
		"GO_WANT_HELPER_PROCESS=1",
	}

	cmd := exec.Command(os.Args[0], cs...)
	cmd.Env = append(env, os.Environ()...)
	cmd.Stdin = os.Stdin
	cmd.Stderr = os.Stderr
	cmd.Stdout = os.Stdout
	return cmd
}

// This is executed by `helperProcess` in a separate process in order to
// provider a proper sub-process environment to test some of our functionality.
func TestHelperProcess(*testing.T) {
	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
		return
	}

	// Find the arguments to our helper, which are the arguments past
	// the "--" in the command line.
	args := os.Args
	for len(args) > 0 {
		if args[0] == "--" {
			args = args[1:]
			break
		}

		args = args[1:]
	}

	if len(args) == 0 {
		fmt.Fprintf(os.Stderr, "No command\n")
		os.Exit(2)
	}

	panicHandler := func(s string) {
		fmt.Fprintf(os.Stdout, "wrapped: %d", len(s))
		os.Exit(0)
	}

	cmd, args := args[0], args[1:]
	switch cmd {
	case "no-panic-ordered-output":
		exitStatus, err := BasicWrap(panicHandler)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			for i := 0; i < 1000; i++ {
				os.Stdout.Write([]byte("a"))
				os.Stderr.Write([]byte("b"))
			}
			os.Exit(0)
		}

		os.Exit(exitStatus)
	case "no-panic-output":
		fmt.Fprint(os.Stdout, "i am output")
		fmt.Fprint(os.Stderr, "stderr out")
		os.Exit(0)
	case "panic-boundary":
		exitStatus, err := BasicWrap(panicHandler)

		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			// Simulate a panic but on two boundaries...
			fmt.Fprint(os.Stderr, "pan")
			os.Stderr.Sync()
			time.Sleep(100 * time.Millisecond)
			fmt.Fprint(os.Stderr, "ic: oh crap")
			os.Exit(2)
		}

		os.Exit(exitStatus)
	case "panic-long":
		exitStatus, err := BasicWrap(panicHandler)

		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			// Make a fake panic by faking the header and adding a
			// bunch of garbage.
			fmt.Fprint(os.Stderr, "panic: foo\n\n")
			for i := 0; i < 1024; i++ {
				fmt.Fprint(os.Stderr, "foobarbaz")
			}

			// Sleep so that it dumps the previous data
			//time.Sleep(1 * time.Millisecond)
			time.Sleep(500 * time.Millisecond)

			// Make a real panic
			panic("I AM REAL!")
		}

		os.Exit(exitStatus)
	case "stack exhaustion":
		exitStatus, err := BasicWrap(panicHandler)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			var f func(a [1000]int64)
			f = func(a [1000]int64) {
				f(a)
			}
			f([1000]int64{})
		}

	case "nil goroutine":
		exitStatus, err := BasicWrap(panicHandler)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			var f func()
			go f()
		}

		os.Exit(exitStatus)
	case "concurrent map write":
		exitStatus, err := BasicWrap(panicHandler)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			m := map[string]int{}

			go func() {
				for {
					m["x"] = 1
				}
			}()
			for {
				_ = m["x"]
			}
		}

		os.Exit(exitStatus)
	case "panic":
		hidePanic := false
		if args[0] == "hide" {
			hidePanic = true
		}

		config := &WrapConfig{
			Handler:   panicHandler,
			HidePanic: hidePanic,
		}

		exitStatus, err := Wrap(config)

		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			panic("uh oh")
		}

		os.Exit(exitStatus)
	case "wrapped":
		child := false
		if len(args) > 0 && args[0] == "child" {
			child = true
		}
		config := &WrapConfig{
			Handler: panicHandler,
		}

		exitStatus, err := Wrap(config)
		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus < 0 {
			if child {
				fmt.Printf("%v", Wrapped(config))
			}
			os.Exit(0)
		}

		if !child {
			fmt.Printf("%v", Wrapped(config))
		}
		os.Exit(exitStatus)
	case "panic-monitor":

		config := &WrapConfig{
			Handler: panicHandler,
			HidePanic: true,
			Monitor: true,
		}

		exitStatus, err := Wrap(config)

		if err != nil {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		if exitStatus != -1 {
			fmt.Fprintf(os.Stderr, "wrap error: %s", err)
			os.Exit(1)
		}

		panic("uh oh")

	default:
		fmt.Fprintf(os.Stderr, "Unknown command: %q\n", cmd)
		os.Exit(2)
	}
}

func TestPanicWrap_Output(t *testing.T) {
	stderr := new(bytes.Buffer)
	stdout := new(bytes.Buffer)

	p := helperProcess("no-panic-output")
	p.Stdout = stdout
	p.Stderr = stderr
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "i am output") {
		t.Fatalf("didn't forward: %#v", stdout.String())
	}

	if !strings.Contains(stderr.String(), "stderr out") {
		t.Fatalf("didn't forward: %#v", stderr.String())
	}
}

/*
TODO(mitchellh): This property would be nice to gain.
func TestPanicWrap_Output_Order(t *testing.T) {
	output := new(bytes.Buffer)

	p := helperProcess("no-panic-ordered-output")
	p.Stdout = output
	p.Stderr = output
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	expectedBuf := new(bytes.Buffer)
	for i := 0; i < 1000; i++ {
		expectedBuf.WriteString("ab")
	}

	actual := strings.TrimSpace(output.String())
	expected := strings.TrimSpace(expectedBuf.String())

	if actual != expected {
		t.Fatalf("bad: %#v", actual)
	}
}
*/

func TestPanicWrap_panicHide(t *testing.T) {
	stdout := new(bytes.Buffer)
	stderr := new(bytes.Buffer)

	p := helperProcess("panic", "hide")
	p.Stdout = stdout
	p.Stderr = stderr
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}

	if strings.Contains(stderr.String(), "panic:") {
		t.Fatalf("shouldn't have panic: %#v", stderr.String())
	}
}

func TestPanicWrap_panicShow(t *testing.T) {
	stdout := new(bytes.Buffer)
	stderr := new(bytes.Buffer)

	p := helperProcess("panic", "show")
	p.Stdout = stdout
	p.Stderr = stderr
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}

	if !strings.Contains(stderr.String(), "panic:") {
		t.Fatalf("should have panic: %#v", stderr.String())
	}
}

func TestPanicWrap_panicLong(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("panic-long")
	p.Stdout = stdout
	p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestPanicWrap_nilGoroutine(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("nil goroutine")
	p.Stdout = stdout
	p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestPanicWrap_stackExhaustion(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("stack exhaustion")
	p.Stdout = stdout
	p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestPanicWrap_concurrentMapWrite(t *testing.T) {
	if runtime.GOARCH == "arm64" && runtime.GOOS == "linux" {
		t.Skip("unsupported on this architecture")
	}
	stdout := new(bytes.Buffer)

	p := helperProcess("concurrent map write")
	p.Stdout = stdout
	p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped:") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestPanicWrap_panicBoundary(t *testing.T) {
	// TODO(mitchellh): panics are currently lost on boundaries
	t.SkipNow()

	stdout := new(bytes.Buffer)

	p := helperProcess("panic-boundary")
	p.Stdout = stdout
	//p.Stderr = new(bytes.Buffer)
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "wrapped: 1015") {
		t.Fatalf("didn't wrap: %#v", stdout.String())
	}
}

func TestWrapped(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("wrapped", "child")
	p.Stdout = stdout
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "true") {
		t.Fatalf("bad: %#v", stdout.String())
	}
}

func TestWrapped_parent(t *testing.T) {
	stdout := new(bytes.Buffer)

	p := helperProcess("wrapped")
	p.Stdout = stdout
	if err := p.Run(); err != nil {
		t.Fatalf("err: %s", err)
	}

	if !strings.Contains(stdout.String(), "false") {
		t.Fatalf("bad: %#v", stdout.String())
	}
}
<|endoftext|>


<commit_before>package parser

import (
	"bufio"
	"bytes"
	"errors"
	"io"
)

type Token int

const (
	ILLEGAL Token = iota
	EOF
	NEWLINE
	WS          // Whitespace
	IDENT       // Identifier, e.g. function name.
	MEMADDR     // Hex address, e.g. 0xcafef00d
	OPEN_PAREN  // (
	CLOSE_PAREN // )
	OPEN_BRACE  // {
	CLOSE_BRACE // }
	STRING      // Delimited by "
	SEP         // ,
	EQUALS      // =
	SIGNAL      // ---
)

var eof = rune(0)
var ErrEOF = errors.New("EOF")

// As it is useful to process newline differently to other
// whitespace don't include it here.
func isWhitespace(ch rune) bool {
	return ch == ' ' || ch == '\t'
}

func isLetter(ch rune) bool {
	return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
}

func isDigit(ch rune) bool {
	return (ch >= '0' && ch <= '9')
}

// Scanner is a lexical scanner implemented with a buffered reader.
type Scanner struct {
	r *bufio.Reader
}

func NewScanner(r io.Reader) *Scanner {
	return &Scanner{r: bufio.NewReader(r)}
}

// read reads the next rune from the buffered reader.
// Returns rune(0) if an error occurs.
func (s *Scanner) read() rune {
	r, _, err := s.r.ReadRune()
	if err != nil {
		return eof
	}
	return r
}

// unreadRune places the previously read rune back on the reader.
func (s *Scanner) unreadRune() error { return s.r.UnreadRune() }

// unreadRunes allows a number of runes to be unread.
func (s *Scanner) unreadRunes(runes int) error {
	for runes > 0 {
		if err := s.r.UnreadRune(); err != nil {
			return err
		}
		runes--
	}
	return nil
}

// Scan returns the next token and literal string it represents.
func (s *Scanner) Scan() (tok Token, lit string) {
	// Read the next rune.
	r := s.read()

	if r == '0' {
		// 0 could be the start of a memory address. Read the next
		// rune and if it is 'x', pass to scanAddress.
		if r := s.read(); r == 'x' {
			return s.scanAddress()
		} else {
			s.unreadRunes(2)
		}
	} else if r == '-' {
		// - could be a signal (lines start with ---).
		if r := s.read(); r == '-' {
			if r := s.read(); r == '-' {
				return SIGNAL, "---"
			} else {
				s.unreadRunes(2)
			}
		} else {
			s.unreadRune()
		}
	} else if r == '"' {
		return s.scanString()
	} else if isWhitespace(r) {
		// Consume all contiguous whitespace.
		s.unreadRune()
		return s.scanWhitespace()
	} else if isLetter(r) || isDigit(r) {
		// If we see a letter then consume as an identifier.
		s.unreadRune()
		return s.scanIdent()
	}

	// Otherwise read the individual character.
	switch r {
	case eof:
		return EOF, ""
	case '(':
		return OPEN_PAREN, string(r)
	case ',':
		return SEP, string(r)
	case ')':
		return CLOSE_PAREN, string(r)
	case '{':
		return OPEN_BRACE, string(r)
	case '}':
		return CLOSE_BRACE, string(r)
	case '=':
		return EQUALS, string(r)
	case '\n':
		return NEWLINE, string(r)
	}

	return ILLEGAL, string(r)
}

// scanAddress consumes a memory address from the scanner.
func (s *Scanner) scanAddress() (tok Token, lit string) {
	var buf bytes.Buffer
	// Prepend 0x as memory addresses are always hex.
	buf.WriteString("0x")

	// Read up to the next whitespace rune.
	for {
		r := s.read()
		if r == eof {
			break
		} else if isWhitespace(r) || r == '\n' {
			s.unreadRune()
			break
		}
		buf.WriteRune(r)
	}

	return MEMADDR, buf.String()
}

// scanString consumes a string from the scanner.
func (s *Scanner) scanString() (tok Token, lit string) {
	var buf bytes.Buffer
	buf.WriteRune('"')

	// Read up to the next inverted comma.
	for {
		r := s.read()
		if r == eof {
			break
		}
		if r == '"' {
			// Consume ellipsis if present.
			if r = s.read(); r == '.' {
				s.read()
				s.read()
				buf.WriteString("...")
			} else {
				s.unreadRune()
			}
			buf.WriteRune(r)
			break
		}
		buf.WriteRune(r)
	}

	return STRING, buf.String()
}

// scanWhitespace consumes the current rune and all contiguous whitespace.
func (s *Scanner) scanWhitespace() (tok Token, lit string) {
	// Create a buffer and read the current character into it.
	var buf bytes.Buffer
	buf.WriteRune(s.read())

	// Read every subsequent whitespace character into the buffer.
	for {
		if r := s.read(); r == eof {
			break
		} else if !isWhitespace(r) {
			s.unreadRune()
			break
		} else {
			buf.WriteRune(r)
		}
	}

	return WS, buf.String()
}

// scanIdent consumes the current rune and all contiguous ident runes.
func (s *Scanner) scanIdent() (tok Token, lit string) {
	// Create a buffer and read the current character into it.
	var buf bytes.Buffer
	buf.WriteRune(s.read())

	// Read every subsequent ident character into the buffer.
	// Non-ident characters and EOF will cause the loop to exit.
	for {
		if r := s.read(); r == eof {
			break
		} else if !isLetter(r) && !isDigit(r) && r != '_' {
			s.unreadRune()
			break
		} else {
			_, _ = buf.WriteRune(r)
		}
	}

	// Otherwise return as a regular identifier.
	return IDENT, buf.String()
}
<commit_msg>Fix ellipsis scanning<commit_after>package parser

import (
	"bufio"
	"bytes"
	"errors"
	"io"
)

type Token int

const (
	ILLEGAL Token = iota
	EOF
	NEWLINE
	WS          // Whitespace
	IDENT       // Identifier, e.g. function name.
	MEMADDR     // Hex address, e.g. 0xcafef00d
	OPEN_PAREN  // (
	CLOSE_PAREN // )
	OPEN_BRACE  // {
	CLOSE_BRACE // }
	STRING      // Delimited by "
	SEP         // ,
	EQUALS      // =
	SIGNAL      // ---
)

var eof = rune(0)
var ErrEOF = errors.New("EOF")

// As it is useful to process newline differently to other
// whitespace don't include it here.
func isWhitespace(ch rune) bool {
	return ch == ' ' || ch == '\t'
}

func isLetter(ch rune) bool {
	return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')
}

func isDigit(ch rune) bool {
	return (ch >= '0' && ch <= '9')
}

// Scanner is a lexical scanner implemented with a buffered reader.
type Scanner struct {
	r *bufio.Reader
}

func NewScanner(r io.Reader) *Scanner {
	return &Scanner{r: bufio.NewReader(r)}
}

// read reads the next rune from the buffered reader.
// Returns rune(0) if an error occurs.
func (s *Scanner) read() rune {
	r, _, err := s.r.ReadRune()
	if err != nil {
		return eof
	}
	return r
}

// unreadRune places the previously read rune back on the reader.
func (s *Scanner) unreadRune() error { return s.r.UnreadRune() }

// unreadRunes allows a number of runes to be unread.
func (s *Scanner) unreadRunes(runes int) error {
	for runes > 0 {
		if err := s.r.UnreadRune(); err != nil {
			return err
		}
		runes--
	}
	return nil
}

// Scan returns the next token and literal string it represents.
func (s *Scanner) Scan() (tok Token, lit string) {
	// Read the next rune.
	r := s.read()

	if r == '0' {
		// 0 could be the start of a memory address. Read the next
		// rune and if it is 'x', pass to scanAddress.
		if r := s.read(); r == 'x' {
			return s.scanAddress()
		} else {
			s.unreadRunes(2)
		}
	} else if r == '-' {
		// - could be a signal (lines start with ---).
		if r := s.read(); r == '-' {
			if r := s.read(); r == '-' {
				return SIGNAL, "---"
			} else {
				s.unreadRunes(2)
			}
		} else {
			s.unreadRune()
		}
	} else if r == '"' {
		return s.scanString()
	} else if isWhitespace(r) {
		// Consume all contiguous whitespace.
		s.unreadRune()
		return s.scanWhitespace()
	} else if isLetter(r) || isDigit(r) {
		// If we see a letter then consume as an identifier.
		s.unreadRune()
		return s.scanIdent()
	}

	// Otherwise read the individual character.
	switch r {
	case eof:
		return EOF, ""
	case '(':
		return OPEN_PAREN, string(r)
	case ',':
		return SEP, string(r)
	case ')':
		return CLOSE_PAREN, string(r)
	case '{':
		return OPEN_BRACE, string(r)
	case '}':
		return CLOSE_BRACE, string(r)
	case '=':
		return EQUALS, string(r)
	case '\n':
		return NEWLINE, string(r)
	}

	return ILLEGAL, string(r)
}

// scanAddress consumes a memory address from the scanner.
func (s *Scanner) scanAddress() (tok Token, lit string) {
	var buf bytes.Buffer
	// Prepend 0x as memory addresses are always hex.
	buf.WriteString("0x")

	// Read up to the next whitespace rune.
	for {
		r := s.read()
		if r == eof {
			break
		} else if isWhitespace(r) || r == '\n' {
			s.unreadRune()
			break
		}
		buf.WriteRune(r)
	}

	return MEMADDR, buf.String()
}

// scanString consumes a string from the scanner.
func (s *Scanner) scanString() (tok Token, lit string) {
	var buf bytes.Buffer
	buf.WriteRune('"')

	// Read up to the next inverted comma.
	for {
		r := s.read()
		if r == eof {
			break
		}
		if r == '"' {
			buf.WriteRune(r)
			// Reached end of literal. Consume ellipsis if present.
			if r = s.read(); r == '.' {
				s.read()
				s.read()
				buf.WriteString("...")
			} else {
				s.unreadRune()
			}
			break
		}
		buf.WriteRune(r)
	}

	return STRING, buf.String()
}

// scanWhitespace consumes the current rune and all contiguous whitespace.
func (s *Scanner) scanWhitespace() (tok Token, lit string) {
	// Create a buffer and read the current character into it.
	var buf bytes.Buffer
	buf.WriteRune(s.read())

	// Read every subsequent whitespace character into the buffer.
	for {
		if r := s.read(); r == eof {
			break
		} else if !isWhitespace(r) {
			s.unreadRune()
			break
		} else {
			buf.WriteRune(r)
		}
	}

	return WS, buf.String()
}

// scanIdent consumes the current rune and all contiguous ident runes.
func (s *Scanner) scanIdent() (tok Token, lit string) {
	// Create a buffer and read the current character into it.
	var buf bytes.Buffer
	buf.WriteRune(s.read())

	// Read every subsequent ident character into the buffer.
	// Non-ident characters and EOF will cause the loop to exit.
	for {
		if r := s.read(); r == eof {
			break
		} else if !isLetter(r) && !isDigit(r) && r != '_' {
			s.unreadRune()
			break
		} else {
			_, _ = buf.WriteRune(r)
		}
	}

	// Otherwise return as a regular identifier.
	return IDENT, buf.String()
}
<|endoftext|>


<commit_before>//
// markup.go
// memeposting markup parser
//
package srnd

import (
  "github.com/mvdan/xurls"
  "html"
  "regexp"
  "strings"
)

// copypasted from https://stackoverflow.com/questions/161738/what-is-the-best-regular-expression-to-check-if-a-string-is-a-valid-url
// var re_external_link = regexp.MustCompile(`((?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?)`);
var re_backlink = regexp.MustCompile(`>> ?([0-9a-f]+)`)

// parse backlink
func backlink(word string) (markup string) {
  re := regexp.MustCompile(`>> ?([0-9a-f]+)`)
  link := re.FindString(word)
  if len(link) > 2 {
    link = re.SubexpNames()[1]
    if len(link) > 2 {
      url := template.findLink(link)
      if len(url) == 0 {
        return ">>" + link + ""
      }
      // backlink exists
      return`<a href="`+url+`">>>` + link + ""
    } else {
      return html.EscapeString(word)
    }
  }
  return html.EscapeString(word)
}

func formatline(line string) (markup string) {
  line = strings.Trim(line, "\t\r\n ")
  if len(line) > 0 {
    if strings.HasPrefix(line, ">") && ! ( strings.HasPrefix(line, ">>") && re_backlink.MatchString(strings.Split(line, " ")[0])) {
      // le ebin meme arrows
      markup += "
"
      markup += html.EscapeString(line)
      markup += "
"
    } else if strings.HasPrefix(line, "==") && strings.HasSuffix(line, "==") {
      // redtext
      markup += "
"
      markup += html.EscapeString(line[2:len(line)-2])
      markup += "
"
    } else {
      // regular line
      markup += "
"
      // for each word
      for _, word := range strings.Split(line, " ") {
        // check for backlink
        if re_backlink.MatchString(word) {
          markup += backlink(word)
        } else {
          // linkify as needed
          word = html.EscapeString(word)
          markup += xurls.Strict.ReplaceAllString(word, `<a href="$1">$1</a>`)
        }
        markup += " "
      }
      markup += "
"
    }
  }
  return
}

// format lines inside a code tag
func formatcodeline(line string) (markup string) {
  markup += html.EscapeString(line)
  markup += "\n"
  return
}

func memeposting(src string) (markup string) {
  found_tag := false
  tag_content := ""
  tag := ""
  // for each line...
  for _, line := range strings.Split(src, "\n") {
    // beginning of code tag ?
    if strings.Count(line, "[code]") > 0 {
      // yes there's a code tag
      found_tag = true
      tag = "code"
    } else if strings.Count(line, "[spoiler]") > 0 {
      // spoiler tag
      found_tag = true
      tag = "spoiler"
    } else if strings.Count(line, "[psy]") > 0 {
      // psy tag
      found_tag = true
      tag = "psy"
    }
    if found_tag {
      // collect content of tag
      tag_content += line + "\n"
      // end of our tag ?
      if strings.Count(line, "[/"+tag+"]") == 1 {
        // yah
        found_tag = false
        var tag_open, tag_close string
        if tag == "code" {
          tag_open = "
"
          tag_close = "
"
        } else if tag == "spoiler" {
          tag_open = ""
          tag_close = ""
        } else if tag == "psy" {
          tag_open = "
"
          tag_close = "
"
        }
        markup += tag_open
        // remove open tag, only once so we can have a code tag verbatum inside
        tag_content = strings.Replace(tag_content, "["+tag+"]", "", 1)
        // remove all close tags, should only have 1
        tag_content = strings.Replace(tag_content, "[/"+tag+"]", "", -1)
        // make into lines
        for _, tag_line := range strings.Split(tag_content, "\n") {
          if tag == "code" {
            markup += formatcodeline(tag_line)
          } else {
            markup += formatline(tag_line)
          }
        }
        // close pre tag
        markup += tag_close
        // reset content buffer
        tag_content = ""
      }
      // next line
      continue
    }
    // format line regularlly
    markup += formatline(line)
  }
  // flush the rest of an incomplete code tag
  for _, line := range strings.Split(tag_content, "\n") {
    markup += formatline(line)
  }
  return
}
<commit_msg>try fixing backlinks again<commit_after>//
// markup.go
// memeposting markup parser
//
package srnd

import (
  "github.com/mvdan/xurls"
  "html"
  "regexp"
  "strings"
)

// copypasted from https://stackoverflow.com/questions/161738/what-is-the-best-regular-expression-to-check-if-a-string-is-a-valid-url
// var re_external_link = regexp.MustCompile(`((?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?)`);
var re_backlink = regexp.MustCompile(`>> ?([0-9a-f]+)`)

// parse backlink
func backlink(word string) (markup string) {
  re := regexp.MustCompile(`>> ?([0-9a-f]+)`)
  link := re.FindString(word)
  if len(link) > 2 {
    link = strings.Trim(link[2:], " ")
    if len(link) > 2 {
      url := template.findLink(link)
      if len(url) == 0 {
        return ">>" + link + ""
      }
      // backlink exists
      return`<a href="`+url+`">>>` + link + ""
    } else {
      return html.EscapeString(word)
    }
  }
  return html.EscapeString(word)
}

func formatline(line string) (markup string) {
  line = strings.Trim(line, "\t\r\n ")
  if len(line) > 0 {
    if strings.HasPrefix(line, ">") && ! ( strings.HasPrefix(line, ">>") && re_backlink.MatchString(strings.Split(line, " ")[0])) {
      // le ebin meme arrows
      markup += "
"
      markup += html.EscapeString(line)
      markup += "
"
    } else if strings.HasPrefix(line, "==") && strings.HasSuffix(line, "==") {
      // redtext
      markup += "
"
      markup += html.EscapeString(line[2:len(line)-2])
      markup += "
"
    } else {
      // regular line
      markup += "
"
      // for each word
      for _, word := range strings.Split(line, " ") {
        // check for backlink
        if re_backlink.MatchString(word) {
          markup += backlink(word)
        } else {
          // linkify as needed
          word = html.EscapeString(word)
          markup += xurls.Strict.ReplaceAllString(word, `<a href="$1">$1</a>`)
        }
        markup += " "
      }
      markup += "
"
    }
  }
  return
}

// format lines inside a code tag
func formatcodeline(line string) (markup string) {
  markup += html.EscapeString(line)
  markup += "\n"
  return
}

func memeposting(src string) (markup string) {
  found_tag := false
  tag_content := ""
  tag := ""
  // for each line...
  for _, line := range strings.Split(src, "\n") {
    // beginning of code tag ?
    if strings.Count(line, "[code]") > 0 {
      // yes there's a code tag
      found_tag = true
      tag = "code"
    } else if strings.Count(line, "[spoiler]") > 0 {
      // spoiler tag
      found_tag = true
      tag = "spoiler"
    } else if strings.Count(line, "[psy]") > 0 {
      // psy tag
      found_tag = true
      tag = "psy"
    }
    if found_tag {
      // collect content of tag
      tag_content += line + "\n"
      // end of our tag ?
      if strings.Count(line, "[/"+tag+"]") == 1 {
        // yah
        found_tag = false
        var tag_open, tag_close string
        if tag == "code" {
          tag_open = "
"
          tag_close = "
"
        } else if tag == "spoiler" {
          tag_open = ""
          tag_close = ""
        } else if tag == "psy" {
          tag_open = "
"
          tag_close = "
"
        }
        markup += tag_open
        // remove open tag, only once so we can have a code tag verbatum inside
        tag_content = strings.Replace(tag_content, "["+tag+"]", "", 1)
        // remove all close tags, should only have 1
        tag_content = strings.Replace(tag_content, "[/"+tag+"]", "", -1)
        // make into lines
        for _, tag_line := range strings.Split(tag_content, "\n") {
          if tag == "code" {
            markup += formatcodeline(tag_line)
          } else {
            markup += formatline(tag_line)
          }
        }
        // close pre tag
        markup += tag_close
        // reset content buffer
        tag_content = ""
      }
      // next line
      continue
    }
    // format line regularlly
    markup += formatline(line)
  }
  // flush the rest of an incomplete code tag
  for _, line := range strings.Split(tag_content, "\n") {
    markup += formatline(line)
  }
  return
}
<|endoftext|>


<commit_before>package build

import (
	"crypto/tls"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path"
	"path/filepath"
	"strings"

	"github.com/cloud66/cxbuild/configuration"
	"github.com/cloud66/cxbuild/squash"
	"github.com/dchest/uniuri"
	"github.com/docker/docker/builder/parser"
	"github.com/fsouza/go-dockerclient"
)

// Builder is a simple Dockerfile builder
type Builder struct {
	Build    *Manifest
	UniqueID string // unique id for this build sequence. This is used for multi-tenanted environments
	Conf     *configuration.Config

	config *tls.Config
	docker docker.Client
	auth   *docker.AuthConfigurations
}

// NewBuilder creates a new builder in a new session
func NewBuilder(manifest *Manifest, conf *configuration.Config) *Builder {
	b := Builder{}
	b.Build = manifest
	b.UniqueID = conf.UniqueID
	b.Conf = conf

	certPath := b.Conf.DockerCert
	endpoint := b.Conf.DockerHost
	ca := path.Join(certPath, "ca.pem")
	cert := path.Join(certPath, "cert.pem")
	key := path.Join(certPath, "key.pem")
	client, err := docker.NewTLSClient(endpoint, cert, key, ca)
	if err != nil {
		b.Conf.Logger.Fatal(err.Error())
		return nil
	}

	b.docker = *client

	usr, err := user.Current()
	if err != nil {
		b.Conf.Logger.Fatalf("Failed to find the current user: %s", err.Error())
	}

	if _, err := os.Stat(filepath.Join(usr.HomeDir, ".dockercfg")); err == nil {
		authStream, err := os.Open(filepath.Join(usr.HomeDir, ".dockercfg"))
		if err != nil {
			b.Conf.Logger.Fatal("Unable to read .dockerconf file")
		}
		defer authStream.Close()

		auth, err := docker.NewAuthConfigurations(authStream)
		if err != nil {
			b.Conf.Logger.Fatalf("Invalid .dockerconf: %s", err.Error())
		}
		b.auth = auth
	}

	if err != nil {
		b.Conf.Logger.Fatalf("Failed to connect to Docker daemon %s", err.Error())
	}

	return &b
}

// StartBuild runs the build process end to end
func (b *Builder) StartBuild(startStep string) error {
	var steps []Step
	if startStep == "" {
		b.Conf.Logger.Notice("Starting the build chain")
		steps = b.Build.Steps
	} else {
		b.Conf.Logger.Notice("Starting the build chain from '%s'", startStep)
		for idx, s := range b.Build.Steps {
			if s.Name == startStep {
				steps = b.Build.Steps[idx:]
				break
			}
		}
	}

	for _, s := range steps {
		err := b.BuildStep(&s)
		if err != nil {
			return err
		}
	}

	// Clear after yourself: images, containers, etc (optional for premium users)
	for _, s := range b.Build.Steps {
		if s.Keep {
			continue
		}

		b.Conf.Logger.Debug("Removing unwanted image %s", b.uniqueStepName(&s))
		err := b.docker.RemoveImage(b.uniqueStepName(&s))
		if err != nil {
			return err
		}
	}
	return nil
}

func (b *Builder) uniqueStepName(step *Step) string {
	if b.UniqueID == "" {
		return step.Name
	}

	return strings.ToLower(fmt.Sprintf("%s.%s", b.UniqueID, step.Name))
}

// BuildStep builds a single step
func (b *Builder) BuildStep(step *Step) error {
	b.Conf.Logger.Notice("Building %s", step.Name)
	// fix the Dockerfile
	err := b.replaceFromField(step)
	if err != nil {
		return err
	}

	// call Docker to build the Dockerfile (from the parsed file)
	opts := docker.BuildImageOptions{
		Name:                b.uniqueStepName(step),
		Dockerfile:          filepath.Base(b.uniqueDockerfile(step)),
		NoCache:             b.Conf.NoCache,
		SuppressOutput:      b.Conf.SuppressOutput,
		RmTmpContainer:      b.Conf.RmTmpContainers,
		ForceRmTmpContainer: b.Conf.ForceRmTmpContainer,
		OutputStream:        os.Stdout, // TODO: use a multi writer to get a stream out for the API
		ContextDir:          b.Build.Workdir,
	}

	if b.auth != nil {
		opts.AuthConfigs = *b.auth
	}

	err = b.docker.BuildImage(opts)
	if err != nil {
		return err
	}

	// if there are any artefacts to be picked up, create a container and copy them over
	// we also need a container if there are cleanup commands
	if len(step.Artefacts) > 0 || len(step.Cleanup.Commands) > 0 {
		b.Conf.Logger.Notice("Building container based on the image")

		// create a container
		container, err := b.createContainer(step)
		if err != nil {
			return err
		}

		if len(step.Cleanup.Commands) > 0 {
			// start the container
			b.Conf.Logger.Notice("Starting container %s to run cleanup commands", container.ID)
			startOpts := &docker.HostConfig{}
			err := b.docker.StartContainer(container.ID, startOpts)
			if err != nil {
				return err
			}

			for _, cmd := range step.Cleanup.Commands {
				b.Conf.Logger.Debug("Running cleanup command %s on %s", cmd, container.ID)
				// create an exec for the commands
				execOpts := docker.CreateExecOptions{
					Container:    container.ID,
					AttachStdin:  false,
					AttachStdout: true,
					AttachStderr: true,
					Tty:          false,
					Cmd:          strings.Split(cmd, " "),
				}
				execObj, err := b.docker.CreateExec(execOpts)
				if err != nil {
					return err
				}

				success := make(chan struct{})
				startExecOpts := docker.StartExecOptions{
					OutputStream: os.Stdout,
					ErrorStream:  os.Stderr,
					RawTerminal:  true,
				}

				go func() {
					if err := b.docker.StartExec(execObj.ID, startExecOpts); err != nil {
						b.Conf.Logger.Error("Failed to run cleanup commands %s", err.Error())
					}
					success <- struct{}{}
				}()
				<-success
			}

			// commit the container
			cmtOpts := docker.CommitContainerOptions{
				Container: container.ID,
			}

			b.Conf.Logger.Debug("Commiting the container %s", container.ID)
			img, err := b.docker.CommitContainer(cmtOpts)
			if err != nil {
				return err
			}

			b.Conf.Logger.Debug("Stopping the container %s", container.ID)
			err = b.docker.StopContainer(container.ID, 0)
			if err != nil {
				return err
			}

			tmpFile, err := ioutil.TempFile("", "cxbuild-export-")
			if err != nil {
				return err
			}
			defer tmpFile.Close()
			tarWriter, err := os.Create(tmpFile.Name())
			if err != nil {
				return err
			}
			defer tarWriter.Close()
			// save the container
			expOpts := docker.ExportImageOptions{
				Name:         img.ID,
				OutputStream: tarWriter,
			}

			b.Conf.Logger.Notice("Exporting cleaned up container %s to %s", img.ID, tmpFile.Name())
			err = b.docker.ExportImage(expOpts)
			if err != nil {
				return err
			}

			// Squash
			sqTmpFile, err := ioutil.TempFile("", "cxbuild-export-")
			if err != nil {
				return err
			}
			defer sqTmpFile.Close()
			b.Conf.Logger.Notice("Squashing image %s into %s", sqTmpFile.Name(), img.ID)

			squasher := squash.Squasher{Conf: b.Conf}
			err = squasher.Squash(tmpFile.Name(), sqTmpFile.Name(), b.uniqueStepName(step))
			if err != nil {
				return err
			}

			b.Conf.Logger.Debug("Removing exported temp files")
			err = os.Remove(tmpFile.Name())
			if err != nil {
				return err
			}
			// Load
			sqashedFile, err := os.Open(sqTmpFile.Name())
			if err != nil {
				return err
			}
			defer sqashedFile.Close()

			loadOps := docker.LoadImageOptions{
				InputStream: sqashedFile,
			}
			b.Conf.Logger.Debug("Loading squashed image into docker")
			err = b.docker.LoadImage(loadOps)
			if err != nil {
				return err
			}

			err = os.Remove(sqTmpFile.Name())
			if err != nil {
				return err
			}
		}

		if len(step.Artefacts) > 0 {
			b.Conf.Logger.Notice("Copying artefacts from %s", container.ID)

			for _, art := range step.Artefacts {
				err = b.copyToHost(&art, container.ID)
				if err != nil {
					return err
				}
			}
		}

		// remove the created container
		removeOpts := docker.RemoveContainerOptions{
			ID:            container.ID,
			RemoveVolumes: true,
			Force:         true,
		}

		b.Conf.Logger.Debug("Removing built container %s", container.ID)
		err = b.docker.RemoveContainer(removeOpts)
		if err != nil {
			return err
		}
	}

	// clean up the parsed docker file. It will remain there if there was a problem
	err = os.Remove(b.uniqueDockerfile(step))
	if err != nil {
		return err
	}

	return nil
}

// this replaces the FROM field in the Dockerfile to one with the previous step's unique name
// it stores the parsed result Dockefile in uniqueSessionName file
func (b *Builder) replaceFromField(step *Step) error {
	b.Conf.Logger.Notice("Parsing and converting '%s'", step.Dockerfile)

	rwc, err := os.Open(path.Join(b.Build.Workdir, step.Dockerfile))
	if err != nil {
		return err
	}
	defer rwc.Close()

	node, err := parser.Parse(rwc)
	if err != nil {
		return err
	}

	for _, child := range node.Children {
		if child.Value == "from" {
			// found it. is it from anyone we know?
			if child.Next == nil {
				return errors.New("invalid Dockerfile. No valid FROM found")
			}

			imageName := child.Next.Value
			found, err := step.Manifest.FindStepByName(imageName)
			if err != nil {
				return err
			}

			if found != nil {
				child.Next.Value = b.uniqueStepName(found)
			}
		}
	}

	// did it have any effect?
	err = ioutil.WriteFile(b.uniqueDockerfile(step), []byte(dumpDockerfile(node)), 0644)
	if err != nil {
		return err
	}

	return nil
}

func (b *Builder) copyToHost(a *Artefact, container string) error {
	// create the dest folder if not there
	err := os.MkdirAll(a.Dest, 0777)
	if err != nil {
		return err
	}

	destFile := path.Join(b.Build.Workdir, a.Dest, filepath.Base(a.Source))
	dest, err := os.Create(destFile)
	if err != nil {
		return err
	}
	defer dest.Close()

	opt := docker.CopyFromContainerOptions{
		OutputStream: dest,
		Container:    container,
		Resource:     a.Source,
	}

	b.Conf.Logger.Info("Copying from %s to %s", a.Source, destFile)

	return b.docker.CopyFromContainer(opt)
}

func (b *Builder) createContainer(step *Step) (*docker.Container, error) {
	config := docker.Config{
		AttachStdout: true,
		AttachStdin:  false,
		AttachStderr: true,
		Image:        b.uniqueStepName(step),
		Cmd:          []string{"/bin/bash"},
		Tty:          true,
	}

	opts := docker.CreateContainerOptions{
		Name:   b.uniqueStepName(step) + "." + uniuri.New(),
		Config: &config,
	}
	container, err := b.docker.CreateContainer(opts)
	if err != nil {
		return nil, err
	}

	return container, nil
}

func dumpDockerfile(node *parser.Node) string {
	str := ""
	str += node.Value

	if len(node.Flags) > 0 {
		str += fmt.Sprintf(" %q", node.Flags)
	}

	for _, n := range node.Children {
		str += dumpDockerfile(n) + "\n"
	}

	if node.Next != nil {
		for n := node.Next; n != nil; n = n.Next {
			if len(n.Children) > 0 {
				str += " " + dumpDockerfile(n)
			} else {
				str += " " + n.Value
			}
		}
	}

	return strings.TrimSpace(str)
}

func (b *Builder) uniqueDockerfile(step *Step) string {
	return filepath.Join(b.Build.Workdir, b.uniqueStepName(step))
}
<commit_msg>builder files were moved to builder/dockerfile at the github repo<commit_after>package build

import (
	"crypto/tls"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path"
	"path/filepath"
	"strings"

	"github.com/cloud66/cxbuild/configuration"
	"github.com/cloud66/cxbuild/squash"
	"github.com/dchest/uniuri"
	"github.com/docker/docker/builder/dockerfile/parser"
	"github.com/fsouza/go-dockerclient"
)

// Builder is a simple Dockerfile builder
type Builder struct {
	Build    *Manifest
	UniqueID string // unique id for this build sequence. This is used for multi-tenanted environments
	Conf     *configuration.Config

	config *tls.Config
	docker docker.Client
	auth   *docker.AuthConfigurations
}

// NewBuilder creates a new builder in a new session
func NewBuilder(manifest *Manifest, conf *configuration.Config) *Builder {
	b := Builder{}
	b.Build = manifest
	b.UniqueID = conf.UniqueID
	b.Conf = conf

	certPath := b.Conf.DockerCert
	endpoint := b.Conf.DockerHost
	ca := path.Join(certPath, "ca.pem")
	cert := path.Join(certPath, "cert.pem")
	key := path.Join(certPath, "key.pem")
	client, err := docker.NewTLSClient(endpoint, cert, key, ca)
	if err != nil {
		b.Conf.Logger.Fatal(err.Error())
		return nil
	}

	b.docker = *client

	usr, err := user.Current()
	if err != nil {
		b.Conf.Logger.Fatalf("Failed to find the current user: %s", err.Error())
	}

	if _, err := os.Stat(filepath.Join(usr.HomeDir, ".dockercfg")); err == nil {
		authStream, err := os.Open(filepath.Join(usr.HomeDir, ".dockercfg"))
		if err != nil {
			b.Conf.Logger.Fatal("Unable to read .dockerconf file")
		}
		defer authStream.Close()

		auth, err := docker.NewAuthConfigurations(authStream)
		if err != nil {
			b.Conf.Logger.Fatalf("Invalid .dockerconf: %s", err.Error())
		}
		b.auth = auth
	}

	if err != nil {
		b.Conf.Logger.Fatalf("Failed to connect to Docker daemon %s", err.Error())
	}

	return &b
}

// StartBuild runs the build process end to end
func (b *Builder) StartBuild(startStep string) error {
	var steps []Step
	if startStep == "" {
		b.Conf.Logger.Notice("Starting the build chain")
		steps = b.Build.Steps
	} else {
		b.Conf.Logger.Notice("Starting the build chain from '%s'", startStep)
		for idx, s := range b.Build.Steps {
			if s.Name == startStep {
				steps = b.Build.Steps[idx:]
				break
			}
		}
	}

	for _, s := range steps {
		err := b.BuildStep(&s)
		if err != nil {
			return err
		}
	}

	// Clear after yourself: images, containers, etc (optional for premium users)
	for _, s := range b.Build.Steps {
		if s.Keep {
			continue
		}

		b.Conf.Logger.Debug("Removing unwanted image %s", b.uniqueStepName(&s))
		err := b.docker.RemoveImage(b.uniqueStepName(&s))
		if err != nil {
			return err
		}
	}
	return nil
}

func (b *Builder) uniqueStepName(step *Step) string {
	if b.UniqueID == "" {
		return step.Name
	}

	return strings.ToLower(fmt.Sprintf("%s.%s", b.UniqueID, step.Name))
}

// BuildStep builds a single step
func (b *Builder) BuildStep(step *Step) error {
	b.Conf.Logger.Notice("Building %s", step.Name)
	// fix the Dockerfile
	err := b.replaceFromField(step)
	if err != nil {
		return err
	}

	// call Docker to build the Dockerfile (from the parsed file)
	opts := docker.BuildImageOptions{
		Name:                b.uniqueStepName(step),
		Dockerfile:          filepath.Base(b.uniqueDockerfile(step)),
		NoCache:             b.Conf.NoCache,
		SuppressOutput:      b.Conf.SuppressOutput,
		RmTmpContainer:      b.Conf.RmTmpContainers,
		ForceRmTmpContainer: b.Conf.ForceRmTmpContainer,
		OutputStream:        os.Stdout, // TODO: use a multi writer to get a stream out for the API
		ContextDir:          b.Build.Workdir,
	}

	if b.auth != nil {
		opts.AuthConfigs = *b.auth
	}

	err = b.docker.BuildImage(opts)
	if err != nil {
		return err
	}

	// if there are any artefacts to be picked up, create a container and copy them over
	// we also need a container if there are cleanup commands
	if len(step.Artefacts) > 0 || len(step.Cleanup.Commands) > 0 {
		b.Conf.Logger.Notice("Building container based on the image")

		// create a container
		container, err := b.createContainer(step)
		if err != nil {
			return err
		}

		if len(step.Cleanup.Commands) > 0 {
			// start the container
			b.Conf.Logger.Notice("Starting container %s to run cleanup commands", container.ID)
			startOpts := &docker.HostConfig{}
			err := b.docker.StartContainer(container.ID, startOpts)
			if err != nil {
				return err
			}

			for _, cmd := range step.Cleanup.Commands {
				b.Conf.Logger.Debug("Running cleanup command %s on %s", cmd, container.ID)
				// create an exec for the commands
				execOpts := docker.CreateExecOptions{
					Container:    container.ID,
					AttachStdin:  false,
					AttachStdout: true,
					AttachStderr: true,
					Tty:          false,
					Cmd:          strings.Split(cmd, " "),
				}
				execObj, err := b.docker.CreateExec(execOpts)
				if err != nil {
					return err
				}

				success := make(chan struct{})
				startExecOpts := docker.StartExecOptions{
					OutputStream: os.Stdout,
					ErrorStream:  os.Stderr,
					RawTerminal:  true,
				}

				go func() {
					if err := b.docker.StartExec(execObj.ID, startExecOpts); err != nil {
						b.Conf.Logger.Error("Failed to run cleanup commands %s", err.Error())
					}
					success <- struct{}{}
				}()
				<-success
			}

			// commit the container
			cmtOpts := docker.CommitContainerOptions{
				Container: container.ID,
			}

			b.Conf.Logger.Debug("Commiting the container %s", container.ID)
			img, err := b.docker.CommitContainer(cmtOpts)
			if err != nil {
				return err
			}

			b.Conf.Logger.Debug("Stopping the container %s", container.ID)
			err = b.docker.StopContainer(container.ID, 0)
			if err != nil {
				return err
			}

			tmpFile, err := ioutil.TempFile("", "cxbuild-export-")
			if err != nil {
				return err
			}
			defer tmpFile.Close()
			tarWriter, err := os.Create(tmpFile.Name())
			if err != nil {
				return err
			}
			defer tarWriter.Close()
			// save the container
			expOpts := docker.ExportImageOptions{
				Name:         img.ID,
				OutputStream: tarWriter,
			}

			b.Conf.Logger.Notice("Exporting cleaned up container %s to %s", img.ID, tmpFile.Name())
			err = b.docker.ExportImage(expOpts)
			if err != nil {
				return err
			}

			// Squash
			sqTmpFile, err := ioutil.TempFile("", "cxbuild-export-")
			if err != nil {
				return err
			}
			defer sqTmpFile.Close()
			b.Conf.Logger.Notice("Squashing image %s into %s", sqTmpFile.Name(), img.ID)

			squasher := squash.Squasher{Conf: b.Conf}
			err = squasher.Squash(tmpFile.Name(), sqTmpFile.Name(), b.uniqueStepName(step))
			if err != nil {
				return err
			}

			b.Conf.Logger.Debug("Removing exported temp files")
			err = os.Remove(tmpFile.Name())
			if err != nil {
				return err
			}
			// Load
			sqashedFile, err := os.Open(sqTmpFile.Name())
			if err != nil {
				return err
			}
			defer sqashedFile.Close()

			loadOps := docker.LoadImageOptions{
				InputStream: sqashedFile,
			}
			b.Conf.Logger.Debug("Loading squashed image into docker")
			err = b.docker.LoadImage(loadOps)
			if err != nil {
				return err
			}

			err = os.Remove(sqTmpFile.Name())
			if err != nil {
				return err
			}
		}

		if len(step.Artefacts) > 0 {
			b.Conf.Logger.Notice("Copying artefacts from %s", container.ID)

			for _, art := range step.Artefacts {
				err = b.copyToHost(&art, container.ID)
				if err != nil {
					return err
				}
			}
		}

		// remove the created container
		removeOpts := docker.RemoveContainerOptions{
			ID:            container.ID,
			RemoveVolumes: true,
			Force:         true,
		}

		b.Conf.Logger.Debug("Removing built container %s", container.ID)
		err = b.docker.RemoveContainer(removeOpts)
		if err != nil {
			return err
		}
	}

	// clean up the parsed docker file. It will remain there if there was a problem
	err = os.Remove(b.uniqueDockerfile(step))
	if err != nil {
		return err
	}

	return nil
}

// this replaces the FROM field in the Dockerfile to one with the previous step's unique name
// it stores the parsed result Dockefile in uniqueSessionName file
func (b *Builder) replaceFromField(step *Step) error {
	b.Conf.Logger.Notice("Parsing and converting '%s'", step.Dockerfile)

	rwc, err := os.Open(path.Join(b.Build.Workdir, step.Dockerfile))
	if err != nil {
		return err
	}
	defer rwc.Close()

	node, err := parser.Parse(rwc)
	if err != nil {
		return err
	}

	for _, child := range node.Children {
		if child.Value == "from" {
			// found it. is it from anyone we know?
			if child.Next == nil {
				return errors.New("invalid Dockerfile. No valid FROM found")
			}

			imageName := child.Next.Value
			found, err := step.Manifest.FindStepByName(imageName)
			if err != nil {
				return err
			}

			if found != nil {
				child.Next.Value = b.uniqueStepName(found)
			}
		}
	}

	// did it have any effect?
	err = ioutil.WriteFile(b.uniqueDockerfile(step), []byte(dumpDockerfile(node)), 0644)
	if err != nil {
		return err
	}

	return nil
}

func (b *Builder) copyToHost(a *Artefact, container string) error {
	// create the dest folder if not there
	err := os.MkdirAll(a.Dest, 0777)
	if err != nil {
		return err
	}

	destFile := path.Join(b.Build.Workdir, a.Dest, filepath.Base(a.Source))
	dest, err := os.Create(destFile)
	if err != nil {
		return err
	}
	defer dest.Close()

	opt := docker.CopyFromContainerOptions{
		OutputStream: dest,
		Container:    container,
		Resource:     a.Source,
	}

	b.Conf.Logger.Info("Copying from %s to %s", a.Source, destFile)

	return b.docker.CopyFromContainer(opt)
}

func (b *Builder) createContainer(step *Step) (*docker.Container, error) {
	config := docker.Config{
		AttachStdout: true,
		AttachStdin:  false,
		AttachStderr: true,
		Image:        b.uniqueStepName(step),
		Cmd:          []string{"/bin/bash"},
		Tty:          true,
	}

	opts := docker.CreateContainerOptions{
		Name:   b.uniqueStepName(step) + "." + uniuri.New(),
		Config: &config,
	}
	container, err := b.docker.CreateContainer(opts)
	if err != nil {
		return nil, err
	}

	return container, nil
}

func dumpDockerfile(node *parser.Node) string {
	str := ""
	str += node.Value

	if len(node.Flags) > 0 {
		str += fmt.Sprintf(" %q", node.Flags)
	}

	for _, n := range node.Children {
		str += dumpDockerfile(n) + "\n"
	}

	if node.Next != nil {
		for n := node.Next; n != nil; n = n.Next {
			if len(n.Children) > 0 {
				str += " " + dumpDockerfile(n)
			} else {
				str += " " + n.Value
			}
		}
	}

	return strings.TrimSpace(str)
}

func (b *Builder) uniqueDockerfile(step *Step) string {
	return filepath.Join(b.Build.Workdir, b.uniqueStepName(step))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"

	"github.com/yutaro/slack-cmd-go"
)

func main() {
	conf := scmd.LoadToml("config.toml")
	bot := scmd.New(conf.TOKEN)

	bot.OneCmd("test", "test options and flags",
		func(c *scmd.Context) {
			flags := c.GetFlags()
			options := c.GetOptions()

			fmt.Println(flags)
			fmt.Println(options)
		})

	bot.Start()
}
<commit_msg>option and args<commit_after>package main

import (
	"fmt"

	"github.com/yutaro/slack-cmd-go"
)

func main() {
	conf := scmd.LoadToml("config.toml")
	bot := scmd.New(conf.TOKEN)

	bot.OneCmd("test", "test options and flags",
		func(c *scmd.Context) {
			args := c.GetArgs()
			flags := c.GetFlags()
			options := c.GetOptions()

			fmt.Println("--- test ---")
			fmt.Printf("options : %v , flags : %v , args : %v \n", options, flags, args)
		})

	bot.Start()
}
<|endoftext|>