<commit_before>package board

import (
	"color"
	"errors"
	"matrix"
	"piece"
)

type Board struct {
	matrix.Matrix
	first [8][8]bool
}

func NewBoard() *Board {
	board := new(Board)
	board.Matrix = matrix.Starting()
	for i := 0; i < 8; i++ {
		board.first[0][i] = true
		board.first[1][i] = true
		board.first[6][i] = true
		board.first[7][i] = true
	}
	return board
}

func (board Board) IsFirst(p matrix.Point) bool {
	return board.first[p.Y][p.X]
}

func (board *Board) IsCastling(from, to matrix.Point) bool {
	isKing := piece.King.IsSymbol(board.Matrix[from.Y][from.X])
	diff := from.Diff(to)
	return isKing && (diff == matrix.Point{0, 2} || diff == matrix.Point{0, -2})
}

func (board *Board) CanCastling(from, to matrix.Point) bool {
	diff := from.Diff(to)
	rfrom := from
	rto := to

	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}
	fsymbol := board.Matrix[rfrom.Y][rfrom.X]
	if piece.Rook.IsSymbol(fsymbol) == false {
		return false
	} else if board.first[rfrom.Y][rfrom.X] == false {
		return false
	} else if board.Matrix.ExistBarrier(rfrom, rto) {
		return false
	}
	return true
}

func (board *Board) Castling(from, to matrix.Point) {
	diff := from.Diff(to)
	rfrom := from
	rto := to
	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}

	board.Matrix[to.Y][to.X] = board.Matrix[from.Y][from.X]
	board.Matrix[from.Y][from.X] = ' '
	board.first[from.Y][from.X] = false
	board.first[to.Y][to.X] = false
	board.Matrix[rto.Y][rto.X] = board.Matrix[rfrom.Y][rfrom.X]
	board.Matrix[rfrom.Y][rfrom.X] = ' '
	board.first[rfrom.Y][rfrom.X] = false
	board.first[rto.Y][rto.X] = false
}

func (board *Board) CanMove(from, to matrix.Point, c color.Color) (bool, error) {
	if matrix.InMatrix(from) == false || matrix.InMatrix(to) == false {
		return false, errors.New("out of board")
	}

	fsymbol := board.Matrix[from.Y][from.X]
	tsymbol := board.Matrix[to.Y][to.X]

	fcolor := color.WhichColor(board.Matrix[from.Y][from.X])
	tcolor := color.WhichColor(board.Matrix[to.Y][to.X])
	diff := matrix.Point{0, 0}
	if fcolor == color.White {
		diff = from.Diff(to)
	} else if fcolor == color.Black {
		diff = to.Diff(from)
	}
	if fcolor != c || tcolor == c {
		return false, errors.New("cannot move pieces that is not yours")
	}

	fpiece := piece.WhichPiece(fsymbol)
	toEnemy := color.WhichColor(board.Matrix[to.Y][to.X]) == c.Enemy()
	canMove := fpiece.CanMove(diff, board.first[from.Y][from.X], toEnemy)
	existBarrier := board.Matrix.ExistBarrier(from, to)
	if canMove == false || (existBarrier && piece.Knight.IsSymbol(fsymbol) == false) {
		return false, errors.New("cannot move this piece to there")
	}

	ffirst := board.first[from.Y][from.X]
	tfirst := board.first[to.Y][to.X]

	isCastling := board.IsCastling(from, to)
	canCastling := isCastling && board.CanCastling(from, to)
	if isCastling && canCastling == false {
		return false, errors.New("cannnot castle to that point")
	} else if canCastling == true {
		board.Castling(from, to)
	} else {
		board.Move(from, to, false)
	}

	isChecked := board.IsChecked(c)
	board.Matrix[from.Y][from.X] = fsymbol
	board.Matrix[to.Y][to.X] = tsymbol
	board.first[from.Y][from.X] = ffirst
	board.first[to.Y][to.X] = tfirst
	if isChecked {
		return false, errors.New("cannot move that piece there: your king will be checked")
	} else {
		return true, nil
	}
}

func (board *Board) Move(from, to matrix.Point, isCastling bool) {
	if isCastling {
		board.Castling(from, to)
	} else {
		board.Matrix[to.Y][to.X] = board.Matrix[from.Y][from.X]
		board.Matrix[from.Y][from.X] = ' '
		board.first[from.Y][from.X] = false
		board.first[to.Y][to.X] = false
	}
}

func (board *Board) Promotion(pawn matrix.Point, choice piece.Piece, c color.Color) {
	if matrix.IsDeepest(pawn, c) {
		board.Matrix[pawn.Y][pawn.X] = choice.Symbol(c)
	}
}
<commit_msg>Check in Promotion too<commit_after>package board

import (
	"color"
	"errors"
	"matrix"
	"piece"
)

type Board struct {
	matrix.Matrix
	first [8][8]bool
}

func NewBoard() *Board {
	board := new(Board)
	board.Matrix = matrix.Starting()
	for i := 0; i < 8; i++ {
		board.first[0][i] = true
		board.first[1][i] = true
		board.first[6][i] = true
		board.first[7][i] = true
	}
	return board
}

func (board Board) IsFirst(p matrix.Point) bool {
	return board.first[p.Y][p.X]
}

func (board *Board) IsCastling(from, to matrix.Point) bool {
	isKing := piece.King.IsSymbol(board.Matrix[from.Y][from.X])
	diff := from.Diff(to)
	return isKing && (diff == matrix.Point{0, 2} || diff == matrix.Point{0, -2})
}

func (board *Board) CanCastling(from, to matrix.Point) bool {
	diff := from.Diff(to)
	rfrom := from
	rto := to

	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}
	fsymbol := board.Matrix[rfrom.Y][rfrom.X]
	if piece.Rook.IsSymbol(fsymbol) == false {
		return false
	} else if board.first[rfrom.Y][rfrom.X] == false {
		return false
	} else if board.Matrix.ExistBarrier(rfrom, rto) {
		return false
	}
	return true
}

func (board *Board) Castling(from, to matrix.Point) {
	diff := from.Diff(to)
	rfrom := from
	rto := to
	if diff.X == 2 {
		rfrom.X = 7
		rto.X = to.X - 1
	} else {
		rfrom.X = 0
		rto.X = to.X + 1
	}

	board.Matrix[to.Y][to.X] = board.Matrix[from.Y][from.X]
	board.Matrix[from.Y][from.X] = ' '
	board.first[from.Y][from.X] = false
	board.first[to.Y][to.X] = false
	board.Matrix[rto.Y][rto.X] = board.Matrix[rfrom.Y][rfrom.X]
	board.Matrix[rfrom.Y][rfrom.X] = ' '
	board.first[rfrom.Y][rfrom.X] = false
	board.first[rto.Y][rto.X] = false
}

func (board *Board) CanMove(from, to matrix.Point, c color.Color) (bool, error) {
	if matrix.InMatrix(from) == false || matrix.InMatrix(to) == false {
		return false, errors.New("out of board")
	}

	fsymbol := board.Matrix[from.Y][from.X]
	tsymbol := board.Matrix[to.Y][to.X]

	fcolor := color.WhichColor(board.Matrix[from.Y][from.X])
	tcolor := color.WhichColor(board.Matrix[to.Y][to.X])
	diff := matrix.Point{0, 0}
	if fcolor == color.White {
		diff = from.Diff(to)
	} else if fcolor == color.Black {
		diff = to.Diff(from)
	}
	if fcolor != c || tcolor == c {
		return false, errors.New("cannot move pieces that is not yours")
	}

	fpiece := piece.WhichPiece(fsymbol)
	toEnemy := color.WhichColor(board.Matrix[to.Y][to.X]) == c.Enemy()
	canMove := fpiece.CanMove(diff, board.first[from.Y][from.X], toEnemy)
	existBarrier := board.Matrix.ExistBarrier(from, to)
	if canMove == false || (existBarrier && piece.Knight.IsSymbol(fsymbol) == false) {
		return false, errors.New("cannot move this piece to there")
	}

	ffirst := board.first[from.Y][from.X]
	tfirst := board.first[to.Y][to.X]

	isCastling := board.IsCastling(from, to)
	canCastling := isCastling && board.CanCastling(from, to)
	if isCastling && canCastling == false {
		return false, errors.New("cannnot castle to that point")
	} else if canCastling == true {
		board.Castling(from, to)
	} else {
		board.Move(from, to, false)
	}

	isChecked := board.IsChecked(c)
	board.Matrix[from.Y][from.X] = fsymbol
	board.Matrix[to.Y][to.X] = tsymbol
	board.first[from.Y][from.X] = ffirst
	board.first[to.Y][to.X] = tfirst
	if isChecked {
		return false, errors.New("cannot move that piece there: your king will be checked")
	} else {
		return true, nil
	}
}

func (board *Board) Move(from, to matrix.Point, isCastling bool) {
	if isCastling {
		board.Castling(from, to)
	} else {
		board.Matrix[to.Y][to.X] = board.Matrix[from.Y][from.X]
		board.Matrix[from.Y][from.X] = ' '
		board.first[from.Y][from.X] = false
		board.first[to.Y][to.X] = false
	}
}

func (board *Board) Promotion(pawn matrix.Point, choice piece.Piece, c color.Color) {
	if matrix.IsDeepest(pawn, c) && piece.CanPromotionTo(choice) {
		board.Matrix[pawn.Y][pawn.X] = choice.Symbol(c)
	}
}
<|endoftext|>


<commit_before>package commands

import (
	"errors"
	"fmt"
	"os"
	"strconv"

	"../dos"
	. "../interpreter"
)

var cd_history = make([]string, 0, 100)
var cd_uniq = map[string]int{}

func push_cd_history() {
	directory, err := os.Getwd()
	if err != nil {
		return
	}
	if i, ok := cd_uniq[directory]; ok {
		for ; i < len(cd_history)-1; i++ {
			cd_history[i] = cd_history[i+1]
			cd_uniq[cd_history[i]] = i
		}
		cd_history[i] = directory
		cd_uniq[directory] = i
	} else {
		cd_uniq[directory] = len(cd_history)
		cd_history = append(cd_history, directory)
	}
}

func cmd_cd(cmd *Interpreter) (NextT, error) {
	var err error
	if len(cmd.Args) >= 2 {
		if cmd.Args[1] == "-" {
			if len(cd_history) < 1 {
				return CONTINUE, errors.New("cd - : there is no previous directory")

			}
			directory := cd_history[len(cd_history)-1]
			push_cd_history()
			err = dos.Chdir(directory)
		} else if cmd.Args[1] == "-h" || cmd.Args[1] == "?" {
			i := len(cd_history) - 10
			if i < 0 {
				i = 0
			}
			for ; i < len(cd_history); i++ {
				fmt.Fprintf(cmd.Stdout, "%d %s\n", i-len(cd_history), cd_history[i])
			}
		} else if i, err := strconv.ParseInt(cmd.Args[1], 10, 0); err == nil && i < 0 {
			i += int64(len(cd_history))
			if i < 0 {
				return CONTINUE, fmt.Errorf("cd %s: too old history", cmd.Args[1])
			}
			directory := cd_history[i]
			push_cd_history()
			err = dos.Chdir(directory)
		} else {
			push_cd_history()
			err = dos.Chdir(cmd.Args[1])
		}
		return CONTINUE, err
	}
	home := dos.GetHome()
	if home != "" {
		push_cd_history()
		return CONTINUE, dos.Chdir(home)
	}
	return cmd_pwd(cmd)
}
<commit_msg>Fix:`cd` didn't show error for unexisted directory<commit_after>package commands

import (
	"errors"
	"fmt"
	"os"
	"strconv"

	"../dos"
	. "../interpreter"
)

var cd_history = make([]string, 0, 100)
var cd_uniq = map[string]int{}

func push_cd_history() {
	directory, err := os.Getwd()
	if err != nil {
		return
	}
	if i, ok := cd_uniq[directory]; ok {
		for ; i < len(cd_history)-1; i++ {
			cd_history[i] = cd_history[i+1]
			cd_uniq[cd_history[i]] = i
		}
		cd_history[i] = directory
		cd_uniq[directory] = i
	} else {
		cd_uniq[directory] = len(cd_history)
		cd_history = append(cd_history, directory)
	}
}

