<commit_before>// Based on https://github.com/martini-contrib/staticbin
package staticbin

import (
	"bytes"
	"log"
	"net/http"
	"path"
	"time"

	"github.com/gin-gonic/gin"
)

type Options struct {
	// SkipLogging will disable [Static] log messages when a static file is served.
	SkipLogging bool
	// IndexFile defines which file to serve as index if it exists.
	IndexFile string
	// Path prefix
	Dir string
}

func (o *Options) init() {
	if o.IndexFile == "" {
		o.IndexFile = "index.html"
	}
}

// Static returns a middleware handler that serves static files in the given directory.
func Static(asset func(string) ([]byte, error), options ...Options) gin.HandlerFunc {
	if asset == nil {
		panic("asset is nil")
	}

	opt := Options{}
	for _, o := range options {
		opt = o
		break
	}
	opt.init()

	modtime := time.Now()

	return func(c *gin.Context) {
		if c.Request.Method != "GET" && c.Request.Method != "HEAD" {
			// Request is not correct. Go farther.
			return
		}

		url := c.Request.URL.Path

		b, err := asset(opt.Dir + url)

		if err != nil {
			// Try to serve the index file.
			b, err = asset(path.Join(opt.Dir+url, opt.IndexFile))

			if err != nil {
				// Go farther if the asset could not be found.
				return
			}
		}

		if !opt.SkipLogging {
			log.Println("[Static] Serving " + url)
		}

		http.ServeContent(c.Writer, c.Request, url, modtime, bytes.NewReader(b))
		c.Abort()
	}
}
<commit_msg>trif path separator prefix form filename<commit_after>// Based on https://github.com/martini-contrib/staticbin
package staticbin

import (
	"bytes"
	"log"
	"net/http"
	"path"
	"path/filepath"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
)

type Options struct {
	// SkipLogging will disable [Static] log messages when a static file is served.
	SkipLogging bool
	// IndexFile defines which file to serve as index if it exists.
	IndexFile string
	// Path prefix
	Dir string
}

func (o *Options) init() {
	if o.IndexFile == "" {
		o.IndexFile = "index.html"
	}
}

// Static returns a middleware handler that serves static files in the given directory.
func Static(asset func(string) ([]byte, error), options ...Options) gin.HandlerFunc {
	if asset == nil {
		panic("asset is nil")
	}

	opt := Options{}
	for _, o := range options {
		opt = o
		break
	}
	opt.init()

	modtime := time.Now()

	return func(c *gin.Context) {
		if c.Request.Method != "GET" && c.Request.Method != "HEAD" {
			// Request is not correct. Go farther.
			return
		}

		url := c.Request.URL.Path
		file := strings.TrimPrefix(opt.Dir+url, string(filepath.Separator))
		b, err := asset(file)

		if err != nil {
			// Try to serve the index file.
			b, err = asset(path.Join(file, opt.IndexFile))

			if err != nil {
				// Go farther if the asset could not be found.
				return
			}
		}

		if !opt.SkipLogging {
			log.Println("[Static] Serving " + url)
		}

		http.ServeContent(c.Writer, c.Request, url, modtime, bytes.NewReader(b))
		c.Abort()
	}
}
<|endoftext|>


<commit_before>package client

// Parse for `fleet status` output
import (
	"bufio"
	execPkg "os/exec"
	"strings"
)

type UnitStatus struct {
	// Unit Name with file extension
	Unit string

	// "-", "loaded"
	Load string

	// "-", "active", "failed"
	Active string

	// The state of the unit, e.g. "-", "running" or "failed"
	Sub         string
	Description string

	// The machine that is used to execute the unit.
	// Is "-", when no machine is assigned.
	// Otherwise is in the format of "uuid/ip", where uuid is shortened version of the host uuid
	// and IP is the IP assigned to that machine.
	Machine string
}

// StatusAll executes "fleetctl status" and parses the output table. Thus, certain fields can be mangled or
// shortened, e.g. the machine column.
func (this *Client) StatusAll() ([]UnitStatus, error) {
	cmd := execPkg.Command(FLEETCTL, ENDPOINT_OPTION, this.etcdPeer, "list-units")
	stdout, err := exec(cmd)
	if err != nil {
		return []UnitStatus{}, err
	}

	return parseFleetStatusOutput(stdout)
}

func parseFleetStatusOutput(output string) ([]UnitStatus, error) {
	result := make([]UnitStatus, 0)

	scanner := bufio.NewScanner(strings.NewReader(output))
	// Scan each line of input.
	lineCount := 0
	for scanner.Scan() {
		line := scanner.Text()
		lineCount++
		if lineCount == 1 {
			continue
		}

		words := filterNonEmpty(strings.Split(line, "\t"))
		unitStatus := UnitStatus{
			Unit:        words[0],
			Load:        words[1],
			Active:      words[2],
			Sub:         words[3],
			Description: words[4],
			Machine:     words[5],
		}
		result = append(result, unitStatus)
	}

	// When finished scanning if any error other than io.EOF occured
	// it will be returned by scanner.Err().
	if err := scanner.Err(); err != nil {
		return result, scanner.Err()
	}
	return result, nil
}

type Status struct {
	Running     bool
	ContainerIP string
}

func (this *Client) Status(unitFileName string) (Status, error) {
	allStatus, err := this.StatusAll()
	if err != nil {
		return Status{}, err
	}

	for _, status := range allStatus {
		if status.Unit == unitFileName {
			result := Status{
				Running:     status.Sub == "running",
				ContainerIP: "127.0.0.1",
			}
			return result, nil
		}
	}
	// Return running=false, because we didn't find it
	return Status{}, nil
}
<commit_msg>Added utility function to load specific unitfile<commit_after>package client

// Parse for `fleet status` output
import (
	"bufio"
	"fmt"
	execPkg "os/exec"
	"strings"
)

type UnitStatus struct {
	// Unit Name with file extension
	Unit string

	// "-", "loaded"
	Load string

	// "-", "active", "failed"
	Active string

	// The state of the unit, e.g. "-", "running" or "failed"
	Sub         string
	Description string

	// The machine that is used to execute the unit.
	// Is "-", when no machine is assigned.
	// Otherwise is in the format of "uuid/ip", where uuid is shortened version of the host uuid
	// and IP is the IP assigned to that machine.
	Machine string
}

// StatusAll executes "fleetctl status" and parses the output table. Thus, certain fields can be mangled or
// shortened, e.g. the machine column.
func (this *Client) StatusAll() ([]UnitStatus, error) {
	cmd := execPkg.Command(FLEETCTL, ENDPOINT_OPTION, this.etcdPeer, "list-units")
	stdout, err := exec(cmd)
	if err != nil {
		return []UnitStatus{}, err
	}

	return parseFleetStatusOutput(stdout)
}

func parseFleetStatusOutput(output string) ([]UnitStatus, error) {
	result := make([]UnitStatus, 0)

	scanner := bufio.NewScanner(strings.NewReader(output))
	// Scan each line of input.
	lineCount := 0
	for scanner.Scan() {
		line := scanner.Text()
		lineCount++
		if lineCount == 1 {
			continue
		}

		words := filterNonEmpty(strings.Split(line, "\t"))
		unitStatus := UnitStatus{
			Unit:        words[0],
			Load:        words[1],
			Active:      words[2],
			Sub:         words[3],
			Description: words[4],
			Machine:     words[5],
		}
		result = append(result, unitStatus)
	}

	// When finished scanning if any error other than io.EOF occured
	// it will be returned by scanner.Err().
	if err := scanner.Err(); err != nil {
		return result, scanner.Err()
	}
	return result, nil
}

// StatusUnit returns the UnitStatus for the given unitfile.
// If the unit is not found or could not be retrieved, an error will be returned.
//
// Internally it executes `fleetctl status` and looks for the matching
// unit file. Its {UnitStatus} will be returned.
func (this *Client) StatusUnit(unitFileName string) (UnitStatus, error) {
	status, err := this.StatusAll()
	if err != nil {
		return UnitStatus{}, err
	}

	for _, s := range status {
		if s.Unit == unitFileName {
			return s, nil
		}
	}
	return UnitStatus{}, fmt.Errorf("Unknown unitfilename: %s", unitFileName)
}

type Status struct {
	Running     bool
	ContainerIP string
}

func (this *Client) Status(unitFileName string) (Status, error) {
	allStatus, err := this.StatusAll()
	if err != nil {
		return Status{}, err
	}

	for _, status := range allStatus {
		if status.Unit == unitFileName {
			result := Status{
				Running:     status.Sub == "running",
				ContainerIP: "127.0.0.1",
			}
			return result, nil
		}
	}
	// Return running=false, because we didn't find it
	return Status{}, nil
}
<|endoftext|>


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

// +build ignore

// The run program is invoked via "go run" from src/run.bash or
// src/run.bat conditionally builds and runs the cmd/api tool.
//
// TODO(bradfitz): the "conditional" condition is always true.
// We should only do this if the user has the hg codereview extension
// enabled and verifies that the go.tools subrepo is checked out with
// a suitably recently version. In prep for the cmd/api rewrite.
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
)

// goToolsVersion is the hg revision of the go.tools subrepo we need
// to build cmd/api.  This only needs to be updated whenever a go/types
// bug fix is needed by the cmd/api tool.
const goToolsVersion = "6698ca2900e2"

var goroot string

func main() {
	log.SetFlags(0)
	goroot = os.Getenv("GOROOT") // should be set by run.{bash,bat}
	if goroot == "" {
		log.Fatal("No $GOROOT set.")
	}
	_, err := exec.LookPath("hg")
	if err != nil {
		fmt.Println("Skipping cmd/api checks; hg not available")
		return
	}

	gopath := prepGoPath()

	cmd := exec.Command("go", "install", "--tags=api_tool", "cmd/api")
	cmd.Env = append([]string{"GOPATH=" + gopath}, filterOut(os.Environ(), "GOARCH")...)
	out, err := cmd.CombinedOutput()
	if err != nil {
		log.Fatalf("Error installing cmd/api: %v\n%s", err, out)
	}

	out, err = exec.Command("go", "tool", "api",
		"-c", file("go1", "go1.1", "go1.2"),
		"-next", file("next"),
		"-except", file("except")).CombinedOutput()
	if err != nil {
		log.Fatalf("Error running API checker: %v\n%s", err, out)
	}
	fmt.Print(string(out))
}

// filterOut returns a copy of the src environment without environment
// variables from remove.
// TODO: delete when issue 6201 is fixed.
func filterOut(src []string, remove ...string) (out []string) {
S:
	for _, s := range src {
		for _, r := range remove {
			if strings.HasPrefix(s, r) && strings.HasPrefix(s, r+"=") {
				continue S
			}
		}
		out = append(out, s)
	}
	return
}

// file expands s to $GOROOT/api/s.txt.
// If there are more than 1, they're comma-separated.
func file(s ...string) string {
	if len(s) > 1 {
		return file(s[0]) + "," + file(s[1:]...)
	}
	return filepath.Join(goroot, "api", s[0]+".txt")
}

// prepGoPath returns a GOPATH for the "go" tool to compile the API tool with.
// It tries to re-use a go.tools checkout from a previous run if possible,
// else it hg clones it.
func prepGoPath() string {
	const tempBase = "go.tools.TMP"

	username := ""
	u, err := user.Current()
	if err == nil {
		username = u.Username
	} else {
		// Only need to handle Unix here, as Windows's os/user uses
		// native syscall and should work fine without cgo.
		username = os.Getenv("USER")
		if username == "" {
			log.Fatalf("Error getting current user: %v", err)
		}
	}

	// The GOPATH we'll return
	gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username), goToolsVersion)

	// cloneDir is where we run "hg clone".
	cloneDir := filepath.Join(gopath, "src", "code.google.com", "p")

	// The dir we clone into. We only atomically rename it to finalDir on
	// clone success.
	tmpDir := filepath.Join(cloneDir, tempBase)

	// finalDir is where the checkout will live once it's complete.
	finalDir := filepath.Join(cloneDir, "go.tools")

	if goToolsCheckoutGood(finalDir) {
		return gopath
	}
	os.RemoveAll(finalDir) // in case it's there but corrupt
	os.RemoveAll(tmpDir)   // in case of aborted hg clone before

	if err := os.MkdirAll(cloneDir, 0700); err != nil {
		log.Fatal(err)
	}
	cmd := exec.Command("hg",
		"clone", "--rev="+goToolsVersion,
		"https://code.google.com/p/go.tools",
		tempBase)
	cmd.Dir = cloneDir
	out, err := cmd.CombinedOutput()
	if err != nil {
		if _, err := http.Head("http://ip.appspot.com/"); err != nil {
			log.Printf("# Skipping API check; network appears to be unavailable")
			os.Exit(0)
		}
		log.Fatalf("Error running hg clone on go.tools: %v\n%s", err, out)
	}
	if err := os.Rename(tmpDir, finalDir); err != nil {
		log.Fatal(err)
	}
	return gopath
}

