<commit_before>package main

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/kwilczynski/packer-provisioner-itamae-local/itamae"
	"github.com/mitchellh/packer/packer/plugin"
)

func main() {
	//
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "-h", "-help", "--help", "help":
			fmt.Printf(
				"Usage: %s [--version] [--help] <COMMAND>\n\n"+
					"Available commands are:\n"+
					"    version    Print the version and exit.\n"+
					"    help       Show this help screen.\n\n",
				filepath.Base(os.Args[0]))
		case "version":
			version := fmt.Sprintf("Provisioner Itamae v%s", itamaelocal.Version)
			if itamaelocal.Revision != "" {
				version += fmt.Sprintf(" (%s)", itamaelocal.Revision)
			}
			fmt.Println(version)
		case "-version", "--version":
			fmt.Printf("%s\n", itamaelocal.Version)
		}
		os.Exit(0)
	}

	server, err := plugin.Server()
	if err != nil {
		panic(err)
	}

	server.RegisterProvisioner(&itamaelocal.Provisioner{})
	server.Serve()
}
<commit_msg>Add `-v` switch to the main application.<commit_after>package main

import (
	"fmt"
	"os"
	"path/filepath"

	"github.com/kwilczynski/packer-provisioner-itamae-local/itamae"
	"github.com/mitchellh/packer/packer/plugin"
)

func main() {
	//
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "-h", "-help", "--help", "help":
			fmt.Printf(
				"Usage: %s [--version] [--help] <COMMAND>\n\n"+
					"Available commands are:\n"+
					"    version    Print the version and exit.\n"+
					"    help       Show this help screen.\n\n",
				filepath.Base(os.Args[0]))
		case "version":
			version := fmt.Sprintf("Provisioner Itamae v%s", itamaelocal.Version)
			if itamaelocal.Revision != "" {
				version += fmt.Sprintf(" (%s)", itamaelocal.Revision)
			}
			fmt.Println(version)
		case "-v", "-version", "--version":
			fmt.Printf("%s\n", itamaelocal.Version)
		}
		os.Exit(0)
	}

	server, err := plugin.Server()
	if err != nil {
		panic(err)
	}

	server.RegisterProvisioner(&itamaelocal.Provisioner{})
	server.Serve()
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"gopkg.in/yaml.v2"
)

var (
	applicationVersion = "0.1.1-alpha"
	//Log ...
	Log *log.Logger
	//RandomSource ...
	RandomSource = rand.NewSource(time.Now().UnixNano())
	//Random ...
	Random = rand.New(RandomSource)
	//ErrorMappings ...
	ErrorMappings = map[string]ErrorCode{}
)

func check(err error) {
	if err != nil {
		for mapping, errorCode := range ErrorMappings {
			if strings.Contains(fmt.Sprintf("%v", err), mapping) {
				fmt.Println(errorCode.Message)
				os.Exit(errorCode.Code)
			}
		}
		Log.Fatalf("UNKNOWN ERROR: %v", err)
	}
}

//ConfigureLogging ...
func ConfigureLogging(config *Configuration) {
	Log = log.New()
	Log.Level = config.LogLevel
	//TODO probably have another ticket to support outputting logs to a file
	//Log.Formatter = config.Logging.Formatter
}

//ExecuteRequest ...
func ExecuteRequest(client *http.Client, stats *Statistics, request *http.Request) {
	Log.Infof("%s to %s", request.Method, request.URL)
	start := time.Now()
	response, responseError := client.Do(request)
	duration := time.Since(start) / time.Millisecond
	check(responseError)

	defer func() {
		err := response.Body.Close()
		if err != nil {
			Log.Warnf("Error closing response Body %v", err)
		}
	}()
	responseBytes, _ := httputil.DumpResponse(response, true)
	stats.BytesReceived(int64(len(responseBytes)))
	if response.StatusCode >= 400 && response.StatusCode < 600 {
		responseError = errors.New("5XX Response Code")
	}

	stats.ResponseTime(int64(duration))
	requestBytes, _ := httputil.DumpRequest(request, true)
	stats.BytesSent(int64(len(requestBytes)))
	stats.Request(responseError)
}

//Execute ...
func Execute(config *Configuration, stats *Statistics) {
	var waitGroup sync.WaitGroup

	reader := NewRequestReader(config.FilePath)

	for i := 0; i < config.Workers; i++ {
		waitGroup.Add(1)
		go func() {
			defer func() { //catch or finally
				if err := recover(); err != nil { //catch
					if strings.Contains(fmt.Sprintf("%v", err), "too many open files") {
						Log.Fatalf("Too many workers man!")
					} else {
						Log.Fatalf("UNKNOWN ERROR: %v", err)
					}
				}
			}()
			client := &http.Client{
				Transport: &http.Transport{
					MaxIdleConnsPerHost: 50,
				},
			}
			var stream RequestStream

			if config.Random {
				stream = NewRandomRequestStream(reader)
			} else {
				stream = NewSequentialRequestStream(reader)
			}
			if config.Duration > 0 {
				stream = NewTimeBasedRequestStream(stream, config.Duration)
			}
			for stream.HasNext() {
				request, err := stream.Next()
				check(err)
				ExecuteRequest(client, stats, request)

				time.Sleep(config.WaitTime)
			}
			waitGroup.Done()
		}()
	}

	waitGroup.Wait()
}

//GenerateExecutionOutput ...
func GenerateExecutionOutput(file string, stats *Statistics) {
	outputPath, err := filepath.Abs(file)
	check(err)
	output := stats.ExecutionOutput()
	yamlOutput, err := yaml.Marshal(&output)
	check(err)
	err = ioutil.WriteFile(outputPath, yamlOutput, 0644)
	check(err)
}

//OutputSummary ...
func OutputSummary(stats *Statistics) {
	output := stats.ExecutionOutput()
	fmt.Println(fmt.Sprintf("Running Time: %v s", output.Summary.RunningTime/1000))
	fmt.Println(fmt.Sprintf("Throughput: %v req/s", int64(output.Summary.Requests.Rate)))
	fmt.Println(fmt.Sprintf("Total Requests: %v", output.Summary.Requests.Total))
	fmt.Println(fmt.Sprintf("Number of Errors: %v", output.Summary.Requests.Errors))
	fmt.Println(fmt.Sprintf("Availability: %v%%", output.Summary.Requests.Availability*100))
	fmt.Println(fmt.Sprintf("Bytes Sent: %v", output.Summary.Bytes.Sent.Sum))
	fmt.Println(fmt.Sprintf("Bytes Received: %v", output.Summary.Bytes.Received.Sum))
	if output.Summary.ResponseTime.Mean > 0 {
		fmt.Println(fmt.Sprintf("Mean Response Time: %.4v ms", output.Summary.ResponseTime.Mean))
	} else {
		fmt.Println(fmt.Sprintf("Mean Response Time: %v ms", output.Summary.ResponseTime.Mean))
	}

	fmt.Println(fmt.Sprintf("Min Response Time: %v ms", output.Summary.ResponseTime.Min))
	fmt.Println(fmt.Sprintf("Max Response Time: %v ms", output.Summary.ResponseTime.Max))
}

func main() {
	config, err := ParseConfiguration(os.Args[1:])
	check(err)

	configureErrorMappings()
	ConfigureLogging(config)

	absolutePath, err := filepath.Abs(config.FilePath)
	check(err)
	file, err := os.Open(absolutePath)
	defer func() {
		err := file.Close()
		if err != nil {
			Log.Printf("Error closing file %v", err)
		}
	}()
	check(err)

	stats := CreateStatistics()

	Execute(config, stats)

	stats.Stop()

	check(err)
	GenerateExecutionOutput("./output.yml", stats)

	if config.Summary {
		OutputSummary(stats)
	}
}
<commit_msg>Fixed one of the failing tests<commit_after>package main

import (
	"errors"
	"fmt"
	"io/ioutil"
	"math/rand"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"time"

	log "github.com/Sirupsen/logrus"
	"gopkg.in/yaml.v2"
)

var (
	applicationVersion = "0.1.1-alpha"
	//Log ...
	Log *log.Logger
	//RandomSource ...
	RandomSource = rand.NewSource(time.Now().UnixNano())
	//Random ...
	Random = rand.New(RandomSource)
	//ErrorMappings ...
	ErrorMappings = map[string]ErrorCode{}
)

func check(err error) {
	if err != nil {
		for mapping, errorCode := range ErrorMappings {
			if strings.Contains(fmt.Sprintf("%v", err), mapping) {
				fmt.Println(errorCode.Message)
				os.Exit(errorCode.Code)
			}
		}
		Log.Fatalf("UNKNOWN ERROR: %v", err)
	}
}

//ConfigureLogging ...
func ConfigureLogging(config *Configuration) {
	Log = log.New()
	Log.Level = config.LogLevel
	//TODO probably have another ticket to support outputting logs to a file
	//Log.Formatter = config.Logging.Formatter
}

//ExecuteRequest ...
func ExecuteRequest(client *http.Client, stats *Statistics, request *http.Request) {
	Log.Infof("%s to %s", request.Method, request.URL)
	start := time.Now()
	response, responseError := client.Do(request)
	duration := time.Since(start) / time.Millisecond
	check(responseError)

	defer func() {
		err := response.Body.Close()
		if err != nil {
			Log.Warnf("Error closing response Body %v", err)
		}
	}()
	responseBytes, _ := httputil.DumpResponse(response, true)
	stats.BytesReceived(int64(len(responseBytes)))
	if response.StatusCode >= 400 && response.StatusCode < 600 {
		responseError = errors.New("5XX Response Code")
	}

	stats.ResponseTime(int64(duration))
	requestBytes, _ := httputil.DumpRequest(request, true)
	stats.BytesSent(int64(len(requestBytes)))
	stats.Request(responseError)
}

//Execute ...
func Execute(config *Configuration, stats *Statistics) {
	var waitGroup sync.WaitGroup

	reader := NewRequestReader(config.FilePath)

	for i := 0; i < config.Workers; i++ {
		waitGroup.Add(1)
		go func() {
			defer func() { //catch or finally
				if err := recover(); err != nil { //catch
					if strings.Contains(fmt.Sprintf("%v", err), "too many open files") {
						Log.Fatalf("Too many workers man!")
					} else {
						Log.Fatalf("UNKNOWN ERROR: %v", err)
					}
				}
			}()
			client := &http.Client{
				Transport: &http.Transport{
					MaxIdleConnsPerHost: 50,
				},
			}
			var stream RequestStream

			if config.Random {
				stream = NewRandomRequestStream(reader)
			} else {
				stream = NewSequentialRequestStream(reader)
			}
			if config.Duration > 0 {
				stream = NewTimeBasedRequestStream(stream, config.Duration)
			}
			for stream.HasNext() {
				request, err := stream.Next()
				check(err)
				ExecuteRequest(client, stats, request)

				time.Sleep(config.WaitTime)
			}
			waitGroup.Done()
		}()
	}

	waitGroup.Wait()
}