func cmd_cd(cmd *Interpreter) (NextT, error) {
	if len(cmd.Args) >= 2 {
		if cmd.Args[1] == "-" {
			if len(cd_history) < 1 {
				return CONTINUE, errors.New("cd - : there is no previous directory")

			}
			directory := cd_history[len(cd_history)-1]
			push_cd_history()
			return CONTINUE, dos.Chdir(directory)
		} else if cmd.Args[1] == "-h" || cmd.Args[1] == "?" {
			i := len(cd_history) - 10
			if i < 0 {
				i = 0
			}
			for ; i < len(cd_history); i++ {
				fmt.Fprintf(cmd.Stdout, "%d %s\n", i-len(cd_history), cd_history[i])
			}
			return CONTINUE, nil
		} else if i, err := strconv.ParseInt(cmd.Args[1], 10, 0); err == nil && i < 0 {
			i += int64(len(cd_history))
			if i < 0 {
				return CONTINUE, fmt.Errorf("cd %s: too old history", cmd.Args[1])
			}
			directory := cd_history[i]
			push_cd_history()
			return CONTINUE, dos.Chdir(directory)
		} else {
			push_cd_history()
			return CONTINUE, dos.Chdir(cmd.Args[1])
		}
	}
	home := dos.GetHome()
	if home != "" {
		push_cd_history()
		return CONTINUE, dos.Chdir(home)
	}
	return cmd_pwd(cmd)
}
<|endoftext|>


<commit_before>package fugu

import (
	"fmt"
	"github.com/docker/docker/nat"
	"github.com/mattes/go-collect/flags"
)

var DockerFlags = make(map[string]*flags.Flags)

func init() {

	// Copy these values from
	// https://github.com/docker/docker/tree/master/api/client

	// Define DockerFlags["build"]
	DockerFlags["build"] = flags.New("docker")
	DockerFlags["build"].String([]string{"t", "-tag"}, "", "Tag for the image (!)")
	DockerFlags["build"].Bool([]string{"q", "-quiet"}, false, "Suppress the verbose output generated by the containers")
	DockerFlags["build"].Bool([]string{"#no-cache", "-no-cache"}, false, "Do not use cache when building the image")
	DockerFlags["build"].Bool([]string{"#rm", "-rm"}, true, "Remove intermediate containers after a successful build")
	DockerFlags["build"].Bool([]string{"-force-rm"}, false, "Always remove intermediate containers")
	DockerFlags["build"].Bool([]string{"-pull"}, false, "Always attempt to pull a newer version of the image")
	DockerFlags["build"].String([]string{"f", "-file"}, "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")

	// Define DockerFlags["run"]
	DockerFlags["run"] = flags.New("docker")
	DockerFlags["run"].Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
	DockerFlags["run"].Bool([]string{"d", "-detach"}, false, "Detached mode: run the container in the background and print the new container ID")
	DockerFlags["run"].Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied.")
	DockerFlags["run"].String([]string{"#name", "-name"}, "", "Assign a name to the container")

	DockerFlags["run"].Var([]string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR.")
	DockerFlags["run"].Var([]string{"v", "-volume"}, "Bind mount a volume (e.g., from the host: -v /host:/container, from Docker: -v /container)")
	DockerFlags["run"].Var([]string{"#link", "-link"}, "Add link to another container in the form of <name|id>:alias")
	DockerFlags["run"].Var([]string{"-device"}, "Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)")

	DockerFlags["run"].Var([]string{"e", "-env"}, "Set environment variables")
	DockerFlags["run"].Var([]string{"-env-file"}, "Read in a line delimited file of environment variables")

	DockerFlags["run"].Var([]string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host\nformat: %s\n(use 'docker port' to see the actual mapping)", nat.PortSpecTemplateFormat))
	DockerFlags["run"].Var([]string{"#expose", "-expose"}, "Expose a port or a range of ports (e.g. --expose=3300-3310) from the container without publishing it to your host")
	DockerFlags["run"].Var([]string{"#dns", "-dns"}, "Set custom DNS servers")
	DockerFlags["run"].Var([]string{"-dns-search"}, "Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)")
	DockerFlags["run"].Var([]string{"-add-host"}, "Add a custom host-to-IP mapping (host:ip)")
	DockerFlags["run"].Var([]string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
	DockerFlags["run"].Var([]string{"#lxc-conf", "-lxc-conf"}, "(lxc exec-driver only) Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")

	DockerFlags["run"].Var([]string{"-cap-add"}, "Add Linux capabilities")
	DockerFlags["run"].Var([]string{"-cap-drop"}, "Drop Linux capabilities")
	DockerFlags["run"].Var([]string{"-security-opt"}, "Security Options")

	DockerFlags["run"].Bool([]string{"#n", "#-networking"}, true, "Enable networking for this container")
	DockerFlags["run"].Bool([]string{"#privileged", "-privileged"}, false, "Give extended privileges to this container")
	DockerFlags["run"].String([]string{"-pid"}, "", "Default is to create a private PID namespace for the container\n'host': use the host PID namespace inside the container.  Note: the host mode gives the container full access to processes on the system and is therefore considered insecure.")
	DockerFlags["run"].Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to random ports on the host interfaces")
	DockerFlags["run"].Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
	DockerFlags["run"].Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
	DockerFlags["run"].String([]string{"#cidfile", "-cidfile"}, "", "Write the container ID to the file")
	DockerFlags["run"].String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default ENTRYPOINT of the image")
	DockerFlags["run"].String([]string{"h", "-hostname"}, "", "Container host name")
	DockerFlags["run"].String([]string{"m", "-memory"}, "", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)")
	DockerFlags["run"].String([]string{"-memory-swap"}, "", "Total memory usage (memory + swap), set '-1' to disable swap (format: <number><optional unit>, where unit = b, k, m or g)")
	DockerFlags["run"].String([]string{"u", "-user"}, "", "Username or UID")
	DockerFlags["run"].String([]string{"w", "-workdir"}, "", "Working directory inside the container")
	DockerFlags["run"].Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
	DockerFlags["run"].String([]string{"-cpuset"}, "", "CPUs in which to allow execution (0-3, 0,1)")
	DockerFlags["run"].String([]string{"-net"}, "bridge", "Set the Network mode for the container\n'bridge': creates a new network stack for the container on the docker bridge\n'none': no networking for this container\n'container:<name|id>': reuses another container network stack\n'host': use the host network stack inside the container.  Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.")
	DockerFlags["run"].String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)")
	DockerFlags["run"].String([]string{"-ipc"}, "", "Default is to create a private IPC namespace (POSIX SysV IPC) for the container\n'container:<name|id>': reuses another container shared memory, semaphores and message queues\n'host': use the host shared memory,semaphores and message queues inside the container.  Note: the host mode gives the container full access to local shared memory and is therefore considered insecure.")
	DockerFlags["run"].String([]string{"-restart"}, "", "Restart policy to apply when a container exits (no, on-failure[:max-retry], always)")
	DockerFlags["run"].Bool([]string{"-read-only"}, false, "Mount the container's root filesystem as read only")

	// Define DockerFlags["exec"]
	DockerFlags["exec"] = flags.New("docker")
	DockerFlags["exec"].Bool([]string{"i", "-interactive"}, true, "Keep STDIN open even if not attached (!)")
	DockerFlags["exec"].Bool([]string{"t", "-tty"}, true, "Allocate a pseudo-TTY (!)")
	DockerFlags["exec"].Bool([]string{"d", "-detach"}, false, "Detached mode: run command in the background")

	// Define DockerFlags["destroy"]
	DockerFlags["destroy"] = flags.New("docker")

	// Define DockerFlags["pull"]
	DockerFlags["pull"] = flags.New("docker")
	DockerFlags["pull"].Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository")

	// Define DockerFlags["push"]
	DockerFlags["push"] = flags.New("docker")

}
<commit_msg>reverse fugu exec to docker defaults (interactive and tty) #14<commit_after>package fugu

import (
	"fmt"
	"github.com/docker/docker/nat"
	"github.com/mattes/go-collect/flags"
)

var DockerFlags = make(map[string]*flags.Flags)

func init() {

	// Copy these values from
	// https://github.com/docker/docker/tree/master/api/client

	// Define DockerFlags["build"]
	DockerFlags["build"] = flags.New("docker")
	DockerFlags["build"].String([]string{"t", "-tag"}, "", "Tag for the image (!)")
	DockerFlags["build"].Bool([]string{"q", "-quiet"}, false, "Suppress the verbose output generated by the containers")
	DockerFlags["build"].Bool([]string{"#no-cache", "-no-cache"}, false, "Do not use cache when building the image")
	DockerFlags["build"].Bool([]string{"#rm", "-rm"}, true, "Remove intermediate containers after a successful build")
	DockerFlags["build"].Bool([]string{"-force-rm"}, false, "Always remove intermediate containers")
	DockerFlags["build"].Bool([]string{"-pull"}, false, "Always attempt to pull a newer version of the image")
	DockerFlags["build"].String([]string{"f", "-file"}, "", "Name of the Dockerfile (Default is 'PATH/Dockerfile')")

	// Define DockerFlags["run"]
	DockerFlags["run"] = flags.New("docker")
	DockerFlags["run"].Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
	DockerFlags["run"].Bool([]string{"d", "-detach"}, false, "Detached mode: run the container in the background and print the new container ID")
	DockerFlags["run"].Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxy received signals to the process (non-TTY mode only). SIGCHLD, SIGSTOP, and SIGKILL are not proxied.")
	DockerFlags["run"].String([]string{"#name", "-name"}, "", "Assign a name to the container")

	DockerFlags["run"].Var([]string{"a", "-attach"}, "Attach to STDIN, STDOUT or STDERR.")
	DockerFlags["run"].Var([]string{"v", "-volume"}, "Bind mount a volume (e.g., from the host: -v /host:/container, from Docker: -v /container)")
	DockerFlags["run"].Var([]string{"#link", "-link"}, "Add link to another container in the form of <name|id>:alias")
	DockerFlags["run"].Var([]string{"-device"}, "Add a host device to the container (e.g. --device=/dev/sdc:/dev/xvdc:rwm)")

	DockerFlags["run"].Var([]string{"e", "-env"}, "Set environment variables")
	DockerFlags["run"].Var([]string{"-env-file"}, "Read in a line delimited file of environment variables")

	DockerFlags["run"].Var([]string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host\nformat: %s\n(use 'docker port' to see the actual mapping)", nat.PortSpecTemplateFormat))
	DockerFlags["run"].Var([]string{"#expose", "-expose"}, "Expose a port or a range of ports (e.g. --expose=3300-3310) from the container without publishing it to your host")
	DockerFlags["run"].Var([]string{"#dns", "-dns"}, "Set custom DNS servers")
	DockerFlags["run"].Var([]string{"-dns-search"}, "Set custom DNS search domains (Use --dns-search=. if you don't wish to set the search domain)")
	DockerFlags["run"].Var([]string{"-add-host"}, "Add a custom host-to-IP mapping (host:ip)")
	DockerFlags["run"].Var([]string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
	DockerFlags["run"].Var([]string{"#lxc-conf", "-lxc-conf"}, "(lxc exec-driver only) Add custom lxc options --lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")

	DockerFlags["run"].Var([]string{"-cap-add"}, "Add Linux capabilities")
	DockerFlags["run"].Var([]string{"-cap-drop"}, "Drop Linux capabilities")
	DockerFlags["run"].Var([]string{"-security-opt"}, "Security Options")

	DockerFlags["run"].Bool([]string{"#n", "#-networking"}, true, "Enable networking for this container")
	DockerFlags["run"].Bool([]string{"#privileged", "-privileged"}, false, "Give extended privileges to this container")
	DockerFlags["run"].String([]string{"-pid"}, "", "Default is to create a private PID namespace for the container\n'host': use the host PID namespace inside the container.  Note: the host mode gives the container full access to processes on the system and is therefore considered insecure.")
	DockerFlags["run"].Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to random ports on the host interfaces")
	DockerFlags["run"].Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
	DockerFlags["run"].Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
	DockerFlags["run"].String([]string{"#cidfile", "-cidfile"}, "", "Write the container ID to the file")
	DockerFlags["run"].String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default ENTRYPOINT of the image")
	DockerFlags["run"].String([]string{"h", "-hostname"}, "", "Container host name")
	DockerFlags["run"].String([]string{"m", "-memory"}, "", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)")
	DockerFlags["run"].String([]string{"-memory-swap"}, "", "Total memory usage (memory + swap), set '-1' to disable swap (format: <number><optional unit>, where unit = b, k, m or g)")
	DockerFlags["run"].String([]string{"u", "-user"}, "", "Username or UID")
	DockerFlags["run"].String([]string{"w", "-workdir"}, "", "Working directory inside the container")
	DockerFlags["run"].Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
	DockerFlags["run"].String([]string{"-cpuset"}, "", "CPUs in which to allow execution (0-3, 0,1)")
	DockerFlags["run"].String([]string{"-net"}, "bridge", "Set the Network mode for the container\n'bridge': creates a new network stack for the container on the docker bridge\n'none': no networking for this container\n'container:<name|id>': reuses another container network stack\n'host': use the host network stack inside the container.  Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure.")
	DockerFlags["run"].String([]string{"-mac-address"}, "", "Container MAC address (e.g. 92:d0:c6:0a:29:33)")
	DockerFlags["run"].String([]string{"-ipc"}, "", "Default is to create a private IPC namespace (POSIX SysV IPC) for the container\n'container:<name|id>': reuses another container shared memory, semaphores and message queues\n'host': use the host shared memory,semaphores and message queues inside the container.  Note: the host mode gives the container full access to local shared memory and is therefore considered insecure.")
	DockerFlags["run"].String([]string{"-restart"}, "", "Restart policy to apply when a container exits (no, on-failure[:max-retry], always)")
	DockerFlags["run"].Bool([]string{"-read-only"}, false, "Mount the container's root filesystem as read only")

	// Define DockerFlags["exec"]
	DockerFlags["exec"] = flags.New("docker")
	DockerFlags["exec"].Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
	DockerFlags["exec"].Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
	DockerFlags["exec"].Bool([]string{"d", "-detach"}, false, "Detached mode: run command in the background")

	// Define DockerFlags["destroy"]
	DockerFlags["destroy"] = flags.New("docker")

	// Define DockerFlags["pull"]
	DockerFlags["pull"] = flags.New("docker")
	DockerFlags["pull"].Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository")

	// Define DockerFlags["push"]
	DockerFlags["push"] = flags.New("docker")

}
<|endoftext|>


<commit_before>package dockerutils

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/fsouza/go-dockerclient"
)

type DockerEnvironment struct {
	DockerHost      string
	DockerTlsVerify string
	DockerCertPath  string
}

func (d *DockerEnvironment) IsDockerTls() bool {
	return IsDockerTls(d.DockerTlsVerify)
}

func (d *DockerEnvironment) EnvStrings() []string {
	envStrings := []string{
		fmt.Sprintf("DOCKER_HOST=%s", d.DockerHost),
	}
	if d.IsDockerTls() {
		envStrings = append(
			envStrings,
			fmt.Sprintf("DOCKER_TLS_VERIFY=%s", d.DockerTlsVerify),
			fmt.Sprintf("DOCKER_CERT_PATH=%s", d.DockerCertPath),
		)
	}
	return envStrings
}

func (d *DockerEnvironment) HostVolumeToVolume() map[string]string {
	hostVolumeToVolume := make(map[string]string)
	if d.IsDockerTls() && d.DockerCertPath != "" {
		hostVolumeToVolume[d.DockerCertPath] = d.DockerCertPath
	}
	if strings.HasPrefix(d.DockerHost, "unix") {
		hostVolumeToVolume[d.DockerHost] = d.DockerHost
	}
	if len(hostVolumeToVolume) == 0 {
		return nil
	}
	return hostVolumeToVolume
}

// TODO(pedge): we are assuming the DOCKER_CERT_PATH is a directory within the host
// regardless of if we are running in a docker container or not, d should actually
// still work but this is not great
func GetDockerEnvironment() (*DockerEnvironment, error) {
	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "unix:///var/run/docker.sock"
	}
	dockerTlsVerify := os.Getenv("DOCKER_TLS_VERIFY")
	var dockerCertPath string
	var err error
	if IsDockerTls(dockerTlsVerify) {
		dockerCertPath = os.Getenv("DOCKER_CERT_PATH")
		if dockerCertPath == "" {
			home := os.Getenv("HOME")
			if home == "" {
				return nil, errors.New("dockerutils: environment variable HOME must be set if DOCKER_CERT_PATH is not set")
			}
			dockerCertPath = filepath.Join(home, ".docker")
			dockerCertPath, err = filepath.Abs(dockerCertPath)
			if err != nil {
				return nil, err
			}
		}
	}
	return &DockerEnvironment{
		DockerHost:      dockerHost,
		DockerTlsVerify: dockerTlsVerify,
		DockerCertPath:  dockerCertPath,
	}, nil
}

func NewDockerClientFromEnv(apiVersion string) (*docker.Client, error) {
	dockerEnvironment, err := GetDockerEnvironment()
	if err != nil {
		return nil, err
	}
	return NewDockerClient(dockerEnvironment, apiVersion)
}

func NewDockerClient(dockerEnvironment *DockerEnvironment, apiVersion string) (*docker.Client, error) {
	dockerHost := dockerEnvironment.DockerHost
	if dockerEnvironment.IsDockerTls() {
		parts := strings.SplitN(dockerHost, "://", 2)
		if len(parts) != 2 {
			return nil, fmt.Errorf("dockerutils: could not split %s into two parts by ://", dockerHost)
		}
		dockerHost = fmt.Sprintf("https://%s", parts[1])
		dockerCertPath := dockerEnvironment.DockerCertPath
		cert := filepath.Join(dockerCertPath, "cert.pem")
		key := filepath.Join(dockerCertPath, "key.pem")
		ca := filepath.Join(dockerCertPath, "ca.pem")
		if err := checkFileExists(dockerCertPath); err != nil {
			return nil, err
		}
		if err := checkFileExists(cert); err != nil {
			return nil, err
		}
		if err := checkFileExists(key); err != nil {
			return nil, err
		}
		if err := checkFileExists(ca); err != nil {
			return nil, err
		}
		return docker.NewVersionedTLSClient(dockerHost, cert, key, ca, apiVersion)
	}
	return docker.NewVersionedClient(dockerHost, apiVersion)
}

func IsDockerTls(dockerTlsVerify string) bool {
	return dockerTlsVerify != ""
}

func DockerPorts(expose []uint16, ports []string) (map[docker.Port]struct{}, map[docker.Port][]docker.PortBinding, error) {
	if (expose == nil || len(expose) == 0) && (ports == nil || len(ports) == 0) {
		return nil, nil, nil
	}
	m := make(map[docker.Port]struct{})
	n := make(map[docker.Port][]docker.PortBinding)
	for _, port := range expose {
		m[docker.Port(fmt.Sprintf("%v/tcp", port))] = emptyStruct()
	}
	for _, port := range ports {
		split := strings.Split(port, ":")
		if len(split) != 2 {
			return nil, nil, fmt.Errorf("invalid port: %s", port)
		}
		hostPort, err := strconv.ParseInt(split[0], 10, 64)
		if err != nil {
			return nil, nil, err
		}
		containerPort, err := strconv.ParseInt(split[1], 10, 64)
		if err != nil {
			return nil, nil, err
		}
		dockerPort := docker.Port(fmt.Sprintf("%v/tcp", containerPort))
		m[dockerPort] = emptyStruct()
		n[dockerPort] = []docker.PortBinding{
			docker.PortBinding{
				HostPort: fmt.Sprintf("%d", hostPort),
			},
		}
	}
	return m, n, nil
}

func DockerVolumes(volumes []string) map[string]struct{} {
	if volumes == nil || len(volumes) == 0 {
		return nil
	}
	m := make(map[string]struct{})
	for _, volume := range volumes {
		m[volume] = emptyStruct()
	}
	return m
}

func DockerVolumesFrom(volumesFrom []string) string {
	return strings.Join(volumesFrom, ",")
}

func DockerBinds(hostVolumeToVolume map[string]string) []string {
	if hostVolumeToVolume == nil || len(hostVolumeToVolume) == 0 {
		return nil
	}
	binds := make([]string, len(hostVolumeToVolume))
	i := 0
	for hostVolume, volume := range hostVolumeToVolume {
		binds[i] = fmt.Sprintf("%s:%s:rw", hostVolume, volume)
		i++
	}
	return binds
}

// ***** PRIVATE *****

func checkFileExists(path string) error {
	exists, err := isFileExists(path)
	if err != nil {
		return err
	}
	if !exists {
		return fmt.Errorf("docker: file %s does not exist", path)
	}
	return nil
}

func isFileExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

// TODO(pedge): what?
func emptyStruct() struct{} {
	var str struct{}
	return str
}
<commit_msg>Supporting dynamic ports<commit_after>package dockerutils

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/fsouza/go-dockerclient"
)

type DockerEnvironment struct {
	DockerHost      string
	DockerTlsVerify string
	DockerCertPath  string
}

func (d *DockerEnvironment) IsDockerTls() bool {
	return IsDockerTls(d.DockerTlsVerify)
}

func (d *DockerEnvironment) EnvStrings() []string {
	envStrings := []string{
		fmt.Sprintf("DOCKER_HOST=%s", d.DockerHost),
	}
	if d.IsDockerTls() {
		envStrings = append(
			envStrings,
			fmt.Sprintf("DOCKER_TLS_VERIFY=%s", d.DockerTlsVerify),
			fmt.Sprintf("DOCKER_CERT_PATH=%s", d.DockerCertPath),
		)
	}
	return envStrings
}

func (d *DockerEnvironment) HostVolumeToVolume() map[string]string {
	hostVolumeToVolume := make(map[string]string)
	if d.IsDockerTls() && d.DockerCertPath != "" {
		hostVolumeToVolume[d.DockerCertPath] = d.DockerCertPath
	}
	if strings.HasPrefix(d.DockerHost, "unix") {
		hostVolumeToVolume[d.DockerHost] = d.DockerHost
	}
	if len(hostVolumeToVolume) == 0 {
		return nil
	}
	return hostVolumeToVolume
}

// TODO(pedge): we are assuming the DOCKER_CERT_PATH is a directory within the host
// regardless of if we are running in a docker container or not, d should actually
// still work but this is not great
func GetDockerEnvironment() (*DockerEnvironment, error) {
	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "unix:///var/run/docker.sock"
	}
	dockerTlsVerify := os.Getenv("DOCKER_TLS_VERIFY")
	var dockerCertPath string
	var err error
	if IsDockerTls(dockerTlsVerify) {
		dockerCertPath = os.Getenv("DOCKER_CERT_PATH")
		if dockerCertPath == "" {
			home := os.Getenv("HOME")
			if home == "" {
				return nil, errors.New("dockerutils: environment variable HOME must be set if DOCKER_CERT_PATH is not set")
			}
			dockerCertPath = filepath.Join(home, ".docker")
			dockerCertPath, err = filepath.Abs(dockerCertPath)
			if err != nil {
				return nil, err
			}
		}
	}
	return &DockerEnvironment{
		DockerHost:      dockerHost,
		DockerTlsVerify: dockerTlsVerify,
		DockerCertPath:  dockerCertPath,
	}, nil
}