func cleanUsername(n string) string {
	b := make([]rune, len(n))
	for i, r := range n {
		if r == '\\' || r == '/' || r == ':' {
			b[i] = '_'
		} else {
			b[i] = r
		}
	}
	return string(b)
}

func goToolsCheckoutGood(dir string) bool {
	if _, err := os.Stat(dir); err != nil {
		return false
	}

	cmd := exec.Command("hg", "id", "--id")
	cmd.Dir = dir
	out, err := cmd.Output()
	if err != nil {
		return false
	}
	id := strings.TrimSpace(string(out))
	if id != goToolsVersion {
		return false
	}

	cmd = exec.Command("hg", "status")
	cmd.Dir = dir
	out, err = cmd.Output()
	if err != nil || len(out) > 0 {
		return false
	}

	return true
}
<commit_msg>cmd/api: ensure GOPATH always points to the correct go.tools<commit_after>// Copyright 2013 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.

// +build ignore

// The run program is invoked via "go run" from src/run.bash or
// src/run.bat conditionally builds and runs the cmd/api tool.
//
// TODO(bradfitz): the "conditional" condition is always true.
// We should only do this if the user has the hg codereview extension
// enabled and verifies that the go.tools subrepo is checked out with
// a suitably recently version. In prep for the cmd/api rewrite.
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"os/user"
	"path/filepath"
	"strings"
)

// goToolsVersion is the hg revision of the go.tools subrepo we need
// to build cmd/api.  This only needs to be updated whenever a go/types
// bug fix is needed by the cmd/api tool.
const goToolsVersion = "6698ca2900e2"

var goroot string

func main() {
	log.SetFlags(0)
	goroot = os.Getenv("GOROOT") // should be set by run.{bash,bat}
	if goroot == "" {
		log.Fatal("No $GOROOT set.")
	}
	_, err := exec.LookPath("hg")
	if err != nil {
		fmt.Println("Skipping cmd/api checks; hg not available")
		return
	}

	gopath := prepGoPath()

	cmd := exec.Command("go", "install", "--tags=api_tool", "cmd/api")
	cmd.Env = append(filterOut(os.Environ(), "GOARCH", "GOPATH"), "GOPATH="+gopath)
	out, err := cmd.CombinedOutput()
	if err != nil {
		log.Fatalf("Error installing cmd/api: %v\n%s", err, out)
	}

	out, err = exec.Command("go", "tool", "api",
		"-c", file("go1", "go1.1", "go1.2"),
		"-next", file("next"),
		"-except", file("except")).CombinedOutput()
	if err != nil {
		log.Fatalf("Error running API checker: %v\n%s", err, out)
	}
	fmt.Print(string(out))
}

// filterOut returns a copy of the src environment without environment
// variables from remove.
// TODO: delete when issue 6201 is fixed.
func filterOut(src []string, remove ...string) (out []string) {
S:
	for _, s := range src {
		for _, r := range remove {
			if strings.HasPrefix(s, r) && strings.HasPrefix(s, r+"=") {
				continue S
			}
		}
		out = append(out, s)
	}
	return
}

// file expands s to $GOROOT/api/s.txt.
// If there are more than 1, they're comma-separated.
func file(s ...string) string {
	if len(s) > 1 {
		return file(s[0]) + "," + file(s[1:]...)
	}
	return filepath.Join(goroot, "api", s[0]+".txt")
}

// prepGoPath returns a GOPATH for the "go" tool to compile the API tool with.
// It tries to re-use a go.tools checkout from a previous run if possible,
// else it hg clones it.
func prepGoPath() string {
	const tempBase = "go.tools.TMP"

	username := ""
	u, err := user.Current()
	if err == nil {
		username = u.Username
	} else {
		// Only need to handle Unix here, as Windows's os/user uses
		// native syscall and should work fine without cgo.
		username = os.Getenv("USER")
		if username == "" {
			log.Fatalf("Error getting current user: %v", err)
		}
	}

	// The GOPATH we'll return
	gopath := filepath.Join(os.TempDir(), "gopath-api-"+cleanUsername(username), goToolsVersion)

	// cloneDir is where we run "hg clone".
	cloneDir := filepath.Join(gopath, "src", "code.google.com", "p")

	// The dir we clone into. We only atomically rename it to finalDir on
	// clone success.
	tmpDir := filepath.Join(cloneDir, tempBase)

	// finalDir is where the checkout will live once it's complete.
	finalDir := filepath.Join(cloneDir, "go.tools")

	if goToolsCheckoutGood(finalDir) {
		return gopath
	}
	os.RemoveAll(finalDir) // in case it's there but corrupt
	os.RemoveAll(tmpDir)   // in case of aborted hg clone before

	if err := os.MkdirAll(cloneDir, 0700); err != nil {
		log.Fatal(err)
	}
	cmd := exec.Command("hg",
		"clone", "--rev="+goToolsVersion,
		"https://code.google.com/p/go.tools",
		tempBase)
	cmd.Dir = cloneDir
	out, err := cmd.CombinedOutput()
	if err != nil {
		if _, err := http.Head("http://ip.appspot.com/"); err != nil {
			log.Printf("# Skipping API check; network appears to be unavailable")
			os.Exit(0)
		}
		log.Fatalf("Error running hg clone on go.tools: %v\n%s", err, out)
	}
	if err := os.Rename(tmpDir, finalDir); err != nil {
		log.Fatal(err)
	}
	return gopath
}

func cleanUsername(n string) string {
	b := make([]rune, len(n))
	for i, r := range n {
		if r == '\\' || r == '/' || r == ':' {
			b[i] = '_'
		} else {
			b[i] = r
		}
	}
	return string(b)
}

func goToolsCheckoutGood(dir string) bool {
	if _, err := os.Stat(dir); err != nil {
		return false
	}

	cmd := exec.Command("hg", "id", "--id")
	cmd.Dir = dir
	out, err := cmd.Output()
	if err != nil {
		return false
	}
	id := strings.TrimSpace(string(out))
	if id != goToolsVersion {
		return false
	}

	cmd = exec.Command("hg", "status")
	cmd.Dir = dir
	out, err = cmd.Output()
	if err != nil || len(out) > 0 {
		return false
	}

	return true
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
	"go/build"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"text/template"
)

// A Command is an implementation of a go command
// like go build or go fix.
type Command struct {
	// Run runs the command.
	// The args are the arguments after the command name.
	Run func(cmd *Command, args []string)

	// UsageLine is the one-line usage message.
	// The first word in the line is taken to be the command name.
	UsageLine string

	// Short is the short description shown in the 'go help' output.
	Short string

	// Long is the long message shown in the 'go help <this-command>' output.
	Long string

	// Flag is a set of flags specific to this command.
	Flag flag.FlagSet

	// CustomFlags indicates that the command will do its own
	// flag parsing.
	CustomFlags bool
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.UsageLine
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) Usage() {
	fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
	fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
	os.Exit(2)
}

// Commands lists the available commands and help topics.
// The order here is the order in which they are printed by 'go help'.
var commands = []*Command{
	cmdBuild,
	cmdDoc,
	cmdFix,
	cmdFmt,
	cmdGet,
	cmdInstall,
	cmdList,
	cmdRun,
	cmdTest,
	cmdVersion,
	cmdVet,

	helpGopath,
	helpImportpath,
	helpRemote,
	helpTestflag,
	helpTestfunc,
}

var exitStatus = 0

func main() {
	flag.Usage = usage
	flag.Parse()
	log.SetFlags(0)

	args := flag.Args()
	if len(args) < 1 {
		usage()
	}

	if args[0] == "help" {
		help(args[1:])
		return
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] && cmd.Run != nil {
			cmd.Flag.Usage = func() { cmd.Usage() }
			if cmd.CustomFlags {
				args = args[1:]
			} else {
				cmd.Flag.Parse(args[1:])
				args = cmd.Flag.Args()
			}
			cmd.Run(cmd, args)
			exit()
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown command %#q\n\n", args[0])
	usage()
}

var usageTemplate = `usage: go command [arguments]

go manages Go source code.

The commands are:
{{range .}}{{if .Run}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use "go help [command]" for more information about a command.

Additional help topics:
{{range .}}{{if not .Run}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use "go help [topic]" for more information about that topic.

`

var helpTemplate = `{{if .Run}}usage: go {{.UsageLine}}

{{end}}{{.Long | trim}}
`

// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) {
	t := template.New("top")
	t.Funcs(template.FuncMap{"trim": strings.TrimSpace})
	template.Must(t.Parse(text))
	if err := t.Execute(w, data); err != nil {
		panic(err)
	}
}

func printUsage(w io.Writer) {
	tmpl(w, usageTemplate, commands)
}

func usage() {
	printUsage(os.Stderr)
	os.Exit(2)
}

// help implements the 'help' command.
func help(args []string) {
	if len(args) == 0 {
		printUsage(os.Stdout)
		// not exit 2: succeeded at 'go help'.
		return
	}
	if len(args) != 1 {
		fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
		os.Exit(2) // failed at 'go help'
	}

	arg := args[0]
	for _, cmd := range commands {
		if cmd.Name() == arg {
			tmpl(os.Stdout, helpTemplate, cmd)
			// not exit 2: succeeded at 'go help cmd'.
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown help topic %#q.  Run 'go help'.\n", arg)
	os.Exit(2) // failed at 'go help cmd'
}

// importPaths returns the import paths to use for the given command line.
func importPaths(args []string) []string {
	if len(args) == 1 {
		if args[0] == "all" || args[0] == "std" {
			return allPackages(args[0])
		}
	}
	if len(args) == 0 {
		return []string{"."}
	}
	return args
}

var atexitFuncs []func()

func atexit(f func()) {
	atexitFuncs = append(atexitFuncs, f)
}

func exit() {
	for _, f := range atexitFuncs {
		f()
	}
	os.Exit(exitStatus)
}

func fatalf(format string, args ...interface{}) {
	errorf(format, args...)
	exit()
}

func errorf(format string, args ...interface{}) {
	log.Printf(format, args...)
	exitStatus = 1
}

var logf = log.Printf

func exitIfErrors() {
	if exitStatus != 0 {
		exit()
	}
}

func run(cmdline ...string) {
	cmd := exec.Command(cmdline[0], cmdline[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		errorf("%v", err)
	}
}

// allPackages returns all the packages that can be found
// under the $GOPATH directories and $GOROOT.
func allPackages(what string) []string {
	have := map[string]bool{
		"builtin": true, // ignore pseudo-package that exists only for documentation
	}
	if !build.DefaultContext.CgoEnabled {
		have["runtime/cgo"] = true // ignore during walk
	}
	var pkgs []string

	// Commands
	goroot := build.Path[0].Path
	cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
	filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() {
			return nil
		}
		name := path[len(cmd):]
		// Commands are all in cmd/, not in subdirectories.
		if strings.Contains(name, string(filepath.Separator)) {
			return filepath.SkipDir
		}

		_, err = build.ScanDir(path)
		if err != nil {
			return nil
		}

		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
		name = "cmd/" + name
		if !have[name] {
			have[name] = true
			pkgs = append(pkgs, name)
		}
		return nil
	})

	for _, t := range build.Path {
		if what == "std" && !t.Goroot {
			continue
		}
		src := t.SrcDir() + string(filepath.Separator)
		filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
			if err != nil || !fi.IsDir() {
				return nil
			}

			// Avoid testdata directory trees.
			if strings.HasSuffix(path, string(filepath.Separator)+"testdata") {
				return filepath.SkipDir
			}

			name := filepath.ToSlash(path[len(src):])
			if what == "std" && strings.Contains(name, ".") {
				return filepath.SkipDir
			}
			if have[name] {
				return nil
			}

			_, err = build.ScanDir(path)
			if err != nil {
				return nil
			}

			pkgs = append(pkgs, name)
			have[name] = true

			// Avoid go/build test data.
			// TODO: Move it into a testdata directory.
			if path == filepath.Join(build.Path[0].SrcDir(), "go/build") {
				return filepath.SkipDir
			}

			return nil
		})
	}
	return pkgs
}
<commit_msg>cmd/go: fix build (piece of 5489100 leaked in to last checkin)<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
	"go/build"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"text/template"
)