//GenerateExecutionOutput ...
func GenerateExecutionOutput(file string, stats *Statistics) {
	outputPath, err := filepath.Abs(file)
	check(err)
	output := stats.ExecutionOutput()
	yamlOutput, err := yaml.Marshal(&output)
	check(err)
	err = ioutil.WriteFile(outputPath, yamlOutput, 0644)
	check(err)
}

//OutputSummary ...
func OutputSummary(stats *Statistics) {
	output := stats.ExecutionOutput()
	fmt.Println(fmt.Sprintf("Running Time: %6e s", output.Summary.RunningTime/1000))
	fmt.Println(fmt.Sprintf("Throughput: %v req/s", int64(output.Summary.Requests.Rate)))
	fmt.Println(fmt.Sprintf("Total Requests: %v", output.Summary.Requests.Total))
	fmt.Println(fmt.Sprintf("Number of Errors: %v", output.Summary.Requests.Errors))
	fmt.Println(fmt.Sprintf("Availability: %v%%", output.Summary.Requests.Availability*100))
	fmt.Println(fmt.Sprintf("Bytes Sent: %v", output.Summary.Bytes.Sent.Sum))
	fmt.Println(fmt.Sprintf("Bytes Received: %v", output.Summary.Bytes.Received.Sum))
	if output.Summary.ResponseTime.Mean > 0 {
		fmt.Println(fmt.Sprintf("Mean Response Time: %.4v ms", output.Summary.ResponseTime.Mean))
	} else {
		fmt.Println(fmt.Sprintf("Mean Response Time: %v ms", output.Summary.ResponseTime.Mean))
	}

	fmt.Println(fmt.Sprintf("Min Response Time: %v ms", output.Summary.ResponseTime.Min))
	fmt.Println(fmt.Sprintf("Max Response Time: %v ms", output.Summary.ResponseTime.Max))
}

func main() {
	config, err := ParseConfiguration(os.Args[1:])
	check(err)

	configureErrorMappings()
	ConfigureLogging(config)

	absolutePath, err := filepath.Abs(config.FilePath)
	check(err)
	file, err := os.Open(absolutePath)
	defer func() {
		err := file.Close()
		if err != nil {
			Log.Printf("Error closing file %v", err)
		}
	}()
	check(err)

	stats := CreateStatistics()

	Execute(config, stats)

	stats.Stop()

	check(err)
	GenerateExecutionOutput("./output.yml", stats)

	if config.Summary {
		OutputSummary(stats)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Google Inc.
//
// 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.

// The shenzhen-go binary serves a visual Go environment.
package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"
)

const pingMsg = "Pong!"

var (
	serveAddr = flag.String("addr", "::1", "Address to bind server to")
	servePort = flag.Int("port", 8088, "Port to serve from")

	identifierRE = regexp.MustCompile(`^[_a-zA-Z][_a-zA-Z0-9]*$`)
)

// Graph models a collection of goroutines (nodes) and channels (channels).
type Graph struct {
	Name        string
	PackageName string
	PackagePath string
	Imports     []string
	Nodes       map[string]*Node
	Channels    map[string]*Channel
}

func (g *Graph) renderToDot(dst io.Writer) error { return dotTemplate.Execute(dst, g) }
func (g *Graph) renderToGo(dst io.Writer) error  { return goTemplate.Execute(dst, g) }

func (g *Graph) renderNodeEditor(dst io.Writer, n *Node) error {
	return nodeEditorTemplate.Execute(dst, struct {
		Graph *Graph
		Node  *Node
	}{g, n})
}

func (g *Graph) renderChannelEditor(dst io.Writer, e *Channel) error {
	return channelEditorTemplate.Execute(dst, struct {
		Graph   *Graph
		Channel *Channel
	}{g, e})
}

// Node models a goroutine.
type Node struct {
	Name string
	Code string
	Wait bool

	// Computed from Code - which channels are read from and written to.
	chansRd, chansWr []string
}

// ChannelsRead returns the names of all channels read by this goroutine.
func (n *Node) ChannelsRead() []string { return n.chansRd }

// ChannelsWritten returns the names of all channels written by this goroutine.
func (n *Node) ChannelsWritten() []string { return n.chansWr }

func (n *Node) updateChans(chans map[string]*Channel) error {
	srcs, dsts, err := extractChannelIdents(n.Code)
	if err != nil {
		return err
	}
	// dsts is definitely all the channels written by this goroutine.
	n.chansWr = dsts

	// srcs can include false positives, so filter them.
	n.chansRd = make([]string, 0, len(srcs))
	for _, s := range srcs {
		if _, found := chans[s]; found {
			n.chansRd = append(n.chansRd, s)
		}
	}
	return nil
}

func (n *Node) String() string { return n.Name }

// Channel models a channel.
type Channel struct {
	Name string
	Type string
	Cap  int
}

func open(args ...string) error {
	cmd := exec.Command(`open`, args...)
	return cmd.Run()
}

func pipeThru(dst io.Writer, cmd *exec.Cmd, src io.Reader) error {
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	if err := cmd.Start(); err != nil {
		return err
	}
	if _, err := io.Copy(stdin, src); err != nil {
		return err
	}
	if err := stdin.Close(); err != nil {
		return err
	}
	if _, err := io.Copy(dst, stdout); err != nil {
		return err
	}
	return cmd.Wait()
}

func dotToSVG(dst io.Writer, src io.Reader) error {
	return pipeThru(dst, exec.Command(`dot`, `-Tsvg`), src)
}

func gofmt(dst io.Writer, src io.Reader) error {
	return pipeThru(dst, exec.Command(`gofmt`), src)
}

func goimports(dst io.Writer, src io.Reader) error {
	return pipeThru(dst, exec.Command(`goimports`), src)
}

func (g *Graph) handleChannelRequest(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s", r.Method, r.URL)
	nm := strings.TrimPrefix(r.URL.Path, "/channel/")

	e, found := g.Channels[nm]
	if nm != "new" && !found {
		http.Error(w, fmt.Sprintf("Channel %q not found", nm), http.StatusNotFound)
		return
	}

	switch r.Method {
	case "POST":
		if e == nil {
			e = new(Channel)
		}

		// Parse...
		if err := r.ParseForm(); err != nil {
			log.Printf("Could not parse form: %v", err)
			http.Error(w, "Could not parse", http.StatusBadRequest)
			return
		}

		// ...Validate...
		nn := r.FormValue("Name")
		if !identifierRE.MatchString(nn) {
			msg := fmt.Sprintf("Invalid identifier %q !~ %q", nn, identifierRE)
			log.Printf(msg)
			http.Error(w, msg, http.StatusBadRequest)
			return
		}

		ci, err := strconv.Atoi(r.FormValue("Cap"))
		if err != nil {
			log.Printf("Capacity is not an integer: %v", err)
			http.Error(w, "Capacity is not an integer", http.StatusBadRequest)
			return
		}
		if ci < 0 {
			log.Printf("Must specify nonnegative capacity [%d < 0]", ci)
			http.Error(w, "Capacity must be non-negative", http.StatusBadRequest)
			return
		}

		// ...update...
		e.Type = r.FormValue("Type")
		e.Cap = ci

		// Do name changes last since they cause a redirect.
		if nn == e.Name {
			break
		}
		delete(g.Channels, e.Name)
		e.Name = nn
		g.Channels[nn] = e
		http.Redirect(w, r, "/channel/"+nn, http.StatusSeeOther) // should cause GET
		return
	}

	if err := g.renderChannelEditor(w, e); err != nil {
		log.Printf("Could not render source editor: %v", err)
		http.Error(w, "Could not render source editor", http.StatusInternalServerError)
		return
	}
	return
}

func (g *Graph) handleNodeRequest(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s", r.Method, r.URL)
	nm := strings.TrimPrefix(r.URL.Path, "/node/")
	n, found := g.Nodes[nm]
	if !found {
		http.Error(w, fmt.Sprintf("Node %q not found", nm), http.StatusNotFound)
		return
	}

	switch r.Method {
	case "POST":
		// Update the node.
		if err := r.ParseForm(); err != nil {
			log.Printf("Could not parse form: %v", err)
			http.Error(w, "Could not parse", http.StatusBadRequest)
			return
		}

		nm := strings.TrimSpace(r.FormValue("Name"))
		if nm == "" {
			log.Printf("Name invalid [%q == \"\"]", nm)
			http.Error(w, "Name invalid", http.StatusBadRequest)
			return
		}

		n.Wait = (r.FormValue("Wait") == "on")
		n.Code = r.FormValue("Code")

		if err := n.updateChans(g.Channels); err != nil {
			log.Printf("Unable to extract channels used from code: %v", err)
			http.Error(w, "Unable to extract channels used from code", http.StatusBadRequest)
			return
		}

		if nm == n.Name {
			break
		}

		delete(g.Nodes, n.Name)
		n.Name = nm
		g.Nodes[nm] = n

		http.Redirect(w, r, "/node/"+nm, http.StatusSeeOther) // should cause GET
		return
	}

	if err := g.renderNodeEditor(w, n); err != nil {
		log.Printf("Could not render source editor: %v", err)
		http.Error(w, "Could not render source editor", http.StatusInternalServerError)
		return
	}
	return
}

func (g *Graph) outputDotSrc(w http.ResponseWriter) {
	h := w.Header()
	h.Set("Content-Type", "text/vnd.graphviz")
	if err := g.renderToDot(w); err != nil {
		log.Printf("Could not render to dot: %v", err)
		http.Error(w, "Could not render to dot", http.StatusInternalServerError)
	}
}

func (g *Graph) writeGoSrc(w io.Writer) error {
	buf := &bytes.Buffer{}
	if err := g.renderToGo(buf); err != nil {
		return err
	}
	return goimports(w, buf)
}

func (g *Graph) outputGoSrc(w http.ResponseWriter) {
	h := w.Header()
	h.Set("Content-Type", "text/golang")
	if err := g.writeGoSrc(w); err != nil {
		log.Printf("Could not render to Go: %v", err)
		http.Error(w, "Could not render to Go", http.StatusInternalServerError)
	}
}

func (g *Graph) outputJSON(w http.ResponseWriter) {
	h := w.Header()
	h.Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(g); err != nil {
		log.Printf("Could not encode JSON: %v", err)
		http.Error(w, "Could not encode JSON", http.StatusInternalServerError)
		return
	}
}

func (g *Graph) handleRootRequest(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s", r.Method, r.URL)
	q := r.URL.Query()
	if _, t := q["dot"]; t {
		g.outputDotSrc(w)
		return
	}
	if _, t := q["go"]; t {
		g.outputGoSrc(w)
		return
	}
	if _, t := q["json"]; t {
		g.outputJSON(w)
		return
	}
	if _, t := q["run"]; t {
		if err := g.saveBuildAndRun(); err != nil {
			log.Printf("Failed to save, build, run: %v", err)
		}
	}

	var dot, svg bytes.Buffer
	if err := g.renderToDot(&dot); err != nil {
		log.Printf("Could not render to dot: %v", err)
		http.Error(w, "Could not render to dot", http.StatusInternalServerError)
	}
	if err := dotToSVG(&svg, &dot); err != nil {
		log.Printf("Could not render dot to SVG: %v", err)
		http.Error(w, "Could not render dot to SVG", http.StatusInternalServerError)
	}
	if err := rootTemplate.Execute(w, template.HTML(svg.String())); err != nil {
		log.Printf("Could not execute root template: %v", err)
		http.Error(w, "Could not execute root template", http.StatusInternalServerError)
	}
}

func (g *Graph) saveGoSrc() error {
	gopath, ok := os.LookupEnv("GOPATH")
	if !ok || gopath == "" {
		return errors.New("cannot use $GOPATH; empty or undefined")
	}
	pp := filepath.Join(gopath, "src", g.PackagePath)
	if err := os.Mkdir(pp, os.FileMode(0755)); err != nil {
		log.Printf("Could not make path %q, continuing: %v", pp, err)
	}
	mp := filepath.Join(pp, "main.go")
	f, err := os.Create(mp)
	if err != nil {
		return err
	}
	defer f.Close()
	if err := g.writeGoSrc(f); err != nil {
		return err
	}
	return f.Close()
}

func (g *Graph) build() error {
	return exec.Command(`go`, `build`, g.PackagePath).Run()
}

func (g *Graph) saveBuildAndRun() error {
	if err := g.saveGoSrc(); err != nil {
		return err
	}
	if err := g.build(); err != nil {
		return err
	}
	// TODO: Be less lazy about the output binary path
	return open("./" + g.PackageName)
}

func openWhenUp(addr string) {
	base := fmt.Sprintf("http://%s/", addr)
	t := time.NewTicker(100 * time.Millisecond)
	for range t.C {
		resp, err := http.Get(base + "ping")
		if err != nil {
			continue
		}
		defer resp.Body.Close()
		msg, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			continue
		}
		if string(msg) != pingMsg {
			continue
		}
		open(base)
		t.Stop()
		return
	}
}