func NewDockerClientFromEnv(apiVersion string) (*docker.Client, error) {
	dockerEnvironment, err := GetDockerEnvironment()
	if err != nil {
		return nil, err
	}
	return NewDockerClient(dockerEnvironment, apiVersion)
}

func NewDockerClient(dockerEnvironment *DockerEnvironment, apiVersion string) (*docker.Client, error) {
	dockerHost := dockerEnvironment.DockerHost
	if dockerEnvironment.IsDockerTls() {
		parts := strings.SplitN(dockerHost, "://", 2)
		if len(parts) != 2 {
			return nil, fmt.Errorf("dockerutils: could not split %s into two parts by ://", dockerHost)
		}
		dockerHost = fmt.Sprintf("https://%s", parts[1])
		dockerCertPath := dockerEnvironment.DockerCertPath
		cert := filepath.Join(dockerCertPath, "cert.pem")
		key := filepath.Join(dockerCertPath, "key.pem")
		ca := filepath.Join(dockerCertPath, "ca.pem")
		if err := checkFileExists(dockerCertPath); err != nil {
			return nil, err
		}
		if err := checkFileExists(cert); err != nil {
			return nil, err
		}
		if err := checkFileExists(key); err != nil {
			return nil, err
		}
		if err := checkFileExists(ca); err != nil {
			return nil, err
		}
		return docker.NewVersionedTLSClient(dockerHost, cert, key, ca, apiVersion)
	}
	return docker.NewVersionedClient(dockerHost, apiVersion)
}

func IsDockerTls(dockerTlsVerify string) bool {
	return dockerTlsVerify != ""
}