// A Command is an implementation of a go command
// like go build or go fix.
type Command struct {
	// Run runs the command.
	// The args are the arguments after the command name.
	Run func(cmd *Command, args []string)

	// UsageLine is the one-line usage message.
	// The first word in the line is taken to be the command name.
	UsageLine string

	// Short is the short description shown in the 'go help' output.
	Short string

	// Long is the long message shown in the 'go help <this-command>' output.
	Long string

	// Flag is a set of flags specific to this command.
	Flag flag.FlagSet

	// CustomFlags indicates that the command will do its own
	// flag parsing.
	CustomFlags bool
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.UsageLine
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) Usage() {
	fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
	fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
	os.Exit(2)
}

// Commands lists the available commands and help topics.
// The order here is the order in which they are printed by 'go help'.
var commands = []*Command{
	cmdBuild,
	cmdDoc,
	cmdFix,
	cmdFmt,
	cmdGet,
	cmdInstall,
	cmdList,
	cmdRun,
	cmdTest,
	cmdVersion,
	cmdVet,

	helpGopath,
	helpImportpath,
	helpRemote,
	helpTestflag,
	helpTestfunc,
}

var exitStatus = 0

func main() {
	flag.Usage = usage
	flag.Parse()
	log.SetFlags(0)

	args := flag.Args()
	if len(args) < 1 {
		usage()
	}

	if args[0] == "help" {
		help(args[1:])
		return
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] && cmd.Run != nil {
			cmd.Flag.Usage = func() { cmd.Usage() }
			if cmd.CustomFlags {
				args = args[1:]
			} else {
				cmd.Flag.Parse(args[1:])
				args = cmd.Flag.Args()
			}
			cmd.Run(cmd, args)
			exit()
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown command %#q\n\n", args[0])
	usage()
}

var usageTemplate = `usage: go command [arguments]

go manages Go source code.

The commands are:
{{range .}}{{if .Run}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use "go help [command]" for more information about a command.

Additional help topics:
{{range .}}{{if not .Run}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use "go help [topic]" for more information about that topic.

`

var helpTemplate = `{{if .Run}}usage: go {{.UsageLine}}

{{end}}{{.Long | trim}}
`

// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) {
	t := template.New("top")
	t.Funcs(template.FuncMap{"trim": strings.TrimSpace})
	template.Must(t.Parse(text))
	if err := t.Execute(w, data); err != nil {
		panic(err)
	}
}

func printUsage(w io.Writer) {
	tmpl(w, usageTemplate, commands)
}

func usage() {
	printUsage(os.Stderr)
	os.Exit(2)
}

// help implements the 'help' command.
func help(args []string) {
	if len(args) == 0 {
		printUsage(os.Stdout)
		// not exit 2: succeeded at 'go help'.
		return
	}
	if len(args) != 1 {
		fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
		os.Exit(2) // failed at 'go help'
	}

	arg := args[0]
	for _, cmd := range commands {
		if cmd.Name() == arg {
			tmpl(os.Stdout, helpTemplate, cmd)
			// not exit 2: succeeded at 'go help cmd'.
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown help topic %#q.  Run 'go help'.\n", arg)
	os.Exit(2) // failed at 'go help cmd'
}

// importPaths returns the import paths to use for the given command line.
func importPaths(args []string) []string {
	if len(args) == 1 {
		if args[0] == "all" || args[0] == "std" {
			return allPackages(args[0])
		}
	}
	if len(args) == 0 {
		return []string{"."}
	}
	return args
}

var atexitFuncs []func()

func atexit(f func()) {
	atexitFuncs = append(atexitFuncs, f)
}

func exit() {
	for _, f := range atexitFuncs {
		f()
	}
	os.Exit(exitStatus)
}

func fatalf(format string, args ...interface{}) {
	errorf(format, args...)
	exit()
}

func errorf(format string, args ...interface{}) {
	log.Printf(format, args...)
	exitStatus = 1
}

var logf = log.Printf

func exitIfErrors() {
	if exitStatus != 0 {
		exit()
	}
}

func run(cmdline ...string) {
	cmd := exec.Command(cmdline[0], cmdline[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		errorf("%v", err)
	}
}

// allPackages returns all the packages that can be found
// under the $GOPATH directories and $GOROOT.
func allPackages(what string) []string {
	have := map[string]bool{
		"builtin": true, // ignore pseudo-package that exists only for documentation
	}
	/*
		if !build.DefaultContext.CgoEnabled {
			have["runtime/cgo"] = true // ignore during walk
		}
	*/
	var pkgs []string

	// Commands
	goroot := build.Path[0].Path
	cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
	filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() {
			return nil
		}
		name := path[len(cmd):]
		// Commands are all in cmd/, not in subdirectories.
		if strings.Contains(name, string(filepath.Separator)) {
			return filepath.SkipDir
		}

		_, err = build.ScanDir(path)
		if err != nil {
			return nil
		}

		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
		name = "cmd/" + name
		if !have[name] {
			have[name] = true
			pkgs = append(pkgs, name)
		}
		return nil
	})

	for _, t := range build.Path {
		if what == "std" && !t.Goroot {
			continue
		}
		src := t.SrcDir() + string(filepath.Separator)
		filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
			if err != nil || !fi.IsDir() {
				return nil
			}

			// Avoid testdata directory trees.
			if strings.HasSuffix(path, string(filepath.Separator)+"testdata") {
				return filepath.SkipDir
			}

			name := filepath.ToSlash(path[len(src):])
			if what == "std" && strings.Contains(name, ".") {
				return filepath.SkipDir
			}
			if have[name] {
				return nil
			}

			_, err = build.ScanDir(path)
			if err != nil {
				return nil
			}

			pkgs = append(pkgs, name)
			have[name] = true

			// Avoid go/build test data.
			// TODO: Move it into a testdata directory.
			if path == filepath.Join(build.Path[0].SrcDir(), "go/build") {
				return filepath.SkipDir
			}

			return nil
		})
	}
	return pkgs
}
<|endoftext|>


<commit_before>/*
Package stream provides filters that can be chained together in a manner
similar to Unix pipelines.  A simple example that prints all go files
under the current directory:

	stream.Run(
		stream.Find("."),
		stream.Grep(`\.go$`),
		stream.WriteLines(os.Stdout),
	)

stream.Run is passed a list of filters that are chained together
(stream.Find, stream.Grep, stream.WriteLines are filters).  Each
filter takes as input a sequence of strings and produces a sequence of
strings. The empty sequence is passed as input to the first
filter. The output of one filter is fed as input to the next filter.

stream.Run is just one way to execute filters.  Others are stream.Contents
(returns the output of the last filter as a []string), and
stream.ForEach (executes a supplied function for every output item).

Error handling

Filter execution can result in errors.  These are returned from stream
functions normally.  For example, the following program will panic.

	err := stream.Run(
		stream.Items("hello", "world"),
		stream.Grep("["), // Invalid regular expression
		stream.WriteLines(os.Stdout),
	)
	// err will be non-nil

User defined filters

Each filter takes as input a sequence of strings (read from a channel)
and produces as output a sequence of strings (written to a channel).
The stream package provides a bunch of useful filters.  Applications can
define their own filters easily. For example, here is a filter that
repeats every input n times:

	func Repeat(n int) stream.FilterFunc {
		return func(arg stream.Arg) error {
			for s := range arg.In {
				for i := 0; i < n; i++ {
					arg.Out <- s
				}
			}
			return nil
		}
	}

	stream.Run(
		stream.Items("hello", "world"),
		Repeat(2),
		stream.WriteLines(os.Stdout),
	)

The output will be:

	hello
	hello
	world
	world

Note that Repeat returns a FilterFunc, a function type that implements the
Filter interface. This is a common implementation pattern: many simple filters
can be expressed as a single function of type FilterFunc.

Tunable Filters

FilterFunc is an appropriate type to use for most filters like Repeat
above.  However for some filters, dynamic customization is
appropriate.  Such filters provide their own implementation of the
Filter interface with extra methods. For example, stream.Sort provides
extra methods that can be used to control how items are sorted:

	stream.Run(
		stream.Command("ls", "-l"),
		stream.Sort().Num(5),  // Sort numerically by size (column 5)
		stream.WriteLines(os.Stdout),
	)

Acknowledgments

The interface of this package is inspired by the http://labix.org/pipe
package. Users may wish to consider that package in case it fits their
needs better.
*/
package stream

import (
	"fmt"
	"sync"
)

// filterErrors records errors accumulated during the execution of a filter.
type filterErrors struct {
	mu  sync.Mutex
	err error
}

func (e *filterErrors) record(err error) {
	if err != nil {
		e.mu.Lock()
		if e.err == nil {
			e.err = err
		}
		e.mu.Unlock()
	}
}

func (e *filterErrors) getError() error {
	e.mu.Lock()
	defer e.mu.Unlock()
	return e.err
}

// Arg contains the data passed to Filter.Run. Arg.In is a channel that
// produces the input to the filter, and Arg.Out is a channel that
// receives the output from the filter.
type Arg struct {
	In    <-chan string
	Out   chan<- string
	dummy bool // To allow later expansion
}

// The Filter interface represents a process that takes as input a
// sequence of strings from a channel and produces a sequence on
// another channel.
type Filter interface {
	// RunFilter reads a sequence of items from Arg.In and produces a
	// sequence of items on Arg.Out.  RunFilter returns nil on success,
	// an error otherwise.  RunFilter must *not* close the Arg.Out
	// channel.
	RunFilter(Arg) error
}

// FilterFunc is an adapter type that allows the use of ordinary
// functions as Filters.  If f is a function with the appropriate
// signature, FilterFunc(f) is a Filter that calls f.
type FilterFunc func(Arg) error

func (f FilterFunc) RunFilter(arg Arg) error { return f(arg) }

const channelBuffer = 1000

// Sequence returns a filter that is the concatenation of all filter arguments.
// The output of a filter is fed as input to the next filter.
func Sequence(filters ...Filter) Filter {
	if len(filters) == 1 {
		return filters[0]
	}
	return FilterFunc(func(arg Arg) error {
		e := &filterErrors{}
		in := arg.In
		for _, f := range filters {
			c := make(chan string, channelBuffer)
			go runFilter(f, Arg{In: in, Out: c}, e)
			in = c
		}
		for s := range in {
			arg.Out <- s
		}
		return e.getError()
	})
}

// Run executes the sequence of filters and discards all output.
// It returns either nil, an error if any filter reported an error.
func Run(filters ...Filter) error {
	return ForEach(Sequence(filters...), func(s string) {})
}

// ForEach calls fn(s) for every item s in the output of filter and
// returns either nil, or any error reported by the execution of the filter.
func ForEach(filter Filter, fn func(s string)) error {
	in := make(chan string, 0)
	close(in)
	out := make(chan string, channelBuffer)
	e := &filterErrors{}
	go runFilter(filter, Arg{In: in, Out: out}, e)
	for s := range out {
		fn(s)
	}
	return e.getError()
}

// Contents returns a slice that contains all items that are
// the output of filters.
func Contents(filters ...Filter) ([]string, error) {
	var result []string
	err := ForEach(Sequence(filters...), func(s string) {
		result = append(result, s)
	})
	if err != nil {
		result = nil // Discard results on error
	}
	return result, err
}

func runFilter(f Filter, arg Arg, e *filterErrors) {
	e.record(f.RunFilter(arg))
	close(arg.Out)
	for _ = range arg.In { // Discard all unhandled input
	}
}

// Items emits items.
func Items(items ...string) Filter {
	return FilterFunc(func(arg Arg) error {
		for _, s := range items {
			arg.Out <- s
		}
		return nil
	})
}

// Numbers emits the integers x..y
func Numbers(x, y int) Filter {
	return FilterFunc(func(arg Arg) error {
		for i := x; i <= y; i++ {
			arg.Out <- fmt.Sprint(i)
		}
		return nil
	})
}