func main() {
	flag.Parse()
	addr := net.JoinHostPort(*serveAddr, strconv.Itoa(*servePort))

	http.HandleFunc("/channel/", exampleGraph.handleChannelRequest)
	http.HandleFunc("/node/", exampleGraph.handleNodeRequest)
	http.HandleFunc("/", exampleGraph.handleRootRequest)
	http.HandleFunc("/ping", func(w http.ResponseWriter, _ *http.Request) {
		fmt.Fprintf(w, pingMsg)
	})

	// As soon as we're serving, launch a web browser.
	// Generally expected to work on macOS...
	go openWhenUp(addr)

	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Did something with /favicon.ico...<commit_after>// Copyright 2016 Google Inc.
//
// 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.

// The shenzhen-go binary serves a visual Go environment.
package main

import (
	"bytes"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"
)

const pingMsg = "Pong!"

var (
	serveAddr = flag.String("addr", "::1", "Address to bind server to")
	servePort = flag.Int("port", 8088, "Port to serve from")

	identifierRE = regexp.MustCompile(`^[_a-zA-Z][_a-zA-Z0-9]*$`)
)

// Graph models a collection of goroutines (nodes) and channels (channels).
type Graph struct {
	Name        string
	PackageName string
	PackagePath string
	Imports     []string
	Nodes       map[string]*Node
	Channels    map[string]*Channel
}

func (g *Graph) renderToDot(dst io.Writer) error { return dotTemplate.Execute(dst, g) }
func (g *Graph) renderToGo(dst io.Writer) error  { return goTemplate.Execute(dst, g) }

func (g *Graph) renderNodeEditor(dst io.Writer, n *Node) error {
	return nodeEditorTemplate.Execute(dst, struct {
		Graph *Graph
		Node  *Node
	}{g, n})
}

func (g *Graph) renderChannelEditor(dst io.Writer, e *Channel) error {
	return channelEditorTemplate.Execute(dst, struct {
		Graph   *Graph
		Channel *Channel
	}{g, e})
}

// Node models a goroutine.
type Node struct {
	Name string
	Code string
	Wait bool

	// Computed from Code - which channels are read from and written to.
	chansRd, chansWr []string
}

// ChannelsRead returns the names of all channels read by this goroutine.
func (n *Node) ChannelsRead() []string { return n.chansRd }

// ChannelsWritten returns the names of all channels written by this goroutine.
func (n *Node) ChannelsWritten() []string { return n.chansWr }

func (n *Node) updateChans(chans map[string]*Channel) error {
	srcs, dsts, err := extractChannelIdents(n.Code)
	if err != nil {
		return err
	}
	// dsts is definitely all the channels written by this goroutine.
	n.chansWr = dsts

	// srcs can include false positives, so filter them.
	n.chansRd = make([]string, 0, len(srcs))
	for _, s := range srcs {
		if _, found := chans[s]; found {
			n.chansRd = append(n.chansRd, s)
		}
	}
	return nil
}

func (n *Node) String() string { return n.Name }

// Channel models a channel.
type Channel struct {
	Name string
	Type string
	Cap  int
}

func open(args ...string) error {
	cmd := exec.Command(`open`, args...)
	return cmd.Run()
}

func pipeThru(dst io.Writer, cmd *exec.Cmd, src io.Reader) error {
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	if err := cmd.Start(); err != nil {
		return err
	}
	if _, err := io.Copy(stdin, src); err != nil {
		return err
	}
	if err := stdin.Close(); err != nil {
		return err
	}
	if _, err := io.Copy(dst, stdout); err != nil {
		return err
	}
	return cmd.Wait()
}

func dotToSVG(dst io.Writer, src io.Reader) error {
	return pipeThru(dst, exec.Command(`dot`, `-Tsvg`), src)
}

func gofmt(dst io.Writer, src io.Reader) error {
	return pipeThru(dst, exec.Command(`gofmt`), src)
}

func goimports(dst io.Writer, src io.Reader) error {
	return pipeThru(dst, exec.Command(`goimports`), src)
}

func (g *Graph) handleChannelRequest(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s", r.Method, r.URL)
	nm := strings.TrimPrefix(r.URL.Path, "/channel/")

	e, found := g.Channels[nm]
	if nm != "new" && !found {
		http.Error(w, fmt.Sprintf("Channel %q not found", nm), http.StatusNotFound)
		return
	}

	switch r.Method {
	case "POST":
		if e == nil {
			e = new(Channel)
		}

		// Parse...
		if err := r.ParseForm(); err != nil {
			log.Printf("Could not parse form: %v", err)
			http.Error(w, "Could not parse", http.StatusBadRequest)
			return
		}

		// ...Validate...
		nn := r.FormValue("Name")
		if !identifierRE.MatchString(nn) {
			msg := fmt.Sprintf("Invalid identifier %q !~ %q", nn, identifierRE)
			log.Printf(msg)
			http.Error(w, msg, http.StatusBadRequest)
			return
		}

		ci, err := strconv.Atoi(r.FormValue("Cap"))
		if err != nil {
			log.Printf("Capacity is not an integer: %v", err)
			http.Error(w, "Capacity is not an integer", http.StatusBadRequest)
			return
		}
		if ci < 0 {
			log.Printf("Must specify nonnegative capacity [%d < 0]", ci)
			http.Error(w, "Capacity must be non-negative", http.StatusBadRequest)
			return
		}

		// ...update...
		e.Type = r.FormValue("Type")
		e.Cap = ci

		// Do name changes last since they cause a redirect.
		if nn == e.Name {
			break
		}
		delete(g.Channels, e.Name)
		e.Name = nn
		g.Channels[nn] = e
		http.Redirect(w, r, "/channel/"+nn, http.StatusSeeOther) // should cause GET
		return
	}

	if err := g.renderChannelEditor(w, e); err != nil {
		log.Printf("Could not render source editor: %v", err)
		http.Error(w, "Could not render source editor", http.StatusInternalServerError)
		return
	}
	return
}

func (g *Graph) handleNodeRequest(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s", r.Method, r.URL)
	nm := strings.TrimPrefix(r.URL.Path, "/node/")
	n, found := g.Nodes[nm]
	if !found {
		http.Error(w, fmt.Sprintf("Node %q not found", nm), http.StatusNotFound)
		return
	}

	switch r.Method {
	case "POST":
		// Update the node.
		if err := r.ParseForm(); err != nil {
			log.Printf("Could not parse form: %v", err)
			http.Error(w, "Could not parse", http.StatusBadRequest)
			return
		}

		nm := strings.TrimSpace(r.FormValue("Name"))
		if nm == "" {
			log.Printf("Name invalid [%q == \"\"]", nm)
			http.Error(w, "Name invalid", http.StatusBadRequest)
			return
		}

		n.Wait = (r.FormValue("Wait") == "on")
		n.Code = r.FormValue("Code")

		if err := n.updateChans(g.Channels); err != nil {
			log.Printf("Unable to extract channels used from code: %v", err)
			http.Error(w, "Unable to extract channels used from code", http.StatusBadRequest)
			return
		}

		if nm == n.Name {
			break
		}

		delete(g.Nodes, n.Name)
		n.Name = nm
		g.Nodes[nm] = n

		http.Redirect(w, r, "/node/"+nm, http.StatusSeeOther) // should cause GET
		return
	}

	if err := g.renderNodeEditor(w, n); err != nil {
		log.Printf("Could not render source editor: %v", err)
		http.Error(w, "Could not render source editor", http.StatusInternalServerError)
		return
	}
	return
}

func (g *Graph) outputDotSrc(w http.ResponseWriter) {
	h := w.Header()
	h.Set("Content-Type", "text/vnd.graphviz")
	if err := g.renderToDot(w); err != nil {
		log.Printf("Could not render to dot: %v", err)
		http.Error(w, "Could not render to dot", http.StatusInternalServerError)
	}
}

func (g *Graph) writeGoSrc(w io.Writer) error {
	buf := &bytes.Buffer{}
	if err := g.renderToGo(buf); err != nil {
		return err
	}
	return goimports(w, buf)
}

func (g *Graph) outputGoSrc(w http.ResponseWriter) {
	h := w.Header()
	h.Set("Content-Type", "text/golang")
	if err := g.writeGoSrc(w); err != nil {
		log.Printf("Could not render to Go: %v", err)
		http.Error(w, "Could not render to Go", http.StatusInternalServerError)
	}
}

func (g *Graph) outputJSON(w http.ResponseWriter) {
	h := w.Header()
	h.Set("Content-Type", "application/json")
	if err := json.NewEncoder(w).Encode(g); err != nil {
		log.Printf("Could not encode JSON: %v", err)
		http.Error(w, "Could not encode JSON", http.StatusInternalServerError)
		return
	}
}

func (g *Graph) handleRootRequest(w http.ResponseWriter, r *http.Request) {
	log.Printf("%s %s", r.Method, r.URL)
	q := r.URL.Query()
	if _, t := q["dot"]; t {
		g.outputDotSrc(w)
		return
	}
	if _, t := q["go"]; t {
		g.outputGoSrc(w)
		return
	}
	if _, t := q["json"]; t {
		g.outputJSON(w)
		return
	}
	if _, t := q["run"]; t {
		if err := g.saveBuildAndRun(); err != nil {
			log.Printf("Failed to save, build, run: %v", err)
		}
	}

	var dot, svg bytes.Buffer
	if err := g.renderToDot(&dot); err != nil {
		log.Printf("Could not render to dot: %v", err)
		http.Error(w, "Could not render to dot", http.StatusInternalServerError)
	}
	if err := dotToSVG(&svg, &dot); err != nil {
		log.Printf("Could not render dot to SVG: %v", err)
		http.Error(w, "Could not render dot to SVG", http.StatusInternalServerError)
	}
	if err := rootTemplate.Execute(w, template.HTML(svg.String())); err != nil {
		log.Printf("Could not execute root template: %v", err)
		http.Error(w, "Could not execute root template", http.StatusInternalServerError)
	}
}

func (g *Graph) saveGoSrc() error {
	gopath, ok := os.LookupEnv("GOPATH")
	if !ok || gopath == "" {
		return errors.New("cannot use $GOPATH; empty or undefined")
	}
	pp := filepath.Join(gopath, "src", g.PackagePath)
	if err := os.Mkdir(pp, os.FileMode(0755)); err != nil {
		log.Printf("Could not make path %q, continuing: %v", pp, err)
	}
	mp := filepath.Join(pp, "main.go")
	f, err := os.Create(mp)
	if err != nil {
		return err
	}
	defer f.Close()
	if err := g.writeGoSrc(f); err != nil {
		return err
	}
	return f.Close()
}

func (g *Graph) build() error {
	return exec.Command(`go`, `build`, g.PackagePath).Run()
}

func (g *Graph) saveBuildAndRun() error {
	if err := g.saveGoSrc(); err != nil {
		return err
	}
	if err := g.build(); err != nil {
		return err
	}
	// TODO: Be less lazy about the output binary path
	return open("./" + g.PackageName)
}

func openWhenUp(addr string) {
	base := fmt.Sprintf("http://%s/", addr)
	t := time.NewTicker(100 * time.Millisecond)
	for range t.C {
		resp, err := http.Get(base + "ping")
		if err != nil {
			continue
		}
		defer resp.Body.Close()
		msg, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			continue
		}
		if string(msg) != pingMsg {
			continue
		}
		open(base)
		t.Stop()
		return
	}
}