func DockerPorts(expose []uint16, ports []string) (map[docker.Port]struct{}, map[docker.Port][]docker.PortBinding, error) {
	if (expose == nil || len(expose) == 0) && (ports == nil || len(ports) == 0) {
		return nil, nil, nil
	}
	m := make(map[docker.Port]struct{})
	n := make(map[docker.Port][]docker.PortBinding)
	for _, port := range expose {
		m[docker.Port(fmt.Sprintf("%v/tcp", port))] = emptyStruct()
	}
	for _, port := range ports {
		var err error
		var hostPort string
		split := strings.Split(port, ":")
		containerPort := split[len(split)-1]

		if len(split) == 2 && split[0] != "" {
			hostPort = split[0]
			_, err = strconv.ParseInt(split[0], 10, 64)
			if err != nil {
				return nil, nil, err
			}
		}

		_, err = strconv.ParseInt(containerPort, 10, 64)
		if err != nil {
			return nil, nil, err
		}
		dockerPort := docker.Port(fmt.Sprintf("%v/tcp", containerPort))
		m[dockerPort] = emptyStruct()
		n[dockerPort] = []docker.PortBinding{
			docker.PortBinding{
				HostPort: fmt.Sprintf("%d", hostPort),
			},
		}
	}
	return m, n, nil
}

func DockerVolumes(volumes []string) map[string]struct{} {
	if volumes == nil || len(volumes) == 0 {
		return nil
	}
	m := make(map[string]struct{})
	for _, volume := range volumes {
		m[volume] = emptyStruct()
	}
	return m
}

func DockerVolumesFrom(volumesFrom []string) string {
	return strings.Join(volumesFrom, ",")
}

func DockerBinds(hostVolumeToVolume map[string]string) []string {
	if hostVolumeToVolume == nil || len(hostVolumeToVolume) == 0 {
		return nil
	}
	binds := make([]string, len(hostVolumeToVolume))
	i := 0
	for hostVolume, volume := range hostVolumeToVolume {
		binds[i] = fmt.Sprintf("%s:%s:rw", hostVolume, volume)
		i++
	}
	return binds
}

// ***** PRIVATE *****

func checkFileExists(path string) error {
	exists, err := isFileExists(path)
	if err != nil {
		return err
	}
	if !exists {
		return fmt.Errorf("docker: file %s does not exist", path)
	}
	return nil
}

func isFileExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

// TODO(pedge): what?
func emptyStruct() struct{} {
	var str struct{}
	return str
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"html/template"
	"net"
	"net/http"
	"net/http/fcgi"
	"os"
	"os/exec"
	"strings"
	"math/rand"
)

var (
	headertpl = `
<!DOCTYPE html>

<title>{{ .Hostname }}</title>

`
	footertpl = `

`

	statustpl = `

{{.Hostname}}

{{.Quote}}

{{ range .Outputs }}

# {{.Cmd}}
{{ range .Output }} {{ . }}
{{ end }}

{{ end }}

#^D

`

	cmds = []string{
		"cat /etc/motd",
		`who | awk '{ printf "%-10s    %s  %s %2s %s\n", $1, $2, $3, $4, $5 }'`,
		"uptime",
		"downtimes",
		"df -h",
	}

	quotes = []string{
		"i need something stronger.",
		"for more enjoyment and greater efficiency, consumption is being standardized. we are sorry ...",
		"everything will be all right. you are in my hands. i am here to protect you. you have nowhere to go. you have nowhere to go.",
		"you have nowhere to go. i am here to protect you.",
		"how shall the new environment be programmed? it all happened so slowly that most men failed to realize that anything had happened at all.",
		"take four red capsules. in 10 minutes take two more. help is on the way.",
		"control center 626 holds no responsibility... for error in mindlock.",
	}
)

type CommandOutput struct {
	Cmd    string
	Output []string
}

func RunSh(cmd string) CommandOutput {
	c := exec.Command("/bin/sh", "-c", cmd)

	output, err := c.CombinedOutput()
	if err != nil {
		return CommandOutput{cmd, []string{err.Error()}}
	}

	buf := bytes.NewBuffer(output)

	sc := bufio.NewScanner(buf)

	var out []string
	for sc.Scan() {
		out = append(out, strings.TrimSpace(sc.Text()))
	}

	return CommandOutput{cmd, out}
}

type Header struct {
	Hostname string
}

type Status struct {
	Hostname string
	Quote string
	Outputs []CommandOutput
}

func status(w http.ResponseWriter, r *http.Request) {
	var err error
	var headdat Header
	var statdat Status
	var outputs []CommandOutput
	var hdr, stat, footer *template.Template

	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered in status", r)
		}
	}()

	wr := bufio.NewWriter(w)

	statdat.Hostname = r.Host
	if statdat.Hostname == "" {
		statdat.Hostname, _ = os.Hostname()
	}

	headdat.Hostname = statdat.Hostname

	statdat.Quote = quotes[rand.Intn(len(quotes))]

	if hdr, err = template.New("header").Parse(headertpl); err != nil {
		goto error
	} else if err = hdr.Execute(wr, headdat); err != nil {
		goto error
	}

	for _, c := range cmds {
		outputs = append(outputs, RunSh(c))
	}

	statdat.Outputs = outputs

	if stat, err = template.New("status").Parse(statustpl); err != nil {
		goto error
	} else if err = stat.Execute(wr, statdat); err != nil {
		goto error
	}

	if footer, err = template.New("footer").Parse(footertpl); err != nil {
		goto error
	} else if err = footer.Execute(wr, nil); err != nil {
		goto error
	}

error:
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: %s\n", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	wr.Flush()

}

func main() {
	listener, _ := net.Listen("unix", "/tmp/mindlockstatus.sock")
	http.HandleFunc("/", status)
	fcgi.Serve(listener, nil)
}
<commit_msg>remove socket, chmod<commit_after>package main

import (
	"bufio"
	"bytes"
	"fmt"
	"html/template"
	"net"
	"net/http"
	"net/http/fcgi"
	"os"
	"os/exec"
	"strings"
	"math/rand"
)

var (
	headertpl = `
<!DOCTYPE html>

<title>{{ .Hostname }}</title>

`
	footertpl = `

`

	statustpl = `

{{.Hostname}}

{{.Quote}}

{{ range .Outputs }}

# {{.Cmd}}
{{ range .Output }} {{ . }}
{{ end }}

{{ end }}

#^D

`

	cmds = []string{
		"cat /etc/motd",
		`who | awk '{ printf "%-10s    %s  %s %2s %s\n", $1, $2, $3, $4, $5 }'`,
		"uptime",
		"downtimes",
		"df -h",
	}

	quotes = []string{
		"i need something stronger.",
		"for more enjoyment and greater efficiency, consumption is being standardized. we are sorry ...",
		"everything will be all right. you are in my hands. i am here to protect you. you have nowhere to go. you have nowhere to go.",
		"you have nowhere to go. i am here to protect you.",
		"how shall the new environment be programmed? it all happened so slowly that most men failed to realize that anything had happened at all.",
		"take four red capsules. in 10 minutes take two more. help is on the way.",
		"control center 626 holds no responsibility... for error in mindlock.",
	}
)

type CommandOutput struct {
	Cmd    string
	Output []string
}

func RunSh(cmd string) CommandOutput {
	c := exec.Command("/bin/sh", "-c", cmd)

	output, err := c.CombinedOutput()
	if err != nil {
		return CommandOutput{cmd, []string{err.Error()}}
	}

	buf := bytes.NewBuffer(output)

	sc := bufio.NewScanner(buf)

	var out []string
	for sc.Scan() {
		out = append(out, strings.TrimSpace(sc.Text()))
	}

	return CommandOutput{cmd, out}
}

type Header struct {
	Hostname string
}

type Status struct {
	Hostname string
	Quote string
	Outputs []CommandOutput
}

func status(w http.ResponseWriter, r *http.Request) {
	var err error
	var headdat Header
	var statdat Status
	var outputs []CommandOutput
	var hdr, stat, footer *template.Template

	defer func() {
		if r := recover(); r != nil {
			fmt.Println("Recovered in status", r)
		}
	}()

	wr := bufio.NewWriter(w)

	statdat.Hostname = r.Host
	if statdat.Hostname == "" {
		statdat.Hostname, _ = os.Hostname()
	}

	headdat.Hostname = statdat.Hostname

	statdat.Quote = quotes[rand.Intn(len(quotes))]

	if hdr, err = template.New("header").Parse(headertpl); err != nil {
		goto error
	} else if err = hdr.Execute(wr, headdat); err != nil {
		goto error
	}

	for _, c := range cmds {
		outputs = append(outputs, RunSh(c))
	}

	statdat.Outputs = outputs

	if stat, err = template.New("status").Parse(statustpl); err != nil {
		goto error
	} else if err = stat.Execute(wr, statdat); err != nil {
		goto error
	}

	if footer, err = template.New("footer").Parse(footertpl); err != nil {
		goto error
	} else if err = footer.Execute(wr, nil); err != nil {
		goto error
	}

error:
	if err != nil {
		fmt.Fprintf(os.Stderr, "error: %s\n", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
	wr.Flush()

}

func main() {
  sock := "/tmp/mindlockstatus.sock"
  os.Remove(sock)
	listener, err := net.Listen("unix", sock)
  if err != nil {
    fmt.Fprintf(os.Stderr, "can't listen on %s: %s", sock, err)
    os.Exit(1)
  }

  // set the right mode
  if err := os.Chmod(sock, os.FileMode(0750)); err != nil {
    fmt.Fprintf(os.Stderr, "can't chmod %s: %s", sock, err)
    os.Exit(1)
  }

	http.HandleFunc("/", status)
	if err := fcgi.Serve(listener, nil); err != nil {
    fmt.Fprintf(os.Stderr, "failed to serve: %s", err)
  }
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/sergi/go-diff/diffmatchpatch"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

func diffStrings(text1, text2 string) []diffmatchpatch.Diff {
	diff := diffmatchpatch.New()
	return diff.DiffCleanupSemantic(diff.DiffMain(text1, text2, false))
}

func serve(kill chan bool) {
	log.Println("Serving...")

	baseFormatBytes, err := ioutil.ReadFile("public/base.html")
	if nil != err {
		log.Fatal(err)
	}

	baseColumnFormatBytes, err := ioutil.ReadFile("public/baseColumns.html")
	if nil != err {
		log.Fatal(err)
	}

	baseDiffBytes, err := ioutil.ReadFile("public/baseDiff.html")
	if nil != err {
		log.Fatal(err)
	}

	baseFormat := string(baseFormatBytes)
	baseColumnFormat := string(baseColumnFormatBytes)
	baseDiff := string(baseDiffBytes)

	r := mux.NewRouter()

	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, baseFormat, "status...", "status...", status())
	})

	r.HandleFunc("/diff/{branch}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		branch := vars["branch"]
		d := diff(branch)
		fmt.Fprintf(w, baseFormat, branch, branch, d)
	})

	r.HandleFunc("/diff/stat/{branch}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		branch := vars["branch"]
		d := diffStat(branch)
		fmt.Fprintf(w, baseFormat, branch, branch, d)
	})

	r.HandleFunc("/show/{branch}/{filename:.*}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		b := vars["branch"]
		filename := vars["filename"]
		w.Header()["x-filename"] = []string{filename}
		fmt.Fprintf(w, baseFormat, filename, filename, gitReadFile(b, filename))
	})

	r.HandleFunc("/split-diff", func(w http.ResponseWriter, r *http.Request) {
		leftBranch := r.FormValue("leftBranch")
		rightBranch := r.FormValue("rightBranch")
		filename := r.FormValue("filename")

		title := fmt.Sprintf("%s..%s -- %s", leftBranch, rightBranch, filename)

		leftFile := gitReadFile(leftBranch, filename)
		rightFile := gitReadFile(rightBranch, filename)

		fmt.Fprintf(w,
			baseDiff,
			title,
			title,
			diffStrings(leftFile, rightFile),
			leftFile,
			rightFile,
		)
	})

	r.HandleFunc("/split-diff.json", func(w http.ResponseWriter, r *http.Request) {
		leftBranch := r.FormValue("leftBranch")
		rightBranch := r.FormValue("rightBranch")
		filename := r.FormValue("filename")

		leftFile := gitReadFile(leftBranch, filename)
		rightFile := gitReadFile(rightBranch, filename)

		json, err := json.Marshal(diffStrings(leftFile, rightFile))
		if nil != err {
			w.WriteHeader(http.StatusNotFound)
		}
		w.Header()["content-type"] = []string{"application/json"}
		w.Write(json)
	})

	r.HandleFunc("/split/", func(w http.ResponseWriter, r *http.Request) {
		leftBranch := r.FormValue("leftBranch")
		rightBranch := r.FormValue("rightBranch")
		filename := r.FormValue("filename")

		title := fmt.Sprintf("%s..%s -- %s", leftBranch, rightBranch, filename)

		leftFile := gitReadFile(leftBranch, filename)
		rightFile := gitReadFile(rightBranch, filename)

		fmt.Fprintf(w,
			baseColumnFormat,
			title,
			title,
			leftFile,
			rightFile,
		)
	})

	r.HandleFunc("/kill", func(w http.ResponseWriter, r *http.Request) {
		close(kill)
	})

	n := negroni.Classic()
	n.UseHandler(r)

	log.Println("Listening...")
	n.Run(":7777")
}