// Map calls fn(x) for every item x and yields the outputs of the fn calls.
func Map(fn func(string) string) Filter {
	return FilterFunc(func(arg Arg) error {
		for s := range arg.In {
			arg.Out <- fn(s)
		}
		return nil
	})
}

// If emits every input x for which fn(x) is true.
func If(fn func(string) bool) Filter {
	return FilterFunc(func(arg Arg) error {
		for s := range arg.In {
			if fn(s) {
				arg.Out <- s
			}
		}
		return nil
	})
}

// Uniq squashes adjacent identical items in arg.In into a single output.
func Uniq() Filter {
	return FilterFunc(func(arg Arg) error {
		first := true
		last := ""
		for s := range arg.In {
			if first || last != s {
				arg.Out <- s
			}
			last = s
			first = false
		}
		return nil
	})
}

// UniqWithCount squashes adjacent identical items in arg.In into a single
// output prefixed with the count of identical items.
func UniqWithCount() Filter {
	return FilterFunc(func(arg Arg) error {
		current := ""
		count := 0
		for s := range arg.In {
			if s != current {
				if count > 0 {
					arg.Out <- fmt.Sprintf("%d %s", count, current)
				}
				count = 0
				current = s
			}
			count++
		}
		if count > 0 {
			arg.Out <- fmt.Sprintf("%d %s", count, current)
		}
		return nil
	})
}

// Reverse yields items in the reverse of the order it received them.
func Reverse() Filter {
	return FilterFunc(func(arg Arg) error {
		var data []string
		for s := range arg.In {
			data = append(data, s)
		}
		for i := len(data) - 1; i >= 0; i-- {
			arg.Out <- data[i]
		}
		return nil
	})
}

// NumberLines prefixes its item with its index in the input sequence
// (starting at 1).
func NumberLines() Filter {
	return FilterFunc(func(arg Arg) error {
		line := 1
		for s := range arg.In {
			arg.Out <- fmt.Sprintf("%5d %s", line, s)
			line++
		}
		return nil
	})
}

// Slice emits s[startOffset:endOffset] for each input item s.  Note
// that Slice follows Go conventions, and unlike the "cut" utility,
// offsets are numbered starting at zero, and the end offset is not
// included in the output.
func Slice(startOffset, endOffset int) Filter {
	return FilterFunc(func(arg Arg) error {
		for s := range arg.In {
			if len(s) > endOffset {
				s = s[:endOffset]
			}
			if len(s) < startOffset {
				s = ""
			} else {
				s = s[startOffset:]
			}
			arg.Out <- s
		}
		return nil
	})
}

// Columns splits each item into columns and yields the concatenation
// of the columns numbers passed as arguments.  Columns are numbered
// starting at 1.  If a column number is bigger than the number of columns
// in an item, it is skipped.
func Columns(columns ...int) Filter {
	return FilterFunc(func(arg Arg) error {
		for _, c := range columns {
			if c <= 0 {
				return fmt.Errorf("stream.Columns: invalid column number %d", c)
			}
		}
		for s := range arg.In {
			result := ""
			for _, col := range columns {
				if _, c := column(s, col); c != "" {
					if result != "" {
						result = result + " "
					}
					result = result + c
				}
			}
			arg.Out <- result
		}
		return nil
	})
}
<commit_msg>fixed out of date comment pointed out by Sameer<commit_after>/*
Package stream provides filters that can be chained together in a manner
similar to Unix pipelines.  A simple example that prints all go files
under the current directory:

	stream.Run(
		stream.Find("."),
		stream.Grep(`\.go$`),
		stream.WriteLines(os.Stdout),
	)

stream.Run is passed a list of filters that are chained together
(stream.Find, stream.Grep, stream.WriteLines are filters).  Each
filter takes as input a sequence of strings and produces a sequence of
strings. The empty sequence is passed as input to the first
filter. The output of one filter is fed as input to the next filter.

stream.Run is just one way to execute filters.  Others are stream.Contents
(returns the output of the last filter as a []string), and
stream.ForEach (executes a supplied function for every output item).

Error handling

Filter execution can result in errors.  These are returned from stream
functions normally.  For example, the following call will return a
non-nil error.

	err := stream.Run(
		stream.Items("hello", "world"),
		stream.Grep("["), // Invalid regular expression
		stream.WriteLines(os.Stdout),
	)
	// err will be non-nil

User defined filters

Each filter takes as input a sequence of strings (read from a channel)
and produces as output a sequence of strings (written to a channel).
The stream package provides a bunch of useful filters.  Applications can
define their own filters easily. For example, here is a filter that
repeats every input n times:

	func Repeat(n int) stream.FilterFunc {
		return func(arg stream.Arg) error {
			for s := range arg.In {
				for i := 0; i < n; i++ {
					arg.Out <- s
				}
			}
			return nil
		}
	}

	stream.Run(
		stream.Items("hello", "world"),
		Repeat(2),
		stream.WriteLines(os.Stdout),
	)

The output will be:

	hello
	hello
	world
	world

Note that Repeat returns a FilterFunc, a function type that implements the
Filter interface. This is a common implementation pattern: many simple filters
can be expressed as a single function of type FilterFunc.

Tunable Filters

FilterFunc is an appropriate type to use for most filters like Repeat
above.  However for some filters, dynamic customization is
appropriate.  Such filters provide their own implementation of the
Filter interface with extra methods. For example, stream.Sort provides
extra methods that can be used to control how items are sorted:

	stream.Run(
		stream.Command("ls", "-l"),
		stream.Sort().Num(5),  // Sort numerically by size (column 5)
		stream.WriteLines(os.Stdout),
	)

Acknowledgments

The interface of this package is inspired by the http://labix.org/pipe
package. Users may wish to consider that package in case it fits their
needs better.
*/
package stream

import (
	"fmt"
	"sync"
)

// filterErrors records errors accumulated during the execution of a filter.
type filterErrors struct {
	mu  sync.Mutex
	err error
}

func (e *filterErrors) record(err error) {
	if err != nil {
		e.mu.Lock()
		if e.err == nil {
			e.err = err
		}
		e.mu.Unlock()
	}
}

func (e *filterErrors) getError() error {
	e.mu.Lock()
	defer e.mu.Unlock()
	return e.err
}

// Arg contains the data passed to Filter.Run. Arg.In is a channel that
// produces the input to the filter, and Arg.Out is a channel that
// receives the output from the filter.
type Arg struct {
	In    <-chan string
	Out   chan<- string
	dummy bool // To allow later expansion
}

// The Filter interface represents a process that takes as input a
// sequence of strings from a channel and produces a sequence on
// another channel.
type Filter interface {
	// RunFilter reads a sequence of items from Arg.In and produces a
	// sequence of items on Arg.Out.  RunFilter returns nil on success,
	// an error otherwise.  RunFilter must *not* close the Arg.Out
	// channel.
	RunFilter(Arg) error
}

// FilterFunc is an adapter type that allows the use of ordinary
// functions as Filters.  If f is a function with the appropriate
// signature, FilterFunc(f) is a Filter that calls f.
type FilterFunc func(Arg) error

func (f FilterFunc) RunFilter(arg Arg) error { return f(arg) }

const channelBuffer = 1000

// Sequence returns a filter that is the concatenation of all filter arguments.
// The output of a filter is fed as input to the next filter.
func Sequence(filters ...Filter) Filter {
	if len(filters) == 1 {
		return filters[0]
	}
	return FilterFunc(func(arg Arg) error {
		e := &filterErrors{}
		in := arg.In
		for _, f := range filters {
			c := make(chan string, channelBuffer)
			go runFilter(f, Arg{In: in, Out: c}, e)
			in = c
		}
		for s := range in {
			arg.Out <- s
		}
		return e.getError()
	})
}

// Run executes the sequence of filters and discards all output.
// It returns either nil, an error if any filter reported an error.
func Run(filters ...Filter) error {
	return ForEach(Sequence(filters...), func(s string) {})
}

// ForEach calls fn(s) for every item s in the output of filter and
// returns either nil, or any error reported by the execution of the filter.
func ForEach(filter Filter, fn func(s string)) error {
	in := make(chan string, 0)
	close(in)
	out := make(chan string, channelBuffer)
	e := &filterErrors{}
	go runFilter(filter, Arg{In: in, Out: out}, e)
	for s := range out {
		fn(s)
	}
	return e.getError()
}

// Contents returns a slice that contains all items that are
// the output of filters.
func Contents(filters ...Filter) ([]string, error) {
	var result []string
	err := ForEach(Sequence(filters...), func(s string) {
		result = append(result, s)
	})
	if err != nil {
		result = nil // Discard results on error
	}
	return result, err
}

func runFilter(f Filter, arg Arg, e *filterErrors) {
	e.record(f.RunFilter(arg))
	close(arg.Out)
	for _ = range arg.In { // Discard all unhandled input
	}
}

// Items emits items.
func Items(items ...string) Filter {
	return FilterFunc(func(arg Arg) error {
		for _, s := range items {
			arg.Out <- s
		}
		return nil
	})
}

// Numbers emits the integers x..y
func Numbers(x, y int) Filter {
	return FilterFunc(func(arg Arg) error {
		for i := x; i <= y; i++ {
			arg.Out <- fmt.Sprint(i)
		}
		return nil
	})
}

// Map calls fn(x) for every item x and yields the outputs of the fn calls.
func Map(fn func(string) string) Filter {
	return FilterFunc(func(arg Arg) error {
		for s := range arg.In {
			arg.Out <- fn(s)
		}
		return nil
	})
}

// If emits every input x for which fn(x) is true.
func If(fn func(string) bool) Filter {
	return FilterFunc(func(arg Arg) error {
		for s := range arg.In {
			if fn(s) {
				arg.Out <- s
			}
		}
		return nil
	})
}

// Uniq squashes adjacent identical items in arg.In into a single output.
func Uniq() Filter {
	return FilterFunc(func(arg Arg) error {
		first := true
		last := ""
		for s := range arg.In {
			if first || last != s {
				arg.Out <- s
			}
			last = s
			first = false
		}
		return nil
	})
}

// UniqWithCount squashes adjacent identical items in arg.In into a single
// output prefixed with the count of identical items.
func UniqWithCount() Filter {
	return FilterFunc(func(arg Arg) error {
		current := ""
		count := 0
		for s := range arg.In {
			if s != current {
				if count > 0 {
					arg.Out <- fmt.Sprintf("%d %s", count, current)
				}
				count = 0
				current = s
			}
			count++
		}
		if count > 0 {
			arg.Out <- fmt.Sprintf("%d %s", count, current)
		}
		return nil
	})
}

// Reverse yields items in the reverse of the order it received them.
func Reverse() Filter {
	return FilterFunc(func(arg Arg) error {
		var data []string
		for s := range arg.In {
			data = append(data, s)
		}
		for i := len(data) - 1; i >= 0; i-- {
			arg.Out <- data[i]
		}
		return nil
	})
}

// NumberLines prefixes its item with its index in the input sequence
// (starting at 1).
func NumberLines() Filter {
	return FilterFunc(func(arg Arg) error {
		line := 1
		for s := range arg.In {
			arg.Out <- fmt.Sprintf("%5d %s", line, s)
			line++
		}
		return nil
	})
}

// Slice emits s[startOffset:endOffset] for each input item s.  Note
// that Slice follows Go conventions, and unlike the "cut" utility,
// offsets are numbered starting at zero, and the end offset is not
// included in the output.
func Slice(startOffset, endOffset int) Filter {
	return FilterFunc(func(arg Arg) error {
		for s := range arg.In {
			if len(s) > endOffset {
				s = s[:endOffset]
			}
			if len(s) < startOffset {
				s = ""
			} else {
				s = s[startOffset:]
			}
			arg.Out <- s
		}
		return nil
	})
}

// Columns splits each item into columns and yields the concatenation
// of the columns numbers passed as arguments.  Columns are numbered
// starting at 1.  If a column number is bigger than the number of columns
// in an item, it is skipped.
func Columns(columns ...int) Filter {
	return FilterFunc(func(arg Arg) error {
		for _, c := range columns {
			if c <= 0 {
				return fmt.Errorf("stream.Columns: invalid column number %d", c)
			}
		}
		for s := range arg.In {
			result := ""
			for _, col := range columns {
				if _, c := column(s, col); c != "" {
					if result != "" {
						result = result + " "
					}
					result = result + c
				}
			}
			arg.Out <- result
		}
		return nil
	})
}
<|endoftext|>


<commit_before>package mysqlproto