func main() {
	flag.Parse()
	addr := net.JoinHostPort(*serveAddr, strconv.Itoa(*servePort))

	http.HandleFunc("/channel/", exampleGraph.handleChannelRequest)
	http.HandleFunc("/node/", exampleGraph.handleNodeRequest)
	http.HandleFunc("/", exampleGraph.handleRootRequest)
	http.HandleFunc("/ping", func(w http.ResponseWriter, _ *http.Request) {
		fmt.Fprintf(w, pingMsg)
	})
	http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s", r.Method, r.URL)
		// TODO: serve a favicon properly
		http.Redirect(w, r, "http://golang.org/favicon.ico", http.StatusFound)
	})

	// As soon as we're serving, launch a web browser.
	// Generally expected to work on macOS...
	go openWhenUp(addr)

	if err := http.ListenAndServe(addr, nil); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/gin-gonic/contrib/static"
	"github.com/gin-gonic/gin"
	"github.com/kavkaz/pavo/attachment"
	"github.com/kavkaz/pavo/upload"
)

func main() {
	flag.Parse()

	r := gin.Default()
	r.Use(CORSMiddleware())
	r.Use(static.Serve(*storage))

	r.POST("/files", CreateAttachment)

	log.Printf("Storage place in: %s", *storage)
	log.Printf("Start server on %s", *host)
	r.Run(*host)

}

func CreateAttachment(c *gin.Context) {
	converts, err := GetConvertParams(c.Request)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"status": "error",
			"error":  fmt.Sprintf("Query params: %s", err),
		})
		return
	}
	converts["original"] = ""

	c.Request.AddCookie(&http.Cookie{Name: "pavo", Value: "huj"})

	files, err := upload.Process(c.Request, *storage)
	if err == upload.Incomplete {
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
			"file":   gin.H{"size": files[0].Size},
		})
		return
	}
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"status": "error",
			"error":  fmt.Sprintf("Upload error: %q", err.Error()),
		})
		return
	}

	data := make([]map[string]interface{}, 0)
	for _, ofile := range files {
		attachment, err := attachment.Create(*storage, ofile, converts)
		if err != nil {
			data = append(data, map[string]interface{}{
				"name":  ofile.Filename,
				"size":  ofile.Size,
				"error": err.Error(),
			})
			continue
		}
		data = append(data, attachment.ToJson())
	}

	c.JSON(http.StatusCreated, gin.H{"status": "ok", "files": data})

}

// Get parameters for convert from Request query string
func GetConvertParams(req *http.Request) (map[string]string, error) {
	raw_converts := req.URL.Query().Get("converts")

	if raw_converts == "" {
		raw_converts = "{}"
	}

	convert := make(map[string]string)

	err := json.Unmarshal([]byte(raw_converts), &convert)
	if err != nil {
		return nil, err
	}

	return convert, nil
}

func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		//c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set(
			"Access-Control-Allow-Methods",
			"POST, GET, OPTIONS, PUT, PATCH, DELETE")
		c.Writer.Header().Set(
			"Access-Control-Allow-Headers",
			"Content-Type, Content-Length, Accept-Encoding, Content-Range, Content-Disposition, Authorization")
		if c.Request.Method == "OPTIONS" {
			c.Abort(200)
			return
		}
		// c.Next()
	}
}
<commit_msg>closes #3 Set cookie<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"
	"time"

	"code.google.com/p/go-uuid/uuid"

	"github.com/gin-gonic/contrib/static"
	"github.com/gin-gonic/gin"
	"github.com/kavkaz/pavo/attachment"
	"github.com/kavkaz/pavo/upload"
)

func main() {
	flag.Parse()

	r := gin.Default()
	r.Use(CORSMiddleware())
	r.Use(static.Serve(*storage))

	r.POST("/files", CreateAttachment)

	log.Printf("Storage place in: %s", *storage)
	log.Printf("Start server on %s", *host)
	r.Run(*host)

}

func CreateAttachment(c *gin.Context) {
	converts, err := GetConvertParams(c.Request)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"status": "error",
			"error":  fmt.Sprintf("Query params: %s", err),
		})
		return
	}
	converts["original"] = ""

	pavo, _ := c.Request.Cookie("pavo")
	if pavo == nil {
		pavo = &http.Cookie{
			Name:    "pavo",
			Value:   uuid.New(),
			Expires: time.Now().Add(10 * 356 * 24 * time.Hour),
			Path:    "/",
		}
		c.Request.AddCookie(pavo)
		http.SetCookie(c.Writer, pavo)
	}

	files, err := upload.Process(c.Request, *storage)
	if err == upload.Incomplete {
		c.JSON(http.StatusOK, gin.H{
			"status": "ok",
			"file":   gin.H{"size": files[0].Size},
		})
		return
	}
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"status": "error",
			"error":  fmt.Sprintf("Upload error: %q", err.Error()),
		})
		return
	}

	data := make([]map[string]interface{}, 0)
	for _, ofile := range files {
		attachment, err := attachment.Create(*storage, ofile, converts)
		if err != nil {
			data = append(data, map[string]interface{}{
				"name":  ofile.Filename,
				"size":  ofile.Size,
				"error": err.Error(),
			})
			continue
		}
		data = append(data, attachment.ToJson())
	}

	c.JSON(http.StatusCreated, gin.H{"status": "ok", "files": data})

}

// Get parameters for convert from Request query string
func GetConvertParams(req *http.Request) (map[string]string, error) {
	raw_converts := req.URL.Query().Get("converts")

	if raw_converts == "" {
		raw_converts = "{}"
	}

	convert := make(map[string]string)

	err := json.Unmarshal([]byte(raw_converts), &convert)
	if err != nil {
		return nil, err
	}

	return convert, nil
}

func CORSMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		//c.Writer.Header().Set("Content-Type", "application/json")
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set(
			"Access-Control-Allow-Methods",
			"POST, GET, OPTIONS, PUT, PATCH, DELETE")
		c.Writer.Header().Set(
			"Access-Control-Allow-Headers",
			"Content-Type, Content-Length, Accept-Encoding, Content-Range, Content-Disposition, Authorization")
		if c.Request.Method == "OPTIONS" {
			c.Abort(200)
			return
		}
		// c.Next()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/url"
	"os"

	"github.com/whyrusleeping/ipfs-shell"
)

func usage() {
	fmt.Fprint(os.Stderr, "usage: git-remote-ipfs <repository> [<URL>]\n")
	os.Exit(2)
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("git-remote-ipfs: ")

	var u string
	v := len(os.Args[1:])
	switch v {
	case 2:
		log.Println("remote?:", os.Args[1])
		log.Println("url:", os.Args[2])
		u = os.Args[2]

	default:
		log.Fatalf("unkonw # of args: %d", v)
	}

	repoUrl, err := url.Parse(u)
	if err != nil {
		log.Fatalf("url.Parse() failed: %s", err)
	}
	log.Printf("dbg: repo url %#v", repoUrl)

	shell := shell.NewShell("http://localhost:5001")

	shell.Get(fmt.Sprintf("/ipfs/%s/%s", repoUrl.Host, repoUrl.Path))

}
<commit_msg>some progress<commit_after>// git-remote-helper implements a git-remote helper that uses the ipfs transport
//
// ie: git clone ipfs://$some/path/to/.git
//
// see https://git-scm.com/docs/gitremote-helpers for more
package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"log"
	"net/url"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"github.com/cryptix/go/debug"
	"github.com/whyrusleeping/ipfs-shell"
)

const usageMsg = `usage git-remote-ipfs <repository> [<URL>]
supports ipfs://$hash/path..

TODO:
- urls like ipfs::/path/
`

func usage() {
	fmt.Fprint(os.Stderr, usageMsg)
	os.Exit(2)
}

var tmpBareRepo string

func main() {
	log.SetFlags(0)
	log.SetOutput(os.Stderr)
	log.SetPrefix("git-remote-ipfs: ")

	//log.Println("Hello", os.Environ())

	var u string
	v := len(os.Args[1:])
	switch v {
	case 2:
		log.Println("repo:", os.Args[1])
		log.Println("url:", os.Args[2])
		u = os.Args[2]

	default:
		log.Fatalf("usage: unkonw # of args: %d", v)
	}

	repoUrl, err := url.Parse(u)
	if err != nil {
		log.Fatalf("url.Parse() failed: %s", err)
	}
	log.Printf("dbg: repo url %#v", repoUrl)

	if repoUrl.Scheme != "ipfs" {
		log.Fatal("only ipfs schema is supported")
	}

	// get root hash of the passed repo path
	path := fmt.Sprintf("/ipfs/%s/%s", repoUrl.Host, repoUrl.Path)
	var b bytes.Buffer
	if err := Execute(&b,
		exec.Command("ipfs", "object", "get", path),
		exec.Command("ipfs", "object", "put", "--inputenc=json"),
	); err != nil {
		log.Fatalln("root hash pipe failed", err)
	}

	hash := b.String()
	const expAdded = "added "
	if !strings.HasPrefix(hash, expAdded) {
		log.Fatal("invalid output of root-hash-pipe, expected: %s got: %s", expAdded, hash)
	}
	hash = hash[len(expAdded):]
	log.Println("root hash: ", hash)

	tmpBareRepo = fetchRepo(hash)

	go speakGit(os.Stdin)

	select {}
}