func git(args ...string) string {
	cmd := exec.Command("git", args...)

	output, err := cmd.CombinedOutput()
	if nil != err {
		return err.Error()
	}

	return string(output)
}

func status() string {
	return git("status")
}

func diff(commit string) string {
	return git("diff", "-M", commit)
}

func diffStat(commit string) string {
	return git("diff", "--stat", "-M", commit)
}

func gitCurrentBranch() string {
	branchInfo := git("branch")

	lines := strings.Split(branchInfo, "\n")
	for _, line := range lines {
		if line[0] == '*' {
			return line[2:]
		}
	}
	return ""
}

func gitReadFile(branch, filename string) string {
	if branch == "" {
		branch = gitCurrentBranch()
	}

	return git("show", fmt.Sprintf("%s:%s", branch, filename))
}

func main() {
	log.Println("Starting...")
	kill := make(chan bool)

	if len(os.Args) == 1 {
		log.Println("No target...")
	}

	commit := os.Args[1]

	go serve(kill)
	go func() {
		addr := fmt.Sprintf("http://localhost:7777/diff/%s", commit)
		log.Printf(`Opening "%s"`+"\n", addr)
		cmd := exec.Command("xdg-open", addr)
		cmd.Start()
	}()

	for _ = range kill {
	}
	log.Println("Ending...")
}
<commit_msg>Off by one<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/sergi/go-diff/diffmatchpatch"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"
)

func diffStrings(text1, text2 string) []diffmatchpatch.Diff {
	diff := diffmatchpatch.New()
	return diff.DiffCleanupSemantic(diff.DiffMain(text1, text2, false))
}

func serve(kill chan bool) {
	log.Println("Serving...")

	baseFormatBytes, err := ioutil.ReadFile("public/base.html")
	if nil != err {
		log.Fatal(err)
	}

	baseColumnFormatBytes, err := ioutil.ReadFile("public/baseColumns.html")
	if nil != err {
		log.Fatal(err)
	}

	baseDiffBytes, err := ioutil.ReadFile("public/baseDiff.html")
	if nil != err {
		log.Fatal(err)
	}

	baseFormat := string(baseFormatBytes)
	baseColumnFormat := string(baseColumnFormatBytes)
	baseDiff := string(baseDiffBytes)

	r := mux.NewRouter()

	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Fprintf(w, baseFormat, "status...", "status...", status())
	})

	r.HandleFunc("/diff/{branch}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		branch := vars["branch"]
		d := diff(branch)
		fmt.Fprintf(w, baseFormat, branch, branch, d)
	})

	r.HandleFunc("/diff/stat/{branch}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		branch := vars["branch"]
		d := diffStat(branch)
		fmt.Fprintf(w, baseFormat, branch, branch, d)
	})

	r.HandleFunc("/show/{branch}/{filename:.*}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		b := vars["branch"]
		filename := vars["filename"]
		w.Header()["x-filename"] = []string{filename}
		fmt.Fprintf(w, baseFormat, filename, filename, gitReadFile(b, filename))
	})

	r.HandleFunc("/split-diff", func(w http.ResponseWriter, r *http.Request) {
		leftBranch := r.FormValue("leftBranch")
		rightBranch := r.FormValue("rightBranch")
		filename := r.FormValue("filename")

		title := fmt.Sprintf("%s..%s -- %s", leftBranch, rightBranch, filename)

		leftFile := gitReadFile(leftBranch, filename)
		rightFile := gitReadFile(rightBranch, filename)

		fmt.Fprintf(w,
			baseDiff,
			title,
			title,
			diffStrings(leftFile, rightFile),
			leftFile,
			rightFile,
		)
	})

	r.HandleFunc("/split-diff.json", func(w http.ResponseWriter, r *http.Request) {
		leftBranch := r.FormValue("leftBranch")
		rightBranch := r.FormValue("rightBranch")
		filename := r.FormValue("filename")

		leftFile := gitReadFile(leftBranch, filename)
		rightFile := gitReadFile(rightBranch, filename)

		json, err := json.Marshal(diffStrings(leftFile, rightFile))
		if nil != err {
			w.WriteHeader(http.StatusNotFound)
		}
		w.Header()["content-type"] = []string{"application/json"}
		w.Write(json)
	})

	r.HandleFunc("/split/", func(w http.ResponseWriter, r *http.Request) {
		leftBranch := r.FormValue("leftBranch")
		rightBranch := r.FormValue("rightBranch")
		filename := r.FormValue("filename")

		title := fmt.Sprintf("%s..%s -- %s", leftBranch, rightBranch, filename)

		leftFile := gitReadFile(leftBranch, filename)
		rightFile := gitReadFile(rightBranch, filename)

		fmt.Fprintf(w,
			baseColumnFormat,
			title,
			title,
			leftFile,
			rightFile,
		)
	})

	r.HandleFunc("/kill", func(w http.ResponseWriter, r *http.Request) {
		close(kill)
	})

	n := negroni.Classic()
	n.UseHandler(r)

	log.Println("Listening...")
	n.Run(":7777")
}

func git(args ...string) string {
	cmd := exec.Command("git", args...)

	output, err := cmd.CombinedOutput()
	if nil != err {
		return err.Error()
	}

	return string(output)
}

func status() string {
	return git("status")
}

func diff(commit string) string {
	return git("diff", "-M", commit)
}

func diffStat(commit string) string {
	return git("diff", "--stat", "-M", commit)
}

func gitCurrentBranch() string {
	branchInfo := git("branch")

	lines := strings.Split(branchInfo, "\n")
	for _, line := range lines {
		if line[0] == '*' {
			return line[2:]
		}
	}
	return ""
}

func gitReadFile(branch, filename string) string {
	if branch == "" {
		branch = gitCurrentBranch()
	}

	return git("show", fmt.Sprintf("%s:%s", branch, filename))
}

func main() {
	log.Println("Starting...")
	kill := make(chan bool)

	if len(os.Args) == 0 {
		log.Println("No target...")
	}

	commit := os.Args[1]

	go serve(kill)
	go func() {
		addr := fmt.Sprintf("http://localhost:7777/diff/%s", commit)
		log.Printf(`Opening "%s"`+"\n", addr)
		cmd := exec.Command("xdg-open", addr)
		cmd.Start()
	}()

	for _ = range kill {
	}
	log.Println("Ending...")
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path"
	"time"

	"github.com/codahale/hdrhistogram"
)

type MeasuredResponse struct {
	sz      uint64
	code    int
	latency int64
	timeout bool
	err     error
}

func newClient(
	compress bool,
	https bool,
	reuse bool,
) *http.Client {
	tr := http.Transport{
		DisableCompression: !compress,
		DisableKeepAlives:  !reuse,
	}
	if https {
		tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}
	return &http.Client{Transport: &tr}
}

func sendRequest(
	client *http.Client,
	url *url.URL,
	host *string,
	received chan *MeasuredResponse,
) {
	req, err := http.NewRequest("GET", url.String(), nil)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		fmt.Fprintln(os.Stderr, "\n")
	}
	req.Host = *host

	// FIX: find a way to measure latency with the http client.
	start := time.Now()
	response, err := client.Do(req)

	elapsed := time.Since(start)
	if err != nil {
		received <- &MeasuredResponse{0, 0, 0, false, err}
	} else {
		sz, _ := io.Copy(ioutil.Discard, response.Body)
		response.Body.Close()
		received <- &MeasuredResponse{uint64(sz), response.StatusCode, elapsed.Nanoseconds(), false, nil}
	}
}

func exUsage(msg string) {
	fmt.Fprintf(os.Stderr, "%s\n", msg)
	fmt.Fprintf(os.Stderr, "Usage: %s [flags]\n", path.Base(os.Args[0]))
	flag.PrintDefaults()
	os.Exit(64)
}

func main() {
	qps := flag.Int("qps", 1, "QPS to send to backends per request thread")
	concurrency := flag.Uint("concurrency", 1, "Number of request threads")
	host := flag.String("host", "web", "value of Host header to set")
	urldest := flag.String("url", "http://localhost:4140/", "Destination url")
	interval := flag.Duration("interval", 10*time.Second, "reporting interval")
	reuse := flag.Bool("reuse", false, "reuse connections")
	compress := flag.Bool("compress", false, "use compression")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [flags]\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()

	if *qps < 1 {
		exUsage("qps must be at least 1")
	}

	if *concurrency < 1 {
		exUsage("concurrency must be at least 1")
	}

	dstURL, err := url.Parse(*urldest)
	if err != nil {
		exUsage(fmt.Sprintf("invalid URL: '%s': %s\n", urldest, err.Error()))
	}

	// Repsonse tracking metadata.
	count := uint64(0)
	size := uint64(0)
	good := uint64(0)
	bad := uint64(0)
	failed := uint64(0)
	// from 0 to 1 minute in nanoseconds
	// FIX: verify that these buckets work correctly for our use case.
	hist := hdrhistogram.New(0, 60000000000, 5)
	received := make(chan *MeasuredResponse)
	timeout := time.After(*interval)

	timeToWait := time.Millisecond * time.Duration(1000 / *qps)

	doTLS := dstURL.Scheme == "https"
	client := newClient(*compress, doTLS, *reuse)

	for i := uint(0); i < *concurrency; i++ {
		ticker := time.NewTicker(timeToWait)
		go func() {
			for _ = range ticker.C {
				sendRequest(client, dstURL, host, received)
			}
		}()
	}

	for {
		select {
		case t := <-timeout:
			// Periodically print stats about the request load.
			fmt.Printf("%s %6d/%1d/%1d requests %6d kilobytes %s [%3d %3d %3d %4d ]\n",
				t.Format(time.RFC3339),
				good,
				bad,
				failed,
				(size / 1024),
				interval,
				hist.ValueAtQuantile(50)/1000000,
				hist.ValueAtQuantile(95)/1000000,
				hist.ValueAtQuantile(99)/1000000,
				hist.ValueAtQuantile(999)/1000000)
			count = 0
			size = 0
			good = 0
			bad = 0
			failed = 0
			hist = hdrhistogram.New(0, 60000000000, 5)
			timeout = time.After(*interval)
		case managedResp := <-received:
			count++
			if managedResp.err != nil {
				fmt.Fprintln(os.Stderr, managedResp.err)
				failed++
			} else {
				size += managedResp.sz
				if managedResp.code >= 200 && managedResp.code < 500 {
					good++
				} else {
					bad++
				}
				hist.RecordValue(managedResp.latency)
			}
		}
	}
}
<commit_msg>limit connections to concurrency<commit_after>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path"
	"time"

	"github.com/codahale/hdrhistogram"
)

type MeasuredResponse struct {
	sz      uint64
	code    int
	latency int64
	timeout bool
	err     error
}

func newClient(
	compress bool,
	https bool,
	reuse bool,
	maxConn uint,
) *http.Client {
	tr := http.Transport{
		DisableCompression:  !compress,
		DisableKeepAlives:   !reuse,
		MaxIdleConnsPerHost: int(maxConn),
	}
	if https {
		tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
	}
	return &http.Client{Transport: &tr}
}

func sendRequest(
	client *http.Client,
	url *url.URL,
	host *string,
	received chan *MeasuredResponse,
) {
	req, err := http.NewRequest("GET", url.String(), nil)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		fmt.Fprintln(os.Stderr, "\n")
	}
	req.Host = *host

	// FIX: find a way to measure latency with the http client.
	start := time.Now()
	response, err := client.Do(req)

	elapsed := time.Since(start)
	if err != nil {
		received <- &MeasuredResponse{0, 0, 0, false, err}
	} else {
		sz, _ := io.Copy(ioutil.Discard, response.Body)
		response.Body.Close()
		received <- &MeasuredResponse{uint64(sz), response.StatusCode, elapsed.Nanoseconds(), false, nil}
	}
}

func exUsage(msg string) {
	fmt.Fprintf(os.Stderr, "%s\n", msg)
	fmt.Fprintf(os.Stderr, "Usage: %s [flags]\n", path.Base(os.Args[0]))
	flag.PrintDefaults()
	os.Exit(64)
}