import (
	"bytes"
	"net"
	"time"
)

const PACKET_BUFFER_SIZE = 1500 // default MTU

type Stream struct {
	stream   net.Conn
	buffer   []byte
	read     int
	left     int
	syscalls int
	ReadTimeout time.Duration
}

func NewStream(stream net.Conn, readTimeout time.Duration) *Stream {
	return &Stream{stream, nil, 0, 0, 0, readTimeout}
}

func (s *Stream) Write(data []byte) (int, error) {
	return s.stream.Write(data)
}

func (s *Stream) Close() error {
	return s.stream.Close()
}

func (s *Stream) NextPacket() (Packet, error) {
	scale := func(size int) {
		if size < PACKET_BUFFER_SIZE {
			size = PACKET_BUFFER_SIZE
		}
		buf := make([]byte, size)
		copy(buf, s.buffer[s.read:s.read+s.left])
		s.buffer = buf
		s.read = 0
	}

	if len(s.buffer)-s.read < 3 { // size of the packet
		scale(PACKET_BUFFER_SIZE)
	}

	if s.left < 3 {
		read, err := s.readAtLeast(s.buffer[s.read+s.left:], 3-s.left)
		if err != nil {
			return Packet{}, err
		}
		s.left += read
	}

	length := int(uint32(s.buffer[s.read]) | uint32(s.buffer[s.read+1])<<8 | uint32(s.buffer[s.read+2])<<16)
	total := length + 4
	if total > len(s.buffer)-s.read {
		scale(total)
	}

	if total > s.left {
		read, err := s.readAtLeast(s.buffer[s.read+s.left:], total-s.left)
		if err != nil {
			return Packet{}, err
		}
		s.left += read
	}

	packet := Packet{
		SequenceID: s.buffer[s.read+3],
		Payload:    s.buffer[s.read+4 : s.read+total],
	}

	s.left -= total
	s.read += total

	return packet, nil
}

func (s *Stream) Syscalls() int {
	return s.syscalls
}

func (s *Stream) ResetStats() {
	s.syscalls = 0
}

func (s *Stream) readAtLeast(buf []byte, min int) (n int, err error) {
	for n < min && err == nil {
		var nn int
		if s.ReadTimeout > 0 {
			if err = s.stream.SetReadDeadline(time.Now().Add(s.ReadTimeout)); err != nil {
				return
			}
		}

		nn, err = s.stream.Read(buf[n:])
		s.syscalls += 1
		n += nn
	}
	return
}

// For testing

type buffer struct {
	*bytes.Buffer
	closed  bool
	writeFn func([]byte) (int, error)
}

func newBuffer(data []byte) *buffer {
	return &buffer{bytes.NewBuffer(data), false, nil}
}

func (b *buffer) Close() error {
	b.closed = true
	return nil
}

func (b *buffer) Write(data []byte) (int, error) {
	if b.writeFn == nil {
		return 0, nil
	}

	return b.writeFn(data)
}
func (b *buffer) RemoteAddr() net.Addr { return MockAddr{} }
func (b *buffer) LocalAddr() net.Addr { return MockAddr{} }
func (b *buffer) SetDeadline(t time.Time) error { return nil}
func (b *buffer) SetReadDeadline(t time.Time) error { return nil}
func (b *buffer) SetWriteDeadline(t time.Time) error { return nil}

type MockAddr struct {}
func (m MockAddr) Network() string { return "" }
func (m MockAddr) String() string { return "" }
<commit_msg>make readTimeout private<commit_after>package mysqlproto

import (
	"bytes"
	"net"
	"time"
)

const PACKET_BUFFER_SIZE = 1500 // default MTU

type Stream struct {
	stream   net.Conn
	buffer   []byte
	read     int
	left     int
	syscalls int
	readTimeout time.Duration
}

func NewStream(stream net.Conn, readTimeout time.Duration) *Stream {
	return &Stream{stream, nil, 0, 0, 0, readTimeout}
}

func (s *Stream) Write(data []byte) (int, error) {
	return s.stream.Write(data)
}

func (s *Stream) Close() error {
	return s.stream.Close()
}

func (s *Stream) NextPacket() (Packet, error) {
	scale := func(size int) {
		if size < PACKET_BUFFER_SIZE {
			size = PACKET_BUFFER_SIZE
		}
		buf := make([]byte, size)
		copy(buf, s.buffer[s.read:s.read+s.left])
		s.buffer = buf
		s.read = 0
	}

	if len(s.buffer)-s.read < 3 { // size of the packet
		scale(PACKET_BUFFER_SIZE)
	}

	if s.left < 3 {
		read, err := s.readAtLeast(s.buffer[s.read+s.left:], 3-s.left)
		if err != nil {
			return Packet{}, err
		}
		s.left += read
	}

	length := int(uint32(s.buffer[s.read]) | uint32(s.buffer[s.read+1])<<8 | uint32(s.buffer[s.read+2])<<16)
	total := length + 4
	if total > len(s.buffer)-s.read {
		scale(total)
	}

	if total > s.left {
		read, err := s.readAtLeast(s.buffer[s.read+s.left:], total-s.left)
		if err != nil {
			return Packet{}, err
		}
		s.left += read
	}

	packet := Packet{
		SequenceID: s.buffer[s.read+3],
		Payload:    s.buffer[s.read+4 : s.read+total],
	}

	s.left -= total
	s.read += total

	return packet, nil
}

func (s *Stream) Syscalls() int {
	return s.syscalls
}

func (s *Stream) ResetStats() {
	s.syscalls = 0
}

func (s *Stream) readAtLeast(buf []byte, min int) (n int, err error) {
	for n < min && err == nil {
		var nn int
		if s.readTimeout > 0 {
			if err = s.stream.SetReadDeadline(time.Now().Add(s.readTimeout)); err != nil {
				return
			}
		}

		nn, err = s.stream.Read(buf[n:])
		s.syscalls += 1
		n += nn
	}
	return
}

// For testing

type buffer struct {
	*bytes.Buffer
	closed  bool
	writeFn func([]byte) (int, error)
}

func newBuffer(data []byte) *buffer {
	return &buffer{bytes.NewBuffer(data), false, nil}
}

func (b *buffer) Close() error {
	b.closed = true
	return nil
}

func (b *buffer) Write(data []byte) (int, error) {
	if b.writeFn == nil {
		return 0, nil
	}

	return b.writeFn(data)
}
func (b *buffer) RemoteAddr() net.Addr { return MockAddr{} }
func (b *buffer) LocalAddr() net.Addr { return MockAddr{} }
func (b *buffer) SetDeadline(t time.Time) error { return nil}
func (b *buffer) SetReadDeadline(t time.Time) error { return nil}
func (b *buffer) SetWriteDeadline(t time.Time) error { return nil}

type MockAddr struct {}
func (m MockAddr) Network() string { return "" }
func (m MockAddr) String() string { return "" }
<|endoftext|>


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

// Package runner contains code for a test runner that can run a list of
// load tests, wait for them to complete, and report on the results.
package runner

import (
	"fmt"
	"log"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	grpcv1 "github.com/grpc/test-infra/api/v1"
	clientset "github.com/grpc/test-infra/clientset"
)

// AfterIntervalFunction returns a function that stops for a time interval.
// This function is provided so it can be replaced with a fake for testing.
func AfterIntervalFunction(d time.Duration) func() {
	return func() {
		<-time.After(d)
	}
}

// Runner contains the information needed to run multiple sets of LoadTests.
type Runner struct {
	Done           chan string
	loadTestGetter clientset.LoadTestGetter
	afterInterval  func()
	retries        uint
}

// NewRunner creates a new Runner object.
func NewRunner(loadTestGetter clientset.LoadTestGetter, afterInterval func(), retries uint) *Runner {
	return &Runner{
		Done:           make(chan string),
		loadTestGetter: loadTestGetter,
		afterInterval:  afterInterval,
		retries:        retries,
	}
}

// Run runs a set of LoadTests at a given concurrency level.
func (r *Runner) Run(qName string, configs []*grpcv1.LoadTest, concurrencyLevel int) {
	done := make(chan int)
	n := 0
	for i, config := range configs {
		if n < concurrencyLevel {
			go r.runTest(qName, config, i, done)
			n++
			continue
		}
		<-done
		n--
	}
	for n > 0 {
		<-done
		n--
	}
	r.Done <- qName
}