func fetchRepo(root string) string {
	// TODO: document host format
	shell := shell.NewShell("localhost:5001")

	tmpPath := filepath.Join("/", os.TempDir(), root)
	s, err := os.Stat(tmpPath)
	if err != nil {
		if os.IsNotExist(err) {
			if err := shell.Get(root, tmpPath); err != nil {
				log.Fatalf("shell.Get(%s, %s) failed: %s", root, tmpPath, err)
			}
			log.Println("shell got:", root)
			return tmpPath
		}
		log.Fatalf("stat err: %s", err)
	}
	if !s.IsDir() {
		log.Fatalf("please delete %s")
	}
	return tmpPath
}

// speakGit acts like a git-remote-helper
// see this for more: https://www.kernel.org/pub/software/scm/git/docs/gitremote-helpers.html
func speakGit(r io.Reader) {
	r = debug.NewReadLogger("from git:", r)
	w := debug.NewWriteLogger("to git:", os.Stdout)
	scanner := bufio.NewScanner(r)
	for scanner.Scan() {
		text := scanner.Text()
		switch {
		case text == "capabilities":
			log.Println("caps line")
			fmt.Fprintf(w, "fetch\n\n")

		case text == "list":
			log.Println("list line")

			var b bytes.Buffer
			log.Println("tmp repo:", tmpBareRepo)
			cmd := exec.Command("git", "ls-remote", tmpBareRepo)
			cmd.Stdout = &b
			cmd.Stderr = &b

			if err := cmd.Run(); err != nil {
				log.Fatalf("git ls-remote wait error: %s", err)
			}

			log.Println("ran git ls-remote")
			tabToSpace := strings.NewReplacer("\t", " ")
			_, err := tabToSpace.WriteString(w, b.String())
			if err != nil {
				log.Fatalf("git ls-remote tabWriter error: %s", err)
			}
			fmt.Fprintln(w, "")

		case strings.HasPrefix(text, "fetch "):
			fetchSplit := strings.Split(text, " ")
			log.Printf("fetch sha1<%s> name<%s>", fetchSplit[1], fetchSplit[2])

		default:
			log.Println("default git speak:", text)
			os.Exit(1)
		}
	}

	if err := scanner.Err(); err != nil {
		log.Fatalf("stdin scanner error: %s", err)
	}
}

// shamefully taken from https://gist.github.com/tyndyll/89fbb2c2273f83a074dc
func Execute(output_buffer *bytes.Buffer, stack ...*exec.Cmd) (err error) {
	var error_buffer bytes.Buffer
	pipe_stack := make([]*io.PipeWriter, len(stack)-1)
	i := 0
	for ; i < len(stack)-1; i++ {
		stdin_pipe, stdout_pipe := io.Pipe()
		stack[i].Stdout = stdout_pipe
		stack[i].Stderr = &error_buffer
		stack[i+1].Stdin = stdin_pipe
		pipe_stack[i] = stdout_pipe
	}
	stack[i].Stdout = output_buffer
	stack[i].Stderr = &error_buffer

	if err := call(stack, pipe_stack); err != nil {
		log.Fatalln(string(error_buffer.Bytes()), err)
	}
	return err
}

func call(stack []*exec.Cmd, pipes []*io.PipeWriter) (err error) {
	if stack[0].Process == nil {
		if err = stack[0].Start(); err != nil {
			return err
		}
	}
	if len(stack) > 1 {
		if err = stack[1].Start(); err != nil {
			return err
		}
		defer func() {
			if err == nil {
				pipes[0].Close()
				err = call(stack[1:], pipes[1:])
			}
		}()
	}
	return stack[0].Wait()
}
<|endoftext|>


<commit_before>package main

func main() {
	py := NewProxy("localhost:9000")
	py.Serve()
}
<commit_msg>Add profiling.<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"runtime/pprof"
)

var c = make(chan os.Signal, 1)

var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")

func main() {
	flag.Parse()
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		signal.Notify(c, os.Interrupt)
		go func() {
			for sig := range c {
				info.Printf("captured %v, stopping profiler and exiting..", sig)
				pprof.StopCPUProfile()
				os.Exit(0)
			}
		}()
	}

	py := NewProxy("localhost:9000")
	py.Serve()
}
<|endoftext|>


<commit_before>package errors

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
)

type _errorh struct {
	ErrStatus      string `json:"status"`
	ErrMessage     string `json:"message"`
	ErrMessageCode string `json:"message_code"`
	ErrCode        int    `json:"code"`
	*stack         `json:"-"`
}

func (e _errorh) Error() string { return e.ErrMessageCode + ": " + e.ErrMessage }

func (e _errorh) Status() string { return e.ErrStatus }

func (e _errorh) Code() int { return e.ErrCode }

func (e _errorh) Message() string { return e.ErrMessage }

func (e _errorh) MessageCode() string { return e.ErrMessageCode }

func (e _errorh) JSONError() error {
	b, _ := json.Marshal(e)
	return errors.New(string(b))
}

func (e _errorh) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			io.WriteString(s, e.ErrMessage)
			fmt.Fprintf(s, "%+v", e.StackTrace())
			return
		}
		fallthrough
	case 's':
		io.WriteString(s, e.ErrMessage)
	}
}

// New returns an error with the supplied message.
func Newh(code int, messageCode, message string) error {
	return _errorh{
		http.StatusText(code),
		message,
		messageCode,
		code,
		callers(),
	}
}

// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
func Errorhf(code int, messageCode, format string, args ...interface{}) error {
	return _errorh{
		http.StatusText(code),
		fmt.Sprintf(format, args...),
		messageCode,
		code,
		callers(),
	}
}

func ParseJSON(err string) _errorh {
	e := _errorh{}
	errr := json.Unmarshal([]byte(err), &e)
	if errr != nil {
		e.ErrStatus = http.StatusText(500)
		e.ErrMessage = errr.Error()
		e.ErrMessageCode = "JSON"
		e.ErrCode = 500
		e.stack = callers()
	}

	e.stack = callers()
	return e
}

func BadRequest(messageCode, message string) error {
	return &_errorh{
		http.StatusText(400),
		message,
		messageCode,
		400,
		callers(),
	}
}

func Unauthorized(messageCode, message string) error {
	return &_errorh{
		http.StatusText(401),
		message,
		messageCode,
		401,
		callers(),
	}
}

func Forbidden(messageCode, message string) error {
	return &_errorh{
		http.StatusText(403),
		message,
		messageCode,
		403,
		callers(),
	}
}

func NotFound(messageCode, message string) error {
	return &_errorh{
		http.StatusText(404),
		message,
		messageCode,
		404,
		callers(),
	}
}

func InternalServerError(messageCode, message string) error {
	return &_errorh{
		http.StatusText(500),
		message,
		messageCode,
		500,
		callers(),
	}
}
<commit_msg>update<commit_after>package errors

import (
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
)

type _errorh struct {
	ErrStatus  string `json:"status"`
	ErrMessage string `json:"message"`
	ErrCode    int    `json:"code"`
	*stack     `json:"-"`
}

func (e _errorh) Error() string { return e.ErrMessage }

func (e _errorh) Status() string { return e.ErrStatus }

func (e _errorh) Code() int { return e.ErrCode }

func (e _errorh) Message() string { return e.ErrMessage }

func (e _errorh) JSONError() error {
	b, _ := json.Marshal(e)
	return errors.New(string(b))
}

func (e _errorh) Format(s fmt.State, verb rune) {
	switch verb {
	case 'v':
		if s.Flag('+') {
			io.WriteString(s, e.ErrMessage)
			fmt.Fprintf(s, "%+v", e.StackTrace())
			return
		}
		fallthrough
	case 's':
		io.WriteString(s, e.ErrMessage)
	}
}

// New returns an error with the supplied message.
func Newh(code int, message string) error {
	return _errorh{
		http.StatusText(code),
		message,
		code,
		callers(),
	}
}

// Errorf formats according to a format specifier and returns the string
// as a value that satisfies error.
func Errorhf(code int, format string, args ...interface{}) error {
	return _errorh{
		http.StatusText(code),
		fmt.Sprintf(format, args...),
		code,
		callers(),
	}
}

func ParseJSON(err string) _errorh {
	e := _errorh{}
	errr := json.Unmarshal([]byte(err), &e)
	if errr != nil {
		e.ErrStatus = http.StatusText(500)
		e.ErrMessage = errr.Error()
		e.ErrCode = 500
		e.stack = callers()
	}

	e.stack = callers()
	return e
}

func BadRequest(message string) error {
	return &_errorh{
		http.StatusText(400),
		message,
		400,
		callers(),
	}
}

func Unauthorized(message string) error {
	return &_errorh{
		http.StatusText(401),
		message,
		401,
		callers(),
	}
}

func Forbidden(message string) error {
	return &_errorh{
		http.StatusText(403),
		message,
		403,
		callers(),
	}
}

func NotFound(message string) error {
	return &_errorh{
		http.StatusText(404),
		message,
		404,
		callers(),
	}
}

func InternalServerError(message string) error {
	return &_errorh{
		http.StatusText(500),
		message,
		500,
		callers(),
	}
}
<|endoftext|>


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

package floats

import (
	"errors"
	"math"
)

// Add returns the element-wise sum of all the slices with the
// results stored in the first slice.
// For computational efficiency, it is assumed that all of
// the variadic arguments have the same length. If this is
// in doubt, EqLen can be used.
func Add(dst []float64, slices ...[]float64) []float64 {
	if len(slices) == 0 {
		return nil
	}
	if len(dst) != len(slices[0]) {
		panic("floats: length of destination does not match length of the slices")
	}
	for _, slice := range slices {
		for j, val := range slice {
			dst[j] += val
		}
	}
	return dst
}

// AddConst adds the value c to all of the values in s
func AddConst(c float64, s []float64) {
	for i := range s {
		s[i] += c
	}
}

// ApplyFunc applies a function f (math.Exp, math.Sin, etc.) to every element
// of the slice s
func Apply(f func(float64) float64, s []float64) {
	for i, val := range s {
		s[i] = f(val)
	}
}

// Count applies the function f to every element of s and returns the number
// of times the function returned true
func Count(f func(float64) bool, s []float64) int {
	var n int
	for _, val := range s {
		if f(val) {
			n++
		}
	}
	return n
}

// Cumprod finds the cumulative product of the first i elements in
// s and puts them in place into the ith element of the
// destination. Panic will occur if lengths of do not match
func CumProd(dst, s []float64) []float64 {
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of the source")
	}
	dst[0] = s[0]
	for i := 1; i < len(s); i++ {
		dst[i] = dst[i-1] * s[i]
	}
	return dst
}