func main() {
	qps := flag.Int("qps", 1, "QPS to send to backends per request thread")
	concurrency := flag.Uint("concurrency", 1, "Number of request threads")
	host := flag.String("host", "web", "value of Host header to set")
	urldest := flag.String("url", "http://localhost:4140/", "Destination url")
	interval := flag.Duration("interval", 10*time.Second, "reporting interval")
	reuse := flag.Bool("reuse", false, "reuse connections")
	compress := flag.Bool("compress", false, "use compression")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [flags]\n", path.Base(os.Args[0]))
		flag.PrintDefaults()
	}

	flag.Parse()

	if *qps < 1 {
		exUsage("qps must be at least 1")
	}

	if *concurrency < 1 {
		exUsage("concurrency must be at least 1")
	}

	dstURL, err := url.Parse(*urldest)
	if err != nil {
		exUsage(fmt.Sprintf("invalid URL: '%s': %s\n", urldest, err.Error()))
	}

	// Repsonse tracking metadata.
	count := uint64(0)
	size := uint64(0)
	good := uint64(0)
	bad := uint64(0)
	failed := uint64(0)
	// from 0 to 1 minute in nanoseconds
	// FIX: verify that these buckets work correctly for our use case.
	hist := hdrhistogram.New(0, 60000000000, 5)
	received := make(chan *MeasuredResponse)
	timeout := time.After(*interval)

	timeToWait := time.Millisecond * time.Duration(1000 / *qps)

	doTLS := dstURL.Scheme == "https"
	client := newClient(*compress, doTLS, *reuse, *concurrency)

	for i := uint(0); i < *concurrency; i++ {
		ticker := time.NewTicker(timeToWait)
		go func() {
			for _ = range ticker.C {
				sendRequest(client, dstURL, host, received)
			}
		}()
	}

	for {
		select {
		case t := <-timeout:
			// Periodically print stats about the request load.
			fmt.Printf("%s %6d/%1d/%1d requests %6d kilobytes %s [%3d %3d %3d %4d ]\n",
				t.Format(time.RFC3339),
				good,
				bad,
				failed,
				(size / 1024),
				interval,
				hist.ValueAtQuantile(50)/1000000,
				hist.ValueAtQuantile(95)/1000000,
				hist.ValueAtQuantile(99)/1000000,
				hist.ValueAtQuantile(999)/1000000)
			count = 0
			size = 0
			good = 0
			bad = 0
			failed = 0
			hist = hdrhistogram.New(0, 60000000000, 5)
			timeout = time.After(*interval)
		case managedResp := <-received:
			count++
			if managedResp.err != nil {
				fmt.Fprintln(os.Stderr, managedResp.err)
				failed++
			} else {
				size += managedResp.sz
				if managedResp.code >= 200 && managedResp.code < 500 {
					good++
				} else {
					bad++
				}
				hist.RecordValue(managedResp.latency)
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)

const (
	version = "0.8.2"
)

func init() {
	flag.Usage = func() {
		h := "Usage:\n"
		h += "  bozr [OPTIONS] (DIR|FILE)\n\n"

		h += "Options:\n"
		h += "  -d, --debug		Enable debug mode\n"
		h += "  -H, --host		Server to test\n"
		h += "  -h, --help		Print usage\n"
		h += "  -i, --info		Enable info mode. Print request and response details.\n"
		h += "      --junit		Enable junit xml reporter\n"
		h += "  -v, --version		Print version information and quit\n\n"

		h += "Examples:\n"
		h += "  bozr ./examples\n"
		h += "  bozr -H http://example.com ./examples \n"

		fmt.Fprintf(os.Stderr, h)
	}
}

var (
	suiteDir    string
	hostFlag    string
	infoFlag    bool
	debugFlag   bool
	helpFlag    bool
	versionFlag bool
	junitFlag   bool

	Info  *log.Logger
	Debug *log.Logger
)

func initLogger() {
	infoHandler := ioutil.Discard
	debugHandler := ioutil.Discard

	if infoFlag {
		infoHandler = os.Stdout
	}

	if debugFlag {
		debugHandler = os.Stdout
	}

	Info = log.New(infoHandler, "", 0)
	Debug = log.New(debugHandler, "DEBUG: ", log.Ltime|log.Lshortfile)
}

func main() {
	flag.BoolVar(&debugFlag, "d", false, "Enable debug mode.")
	flag.BoolVar(&debugFlag, "debug", false, "Enable debug mode")

	flag.BoolVar(&infoFlag, "i", false, "Enable info mode. Print request and response details.")
	flag.BoolVar(&infoFlag, "info", false, "Enable info mode. Print request and response details.")

	flag.StringVar(&hostFlag, "H", "http://localhost:8080", "Test server address")

	flag.BoolVar(&helpFlag, "h", false, "Print usage")
	flag.BoolVar(&helpFlag, "help", false, "Print usage")

	flag.BoolVar(&versionFlag, "v", false, "Print version information and quit")
	flag.BoolVar(&versionFlag, "version", false, "Print version information and quit")

	flag.BoolVar(&junitFlag, "junit", false, "Enable junit xml reporter")

	flag.Parse()

	if versionFlag {
		fmt.Println("bozr version " + version)
		return
	}

	if helpFlag {
		flag.Usage()
		return
	}

	initLogger()

	src := flag.Arg(0)

	if src == "" {
		fmt.Print("You must specify a directory or file with tests.\n\n")
		flag.Usage()
		return
	}

	// check specified source dir/file exists
	_, err := os.Lstat(src)
	if err != nil {
		fmt.Println(err)
		return
	}

	var ch <-chan TestSuite
	if filepath.Ext(src) == "" {
		debugMsg("Loading from directory...")
		suiteDir = src
		ch = NewDirLoader(suiteDir)
	} else {
		debugMsg("Loading from file...")
		suiteDir = filepath.Dir(src)
		ch = NewFileLoader(src)
	}
	time.Sleep(time.Second * 2)

	reporters := []Reporter{NewConsoleReporter()}
	if junitFlag {
		path, _ := filepath.Abs("./report")
		reporters = append(reporters, NewJUnitReporter(path))
	}
	reporter := NewMultiReporter(reporters...)

	// test case runner?
	for suite := range ch {
		for _, testCase := range suite.Cases {

			rememberedMap := make(map[string]interface{})

			for _, c := range testCase.Calls {
				addAll(c.Args, rememberedMap)
				tr := call(suite, testCase, c, rememberedMap)
				tr.Suite = suite
				reporter.Report(*tr)
			}
		}
	}

	reporter.Flush()
}

func addAll(src, target map[string]interface{}) {
	for key, val := range src {
		target[key] = val
	}
}

func call(testSuite TestSuite, testCase TestCase, call Call, rememberMap map[string]interface{}) (result *TestResult) {
	debugMsg("--- Starting call ...") // TODO add call description
	start := time.Now()
	result = &TestResult{Case: testCase}

	on := call.On

	dat := []byte(on.Body)
	if on.BodyFile != "" {
		uri, err := toAbsPath(testSuite.Dir, on.BodyFile)
		if err != nil {
			result.Cause = err
			return
		}

		if d, err := ioutil.ReadFile(uri); err == nil {
			dat = d
		} else {
			result.Cause = fmt.Errorf("Can't read body file: %s", err.Error())
			return
		}
	}

	req, err := populateRequest(on, string(dat), rememberMap)
	if err != nil {
		result.Cause = err
		return
	}

	printRequestInfo(req, dat)

	client := &http.Client{}

	resp, err := client.Do(req)

	if err != nil {
		debugMsg("Error when sending request", err)
		result.Cause = err
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		debugMsg("Error reading response")
		result.Cause = err
		return
	}

	end := time.Now()

	testResp := Response{http: *resp, body: body}
	result.Resp = testResp
	result.Duration = end.Sub(start)

	Info.Println(strings.Repeat("-", 50))
	Info.Println(testResp.ToString())
	Info.Println("")

	exps, err := expectations(call, testSuite.Dir)
	if err != nil {
		result.Cause = err
		return
	}

	for _, exp := range exps {
		checkErr := exp.check(testResp)
		if checkErr != nil {
			result.Cause = checkErr
			return
		}
	}

	m, err := testResp.parseBody()
	if err != nil {
		debugMsg("Can't parse response body to Map for [remember]")
		result.Cause = err
		return
	}

	err = remember(m, call.Remember, rememberMap)
	debugMsg("Remember: ", rememberMap)
	if err != nil {
		debugMsg("Error remember")
		result.Cause = err
		return
	}

	return result
}

func populateRequest(on On, body string, rememberMap map[string]interface{}) (*http.Request, error) {

	url, err := urlPrefix(populateRememberedVars(on.URL, rememberMap))
	if err != nil {
		return nil, errors.New("Cannot create request. Invalid url: " + on.URL)
	}

	body = populateRememberedVars(body, rememberMap)
	dat := []byte(body)

	req, _ := http.NewRequest(on.Method, url, bytes.NewBuffer(dat))

	for key, value := range on.Headers {
		req.Header.Add(key, populateRememberedVars(value, rememberMap))
	}

	q := req.URL.Query()
	for key, value := range on.Params {
		q.Add(key, populateRememberedVars(value, rememberMap))
	}
	req.URL.RawQuery = q.Encode()

	return req, nil
}

func urlPrefix(p string) (string, error) {
	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
		return p, nil
	}

	return concatURL(hostFlag, p)
}

func concatURL(base string, p string) (string, error) {
	baseURL, err := url.Parse(base)
	if err != nil {
		return "", err
	}
	return baseURL.Scheme + "://" + baseURL.Host + path.Join(baseURL.Path, p), nil
}

func populateRememberedVars(str string, rememberMap map[string]interface{}) string {
	res := str
	for varName, val := range rememberMap {
		placeholder := "{" + varName + "}"
		res = strings.Replace(res, placeholder, toString(val), -1)
	}
	return res
}

// toString returns value suitable to insert as an argument
// if value if a float where decimal part is zero - convert to int
func toString(rw interface{}) string {
	var sv interface{} = rw
	if fv, ok := rw.(float64); ok {
		_, frac := math.Modf(fv)
		if frac == 0 {
			sv = int(fv)
		}
	}

	return fmt.Sprintf("%v", sv)
}

func expectations(call Call, srcDir string) ([]ResponseExpectation, error) {
	var exps []ResponseExpectation
	if call.Expect.StatusCode != 0 {
		exps = append(exps, StatusCodeExpectation{statusCode: call.Expect.StatusCode})
	}

	if call.Expect.hasSchema() {
		var (
			schemeURI string
			err       error
		)

		if call.Expect.BodySchemaFile != "" {
			schemeURI, err = toAbsPath(srcDir, call.Expect.BodySchemaFile)
			if err != nil {
				return nil, err
			}
			schemeURI = "file:///" + schemeURI
		}

		if call.Expect.BodySchemaURI != "" {
			isHTTP := strings.HasPrefix(call.Expect.BodySchemaURI, "http://")
			isHTTPS := strings.HasPrefix(call.Expect.BodySchemaURI, "https://")
			if !(isHTTP || isHTTPS) {
				schemeURI = hostFlag + call.Expect.BodySchemaURI
			} else {
				schemeURI = call.Expect.BodySchemaURI
			}
		}
		exps = append(exps, BodySchemaExpectation{schemaURI: schemeURI})
	}

	if len(call.Expect.Body) > 0 {
		exps = append(exps, BodyExpectation{pathExpectations: call.Expect.Body})
	}

	if len(call.Expect.Headers) > 0 {
		for k, v := range call.Expect.Headers {
			exps = append(exps, HeaderExpectation{Name: k, Value: v})
		}
	}

	if call.Expect.ContentType != "" {
		exps = append(exps, ContentTypeExpectation{call.Expect.ContentType})
	}

	// and so on
	return exps, nil
}

func toAbsPath(srcDir string, assetPath string) (string, error) {
	if filepath.IsAbs(assetPath) {
		// ignore srcDir
		return assetPath, nil
	}

	uri, err := filepath.Abs(filepath.Join(suiteDir, srcDir, assetPath))
	if err != nil {
		return "", errors.New("Invalid file path: " + assetPath)
	}

	return filepath.ToSlash(uri), nil
}

func remember(body interface{}, remember map[string]string, rememberedMap map[string]interface{}) (err error) {

	for varName, path := range remember {

		splitPath := strings.Split(path, ".")

		if rememberVar, err := getByPath(body, splitPath...); err == nil {
			rememberedMap[varName] = rememberVar
		} else {
			strErr := fmt.Sprintf("Remembered value not found, path: %v", path)
			err = errors.New(strErr)
		}
		//fmt.Printf("v: %v\n", getByPath(bodyMap, b...))
	}

	return err
}

func printRequestInfo(req *http.Request, body []byte) {
	Info.Println()
	Info.Printf("%s %s %s\n", req.Method, req.URL.String(), req.Proto)

	if len(req.Header) > 0 {
		Info.Println()
	}

	for k, v := range req.Header {
		Info.Printf("%s: %s", k, strings.Join(v, " "))
	}
	Info.Println()

	if len(body) > 0 {
		Info.Printf(string(body))
	}
}

func debugMsg(a ...interface{}) {
	Debug.Print(a)
}

func debugMsgF(tpl string, a ...interface{}) {
	Debug.Printf(tpl, a)
}
<commit_msg>clean up debug messages<commit_after>package main

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"math"
	"net/http"
	"net/url"
	"os"
	"path"
	"path/filepath"
	"strings"
	"time"
)