// runTest creates a single LoadTest and monitors it to completion.
func (r *Runner) runTest(qName string, config *grpcv1.LoadTest, i int, done chan int) {
	id := fmt.Sprintf("%-14s %3d", qName, i)
	var retries uint

	for {
		loadTest, err := r.loadTestGetter.Create(config, metav1.CreateOptions{})
		if err != nil {
			log.Printf("[%s] Failed to create test %s", id, config.Name)
			if retries < r.retries {
				retries++
				log.Printf("[%s] Scheduling retry %d/%d to create test", id, retries, r.retries)
				r.afterInterval()
				continue
			}
			log.Printf("[%s] Aborting after %d retries to create test %s", id, r.retries, config.Name)
			done <- i
			return
		}
		retries = 0
		config.Status = loadTest.Status
		log.Printf("[%s] Created test %s", id, config.Name)
		break
	}

	for {
		loadTest, err := r.loadTestGetter.Get(config.Name, metav1.GetOptions{})
		if err != nil {
			log.Printf("[%s] Failed to poll test %s", id, config.Name)
			if retries < r.retries {
				retries++
				log.Printf("[%s] Scheduling retry %d/%d to poll test", id, retries, r.retries)
				r.afterInterval()
				continue
			}
			log.Printf("[%s] Aborting test after %d retries to poll test %s", id, r.retries, config.Name)
			done <- i
			return
		}
		retries = 0
		config.Status = loadTest.Status
		if loadTest.Status.State.IsTerminated() {
			log.Printf("[%s] %s", id, loadTest.Status.State)
			done <- i
			return
		}
		if loadTest.Status.State == grpcv1.Running {
			log.Printf("[%s] %s", id, loadTest.Status.State)
			r.afterInterval()
			continue
		}
		// Use a longer polling interval for tests that have not started.
		r.afterInterval()
		r.afterInterval()
	}
}
<commit_msg>Print more complete status strings.<commit_after>/*
Copyright 2021 gRPC authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package runner contains code for a test runner that can run a list of
// load tests, wait for them to complete, and report on the results.
package runner

import (
	"fmt"
	"log"
	"strings"
	"time"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	grpcv1 "github.com/grpc/test-infra/api/v1"
	clientset "github.com/grpc/test-infra/clientset"
)

// AfterIntervalFunction returns a function that stops for a time interval.
// This function is provided so it can be replaced with a fake for testing.
func AfterIntervalFunction(d time.Duration) func() {
	return func() {
		<-time.After(d)
	}
}

// Runner contains the information needed to run multiple sets of LoadTests.
type Runner struct {
	Done           chan string
	loadTestGetter clientset.LoadTestGetter
	afterInterval  func()
	retries        uint
}

// NewRunner creates a new Runner object.
func NewRunner(loadTestGetter clientset.LoadTestGetter, afterInterval func(), retries uint) *Runner {
	return &Runner{
		Done:           make(chan string),
		loadTestGetter: loadTestGetter,
		afterInterval:  afterInterval,
		retries:        retries,
	}
}

// Run runs a set of LoadTests at a given concurrency level.
func (r *Runner) Run(qName string, configs []*grpcv1.LoadTest, concurrencyLevel int) {
	done := make(chan int)
	n := 0
	for i, config := range configs {
		if n < concurrencyLevel {
			go r.runTest(qName, config, i, done)
			n++
			continue
		}
		<-done
		n--
	}
	for n > 0 {
		<-done
		n--
	}
	r.Done <- qName
}

// runTest creates a single LoadTest and monitors it to completion.
func (r *Runner) runTest(qName string, config *grpcv1.LoadTest, i int, done chan int) {
	id := fmt.Sprintf("%-14s %3d", qName, i)
	var status string
	var retries uint

	for {
		loadTest, err := r.loadTestGetter.Create(config, metav1.CreateOptions{})
		if err != nil {
			log.Printf("[%s] Failed to create test %s", id, config.Name)
			if retries < r.retries {
				retries++
				log.Printf("[%s] Scheduling retry %d/%d to create test", id, retries, r.retries)
				r.afterInterval()
				continue
			}
			log.Printf("[%s] Aborting after %d retries to create test %s", id, r.retries, config.Name)
			done <- i
			return
		}
		retries = 0
		config.Status = loadTest.Status
		log.Printf("[%s] Created test %s", id, config.Name)
		break
	}

	for {
		loadTest, err := r.loadTestGetter.Get(config.Name, metav1.GetOptions{})
		if err != nil {
			log.Printf("[%s] Failed to poll test %s", id, config.Name)
			if retries < r.retries {
				retries++
				log.Printf("[%s] Scheduling retry %d/%d to poll test", id, retries, r.retries)
				r.afterInterval()
				continue
			}
			log.Printf("[%s] Aborting test after %d retries to poll test %s", id, r.retries, config.Name)
			done <- i
			return
		}
		retries = 0
		config.Status = loadTest.Status
		s := status
		status := statusString(config)
		switch {
		case loadTest.Status.State.IsTerminated():
			log.Printf("[%s] %s", id, status)
			done <- i
			return
		case loadTest.Status.State == grpcv1.Running:
			log.Printf("[%s] %s", id, status)
			r.afterInterval()
		default:
			if s != status {
				log.Printf("[%s] %s", id, status)
			}
			// Use a longer polling interval for tests that have not started.
			r.afterInterval()
			r.afterInterval()
		}
	}
}

func statusString(config *grpcv1.LoadTest) string {
	s := []string{string(config.Status.State)}
	if reason := strings.TrimSpace(config.Status.Reason); reason != "" {
		s = append(s, reason)
	}
	if message := strings.TrimSpace(config.Status.Message); message != "" {
		s = append(s, message)
	}
	return strings.Join(s, "; ")
}
<|endoftext|>


<commit_before>//Generator is used to create Tritium templates from an Osaka project.
package transform

import (
	"errors"
	"text/template"
)
import "bytes"

import "fmt"
import "encoding/json"
import "path/filepath"

import "manhattan/project/options"
import "manhattan/project"
import "rubex"
import tp "tritium/proto"
import proto "code.google.com/p/goprotobuf/proto"

func runTemplate(name string, rawTemplate []byte, options options.Options, project *project.Project) ([]byte, error) {
	segmentTemplate := template.New(name)
	request, err := segmentTemplate.Parse(string(rawTemplate))

	if err != nil {
		return nil, errors.New(fmt.Sprintf("Error loading template: %v", err))
	}

	var buf bytes.Buffer
	err = request.Execute(&buf, project)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Error running template: %v", err))
	}
	return buf.Bytes(), nil
}

func Generate(options options.Options, project *project.Project, mixer *tp.Mixer) (map[string][]byte, error) {
	// HACKY
	type TempRewriter struct {
		ToBeReplacedWithmatcher     string
		ToBeReplacedWithreplacement string
	}
	tmpRewriter := make([]TempRewriter, len(project.Rewriter.Host))
	for i, v := range project.Rewriter.Host {
		tmpRewriter[i].ToBeReplacedWithmatcher = v.Matcher
		tmpRewriter[i].ToBeReplacedWithreplacement = v.Replacement
	}
	// Make JSON
	data, err := json.Marshal(tmpRewriter)
	if err != nil {
		project.HostJson = "{}"
	} else {
		project.HostJson = string(data)
	}
	// Lowercase hack
	r := rubex.MustCompile("ToBeReplacedWithmatcher")
	project.HostJson = r.Gsub(project.HostJson, "matcher")
	r = rubex.MustCompile("ToBeReplacedWithreplacement")
	project.HostJson = r.Gsub(project.HostJson, "replacement")
	// Escape quotes
	r = rubex.MustCompile("\"")
	project.HostJson = r.Gsub(project.HostJson, "\\\"")

	// END HACKY

	segments := [4]string{"request.ts", "response_pre.ts", "body.ts", "response_post.ts"}
	var finalError error

	renderedSegments := make(map[string][]byte, 4)

	for _, segment := range segments {
		rawTemplate, err := getRawTemplate(segment, mixer)

		if err != nil {
			panic(err)
		}

		renderedSegment, err := runTemplate(segment, rawTemplate, options, project)

		if err != nil {
			// Should really return an array of errors
			finalError = err
		} else {
			renderedSegments[segment] = renderedSegment
		}
	}

	return renderedSegments, finalError
}

func getRawTemplate(segmentName string, mixer *tp.Mixer) (rawTemplate []uint8, err error) {

	for _, segment := range mixer.Rewriters {
		_, thisName := filepath.Split(proto.GetString(segment.Path))
		if thisName == segmentName {
			return segment.Data[0], nil
		}
	}

	return nil, errors.New(fmt.Sprintf("Could not find rewriter: %v", segmentName))
}
<commit_msg>use Data as an array<commit_after>//Generator is used to create Tritium templates from an Osaka project.
package transform

import (
	"errors"
	"text/template"
)
import "bytes"

import "fmt"
import "encoding/json"
import "path/filepath"

import "manhattan/project/options"
import "manhattan/project"
import "rubex"
import tp "tritium/proto"
import proto "code.google.com/p/goprotobuf/proto"

func runTemplate(name string, rawTemplate []byte, options options.Options, project *project.Project) ([]byte, error) {
	segmentTemplate := template.New(name)
	request, err := segmentTemplate.Parse(string(rawTemplate))

	if err != nil {
		return nil, errors.New(fmt.Sprintf("Error loading template: %v", err))
	}

	var buf bytes.Buffer
	err = request.Execute(&buf, project)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Error running template: %v", err))
	}
	return buf.Bytes(), nil
}

func Generate(options options.Options, project *project.Project, mixer *tp.Mixer) (map[string][]byte, error) {
	// HACKY
	type TempRewriter struct {
		ToBeReplacedWithmatcher     string
		ToBeReplacedWithreplacement string
	}
	tmpRewriter := make([]TempRewriter, len(project.Rewriter.Host))
	for i, v := range project.Rewriter.Host {
		tmpRewriter[i].ToBeReplacedWithmatcher = v.Matcher
		tmpRewriter[i].ToBeReplacedWithreplacement = v.Replacement
	}
	// Make JSON
	data, err := json.Marshal(tmpRewriter)
	if err != nil {
		project.HostJson = "{}"
	} else {
		project.HostJson = string(data)
	}
	// Lowercase hack
	r := rubex.MustCompile("ToBeReplacedWithmatcher")
	project.HostJson = r.Gsub(project.HostJson, "matcher")
	r = rubex.MustCompile("ToBeReplacedWithreplacement")
	project.HostJson = r.Gsub(project.HostJson, "replacement")
	// Escape quotes
	r = rubex.MustCompile("\"")
	project.HostJson = r.Gsub(project.HostJson, "\\\"")

	// END HACKY

	segments := [4]string{"request.ts", "response_pre.ts", "body.ts", "response_post.ts"}
	var finalError error

	renderedSegments := make(map[string][]byte, 4)

	for _, segment := range segments {
		rawTemplate, err := getRawTemplate(segment, mixer)

		if err != nil {
			panic(err)
		}

		renderedSegment, err := runTemplate(segment, rawTemplate, options, project)

		if err != nil {
			// Should really return an array of errors
			finalError = err
		} else {
			renderedSegments[segment] = renderedSegment
		}
	}

	return renderedSegments, finalError
}

func getRawTemplate(segmentName string, mixer *tp.Mixer) (rawTemplate []uint8, err error) {

	for _, segment := range mixer.Rewriters {
		_, thisName := filepath.Split(proto.GetString(segment.Path))
		if thisName == segmentName {
			return segment.Data, nil
		}
	}

	return nil, errors.New(fmt.Sprintf("Could not find rewriter: %v", segmentName))
}
<|endoftext|>


<commit_before>package resource

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"testing"

	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/terraform"
)

const TestEnvVar = "TF_ACC"

// TestCheckFunc is the callback type used with acceptance tests to check
// the state of a resource. The state passed in is the latest state known,
// or in the case of being after a destroy, it is the last known state when
// it was created.
type TestCheckFunc func(*terraform.State) error

// TestCase is a single acceptance test case used to test the apply/destroy
// lifecycle of a resource in a specific configuration.
//
// When the destroy plan is executed, the config from the last TestStep
// is used to plan it.
type TestCase struct {
	// PreCheck, if non-nil, will be called before any test steps are
	// executed. It will only be executed in the case that the steps
	// would run, so it can be used for some validation before running
	// acceptance tests, such as verifying that keys are setup.
	PreCheck func()

	// Provider is the ResourceProvider that will be under test.
	Providers map[string]terraform.ResourceProvider

	// CheckDestroy is called after the resource is finally destroyed
	// to allow the tester to test that the resource is truly gone.
	CheckDestroy TestCheckFunc

	// Steps are the apply sequences done within the context of the
	// same state. Each step can have its own check to verify correctness.
	Steps []TestStep
}

// TestStep is a single apply sequence of a test, done within the
// context of a state.
//
// Multiple TestSteps can be sequenced in a Test to allow testing
// potentially complex update logic. In general, simply create/destroy
// tests will only need one step.
type TestStep struct {
	// Config a string of the configuration to give to Terraform.
	Config string

	// Check is called after the Config is applied. Use this step to
	// make your own API calls to check the status of things, and to
	// inspect the format of the ResourceState itself.
	//
	// If an error is returned, the test will fail. In this case, a
	// destroy plan will still be attempted.
	//
	// If this is nil, no check is done on this step.
	Check TestCheckFunc

	// Destroy will create a destroy plan if set to true.
	Destroy bool
}

// Test performs an acceptance test on a resource.
//
// Tests are not run unless an environmental variable "TF_ACC" is
// set to some non-empty value. This is to avoid test cases surprising
// a user by creating real resources.
//
// Tests will fail unless the verbose flag (`go test -v`, or explicitly
// the "-test.v" flag) is set. Because some acceptance tests take quite
// long, we require the verbose flag so users are able to see progress
// output.
func Test(t TestT, c TestCase) {
	// We only run acceptance tests if an env var is set because they're
	// slow and generally require some outside configuration.
	if os.Getenv(TestEnvVar) == "" {
		t.Skip(fmt.Sprintf(
			"Acceptance tests skipped unless env '%s' set",
			TestEnvVar))
		return
	}

	// We require verbose mode so that the user knows what is going on.
	if !testTesting && !testing.Verbose() {
		t.Fatal("Acceptance tests must be run with the -v flag on tests")
		return
	}

	// Run the PreCheck if we have it
	if c.PreCheck != nil {
		c.PreCheck()
	}

	// Build our context options that we can
	ctxProviders := make(map[string]terraform.ResourceProviderFactory)
	for k, p := range c.Providers {
		ctxProviders[k] = terraform.ResourceProviderFactoryFixed(p)
	}
	opts := terraform.ContextOpts{Providers: ctxProviders}

	// A single state variable to track the lifecycle, starting with no state
	var state *terraform.State

	// Go through each step and run it
	for i, step := range c.Steps {
		var err error
		log.Printf("[WARN] Test: Executing step %d", i)
		state, err = testStep(opts, state, step)
		if err != nil {
			t.Error(fmt.Sprintf(
				"Step %d error: %s", i, err))
			break
		}
	}

	// If we have a state, then run the destroy
	if state != nil {
		destroyStep := TestStep{
			Config:  c.Steps[len(c.Steps)-1].Config,
			Check:   c.CheckDestroy,
			Destroy: true,
		}

		log.Printf("[WARN] Test: Executing destroy step")
		state, err := testStep(opts, state, destroyStep)
		if err != nil {
			t.Error(fmt.Sprintf(
				"Error destroying resource! WARNING: Dangling resources\n"+
					"may exist. The full state and error is shown below.\n\n"+
					"Error: %s\n\nState: %s",
				err,
				state))
		}
	} else {
		log.Printf("[WARN] Skipping destroy test since there is no state.")
	}
}

func testStep(
	opts terraform.ContextOpts,
	state *terraform.State,
	step TestStep) (*terraform.State, error) {
	// Write the configuration
	cfgF, err := ioutil.TempFile("", "tf-test")
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}
	cfgPath := cfgF.Name() + ".tf"
	cfgF.Close()
	os.Remove(cfgF.Name())

	cfgF, err = os.Create(cfgPath)
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}
	defer os.Remove(cfgPath)

	_, err = io.Copy(cfgF, strings.NewReader(step.Config))
	cfgF.Close()
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}

	// Parse the configuration
	config, err := config.Load(cfgPath)
	if err != nil {
		return state, fmt.Errorf(
			"Error parsing configuration: %s", err)
	}

	// Build the context
	opts.Config = config
	opts.State = state
	ctx := terraform.NewContext(&opts)
	if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
		estrs := make([]string, len(es))
		for i, e := range es {
			estrs[i] = e.Error()
		}
		return state, fmt.Errorf(
			"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
			ws, estrs)
	}

	// Refresh!
	state, err = ctx.Refresh()
	if err != nil {
		return state, fmt.Errorf(
			"Error refreshing: %s", err)
	}

	// Plan!
	if p, err := ctx.Plan(&terraform.PlanOpts{Destroy: step.Destroy}); err != nil {
		return state, fmt.Errorf(
			"Error planning: %s", err)
	} else {
		log.Printf("[WARN] Test: Step plan: %s", p)
	}

	// Apply!
	state, err = ctx.Apply()
	if err != nil {
		return state, fmt.Errorf("Error applying: %s", err)
	}

	// Check! Excitement!
	if step.Check != nil {
		if err = step.Check(state); err != nil {
			err = fmt.Errorf("Check failed: %s", err)
		}
	}

	return state, err
}

// ComposeTestCheckFunc lets you compose multiple TestCheckFuncs into
// a single TestCheckFunc.
//
// As a user testing their provider, this lets you decompose your checks
// into smaller pieces more easily.
func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc {
	return func(s *terraform.State) error {
		for _, f := range fs {
			if err := f(s); err != nil {
				return err
			}
		}

		return nil
	}
}

func TestCheckResourceAttr(name, key, value string) TestCheckFunc {
	return func(s *terraform.State) error {
		ms := s.RootModule()
		rs, ok := ms.Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		is := rs.Primary
		if is == nil {
			return fmt.Errorf("No primary instance: %s", name)
		}

		if is.Attributes[key] != value {
			return fmt.Errorf(
				"%s: Attribute '%s' expected %#v, got %#v",
				name,
				key,
				value,
				is.Attributes[key])
		}

		return nil
	}
}

// TestT is the interface used to handle the test lifecycle of a test.
//
// Users should just use a *testing.T object, which implements this.
type TestT interface {
	Error(args ...interface{})
	Fatal(args ...interface{})
	Skip(args ...interface{})
}

// This is set to true by unit tests to alter some behavior
var testTesting = false
<commit_msg>helper/resource: compile<commit_after>package resource

import (
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"github.com/hashicorp/terraform/config/module"
	"github.com/hashicorp/terraform/terraform"
)

const TestEnvVar = "TF_ACC"

// TestCheckFunc is the callback type used with acceptance tests to check
// the state of a resource. The state passed in is the latest state known,
// or in the case of being after a destroy, it is the last known state when
// it was created.
type TestCheckFunc func(*terraform.State) error

// TestCase is a single acceptance test case used to test the apply/destroy
// lifecycle of a resource in a specific configuration.
//
// When the destroy plan is executed, the config from the last TestStep
// is used to plan it.
type TestCase struct {
	// PreCheck, if non-nil, will be called before any test steps are
	// executed. It will only be executed in the case that the steps
	// would run, so it can be used for some validation before running
	// acceptance tests, such as verifying that keys are setup.
	PreCheck func()

	// Provider is the ResourceProvider that will be under test.
	Providers map[string]terraform.ResourceProvider

	// CheckDestroy is called after the resource is finally destroyed
	// to allow the tester to test that the resource is truly gone.
	CheckDestroy TestCheckFunc

	// Steps are the apply sequences done within the context of the
	// same state. Each step can have its own check to verify correctness.
	Steps []TestStep
}

// TestStep is a single apply sequence of a test, done within the
// context of a state.
//
// Multiple TestSteps can be sequenced in a Test to allow testing
// potentially complex update logic. In general, simply create/destroy
// tests will only need one step.
type TestStep struct {
	// Config a string of the configuration to give to Terraform.
	Config string

	// Check is called after the Config is applied. Use this step to
	// make your own API calls to check the status of things, and to
	// inspect the format of the ResourceState itself.
	//
	// If an error is returned, the test will fail. In this case, a
	// destroy plan will still be attempted.
	//
	// If this is nil, no check is done on this step.
	Check TestCheckFunc

	// Destroy will create a destroy plan if set to true.
	Destroy bool
}

// Test performs an acceptance test on a resource.
//
// Tests are not run unless an environmental variable "TF_ACC" is
// set to some non-empty value. This is to avoid test cases surprising
// a user by creating real resources.
//
// Tests will fail unless the verbose flag (`go test -v`, or explicitly
// the "-test.v" flag) is set. Because some acceptance tests take quite
// long, we require the verbose flag so users are able to see progress
// output.
func Test(t TestT, c TestCase) {
	// We only run acceptance tests if an env var is set because they're
	// slow and generally require some outside configuration.
	if os.Getenv(TestEnvVar) == "" {
		t.Skip(fmt.Sprintf(
			"Acceptance tests skipped unless env '%s' set",
			TestEnvVar))
		return
	}

	// We require verbose mode so that the user knows what is going on.
	if !testTesting && !testing.Verbose() {
		t.Fatal("Acceptance tests must be run with the -v flag on tests")
		return
	}

	// Run the PreCheck if we have it
	if c.PreCheck != nil {
		c.PreCheck()
	}

	// Build our context options that we can
	ctxProviders := make(map[string]terraform.ResourceProviderFactory)
	for k, p := range c.Providers {
		ctxProviders[k] = terraform.ResourceProviderFactoryFixed(p)
	}
	opts := terraform.ContextOpts{Providers: ctxProviders}

	// A single state variable to track the lifecycle, starting with no state
	var state *terraform.State

	// Go through each step and run it
	for i, step := range c.Steps {
		var err error
		log.Printf("[WARN] Test: Executing step %d", i)
		state, err = testStep(opts, state, step)
		if err != nil {
			t.Error(fmt.Sprintf(
				"Step %d error: %s", i, err))
			break
		}
	}

	// If we have a state, then run the destroy
	if state != nil {
		destroyStep := TestStep{
			Config:  c.Steps[len(c.Steps)-1].Config,
			Check:   c.CheckDestroy,
			Destroy: true,
		}

		log.Printf("[WARN] Test: Executing destroy step")
		state, err := testStep(opts, state, destroyStep)
		if err != nil {
			t.Error(fmt.Sprintf(
				"Error destroying resource! WARNING: Dangling resources\n"+
					"may exist. The full state and error is shown below.\n\n"+
					"Error: %s\n\nState: %s",
				err,
				state))
		}
	} else {
		log.Printf("[WARN] Skipping destroy test since there is no state.")
	}
}

func testStep(
	opts terraform.ContextOpts,
	state *terraform.State,
	step TestStep) (*terraform.State, error) {
	cfgPath, err := ioutil.TempDir("", "tf-test")
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary directory for config: %s", err)
	}
	defer os.RemoveAll(cfgPath)

	// Write the configuration
	cfgF, err := os.Create(filepath.Join(cfgPath, "main.tf"))
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}

	_, err = io.Copy(cfgF, strings.NewReader(step.Config))
	cfgF.Close()
	if err != nil {
		return state, fmt.Errorf(
			"Error creating temporary file for config: %s", err)
	}

	// Parse the configuration
	mod, err := module.NewTreeModule("", cfgPath)
	if err != nil {
		return state, fmt.Errorf(
			"Error loading configuration: %s", err)
	}

	// Load the modules
	modStorage := &module.FolderStorage{
		StorageDir: filepath.Join(cfgPath, ".tfmodules"),
	}
	err = mod.Load(modStorage, module.GetModeGet)
	if err != nil {
		return state, fmt.Errorf("Error downloading modules: %s", err)
	}

	// Build the context
	opts.Module = mod
	opts.State = state
	ctx := terraform.NewContext(&opts)
	if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
		estrs := make([]string, len(es))
		for i, e := range es {
			estrs[i] = e.Error()
		}
		return state, fmt.Errorf(
			"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
			ws, estrs)
	}

	// Refresh!
	state, err = ctx.Refresh()
	if err != nil {
		return state, fmt.Errorf(
			"Error refreshing: %s", err)
	}

	// Plan!
	if p, err := ctx.Plan(&terraform.PlanOpts{Destroy: step.Destroy}); err != nil {
		return state, fmt.Errorf(
			"Error planning: %s", err)
	} else {
		log.Printf("[WARN] Test: Step plan: %s", p)
	}

	// Apply!
	state, err = ctx.Apply()
	if err != nil {
		return state, fmt.Errorf("Error applying: %s", err)
	}

	// Check! Excitement!
	if step.Check != nil {
		if err = step.Check(state); err != nil {
			err = fmt.Errorf("Check failed: %s", err)
		}
	}

	return state, err
}

// ComposeTestCheckFunc lets you compose multiple TestCheckFuncs into
// a single TestCheckFunc.
//
// As a user testing their provider, this lets you decompose your checks
// into smaller pieces more easily.
func ComposeTestCheckFunc(fs ...TestCheckFunc) TestCheckFunc {
	return func(s *terraform.State) error {
		for _, f := range fs {
			if err := f(s); err != nil {
				return err
			}
		}

		return nil
	}
}

func TestCheckResourceAttr(name, key, value string) TestCheckFunc {
	return func(s *terraform.State) error {
		ms := s.RootModule()
		rs, ok := ms.Resources[name]
		if !ok {
			return fmt.Errorf("Not found: %s", name)
		}

		is := rs.Primary
		if is == nil {
			return fmt.Errorf("No primary instance: %s", name)
		}

		if is.Attributes[key] != value {
			return fmt.Errorf(
				"%s: Attribute '%s' expected %#v, got %#v",
				name,
				key,
				value,
				is.Attributes[key])
		}

		return nil
	}
}

// TestT is the interface used to handle the test lifecycle of a test.
//
// Users should just use a *testing.T object, which implements this.
type TestT interface {
	Error(args ...interface{})
	Fatal(args ...interface{})
	Skip(args ...interface{})
}

// This is set to true by unit tests to alter some behavior
var testTesting = false
<|endoftext|>


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

package test

import (
	"reflect"
	"testing"
)

func TestUniqueInt64s(t *testing.T) {
	input := []int64{1, 2, 3, 2, 1}
	want := []int64{1, 2, 3}
	got := deriveUniqueInt64s(input)
	if !reflect.DeepEqual(got, want) {
		t.Fatalf("got %v, want %v", got, want)
	}
}

func TestUniqueStructs(t *testing.T) {
	var b *BuiltInTypes
	b1 := random(b).(*BuiltInTypes)
	b2 := random(b).(*BuiltInTypes)
	b3 := random(b).(*BuiltInTypes)
	input := []*BuiltInTypes{b1, b2, b3, b2, b1}
	want := []*BuiltInTypes{b1, b2, b3}
	got := deriveUniqueStructs(input)
	if len(got) != len(want) {
		t.Fatalf("got too long: %#v", got)
	}
	for _, g := range got {
		if !deriveContainsStruct(want, g) {
			t.Fatalf("did not get %#v", g)
		}
	}
}
<commit_msg>more robust unique tests<commit_after>//  Copyright 2017 Walter Schulze
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

package test

import (
	"testing"
)

func TestUniqueInt64s(t *testing.T) {
	input := []int64{1, 2, 3, 2, 1}
	want := []int64{1, 2, 3}
	got := deriveUniqueInt64s(input)
	if len(got) != len(want) {
		t.Fatalf("got too long: %#v", got)
	}
	for _, g := range got {
		if !deriveContainsInt64s(want, g) {
			t.Fatalf("did not get %d", g)
		}
	}
}

func TestUniqueStructs(t *testing.T) {
	var b *BuiltInTypes
	b1 := random(b).(*BuiltInTypes)
	b2 := random(b).(*BuiltInTypes)
	b3 := random(b).(*BuiltInTypes)
	input := []*BuiltInTypes{b1, b2, b3, b2, b1}
	want := []*BuiltInTypes{b1, b2, b3}
	got := deriveUniqueStructs(input)
	if len(got) != len(want) {
		t.Fatalf("got too long: %#v", got)
	}
	for _, g := range got {
		if !deriveContainsStruct(want, g) {
			t.Fatalf("did not get %#v", g)
		}
	}
}
<|endoftext|>


<commit_before>package gcs

import (
	"context"
	"io"

	"cloud.google.com/go/storage"
)

// GCSClient is an interface for interacting with Google Cloud Storage (GCS). Introducing
// the interface allows for easier mocking and testing for unit (small) tests. GCSClient
// should have common, general functionality. Users should feel free to create a
// instance-specific GCSClient that creates an abstraction for more instance-specific method calls.
// One intentional thing missing from these method calls is bucket name. The bucket name
// is given at creation time, so as to simplify the method signatures.
// In all methods, context.Background() is a safe value for ctx if you don't want to use
// the context of the web request, for example.
// See also test_gcsclient.NewMockClient() for mocking this for unit tests.
// See also mem_gcsclient.New() for an alternative.
type GCSClient interface {
	// FileReader returns an io.ReadCloser pointing to path on GCS, using the provided
	// context. storage.ErrObjectNotExist will be returned if the file is not found.
	// The caller must call Close on the returned Reader when done reading.
	// Note that per https://cloud.google.com/storage/docs/transcoding, a file that is gzip encoded
	// will be automatically uncompressed.
	FileReader(ctx context.Context, path string) (io.ReadCloser, error)
	// FileWriter returns an io.WriteCloser that writes to the GCS file given by path
	// using the provided context. A new GCS file will be created if it doesn't already exist.
	// Otherwise, the existing file will be overwritten. The caller must call Close on
	// the returned Writer to flush the writes.
	FileWriter(ctx context.Context, path string, opts FileWriteOptions) io.WriteCloser
	// DoesFileExist returns true if the specified path exists and false if it does not.
	// This is a convenience wrapper around
	// https://godoc.org/cloud.google.com/go/storage#ObjectHandle.Attrs
	// If any error, other than storage.ErrObjectNotExist, is encountered then it will be
	// returned.
	DoesFileExist(ctx context.Context, path string) (bool, error)
	// GetFileContents returns the []byte represented by the GCS file at path. This is a
	// convenience wrapper around FileReader. storage.ErrObjectNotExist will be returned
	// if the file is not found.
	// Note that per https://cloud.google.com/storage/docs/transcoding, a file that is gzip encoded
	// will be automatically uncompressed.
	GetFileContents(ctx context.Context, path string) ([]byte, error)
	// SetFileContents writes the []byte to the GCS file at path. This is a
	// convenience wrapper around FileWriter. The GCS file will be created if it doesn't exist.
	SetFileContents(ctx context.Context, path string, opts FileWriteOptions, contents []byte) error
	// GetFileObjectAttrs returns the storage.ObjectAttrs associated with the given
	// path.
	GetFileObjectAttrs(ctx context.Context, path string) (*storage.ObjectAttrs, error)
	// AllFilesInDirectory executes the callback on all GCS files with the given prefix,
	// i.e. in the directory prefix. It returns an error if it fails to read any of the
	// ObjectAttrs belonging to files.
	AllFilesInDirectory(ctx context.Context, prefix string, callback func(item *storage.ObjectAttrs)) error
	// DeleteFile deletes the given file, returning any error.
	DeleteFile(ctx context.Context, path string) error
	// Bucket returns the bucket name of this client
	Bucket() string
}

// FileWriteOptions represents the metadata for a GCS file.  See storage.ObjectAttrs
// for a more detailed description of what these are.
type FileWriteOptions struct {
	ContentEncoding    string
	ContentType        string
	ContentLanguage    string
	ContentDisposition string
	Metadata           map[string]string
}

var FILE_WRITE_OPTS_TEXT = FileWriteOptions{ContentEncoding: "text/plain"}
<commit_msg>Fix gcs.FILE_WRITE_OPTS_TEXT.<commit_after>package gcs

import (
	"context"
	"io"

	"cloud.google.com/go/storage"
)

// GCSClient is an interface for interacting with Google Cloud Storage (GCS). Introducing
// the interface allows for easier mocking and testing for unit (small) tests. GCSClient
// should have common, general functionality. Users should feel free to create a
// instance-specific GCSClient that creates an abstraction for more instance-specific method calls.
// One intentional thing missing from these method calls is bucket name. The bucket name
// is given at creation time, so as to simplify the method signatures.
// In all methods, context.Background() is a safe value for ctx if you don't want to use
// the context of the web request, for example.
// See also test_gcsclient.NewMockClient() for mocking this for unit tests.
// See also mem_gcsclient.New() for an alternative.
type GCSClient interface {
	// FileReader returns an io.ReadCloser pointing to path on GCS, using the provided
	// context. storage.ErrObjectNotExist will be returned if the file is not found.
	// The caller must call Close on the returned Reader when done reading.
	// Note that per https://cloud.google.com/storage/docs/transcoding, a file that is gzip encoded
	// will be automatically uncompressed.
	FileReader(ctx context.Context, path string) (io.ReadCloser, error)
	// FileWriter returns an io.WriteCloser that writes to the GCS file given by path
	// using the provided context. A new GCS file will be created if it doesn't already exist.
	// Otherwise, the existing file will be overwritten. The caller must call Close on
	// the returned Writer to flush the writes.
	FileWriter(ctx context.Context, path string, opts FileWriteOptions) io.WriteCloser
	// DoesFileExist returns true if the specified path exists and false if it does not.
	// This is a convenience wrapper around
	// https://godoc.org/cloud.google.com/go/storage#ObjectHandle.Attrs
	// If any error, other than storage.ErrObjectNotExist, is encountered then it will be
	// returned.
	DoesFileExist(ctx context.Context, path string) (bool, error)
	// GetFileContents returns the []byte represented by the GCS file at path. This is a
	// convenience wrapper around FileReader. storage.ErrObjectNotExist will be returned
	// if the file is not found.
	// Note that per https://cloud.google.com/storage/docs/transcoding, a file that is gzip encoded
	// will be automatically uncompressed.
	GetFileContents(ctx context.Context, path string) ([]byte, error)
	// SetFileContents writes the []byte to the GCS file at path. This is a
	// convenience wrapper around FileWriter. The GCS file will be created if it doesn't exist.
	SetFileContents(ctx context.Context, path string, opts FileWriteOptions, contents []byte) error
	// GetFileObjectAttrs returns the storage.ObjectAttrs associated with the given
	// path.
	GetFileObjectAttrs(ctx context.Context, path string) (*storage.ObjectAttrs, error)
	// AllFilesInDirectory executes the callback on all GCS files with the given prefix,
	// i.e. in the directory prefix. It returns an error if it fails to read any of the
	// ObjectAttrs belonging to files.
	AllFilesInDirectory(ctx context.Context, prefix string, callback func(item *storage.ObjectAttrs)) error
	// DeleteFile deletes the given file, returning any error.
	DeleteFile(ctx context.Context, path string) error
	// Bucket returns the bucket name of this client
	Bucket() string
}

// FileWriteOptions represents the metadata for a GCS file.  See storage.ObjectAttrs
// for a more detailed description of what these are.
type FileWriteOptions struct {
	ContentEncoding    string
	ContentType        string
	ContentLanguage    string
	ContentDisposition string
	Metadata           map[string]string
}

// FILE_WRITE_OPTS_TEXT are default options for writing a text file.
var FILE_WRITE_OPTS_TEXT = FileWriteOptions{ContentType: "text/plain"}
<|endoftext|>


<commit_before>package transport

import (
	"bufio"
	"context"
	pb "github.com/Randomsock5/tcptunnel/proto"
	"log"
	"net"
	"time"

	"sync"
)

func handleErr(err error) {
	if err != nil {
		panic(err)
	}
}

func recoverHandle() {
	if rec := recover(); rec != nil {
		err := rec.(error)
		log.Println(err)
	}
}

type proxyService struct {
	forward string
}

func (s *proxyService) Stream(stream pb.ProxyService_StreamServer) error {
	forwardConn, err := net.Dial("tcp", s.forward)
	if err != nil {
		log.Println(err)
		return err
	}
	defer forwardConn.Close()
	wg := &sync.WaitGroup{}

	go func() {
		defer wg.Done()
		defer recoverHandle()

		for {
			buf := make([]byte, 768)
			i, err := forwardConn.Read(buf)
			handleErr(err)

			var payload pb.Payload
			payload.Data = buf[:i]

			err = stream.Send(&payload)
			handleErr(err)
		}
	}()

	go func() {
		defer recoverHandle()
		defer wg.Done()
		writeBuff := bufio.NewWriter(forwardConn)

		for {
			payload, err := stream.Recv()
			handleErr(err)

			data := payload.GetData()
			_, err = writeBuff.Write(data)
			handleErr(err)

			err = writeBuff.Flush()
			handleErr(err)
		}
	}()

	wg.Add(2)
	wg.Wait()

	return nil
}

func NewServer(forward string) pb.ProxyServiceServer {
	s := &proxyService{forward: forward}
	return s
}

func ClientProxyService(conn net.Conn, client pb.ProxyServiceClient) {
	defer conn.Close()

	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()
	stream, err := client.Stream(ctx)
	if err != nil {
		log.Println(err)
		return
	}
	defer stream.CloseSend()
	wg := &sync.WaitGroup{}

	go func() {
		defer recoverHandle()
		defer wg.Done()

		for {
			buf := make([]byte, 768)
			i, err := conn.Read(buf)
			handleErr(err)

			var payload pb.Payload
			payload.Data = buf[:i]

			err = stream.Send(&payload)
			handleErr(err)
		}
	}()

	go func() {
		defer recoverHandle()
		defer wg.Done()
		writeBuff := bufio.NewWriter(conn)

		for {
			payload, err := stream.Recv()
			handleErr(err)

			data := payload.GetData()
			_, err = writeBuff.Write(data)
			handleErr(err)

			err = writeBuff.Flush()
			handleErr(err)
		}
	}()

	wg.Add(2)
	wg.Wait()

	return
}
<commit_msg>fix client bug<commit_after>package transport

import (
	"bufio"
	"context"
	pb "github.com/Randomsock5/tcptunnel/proto"
	"io"
	"log"
	"net"
	"time"

	"sync"
)

func handleErr(err error) {
	if err != nil {
		panic(err)
	}
}

func recoverHandle() {
	if rec := recover(); rec != nil {
		err := rec.(error)
		if err != io.EOF {
			log.Println(err)
		}
	}
}

type proxyService struct {
	forward string
}

func (s *proxyService) Stream(stream pb.ProxyService_StreamServer) error {
	forwardConn, err := net.Dial("tcp", s.forward)
	if err != nil {
		log.Println(err)
		return err
	}
	defer forwardConn.Close()
	wg := &sync.WaitGroup{}

	go func() {
		defer wg.Done()
		defer recoverHandle()

		for {
			buf := make([]byte, 768)
			i, err := forwardConn.Read(buf)
			handleErr(err)

			var payload pb.Payload
			payload.Data = buf[:i]

			err = stream.Send(&payload)
			handleErr(err)
		}
	}()

	go func() {
		defer recoverHandle()
		defer wg.Done()
		writeBuff := bufio.NewWriter(forwardConn)

		for {
			payload, err := stream.Recv()
			handleErr(err)

			data := payload.GetData()
			_, err = writeBuff.Write(data)
			handleErr(err)

			err = writeBuff.Flush()
			handleErr(err)
		}
	}()

	wg.Add(2)
	wg.Wait()

	return nil
}

func NewServer(forward string) pb.ProxyServiceServer {
	s := &proxyService{forward: forward}
	return s
}

func ClientProxyService(conn net.Conn, client pb.ProxyServiceClient) {
	defer conn.Close()

	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
	defer cancel()
	stream, err := client.Stream(ctx)
	if err != nil {
		log.Println(err)
		return
	}
	defer stream.CloseSend()
	wg := &sync.WaitGroup{}

	go func() {
		defer recoverHandle()
		defer wg.Done()

		for {
			buf := make([]byte, 768)
			i, err := conn.Read(buf)
			handleErr(err)

			var payload pb.Payload
			payload.Data = buf[:i]

			err = stream.Send(&payload)
			handleErr(err)
		}
	}()

	go func() {
		defer recoverHandle()
		defer wg.Done()
		writeBuff := bufio.NewWriter(conn)

		for {
			payload, err := stream.Recv()
			handleErr(err)

			data := payload.GetData()
			_, err = writeBuff.Write(data)
			handleErr(err)

			err = writeBuff.Flush()
			handleErr(err)
		}
	}()

	wg.Add(2)
	wg.Wait()

	return
}
<|endoftext|>