// Cumsum finds the cumulative sum of the first i elements in
// s and puts them in place into the ith element of the
// destination. Panic will occur if lengths of arguments do not match
func CumSum(dst, s []float64) []float64 {
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of the source")
	}
	dst[0] = s[0]
	for i := 1; i < len(s); i++ {
		dst[i] = dst[i-1] + s[i]
	}
	return dst
}

// Dot computes the dot product of s1 and s2, i.e.
// sum_{i = 1}^N s1[i]*s2[i]
// Panic will occur if lengths of arguments do not match
func Dot(s1, s2 []float64) float64 {
	if len(s1) != len(s2) {
		panic("floats: lengths of the slices do not match")
	}
	var sum float64
	for i, val := range s1 {
		sum += val * s2[i]
	}
	return sum
}

// Eq returns false if the slices have different lengths
// or if |s1[i] - s2[i]| > tol for any i.
func Eq(s1, s2 []float64, tol float64) bool {
	if len(s1) != len(s2) {
		return false
	}
	for i, val := range s1 {
		if math.Abs(s2[i]-val) > tol {
			return false
		}
	}
	return true
}

// Eqlen returns true if all of the slices have equal length,
// and false otherwise. Returns true if there are no input slices
func EqLen(slices ...[]float64) bool {
	// This length check is needed: http://play.golang.org/p/sdty6YiLhM
	if len(slices) == 0 {
		return true
	}
	l := len(slices[0])
	for i := 1; i < len(slices); i++ {
		if len(slices[i]) != l {
			return false
		}
	}
	return true
}

// Find applies f to every element of s and returns the first
// k elements for which the f returns true, or all such elements
// if k < 0.
// Find will reslice inds to have 0 length, and will append
// found indices to inds.
// If k > 0 and there are fewer than k elements in s satisfying f,
// all of the found elements will be returned along with an error
func Find(inds []int, f func(float64) bool, s []float64, k int) ([]int, error) {

	// inds is also returned to allow for calling with nil

	// Reslice inds to have zero length
	inds = inds[:0]

	// If zero elements requested, can just return
	if k == 0 {
		return inds, nil
	}

	// If k < 0, return all of the found indices
	if k < 0 {
		for i, val := range s {
			if f(val) {
				inds = append(inds, i)
			}
		}
		return inds, nil
	}

	// Otherwise, find the first k elements
	nFound := 0
	for i, val := range s {
		if f(val) {
			inds = append(inds, i)
			nFound++
			if nFound == k {
				return inds, nil
			}
		}
	}
	// Finished iterating over the loop, which means k elements were not found
	return inds, errors.New("floats: insufficient elements found")
}

// LogSpan returns a set of n equally spaced points in log space between,
// l and u where N is equal to len(dst). The first element of the
// resulting dst will be l and the final element of dst will be u.
// Panics if len(dst) < 2
// Note that this call will return NaNs if either l or u are negative, and
// will return all zeros if l or u is zero.
func LogSpan(dst []float64, l, u float64) []float64 {
	Span(dst, math.Log(l), math.Log(u))
	Apply(math.Exp, dst)
	return dst
}

// Logsumexp returns the log of the sum of the exponentials of the values in s
func LogSumExp(s []float64) (lse float64) {
	// Want to do this in a numerically stable way which avoids
	// overflow and underflow
	// First, find the maximum value in the slice.
	maxval, _ := Max(s)
	if math.IsInf(maxval, 0) {
		// If it's infinity either way, the logsumexp will be infinity as well
		// returning now avoids NaNs
		return maxval
	}
	// Compute the sumexp part
	for _, val := range s {
		lse += math.Exp(val - maxval)
	}
	// Take the log and add back on the constant taken out
	lse = math.Log(lse) + maxval
	return lse
}

// Max returns the maximum value in the slice and the location of
// the maximum value. If the input slice is empty, the code will panic
func Max(s []float64) (max float64, ind int) {
	max = s[0]
	ind = 0
	for i, val := range s {
		if val > max {
			max = val
			ind = i
		}
	}
	return max, ind
}

// Min returns the minimum value in the slice and the index of
// the minimum value. If the input slice is empty, zero is returned
// as the minimum value and -1 is returned as the index.
func Min(s []float64) (min float64, ind int) {
	min = s[0]
	ind = 0
	for i, val := range s {
		if val < min {
			min = val
			ind = i
		}
	}
	return min, ind
}

// Nearest returns the index of the element in s
// whose value is nearest to v.  If several such
// elements exist, the lowest index is returned
func Nearest(s []float64, v float64) (ind int) {
	dist := math.Abs(v - s[0])
	ind = 0
	for i, val := range s {
		newDist := math.Abs(v - val)
		if newDist < dist {
			dist = newDist
			ind = i
		}
	}
	return
}

// NearestInSpan return the index of a hypothetical vector created
// by Span with length n and bounds l and u whose value is closest
// to v. Assumes u > l. If the value is greater than u or less than
// l, the function will panic.
func NearestWithinSpan(n int, l, u float64, v float64) int {
	if v < l || v > u {
		panic("floats: value outside span bounds")
	}

	// Can't guarantee anything about exactly halfway between
	// because of floating point weirdness
	return int((float64(n)-1)/(u-l)*(v-l) + 0.5)
}

// Norm returns the L norm of the slice S, defined as
// (sum_{i=1}^N s[i]^N)^{1/N}
// Special cases:
// L = math.Inf(1) gives the maximum value
// Does not correctly compute the zero norm (use Count)
func Norm(s []float64, L float64) (norm float64) {
	// Should this complain if L is not positive?
	// Should this be done in log space for better numerical stability?
	//	would be more cost
	//	maybe only if L is high?
	if L == 2 {
		for _, val := range s {
			norm += val * val
		}
		return math.Pow(norm, 0.5)
	}
	if L == 1 {
		for _, val := range s {
			norm += math.Abs(val)
		}
		return norm
	}
	if math.IsInf(L, 1) {
		norm, _ = Max(s)
		return norm
	}
	for _, val := range s {
		norm += math.Pow(math.Abs(val), L)
	}
	return math.Pow(norm, 1/L)
}

// Prod returns the product of the elements of the slice
// Returns 1 if len(s) = 0
func Prod(s []float64) (prod float64) {
	prod = 1
	for _, val := range s {
		prod *= val
	}
	return prod
}

// Scale multiplies every element in s by c
func Scale(c float64, s []float64) {
	for i := range s {
		s[i] *= c
	}
}

// Span returns a set of N equally spaced points between l and u, where N
// is equal to the length of the destination. The first element of the destination
// is l, the final element of the destination is u.
// Panics if len(dst) < 2
func Span(dst []float64, l, u float64) []float64 {
	n := len(dst)
	if n < 2 {
		panic("floats: destination must have length >1")
	}
	step := (u - l) / float64(n-1)
	for i := range dst {
		dst[i] = l + step*float64(i)
	}
	return dst
}

// Sub subtracts, element-wise, the first argument from the second. Assumes
// the lengths of s and t match (can be tested with EqLen)
func Sub(s, t []float64) {
	if len(s) != len(t) {
		panic("floats: length of the slices do not match")
	}
	for i, val := range t {
		s[i] -= val
	}
}

// SubTo subtracts, element-wise, the first argument from the second and
// stores the result in dest. Panics if the lengths of s and t do not match
func SubTo(dst, s, t []float64) []float64 {
	if len(s) != len(t) {
		panic("floats: length of subtractor and subtractee do not match")
	}
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of subtractor")
	}
	for i, val := range t {
		dst[i] = s[i] - val
	}
	return dst
}

// Sum returns the sum of the elements of the slice
func Sum(s []float64) (sum float64) {
	for _, val := range s {
		sum += val
	}
	return
}
<commit_msg>Added Mul function<commit_after>// Copyright 2013 The Gonum Authors. All rights reserved.
// Use of this code is governed by a BSD-style
// license that can be found in the LICENSE file

package floats

import (
	"errors"
	"math"
)

// Add returns the element-wise sum of all the slices with the
// results stored in the first slice.
// For computational efficiency, it is assumed that all of
// the variadic arguments have the same length. If this is
// in doubt, EqLen can be used.
func Add(dst []float64, slices ...[]float64) []float64 {
	if len(slices) == 0 {
		return nil
	}
	if len(dst) != len(slices[0]) {
		panic("floats: length of destination does not match length of the slices")
	}
	for _, slice := range slices {
		for j, val := range slice {
			dst[j] += val
		}
	}
	return dst
}

// AddConst adds the value c to all of the values in s
func AddConst(c float64, s []float64) {
	for i := range s {
		s[i] += c
	}
}

// ApplyFunc applies a function f (math.Exp, math.Sin, etc.) to every element
// of the slice s
func Apply(f func(float64) float64, s []float64) {
	for i, val := range s {
		s[i] = f(val)
	}
}

// Count applies the function f to every element of s and returns the number
// of times the function returned true
func Count(f func(float64) bool, s []float64) int {
	var n int
	for _, val := range s {
		if f(val) {
			n++
		}
	}
	return n
}

// Cumprod finds the cumulative product of the first i elements in
// s and puts them in place into the ith element of the
// destination. Panic will occur if lengths of do not match
func CumProd(dst, s []float64) []float64 {
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of the source")
	}
	dst[0] = s[0]
	for i := 1; i < len(s); i++ {
		dst[i] = dst[i-1] * s[i]
	}
	return dst
}

// Cumsum finds the cumulative sum of the first i elements in
// s and puts them in place into the ith element of the
// destination. Panic will occur if lengths of arguments do not match
func CumSum(dst, s []float64) []float64 {
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of the source")
	}
	dst[0] = s[0]
	for i := 1; i < len(s); i++ {
		dst[i] = dst[i-1] + s[i]
	}
	return dst
}

// Dot computes the dot product of s1 and s2, i.e.
// sum_{i = 1}^N s1[i]*s2[i]
// Panic will occur if lengths of arguments do not match
func Dot(s1, s2 []float64) float64 {
	if len(s1) != len(s2) {
		panic("floats: lengths of the slices do not match")
	}
	var sum float64
	for i, val := range s1 {
		sum += val * s2[i]
	}
	return sum
}

// Eq returns false if the slices have different lengths
// or if |s1[i] - s2[i]| > tol for any i.
func Eq(s1, s2 []float64, tol float64) bool {
	if len(s1) != len(s2) {
		return false
	}
	for i, val := range s1 {
		if math.Abs(s2[i]-val) > tol {
			return false
		}
	}
	return true
}

// Eqlen returns true if all of the slices have equal length,
// and false otherwise. Returns true if there are no input slices
func EqLen(slices ...[]float64) bool {
	// This length check is needed: http://play.golang.org/p/sdty6YiLhM
	if len(slices) == 0 {
		return true
	}
	l := len(slices[0])
	for i := 1; i < len(slices); i++ {
		if len(slices[i]) != l {
			return false
		}
	}
	return true
}