const (
	version = "0.8.2"
)

func init() {
	flag.Usage = func() {
		h := "Usage:\n"
		h += "  bozr [OPTIONS] (DIR|FILE)\n\n"

		h += "Options:\n"
		h += "  -d, --debug		Enable debug mode\n"
		h += "  -H, --host		Server to test\n"
		h += "  -h, --help		Print usage\n"
		h += "  -i, --info		Enable info mode. Print request and response details.\n"
		h += "      --junit		Enable junit xml reporter\n"
		h += "  -v, --version		Print version information and quit\n\n"

		h += "Examples:\n"
		h += "  bozr ./examples\n"
		h += "  bozr -H http://example.com ./examples \n"

		fmt.Fprintf(os.Stderr, h)
	}
}

var (
	suiteDir    string
	hostFlag    string
	infoFlag    bool
	debugFlag   bool
	helpFlag    bool
	versionFlag bool
	junitFlag   bool

	Info  *log.Logger
	Debug *log.Logger
)

func initLogger() {
	infoHandler := ioutil.Discard
	debugHandler := ioutil.Discard

	if infoFlag {
		infoHandler = os.Stdout
	}

	if debugFlag {
		debugHandler = os.Stdout
	}

	Info = log.New(infoHandler, "", 0)
	Debug = log.New(debugHandler, "DEBUG: ", log.Ltime|log.Lshortfile)
}

func main() {
	flag.BoolVar(&debugFlag, "d", false, "Enable debug mode.")
	flag.BoolVar(&debugFlag, "debug", false, "Enable debug mode")

	flag.BoolVar(&infoFlag, "i", false, "Enable info mode. Print request and response details.")
	flag.BoolVar(&infoFlag, "info", false, "Enable info mode. Print request and response details.")

	flag.StringVar(&hostFlag, "H", "http://localhost:8080", "Test server address")

	flag.BoolVar(&helpFlag, "h", false, "Print usage")
	flag.BoolVar(&helpFlag, "help", false, "Print usage")

	flag.BoolVar(&versionFlag, "v", false, "Print version information and quit")
	flag.BoolVar(&versionFlag, "version", false, "Print version information and quit")

	flag.BoolVar(&junitFlag, "junit", false, "Enable junit xml reporter")

	flag.Parse()

	if versionFlag {
		fmt.Println("bozr version " + version)
		return
	}

	if helpFlag {
		flag.Usage()
		return
	}

	initLogger()

	src := flag.Arg(0)

	if src == "" {
		fmt.Print("You must specify a directory or file with tests.\n\n")
		flag.Usage()
		return
	}

	// check specified source dir/file exists
	_, err := os.Lstat(src)
	if err != nil {
		fmt.Println(err)
		return
	}

	var ch <-chan TestSuite
	if filepath.Ext(src) == "" {
		debugMsg("Loading from directory")
		suiteDir = src
		ch = NewDirLoader(suiteDir)
	} else {
		debugMsg("Loading from file")
		suiteDir = filepath.Dir(src)
		ch = NewFileLoader(src)
	}

	reporters := []Reporter{NewConsoleReporter()}
	if junitFlag {
		path, _ := filepath.Abs("./report")
		reporters = append(reporters, NewJUnitReporter(path))
	}
	reporter := NewMultiReporter(reporters...)

	// test case runner?
	for suite := range ch {
		for _, testCase := range suite.Cases {

			rememberedMap := make(map[string]interface{})

			for _, c := range testCase.Calls {
				addAll(c.Args, rememberedMap)
				tr := call(suite, testCase, c, rememberedMap)
				tr.Suite = suite
				reporter.Report(*tr)
			}
		}
	}

	reporter.Flush()
}

func addAll(src, target map[string]interface{}) {
	for key, val := range src {
		target[key] = val
	}
}

func call(testSuite TestSuite, testCase TestCase, call Call, rememberMap map[string]interface{}) (result *TestResult) {
	debugMsgF("Starting call: %s - %s", testSuite.Name, testCase.Name)
	start := time.Now()
	result = &TestResult{Case: testCase}

	on := call.On

	dat := []byte(on.Body)
	if on.BodyFile != "" {
		uri, err := toAbsPath(testSuite.Dir, on.BodyFile)
		if err != nil {
			result.Cause = err
			return
		}

		if d, err := ioutil.ReadFile(uri); err == nil {
			dat = d
		} else {
			result.Cause = fmt.Errorf("Can't read body file: %s", err.Error())
			return
		}
	}

	req, err := populateRequest(on, string(dat), rememberMap)
	if err != nil {
		result.Cause = err
		return
	}

	printRequestInfo(req, dat)

	client := &http.Client{}

	resp, err := client.Do(req)

	if err != nil {
		debugMsg("Error when sending request", err)
		result.Cause = err
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		debugMsg("Error reading response")
		result.Cause = err
		return
	}

	end := time.Now()

	testResp := Response{http: *resp, body: body}
	result.Resp = testResp
	result.Duration = end.Sub(start)

	Info.Println(strings.Repeat("-", 50))
	Info.Println(testResp.ToString())
	Info.Println("")

	exps, err := expectations(call, testSuite.Dir)
	if err != nil {
		result.Cause = err
		return
	}

	for _, exp := range exps {
		checkErr := exp.check(testResp)
		if checkErr != nil {
			result.Cause = checkErr
			return
		}
	}

	m, err := testResp.parseBody()
	if err != nil {
		debugMsg("Can't parse response body to Map for [remember]")
		result.Cause = err
		return
	}

	err = remember(m, call.Remember, rememberMap)
	debugMsg("Remember: ", rememberMap)
	if err != nil {
		debugMsg("Error remember")
		result.Cause = err
		return
	}

	return result
}

func populateRequest(on On, body string, rememberMap map[string]interface{}) (*http.Request, error) {

	url, err := urlPrefix(populateRememberedVars(on.URL, rememberMap))
	if err != nil {
		return nil, errors.New("Cannot create request. Invalid url: " + on.URL)
	}

	body = populateRememberedVars(body, rememberMap)
	dat := []byte(body)

	req, _ := http.NewRequest(on.Method, url, bytes.NewBuffer(dat))

	for key, value := range on.Headers {
		req.Header.Add(key, populateRememberedVars(value, rememberMap))
	}

	q := req.URL.Query()
	for key, value := range on.Params {
		q.Add(key, populateRememberedVars(value, rememberMap))
	}
	req.URL.RawQuery = q.Encode()

	return req, nil
}

func urlPrefix(p string) (string, error) {
	if strings.HasPrefix(p, "http://") || strings.HasPrefix(p, "https://") {
		return p, nil
	}

	return concatURL(hostFlag, p)
}

func concatURL(base string, p string) (string, error) {
	baseURL, err := url.Parse(base)
	if err != nil {
		return "", err
	}
	return baseURL.Scheme + "://" + baseURL.Host + path.Join(baseURL.Path, p), nil
}

func populateRememberedVars(str string, rememberMap map[string]interface{}) string {
	res := str
	for varName, val := range rememberMap {
		placeholder := "{" + varName + "}"
		res = strings.Replace(res, placeholder, toString(val), -1)
	}
	return res
}

// toString returns value suitable to insert as an argument
// if value if a float where decimal part is zero - convert to int
func toString(rw interface{}) string {
	var sv interface{} = rw
	if fv, ok := rw.(float64); ok {
		_, frac := math.Modf(fv)
		if frac == 0 {
			sv = int(fv)
		}
	}

	return fmt.Sprintf("%v", sv)
}

func expectations(call Call, srcDir string) ([]ResponseExpectation, error) {
	var exps []ResponseExpectation
	if call.Expect.StatusCode != 0 {
		exps = append(exps, StatusCodeExpectation{statusCode: call.Expect.StatusCode})
	}

	if call.Expect.hasSchema() {
		var (
			schemeURI string
			err       error
		)

		if call.Expect.BodySchemaFile != "" {
			schemeURI, err = toAbsPath(srcDir, call.Expect.BodySchemaFile)
			if err != nil {
				return nil, err
			}
			schemeURI = "file:///" + schemeURI
		}

		if call.Expect.BodySchemaURI != "" {
			isHTTP := strings.HasPrefix(call.Expect.BodySchemaURI, "http://")
			isHTTPS := strings.HasPrefix(call.Expect.BodySchemaURI, "https://")
			if !(isHTTP || isHTTPS) {
				schemeURI = hostFlag + call.Expect.BodySchemaURI
			} else {
				schemeURI = call.Expect.BodySchemaURI
			}
		}
		exps = append(exps, BodySchemaExpectation{schemaURI: schemeURI})
	}

	if len(call.Expect.Body) > 0 {
		exps = append(exps, BodyExpectation{pathExpectations: call.Expect.Body})
	}

	if len(call.Expect.Headers) > 0 {
		for k, v := range call.Expect.Headers {
			exps = append(exps, HeaderExpectation{Name: k, Value: v})
		}
	}

	if call.Expect.ContentType != "" {
		exps = append(exps, ContentTypeExpectation{call.Expect.ContentType})
	}

	// and so on
	return exps, nil
}

func toAbsPath(srcDir string, assetPath string) (string, error) {
	if filepath.IsAbs(assetPath) {
		// ignore srcDir
		return assetPath, nil
	}

	uri, err := filepath.Abs(filepath.Join(suiteDir, srcDir, assetPath))
	if err != nil {
		return "", errors.New("Invalid file path: " + assetPath)
	}

	return filepath.ToSlash(uri), nil
}

func remember(body interface{}, remember map[string]string, rememberedMap map[string]interface{}) (err error) {

	for varName, path := range remember {

		splitPath := strings.Split(path, ".")

		if rememberVar, err := getByPath(body, splitPath...); err == nil {
			rememberedMap[varName] = rememberVar
		} else {
			strErr := fmt.Sprintf("Remembered value not found, path: %v", path)
			err = errors.New(strErr)
		}
		//fmt.Printf("v: %v\n", getByPath(bodyMap, b...))
	}

	return err
}

func printRequestInfo(req *http.Request, body []byte) {
	Info.Println()
	Info.Printf("%s %s %s\n", req.Method, req.URL.String(), req.Proto)

	if len(req.Header) > 0 {
		Info.Println()
	}

	for k, v := range req.Header {
		Info.Printf("%s: %s", k, strings.Join(v, " "))
	}
	Info.Println()

	if len(body) > 0 {
		Info.Printf(string(body))
	}
}

func debugMsg(a ...interface{}) {
	Debug.Print(a...)
}

func debugMsgF(tpl string, a ...interface{}) {
	Debug.Printf(tpl, a...)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"io/ioutil"
	"os"

	"github.com/mithrandie/csvq/lib/action"
	"github.com/mithrandie/csvq/lib/cmd"
	"github.com/mithrandie/csvq/lib/query"

	"github.com/urfave/cli"
)

var version = "v0.8.4"