// Find applies f to every element of s and returns the first
// k elements for which the f returns true, or all such elements
// if k < 0.
// Find will reslice inds to have 0 length, and will append
// found indices to inds.
// If k > 0 and there are fewer than k elements in s satisfying f,
// all of the found elements will be returned along with an error
func Find(inds []int, f func(float64) bool, s []float64, k int) ([]int, error) {

	// inds is also returned to allow for calling with nil

	// Reslice inds to have zero length
	inds = inds[:0]

	// If zero elements requested, can just return
	if k == 0 {
		return inds, nil
	}

	// If k < 0, return all of the found indices
	if k < 0 {
		for i, val := range s {
			if f(val) {
				inds = append(inds, i)
			}
		}
		return inds, nil
	}

	// Otherwise, find the first k elements
	nFound := 0
	for i, val := range s {
		if f(val) {
			inds = append(inds, i)
			nFound++
			if nFound == k {
				return inds, nil
			}
		}
	}
	// Finished iterating over the loop, which means k elements were not found
	return inds, errors.New("floats: insufficient elements found")
}

// LogSpan returns a set of n equally spaced points in log space between,
// l and u where N is equal to len(dst). The first element of the
// resulting dst will be l and the final element of dst will be u.
// Panics if len(dst) < 2
// Note that this call will return NaNs if either l or u are negative, and
// will return all zeros if l or u is zero.
func LogSpan(dst []float64, l, u float64) []float64 {
	Span(dst, math.Log(l), math.Log(u))
	Apply(math.Exp, dst)
	return dst
}

// Logsumexp returns the log of the sum of the exponentials of the values in s
func LogSumExp(s []float64) (lse float64) {
	// Want to do this in a numerically stable way which avoids
	// overflow and underflow
	// First, find the maximum value in the slice.
	maxval, _ := Max(s)
	if math.IsInf(maxval, 0) {
		// If it's infinity either way, the logsumexp will be infinity as well
		// returning now avoids NaNs
		return maxval
	}
	// Compute the sumexp part
	for _, val := range s {
		lse += math.Exp(val - maxval)
	}
	// Take the log and add back on the constant taken out
	lse = math.Log(lse) + maxval
	return lse
}

// Max returns the maximum value in the slice and the location of
// the maximum value. If the input slice is empty, the code will panic
func Max(s []float64) (max float64, ind int) {
	max = s[0]
	ind = 0
	for i, val := range s {
		if val > max {
			max = val
			ind = i
		}
	}
	return max, ind
}

// Min returns the minimum value in the slice and the index of
// the minimum value. If the input slice is empty, zero is returned
// as the minimum value and -1 is returned as the index.
func Min(s []float64) (min float64, ind int) {
	min = s[0]
	ind = 0
	for i, val := range s {
		if val < min {
			min = val
			ind = i
		}
	}
	return min, ind
}

// Mul performs element-wise multiplication between s
// and t and stores the value in s. Panics if the
// lengths of s and t are not equal
func Mul(s []float64, t []float64) {
	if len(s) != len(t) {
		panic("floats: slice lengths do not match")
	}
	for i, val := range t {
		s[i] *= val
	}
}

// Nearest returns the index of the element in s
// whose value is nearest to v.  If several such
// elements exist, the lowest index is returned
func Nearest(s []float64, v float64) (ind int) {
	dist := math.Abs(v - s[0])
	ind = 0
	for i, val := range s {
		newDist := math.Abs(v - val)
		if newDist < dist {
			dist = newDist
			ind = i
		}
	}
	return
}

// NearestInSpan return the index of a hypothetical vector created
// by Span with length n and bounds l and u whose value is closest
// to v. Assumes u > l. If the value is greater than u or less than
// l, the function will panic.
func NearestWithinSpan(n int, l, u float64, v float64) int {
	if v < l || v > u {
		panic("floats: value outside span bounds")
	}

	// Can't guarantee anything about exactly halfway between
	// because of floating point weirdness
	return int((float64(n)-1)/(u-l)*(v-l) + 0.5)
}

// Norm returns the L norm of the slice S, defined as
// (sum_{i=1}^N s[i]^N)^{1/N}
// Special cases:
// L = math.Inf(1) gives the maximum value
// Does not correctly compute the zero norm (use Count)
func Norm(s []float64, L float64) (norm float64) {
	// Should this complain if L is not positive?
	// Should this be done in log space for better numerical stability?
	//	would be more cost
	//	maybe only if L is high?
	if L == 2 {
		for _, val := range s {
			norm += val * val
		}
		return math.Pow(norm, 0.5)
	}
	if L == 1 {
		for _, val := range s {
			norm += math.Abs(val)
		}
		return norm
	}
	if math.IsInf(L, 1) {
		norm, _ = Max(s)
		return norm
	}
	for _, val := range s {
		norm += math.Pow(math.Abs(val), L)
	}
	return math.Pow(norm, 1/L)
}

// Prod returns the product of the elements of the slice
// Returns 1 if len(s) = 0
func Prod(s []float64) (prod float64) {
	prod = 1
	for _, val := range s {
		prod *= val
	}
	return prod
}

// Scale multiplies every element in s by c
func Scale(c float64, s []float64) {
	for i := range s {
		s[i] *= c
	}
}

// Span returns a set of N equally spaced points between l and u, where N
// is equal to the length of the destination. The first element of the destination
// is l, the final element of the destination is u.
// Panics if len(dst) < 2
func Span(dst []float64, l, u float64) []float64 {
	n := len(dst)
	if n < 2 {
		panic("floats: destination must have length >1")
	}
	step := (u - l) / float64(n-1)
	for i := range dst {
		dst[i] = l + step*float64(i)
	}
	return dst
}

// Sub subtracts, element-wise, the first argument from the second. Assumes
// the lengths of s and t match (can be tested with EqLen)
func Sub(s, t []float64) {
	if len(s) != len(t) {
		panic("floats: length of the slices do not match")
	}
	for i, val := range t {
		s[i] -= val
	}
}

// SubTo subtracts, element-wise, the first argument from the second and
// stores the result in dest. Panics if the lengths of s and t do not match
func SubTo(dst, s, t []float64) []float64 {
	if len(s) != len(t) {
		panic("floats: length of subtractor and subtractee do not match")
	}
	if len(dst) != len(s) {
		panic("floats: length of destination does not match length of subtractor")
	}
	for i, val := range t {
		dst[i] = s[i] - val
	}
	return dst
}

// Sum returns the sum of the elements of the slice
func Sum(s []float64) (sum float64) {
	for _, val := range s {
		sum += val
	}
	return
}
<|endoftext|>


<commit_before>//Package wmenu creates menus for cli programs.
//It uses wlog for it's interface with the command line.
//It uses os.Stdin, os.Stdout, and os.Stderr with concurrency by default.
//wmenu allows you to change the color of the different parts of the menu.
package wmenu

//TODO add options to change where wlog writes to
import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/dixonwille/wlog"
)

//Menu is used to display options to a user.
//A user can then select options and Menu will validate the response and perform the correct action.
type Menu struct {
	question        string
	defaultFunction func(Option)
	options         []Option
	ui              wlog.UI
	multiSeperator  string
	multiFunction   func([]Option)
	loopOnInvalid   bool
	clear           bool
}

//NewMenu creates a menu with a wlog.UI as the writer.
func NewMenu(question string) *Menu {
	//Create a default ui to use for menu
	var ui wlog.UI
	ui = wlog.New(os.Stdin, os.Stdout, os.Stderr)
	ui = wlog.AddConcurrent(ui)

	return &Menu{
		question:        question,
		defaultFunction: nil,
		options:         nil,
		ui:              ui,
		multiSeperator:  " ",
		multiFunction:   nil,
		loopOnInvalid:   false,
		clear:           false,
	}
}

//AddColor will change the color of the menu items.
//optionColor changes the color of the options.
//questionColor changes the color of the questions.
//errorColor changes the color of the question.
//Use wlog.None if you do not want to change the color.
func (m *Menu) AddColor(optionColor, questionColor, errorColor wlog.Color) {
	m.ui = wlog.AddColor(wlog.None, optionColor, wlog.None, questionColor, errorColor, wlog.None, wlog.None, m.ui)
}

//ClearOnMenuRun will clear the screen when a menu is ran.
//This is checked when LoopOnInvalid is activated.
//Meaning if an error occured then it will clear the screen before asking again.
func (m *Menu) ClearOnMenuRun() {
	m.clear = true
}

//SetSeperator sets the seperator to use when multiple options are valid responses.
//Default value is a space.
func (m *Menu) SetSeperator(sep string) {
	m.multiSeperator = sep
}

//LoopOnInvalid is used if an invalid option was given then it will prompt the user again.
func (m *Menu) LoopOnInvalid() {
	m.loopOnInvalid = true
}

//Option adds an option to the menu for the user to select from.
//title is the string the user will select
//isDefault is whether this option is a default option (IE when no options are selected).
//function is what is called when only this option is selected.
//If function is nil then it will default to the menu's Action.
func (m *Menu) Option(title string, isDefault bool, function func()) {
	option := newOption(len(m.options), title, isDefault, function)
	m.options = append(m.options, *option)
}

//Action adds a default action to use in certain scenarios.
//If the selected option (by default or user selected) does not have a function applied to it this will be called.
//If there are no default options and no option was selected this will be called with an option that has an ID of -1.
func (m *Menu) Action(function func(Option)) {
	m.defaultFunction = function
}

//MultipleAction is called when multiple options are selected (by default or user selected).
//If this is set then it uses the seperator string specified by SetSeperator (Default is a space) to seperate the responses.
//If this is not set then it is implied that the menu only allows for one option to be selected.
func (m *Menu) MultipleAction(function func([]Option)) {
	m.multiFunction = function
}

//Run is used to execute the menu.
//It will print to options and question to the screen.
//It will only clear the screen if ClearOnMenuRun is activated.
//This will validate all responses.
//Errors are of type MenuError.
func (m *Menu) Run() error {
	if m.clear {
		Clear()
	}
	valid := false
	var options []Option
	//Loop and on error check if loopOnInvalid is enabled.
	//If it is Clear the screen and write error.
	//Then ask again
	for !valid {
		//step 1 print things to screen
		m.print()
		//step 2 get and validate response
		opt, err := m.ask()
		if err != nil {
			if m.loopOnInvalid {
				if m.clear {
					Clear()
				}
				m.ui.Error(err.Error())
			} else {
				return err
			}
		} else {
			options = opt
			valid = true
		}
	}
	//step 3 call appropriate action with the responses
	switch len(options) {
	//if no options go through options and look for default options
	case 0:
		opt := m.getDefault()
		switch len(opt) {
		//if there are no default options call the defaultFunction of the menu
		case 0:
			m.defaultFunction(Option{ID: -1})
			//if there is one default option call it's function if it exist
			//if it does not, call the menu's defaultFunction
		case 1:
			if opt[0].function == nil {
				m.defaultFunction(opt[0])
			} else {
				opt[0].function()
			}
			//if there is more than one default option call the menu's multiFunction
		default:
			m.multiFunction(opt)
		}
		//if there is one option call it's funciton if it exist
		//if it does not, call the menu's defaultFunction
	case 1:
		if options[0].function == nil {
			m.defaultFunction(options[0])
		} else {
			options[0].function()
		}
		//if there is more than one option call the menu's multiFunction
	default:
		m.multiFunction(options)
	}
	return nil
}

func (m *Menu) print() {
	for _, opt := range m.options {
		m.ui.Output(fmt.Sprintf("%d) %s", opt.ID, opt.Text))
	}
	m.ui.Info(m.question)
}

func (m *Menu) ask() ([]Option, error) {
	reader := bufio.NewReader(os.Stdin)
	res, _ := reader.ReadString('\n')
	res = strings.Replace(res, "\r", "", -1) //this will only be useful under windows
	res = strings.Replace(res, "\n", "", -1)

	//Validate responses
	//Check if no responses are returned and no action to call
	if res == "" {
		//get default options
		opt := m.getDefault()
		if m.checkOptAndFunc(opt) {
			return nil, newMenuError(ErrNoResponse, "")
		}
		return nil, nil
	}

	resStrings := strings.Split(res, m.multiSeperator) //split responses by spaces
	//Check if we don't want multiple responses
	if m.multiFunction == nil && len(resStrings) > 1 {
		return nil, newMenuError(ErrTooMany, "")
	}

	//Convert responses to intigers
	var responses []int
	for _, response := range resStrings {
		//Check if it is an intiger
		r, err := strconv.Atoi(response)
		if err != nil {
			return nil, newMenuError(ErrInvalid, response)
		}
		responses = append(responses, r)
	}

	//Check if response is in the range of options
	//If it is make sure it is not duplicated
	var tmp []int
	for _, response := range responses {
		if response < 0 || len(m.options)-1 < response {
			return nil, newMenuError(ErrInvalid, strconv.Itoa(response))
		}

		if exist(tmp, response) {
			return nil, newMenuError(ErrDuplicate, strconv.Itoa(response))
		}

		tmp = append(tmp, response)
	}

	//Parse responses and return them as options
	var finalOptions []Option
	for _, response := range responses {
		finalOptions = append(finalOptions, m.options[response])
	}

	return finalOptions, nil
}

//Simply checks if number exists in the slice
func exist(slice []int, number int) bool {
	for _, s := range slice {
		if number == s {
			return true
		}
	}
	return false
}

func (m *Menu) getDefault() []Option {
	var opt []Option
	for _, o := range m.options {
		if o.isDefault {
			opt = append(opt, o)
		}
	}
	return opt
}

//make sure that there is an action available to be called in certain cases
func (m *Menu) checkOptAndFunc(opt []Option) bool {
	return ((len(opt) == 0 && m.defaultFunction == nil) || (len(opt) == 1 && opt[0].function == nil && m.defaultFunction == nil) || (len(opt) > 0 && m.multiFunction == nil))
}
<commit_msg>Add package comment<commit_after>//Package wmenu creates menus for cli programs.
//It uses wlog for it's interface with the command line.
//It uses os.Stdin, os.Stdout, and os.Stderr with concurrency by default.
//wmenu allows you to change the color of the different parts of the menu.
//This package also creates it's own error structure so you can type assert if you need to.
package wmenu

//TODO add options to change where wlog writes to
import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"

	"github.com/dixonwille/wlog"
)

//Menu is used to display options to a user.
//A user can then select options and Menu will validate the response and perform the correct action.
type Menu struct {
	question        string
	defaultFunction func(Option)
	options         []Option
	ui              wlog.UI
	multiSeperator  string
	multiFunction   func([]Option)
	loopOnInvalid   bool
	clear           bool
}

//NewMenu creates a menu with a wlog.UI as the writer.
func NewMenu(question string) *Menu {
	//Create a default ui to use for menu
	var ui wlog.UI
	ui = wlog.New(os.Stdin, os.Stdout, os.Stderr)
	ui = wlog.AddConcurrent(ui)

	return &Menu{
		question:        question,
		defaultFunction: nil,
		options:         nil,
		ui:              ui,
		multiSeperator:  " ",
		multiFunction:   nil,
		loopOnInvalid:   false,
		clear:           false,
	}
}

//AddColor will change the color of the menu items.
//optionColor changes the color of the options.
//questionColor changes the color of the questions.
//errorColor changes the color of the question.
//Use wlog.None if you do not want to change the color.
func (m *Menu) AddColor(optionColor, questionColor, errorColor wlog.Color) {
	m.ui = wlog.AddColor(wlog.None, optionColor, wlog.None, questionColor, errorColor, wlog.None, wlog.None, m.ui)
}

//ClearOnMenuRun will clear the screen when a menu is ran.
//This is checked when LoopOnInvalid is activated.
//Meaning if an error occured then it will clear the screen before asking again.
func (m *Menu) ClearOnMenuRun() {
	m.clear = true
}

//SetSeperator sets the seperator to use when multiple options are valid responses.
//Default value is a space.
func (m *Menu) SetSeperator(sep string) {
	m.multiSeperator = sep
}

//LoopOnInvalid is used if an invalid option was given then it will prompt the user again.
func (m *Menu) LoopOnInvalid() {
	m.loopOnInvalid = true
}

//Option adds an option to the menu for the user to select from.
//title is the string the user will select
//isDefault is whether this option is a default option (IE when no options are selected).
//function is what is called when only this option is selected.
//If function is nil then it will default to the menu's Action.
func (m *Menu) Option(title string, isDefault bool, function func()) {
	option := newOption(len(m.options), title, isDefault, function)
	m.options = append(m.options, *option)
}

//Action adds a default action to use in certain scenarios.
//If the selected option (by default or user selected) does not have a function applied to it this will be called.
//If there are no default options and no option was selected this will be called with an option that has an ID of -1.
func (m *Menu) Action(function func(Option)) {
	m.defaultFunction = function
}

//MultipleAction is called when multiple options are selected (by default or user selected).
//If this is set then it uses the seperator string specified by SetSeperator (Default is a space) to seperate the responses.
//If this is not set then it is implied that the menu only allows for one option to be selected.
func (m *Menu) MultipleAction(function func([]Option)) {
	m.multiFunction = function
}

//Run is used to execute the menu.
//It will print to options and question to the screen.
//It will only clear the screen if ClearOnMenuRun is activated.
//This will validate all responses.
//Errors are of type MenuError.
func (m *Menu) Run() error {
	if m.clear {
		Clear()
	}
	valid := false
	var options []Option
	//Loop and on error check if loopOnInvalid is enabled.
	//If it is Clear the screen and write error.
	//Then ask again
	for !valid {
		//step 1 print things to screen
		m.print()
		//step 2 get and validate response
		opt, err := m.ask()
		if err != nil {
			if m.loopOnInvalid {
				if m.clear {
					Clear()
				}
				m.ui.Error(err.Error())
			} else {
				return err
			}
		} else {
			options = opt
			valid = true
		}
	}
	//step 3 call appropriate action with the responses
	switch len(options) {
	//if no options go through options and look for default options
	case 0:
		opt := m.getDefault()
		switch len(opt) {
		//if there are no default options call the defaultFunction of the menu
		case 0:
			m.defaultFunction(Option{ID: -1})
			//if there is one default option call it's function if it exist
			//if it does not, call the menu's defaultFunction
		case 1:
			if opt[0].function == nil {
				m.defaultFunction(opt[0])
			} else {
				opt[0].function()
			}
			//if there is more than one default option call the menu's multiFunction
		default:
			m.multiFunction(opt)
		}
		//if there is one option call it's funciton if it exist
		//if it does not, call the menu's defaultFunction
	case 1:
		if options[0].function == nil {
			m.defaultFunction(options[0])
		} else {
			options[0].function()
		}
		//if there is more than one option call the menu's multiFunction
	default:
		m.multiFunction(options)
	}
	return nil
}

func (m *Menu) print() {
	for _, opt := range m.options {
		m.ui.Output(fmt.Sprintf("%d) %s", opt.ID, opt.Text))
	}
	m.ui.Info(m.question)
}

func (m *Menu) ask() ([]Option, error) {
	reader := bufio.NewReader(os.Stdin)
	res, _ := reader.ReadString('\n')
	res = strings.Replace(res, "\r", "", -1) //this will only be useful under windows
	res = strings.Replace(res, "\n", "", -1)

	//Validate responses
	//Check if no responses are returned and no action to call
	if res == "" {
		//get default options
		opt := m.getDefault()
		if m.checkOptAndFunc(opt) {
			return nil, newMenuError(ErrNoResponse, "")
		}
		return nil, nil
	}

	resStrings := strings.Split(res, m.multiSeperator) //split responses by spaces
	//Check if we don't want multiple responses
	if m.multiFunction == nil && len(resStrings) > 1 {
		return nil, newMenuError(ErrTooMany, "")
	}

	//Convert responses to intigers
	var responses []int
	for _, response := range resStrings {
		//Check if it is an intiger
		r, err := strconv.Atoi(response)
		if err != nil {
			return nil, newMenuError(ErrInvalid, response)
		}
		responses = append(responses, r)
	}

	//Check if response is in the range of options
	//If it is make sure it is not duplicated
	var tmp []int
	for _, response := range responses {
		if response < 0 || len(m.options)-1 < response {
			return nil, newMenuError(ErrInvalid, strconv.Itoa(response))
		}

		if exist(tmp, response) {
			return nil, newMenuError(ErrDuplicate, strconv.Itoa(response))
		}

		tmp = append(tmp, response)
	}

	//Parse responses and return them as options
	var finalOptions []Option
	for _, response := range responses {
		finalOptions = append(finalOptions, m.options[response])
	}

	return finalOptions, nil
}

//Simply checks if number exists in the slice
func exist(slice []int, number int) bool {
	for _, s := range slice {
		if number == s {
			return true
		}
	}
	return false
}

func (m *Menu) getDefault() []Option {
	var opt []Option
	for _, o := range m.options {
		if o.isDefault {
			opt = append(opt, o)
		}
	}
	return opt
}

//make sure that there is an action available to be called in certain cases
func (m *Menu) checkOptAndFunc(opt []Option) bool {
	return ((len(opt) == 0 && m.defaultFunction == nil) || (len(opt) == 1 && opt[0].function == nil && m.defaultFunction == nil) || (len(opt) > 0 && m.multiFunction == nil))
}
<|endoftext|>


<commit_before>package traytor

// Vertex is a single vertex in a mesh
type Vertex struct {
	Normal      Vec3
	Coordinates Vec3
	UV          Vec3
}

// Triangle is a face with 3 vertices (indices in the vertex array)
type Triangle struct {
	Points [3]int
}

// Mesh is a triangle mesh
type Mesh struct {
	Vertices []Vertex
	Faces    []Triangle
}
<commit_msg>Json for mesh<commit_after>package traytor

// Vertex is a single vertex in a mesh
type Vertex struct {
	Normal      Vec3 `json:"normal"`
	Coordinates Vec3 `json:"coordinates"`
	UV          Vec3 `json:"uv"`
}

// Triangle is a face with 3 vertices (indices in the vertex array)
type Triangle struct {
	Vertices [3]int `json:"vertices"`
	Material int    `json:"material"`
	normal   Vec3   `json:"normal"`
}

// Mesh is a triangle mesh
type Mesh struct {
	Vertices []Vertex   `json:"vertices"`
	Faces    []Triangle `json:"faces"`
}
<|endoftext|>