func main() {
	cli.AppHelpTemplate = appHHelpTemplate
	cli.CommandHelpTemplate = commandHelpTemplate

	app := cli.NewApp()

	app.Name = "csvq"
	app.Usage = "SQL like query language for csv"
	app.ArgsUsage = "[\"query\"|\"statements\"|argument]"
	app.Version = version

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "delimiter, d",
			Usage: "field delimiter. Default is \",\" for csv files, \"\\t\" for tsv files.",
		},
		cli.StringFlag{
			Name:  "encoding, e",
			Value: "UTF8",
			Usage: "file encoding. one of: UTF8|SJIS",
		},
		cli.StringFlag{
			Name:  "line-break, l",
			Value: "LF",
			Usage: "line break. one of: CRLF|LF|CR",
		},
		cli.StringFlag{
			Name:  "timezone, z",
			Value: "Local",
			Usage: "default timezone. \"Local\", \"UTC\" or a timezone name(e.g. \"America/Los_Angeles\")",
		},
		cli.StringFlag{
			Name:  "repository, r",
			Usage: "directory path where files are located",
		},
		cli.StringFlag{
			Name:  "source, s",
			Usage: "load query from `FILE`",
		},
		cli.StringFlag{
			Name:  "datetime-format, t",
			Usage: "set datetime format to parse strings",
		},
		cli.StringFlag{
			Name:  "wait-timeout, w",
			Value: "10",
			Usage: "limit of the waiting time in seconds to wait for locked files to be released",
		},
		cli.BoolFlag{
			Name:  "no-header, n",
			Usage: "import the first line as a record",
		},
		cli.BoolFlag{
			Name:  "without-null, a",
			Usage: "parse empty fields as empty strings",
		},
		cli.StringFlag{
			Name:  "write-encoding, E",
			Value: "UTF8",
			Usage: "file encoding. one of: UTF8|SJIS",
		},
		cli.StringFlag{
			Name:  "out, o",
			Usage: "write output to `FILE`",
		},
		cli.StringFlag{
			Name:  "format, f",
			Usage: "output format. one of: CSV|TSV|JSON|TEXT",
		},
		cli.StringFlag{
			Name:  "write-delimiter, D",
			Usage: "field delimiter for CSV",
		},
		cli.BoolFlag{
			Name:  "without-header, N",
			Usage: "when the file format is specified as CSV or TSV, write without the header line",
		},
		cli.BoolFlag{
			Name:  "quiet, q",
			Usage: "suppress operation log output",
		},
		cli.IntFlag{
			Name:  "cpu, p",
			Usage: "hint for the number of cpu cores to be used. 1 - number of cpu cores",
		},
		cli.BoolFlag{
			Name:  "stats, x",
			Usage: "show execution time and memory statistics",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:      "fields",
			Usage:     "Show fields in a file",
			ArgsUsage: "CSV_FILE_PATH",
			Action: func(c *cli.Context) error {
				if c.NArg() != 1 {
					cli.ShowCommandHelp(c, "fields")
					return cli.NewExitError("table is not specified", 1)
				}

				table := c.Args().First()

				err := action.ShowFields(table)
				if err != nil {
					return cli.NewExitError(err.Error(), 1)
				}

				return nil
			},
		},
		{
			Name:      "calc",
			Usage:     "Calculate a value from stdin",
			ArgsUsage: "\"expression\"",
			Action: func(c *cli.Context) error {
				if c.NArg() != 1 {
					cli.ShowCommandHelp(c, "calc")
					return cli.NewExitError("expression is empty", 1)
				}

				expr := c.Args().First()
				err := action.Calc(expr)
				if err != nil {
					return cli.NewExitError(err.Error(), 1)
				}

				return nil
			},
		},
	}

	app.Before = func(c *cli.Context) error {
		err := setFlags(c)
		if err != nil {
			return cli.NewExitError(err.Error(), 1)
		}
		return nil
	}

	app.Action = func(c *cli.Context) error {
		queryString, err := readQuery(c)
		if err != nil {
			cli.ShowAppHelp(c)
			return cli.NewExitError(err.Error(), 1)
		}

		if len(queryString) < 1 {
			err = action.LaunchInteractiveShell()
		} else {
			err = action.Run(queryString, cmd.GetFlags().Source)
		}

		if err != nil {
			code := 1
			if apperr, ok := err.(query.AppError); ok {
				code = apperr.GetCode()
			} else if ex, ok := err.(*query.Exit); ok {
				code = ex.GetCode()
			}
			return cli.NewExitError(err.Error(), code)
		}

		return nil
	}

	app.Run(os.Args)
}

func readQuery(c *cli.Context) (string, error) {
	var queryString string

	flags := cmd.GetFlags()
	if 0 < len(flags.Source) {
		fp, err := os.Open(flags.Source)
		if err != nil {
			return queryString, err
		}
		defer fp.Close()

		buf, err := ioutil.ReadAll(fp)
		if err != nil {
			return queryString, err
		}
		queryString = string(buf)

	} else {
		if 1 < c.NArg() {
			return queryString, errors.New("multiple queries or statements were passed")
		}
		queryString = c.Args().First()
	}

	return queryString, nil
}

func setFlags(c *cli.Context) error {
	if err := cmd.SetDelimiter(c.GlobalString("delimiter")); err != nil {
		return err
	}
	if err := cmd.SetEncoding(c.GlobalString("encoding")); err != nil {
		return err
	}
	if err := cmd.SetLineBreak(c.String("line-break")); err != nil {
		return err
	}
	if err := cmd.SetLocation(c.String("timezone")); err != nil {
		return err
	}
	if err := cmd.SetRepository(c.GlobalString("repository")); err != nil {
		return err
	}
	if err := cmd.SetSource(c.GlobalString("source")); err != nil {
		return err
	}
	cmd.SetDatetimeFormat(c.GlobalString("datetime-format"))
	if err := cmd.SetWaitTimeout(c.GlobalString("wait-timeout")); err != nil {
		return err
	}
	cmd.SetNoHeader(c.GlobalBool("no-header"))
	cmd.SetWithoutNull(c.GlobalBool("without-null"))

	if err := cmd.SetWriteEncoding(c.GlobalString("write-encoding")); err != nil {
		return err
	}
	if err := cmd.SetOut(c.GlobalString("out")); err != nil {
		return err
	}
	if err := cmd.SetFormat(c.GlobalString("format")); err != nil {
		return err
	}
	if err := cmd.SetWriteDelimiter(c.GlobalString("write-delimiter")); err != nil {
		return err
	}
	cmd.SetWithoutHeader(c.GlobalBool("without-header"))

	cmd.SetQuiet(c.GlobalBool("quiet"))
	cmd.SetCPU(c.GlobalInt("cpu"))
	cmd.SetStats(c.GlobalBool("stats"))

	return nil
}
<commit_msg>Update version for Release v0.8.5<commit_after>package main

import (
	"errors"
	"io/ioutil"
	"os"

	"github.com/mithrandie/csvq/lib/action"
	"github.com/mithrandie/csvq/lib/cmd"
	"github.com/mithrandie/csvq/lib/query"

	"github.com/urfave/cli"
)

var version = "v0.8.5"

func main() {
	cli.AppHelpTemplate = appHHelpTemplate
	cli.CommandHelpTemplate = commandHelpTemplate

	app := cli.NewApp()

	app.Name = "csvq"
	app.Usage = "SQL like query language for csv"
	app.ArgsUsage = "[\"query\"|\"statements\"|argument]"
	app.Version = version

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "delimiter, d",
			Usage: "field delimiter. Default is \",\" for csv files, \"\\t\" for tsv files.",
		},
		cli.StringFlag{
			Name:  "encoding, e",
			Value: "UTF8",
			Usage: "file encoding. one of: UTF8|SJIS",
		},
		cli.StringFlag{
			Name:  "line-break, l",
			Value: "LF",
			Usage: "line break. one of: CRLF|LF|CR",
		},
		cli.StringFlag{
			Name:  "timezone, z",
			Value: "Local",
			Usage: "default timezone. \"Local\", \"UTC\" or a timezone name(e.g. \"America/Los_Angeles\")",
		},
		cli.StringFlag{
			Name:  "repository, r",
			Usage: "directory path where files are located",
		},
		cli.StringFlag{
			Name:  "source, s",
			Usage: "load query from `FILE`",
		},
		cli.StringFlag{
			Name:  "datetime-format, t",
			Usage: "set datetime format to parse strings",
		},
		cli.StringFlag{
			Name:  "wait-timeout, w",
			Value: "10",
			Usage: "limit of the waiting time in seconds to wait for locked files to be released",
		},
		cli.BoolFlag{
			Name:  "no-header, n",
			Usage: "import the first line as a record",
		},
		cli.BoolFlag{
			Name:  "without-null, a",
			Usage: "parse empty fields as empty strings",
		},
		cli.StringFlag{
			Name:  "write-encoding, E",
			Value: "UTF8",
			Usage: "file encoding. one of: UTF8|SJIS",
		},
		cli.StringFlag{
			Name:  "out, o",
			Usage: "write output to `FILE`",
		},
		cli.StringFlag{
			Name:  "format, f",
			Usage: "output format. one of: CSV|TSV|JSON|TEXT",
		},
		cli.StringFlag{
			Name:  "write-delimiter, D",
			Usage: "field delimiter for CSV",
		},
		cli.BoolFlag{
			Name:  "without-header, N",
			Usage: "when the file format is specified as CSV or TSV, write without the header line",
		},
		cli.BoolFlag{
			Name:  "quiet, q",
			Usage: "suppress operation log output",
		},
		cli.IntFlag{
			Name:  "cpu, p",
			Usage: "hint for the number of cpu cores to be used. 1 - number of cpu cores",
		},
		cli.BoolFlag{
			Name:  "stats, x",
			Usage: "show execution time and memory statistics",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:      "fields",
			Usage:     "Show fields in a file",
			ArgsUsage: "CSV_FILE_PATH",
			Action: func(c *cli.Context) error {
				if c.NArg() != 1 {
					cli.ShowCommandHelp(c, "fields")
					return cli.NewExitError("table is not specified", 1)
				}

				table := c.Args().First()

				err := action.ShowFields(table)
				if err != nil {
					return cli.NewExitError(err.Error(), 1)
				}

				return nil
			},
		},
		{
			Name:      "calc",
			Usage:     "Calculate a value from stdin",
			ArgsUsage: "\"expression\"",
			Action: func(c *cli.Context) error {
				if c.NArg() != 1 {
					cli.ShowCommandHelp(c, "calc")
					return cli.NewExitError("expression is empty", 1)
				}

				expr := c.Args().First()
				err := action.Calc(expr)
				if err != nil {
					return cli.NewExitError(err.Error(), 1)
				}

				return nil
			},
		},
	}

	app.Before = func(c *cli.Context) error {
		err := setFlags(c)
		if err != nil {
			return cli.NewExitError(err.Error(), 1)
		}
		return nil
	}

	app.Action = func(c *cli.Context) error {
		queryString, err := readQuery(c)
		if err != nil {
			cli.ShowAppHelp(c)
			return cli.NewExitError(err.Error(), 1)
		}

		if len(queryString) < 1 {
			err = action.LaunchInteractiveShell()
		} else {
			err = action.Run(queryString, cmd.GetFlags().Source)
		}

		if err != nil {
			code := 1
			if apperr, ok := err.(query.AppError); ok {
				code = apperr.GetCode()
			} else if ex, ok := err.(*query.Exit); ok {
				code = ex.GetCode()
			}
			return cli.NewExitError(err.Error(), code)
		}

		return nil
	}

	app.Run(os.Args)
}

func readQuery(c *cli.Context) (string, error) {
	var queryString string

	flags := cmd.GetFlags()
	if 0 < len(flags.Source) {
		fp, err := os.Open(flags.Source)
		if err != nil {
			return queryString, err
		}
		defer fp.Close()

		buf, err := ioutil.ReadAll(fp)
		if err != nil {
			return queryString, err
		}
		queryString = string(buf)

	} else {
		if 1 < c.NArg() {
			return queryString, errors.New("multiple queries or statements were passed")
		}
		queryString = c.Args().First()
	}

	return queryString, nil
}

func setFlags(c *cli.Context) error {
	if err := cmd.SetDelimiter(c.GlobalString("delimiter")); err != nil {
		return err
	}
	if err := cmd.SetEncoding(c.GlobalString("encoding")); err != nil {
		return err
	}
	if err := cmd.SetLineBreak(c.String("line-break")); err != nil {
		return err
	}
	if err := cmd.SetLocation(c.String("timezone")); err != nil {
		return err
	}
	if err := cmd.SetRepository(c.GlobalString("repository")); err != nil {
		return err
	}
	if err := cmd.SetSource(c.GlobalString("source")); err != nil {
		return err
	}
	cmd.SetDatetimeFormat(c.GlobalString("datetime-format"))
	if err := cmd.SetWaitTimeout(c.GlobalString("wait-timeout")); err != nil {
		return err
	}
	cmd.SetNoHeader(c.GlobalBool("no-header"))
	cmd.SetWithoutNull(c.GlobalBool("without-null"))

	if err := cmd.SetWriteEncoding(c.GlobalString("write-encoding")); err != nil {
		return err
	}
	if err := cmd.SetOut(c.GlobalString("out")); err != nil {
		return err
	}
	if err := cmd.SetFormat(c.GlobalString("format")); err != nil {
		return err
	}
	if err := cmd.SetWriteDelimiter(c.GlobalString("write-delimiter")); err != nil {
		return err
	}
	cmd.SetWithoutHeader(c.GlobalBool("without-header"))

	cmd.SetQuiet(c.GlobalBool("quiet"))
	cmd.SetCPU(c.GlobalInt("cpu"))
	cmd.SetStats(c.GlobalBool("stats"))

	return nil
}
<|endoftext|>