<commit_before>package main

import (
	"bufio"
	"crypto/tls"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/fatih/color"
)

const (
	HTTPS_TEMPLATE = `` +
		`  DNS Lookup   TCP Connection   TLS Handshake   Server Processing   Content Transfer` + "\n" +
		`[%s  |     %s  |    %s  |        %s  |       %s  ]` + "\n" +
		`            |                |               |                   |                  |` + "\n" +
		`   namelookup:%s      |               |                   |                  |` + "\n" +
		`                       connect:%s     |                   |                  |` + "\n" +
		`                                   pretransfer:%s         |                  |` + "\n" +
		`                                                     starttransfer:%s        |` + "\n" +
		`                                                                                total:%s` + "\n"

	HTTP_TEMPLATE = `` +
		`   DNS Lookup   TCP Connection   Server Processing   Content Transfer` + "\n" +
		`[ %s  |     %s  |        %s  |       %s  ]` + "\n" +
		`             |                |                   |                  |` + "\n" +
		`    namelookup:%s      |                   |                  |` + "\n" +
		`                        connect:%s         |                  |` + "\n" +
		`                                      starttransfer:%s        |` + "\n" +
		`                                                                 total:%s` + "\n"
)

var (
	requestBody io.Reader

	grayscale = func(code int) func(string) string {
		if color.NoColor {
			return func(s string) string { return s }
		}
		return func(s string) string {
			return fmt.Sprintf("\x1b[;38;5;%dm%s\x1b[0m", code+232, s)
		}
	}

	// Command line flags.
	httpMethod      string
	postBody        string
	followRedirects bool
	onlyHeader      bool
	insecure        bool
	httpHeaders     headers
	saveOutput      bool
	outputFile      string

	// number of redirects followed
	redirectsFollowed int

	usage = fmt.Sprintf("usage: %s URL", os.Args[0])
)

const maxRedirects = 10

func init() {
	flag.StringVar(&httpMethod, "X", "GET", "HTTP method to use")
	flag.StringVar(&postBody, "d", "", "the body of a POST or PUT request")
	flag.BoolVar(&followRedirects, "L", false, "follow 30x redirects")
	flag.BoolVar(&onlyHeader, "I", false, "don't read body of request")
	flag.BoolVar(&insecure, "k", false, "allow insecure SSL connections")
	flag.Var(&httpHeaders, "H", "HTTP Header(s) to set. Can be used multiple times. -H 'Accept:...' -H 'Range:....'")
	flag.BoolVar(&saveOutput, "O", false, "Save body as remote filename")
	flag.StringVar(&outputFile, "o", "", "output file for body")

	flag.Usage = func() {
		os.Stderr.WriteString(usage + "\n")
		flag.PrintDefaults()
		os.Exit(2)
	}
}

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) != 1 {
		flag.Usage()
	}

	if (httpMethod == "POST" || httpMethod == "PUT") && postBody == "" {
		log.Fatal("must supply post body using -d when POST or PUT is used")
	}

	url, err := url.Parse(args[0])
	if err != nil {
		log.Fatalf("could not parse url %q: %v", args[0], err)
	}
	visit(url)
}

func headerKeyValue(h string) (string, string) {
	i := strings.Index(h, ":")
	if i == -1 {
		log.Fatalf("Header '%s' has invalid format, missing ':'", h)
	}
	return strings.TrimRight(h[:i], " "), strings.TrimLeft(h[i:], " :")
}

// visit visits a url and times the interaction.
// If the response is a 30x, visit follows the redirect.
func visit(url *url.URL) {
	scheme := url.Scheme
	hostport := url.Host
	host, port := func() (string, string) {
		host, port, err := net.SplitHostPort(hostport)
		if err != nil {
			host = hostport
		}
		switch scheme {
		case "https":
			if port == "" {
				port = "443"
			}
		case "http":
			if port == "" {
				port = "80"
			}
		default:
			log.Fatalf("unsupported url scheme %q", scheme)
		}
		return host, port
	}()

	t0 := time.Now() // before dns resolution
	raddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%s", host, port))
	if err != nil {
		log.Fatalf("unable to resolve host: %v", err)
	}

	var conn net.Conn
	t1 := time.Now() // after dns resolution, before connect
	conn, err = net.DialTCP("tcp", nil, raddr)
	if err != nil {
		log.Fatalf("unable to connect to host %vv %v", raddr, err)
	}
	fmt.Printf("\n%s%s\n", color.GreenString("Connected to "), color.CyanString(raddr.String()))

	var t2 time.Time // after connect, before TLS handshake
	if scheme == "https" {
		t2 = time.Now()
		c := tls.Client(conn, &tls.Config{
			ServerName:         host,
			InsecureSkipVerify: insecure,
		})
		if err := c.Handshake(); err != nil {
			log.Fatalf("unable to negotiate TLS handshake: %v", err)
		}
		conn = c
	}

	t3 := time.Now() // after connect, before request
	if onlyHeader {
		httpMethod = "HEAD"
	}
	req, err := http.NewRequest(httpMethod, url.String(), createBody(postBody))
	if err != nil {
		log.Fatalf("unable to create request: %v", err)
	}
	for _, h := range httpHeaders {
		req.Header.Add(headerKeyValue(h))
	}

	if err := req.Write(conn); err != nil {
		log.Fatalf("failed to write request: %v", err)
	}

	t4 := time.Now() // after request, before read response
	resp, err := http.ReadResponse(bufio.NewReader(conn), req)
	if err != nil {
		log.Fatalf("failed to read response: %v", err)
	}

	t5 := time.Now() // after read response
	bodyMsg := readResponseBody(req, resp)
	resp.Body.Close()

	t6 := time.Now() // after read body

	// print status line and headers
	fmt.Printf("\n%s%s%s\n", color.GreenString("HTTP"), grayscale(14)("/"), color.CyanString("%d.%d %s", resp.ProtoMajor, resp.ProtoMinor, resp.Status))

	names := make([]string, 0, len(resp.Header))
	for k := range resp.Header {
		names = append(names, k)
	}
	sort.Sort(headers(names))
	for _, k := range names {
		fmt.Println(grayscale(14)(k+":"), color.CyanString(strings.Join(resp.Header[k], ",")))
	}

	if bodyMsg != "" {
		fmt.Printf("\n%s\n", bodyMsg)
	}

	fmta := func(d time.Duration) string {
		return color.CyanString("%7dms", int(d/time.Millisecond))
	}

	fmtb := func(d time.Duration) string {
		return color.CyanString("%-9s", strconv.Itoa(int(d/time.Millisecond))+"ms")
	}

	colorize := func(s string) string {
		v := strings.Split(s, "\n")
		v[0] = grayscale(16)(v[0])
		return strings.Join(v, "\n")
	}

	fmt.Println()

	switch scheme {
	case "https":
		fmt.Printf(colorize(HTTPS_TEMPLATE),
			fmta(t1.Sub(t0)), // dns lookup
			fmta(t2.Sub(t1)), // tcp connection
			fmta(t3.Sub(t2)), // tls handshake
			fmta(t5.Sub(t4)), // server processing
			fmta(t6.Sub(t5)), // content transfer
			fmtb(t1.Sub(t0)), // namelookup
			fmtb(t2.Sub(t0)), // connect
			fmtb(t3.Sub(t0)), // pretransfer
			fmtb(t5.Sub(t0)), // starttransfer
			fmtb(t6.Sub(t0)), // total
		)
	case "http":
		fmt.Printf(colorize(HTTP_TEMPLATE),
			fmta(t1.Sub(t0)), // dns lookup
			fmta(t3.Sub(t1)), // tcp connection
			fmta(t5.Sub(t3)), // server processing
			fmta(t6.Sub(t5)), // content transfer
			fmtb(t1.Sub(t0)), // namelookup
			fmtb(t3.Sub(t0)), // connect
			fmtb(t5.Sub(t0)), // starttransfer
			fmtb(t6.Sub(t0)), // total
		)
	}

	if followRedirects && isRedirect(resp) {
		loc, err := resp.Location()
		if err != nil {
			if err == http.ErrNoLocation {
				// 30x but no Location to follow, give up.
				return
			}
			log.Fatalf("unable to follow redirect: %v", err)
		}

		redirectsFollowed++
		if redirectsFollowed > maxRedirects {
			log.Fatalf("maximum number of redirects (%d) followed\n", maxRedirects)
		}

		visit(loc)
	}
}

func isRedirect(resp *http.Response) bool {
	return resp.StatusCode > 299 && resp.StatusCode < 400
}

func createBody(body string) io.Reader {
	if strings.HasPrefix(body, "@") {
		filename := body[1:]
		f, err := os.Open(filename)
		if err != nil {
			log.Fatalf("failed to open data file %s: %v", filename, err)
		}
		return f
	}
	return strings.NewReader(body)
}

// readResponseBody consumes the body of the response.
// readResponseBody returns an informational message about the
// disposition of the response body's contents.
func readResponseBody(req *http.Request, resp *http.Response) string {
	if isRedirect(resp) || req.Method == http.MethodHead {
		return ""
	}

	w := ioutil.Discard
	msg := color.CyanString("Body discarded")

	if saveOutput == true || outputFile != "" {
		filename := outputFile

		if saveOutput == true {
			// TODO(dfc) handle Content-Disposition: attachment
			filename = path.Base(req.URL.RequestURI())

			if filename == "/" {
				log.Fatalf("No remote filename; specify output filename with -o to save response body")
			}
		}

		var err error
		w, err = os.Create(filename)
		if err != nil {
			log.Fatalf("unable to create file %s", outputFile)
		}
		msg = color.CyanString("Body read")
	}

	if _, err := io.Copy(w, resp.Body); err != nil {
		log.Fatalf("failed to read response body: %v", err)
	}

	return msg
}

type headers []string

func (h headers) String() string {
	var o []string
	for _, v := range h {
		o = append(o, "-H "+v)
	}
	return strings.Join(o, " ")
}

func (h *headers) Set(v string) error {
	*h = append(*h, v)
	return nil
}

func (h headers) Len() int      { return len(h) }
func (h headers) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h headers) Less(i, j int) bool {
	a, b := h[i], h[j]

	// server always sorts at the top
	if a == "Server" {
		return true
	}
	if b == "Server" {
		return false
	}

	endtoend := func(n string) bool {
		// https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
		switch n {
		case "Connection",
			"Keep-Alive",
			"Proxy-Authenticate",
			"Proxy-Authorization",
			"TE",
			"Trailers",
			"Transfer-Encoding",
			"Upgrade":
			return false
		default:
			return true
		}
	}

	x, y := endtoend(a), endtoend(b)
	if x == y {
		// both are of the same class
		return a < b
	}
	return x
}
<commit_msg>Windows Color (#65)<commit_after>package main

import (
	"bufio"
	"crypto/tls"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"net/url"
	"os"
	"path"
	"sort"
	"strconv"
	"strings"
	"time"

	"github.com/fatih/color"
)

const (
	HTTPS_TEMPLATE = `` +
		`  DNS Lookup   TCP Connection   TLS Handshake   Server Processing   Content Transfer` + "\n" +
		`[%s  |     %s  |    %s  |        %s  |       %s  ]` + "\n" +
		`            |                |               |                   |                  |` + "\n" +
		`   namelookup:%s      |               |                   |                  |` + "\n" +
		`                       connect:%s     |                   |                  |` + "\n" +
		`                                   pretransfer:%s         |                  |` + "\n" +
		`                                                     starttransfer:%s        |` + "\n" +
		`                                                                                total:%s` + "\n"

	HTTP_TEMPLATE = `` +
		`   DNS Lookup   TCP Connection   Server Processing   Content Transfer` + "\n" +
		`[ %s  |     %s  |        %s  |       %s  ]` + "\n" +
		`             |                |                   |                  |` + "\n" +
		`    namelookup:%s      |                   |                  |` + "\n" +
		`                        connect:%s         |                  |` + "\n" +
		`                                      starttransfer:%s        |` + "\n" +
		`                                                                 total:%s` + "\n"
)

var (
	requestBody io.Reader

	grayscale = func(code int) func(string) string {
		if color.NoColor {
			return func(s string) string { return s }
		}
		return func(s string) string {
			return fmt.Sprintf("\x1b[;38;5;%dm%s\x1b[0m", code+232, s)
		}
	}

	// Command line flags.
	httpMethod      string
	postBody        string
	followRedirects bool
	onlyHeader      bool
	insecure        bool
	httpHeaders     headers
	saveOutput      bool
	outputFile      string

	// number of redirects followed
	redirectsFollowed int

	usage = fmt.Sprintf("usage: %s URL", os.Args[0])
)

const maxRedirects = 10

func init() {
	flag.StringVar(&httpMethod, "X", "GET", "HTTP method to use")
	flag.StringVar(&postBody, "d", "", "the body of a POST or PUT request")
	flag.BoolVar(&followRedirects, "L", false, "follow 30x redirects")
	flag.BoolVar(&onlyHeader, "I", false, "don't read body of request")
	flag.BoolVar(&insecure, "k", false, "allow insecure SSL connections")
	flag.Var(&httpHeaders, "H", "HTTP Header(s) to set. Can be used multiple times. -H 'Accept:...' -H 'Range:....'")
	flag.BoolVar(&saveOutput, "O", false, "Save body as remote filename")
	flag.StringVar(&outputFile, "o", "", "output file for body")

	flag.Usage = func() {
		os.Stderr.WriteString(usage + "\n")
		flag.PrintDefaults()
		os.Exit(2)
	}
}

func printf(format string, a ...interface{}) (n int, err error) {
	if color.Output == os.Stdout {
		return fmt.Printf(format, a...)
	}
	return fmt.Fprintf(color.Output, format, a...)
}

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) != 1 {
		flag.Usage()
	}

	if (httpMethod == "POST" || httpMethod == "PUT") && postBody == "" {
		log.Fatal("must supply post body using -d when POST or PUT is used")
	}

	url, err := url.Parse(args[0])
	if err != nil {
		log.Fatalf("could not parse url %q: %v", args[0], err)
	}
	visit(url)
}

func headerKeyValue(h string) (string, string) {
	i := strings.Index(h, ":")
	if i == -1 {
		log.Fatalf("Header '%s' has invalid format, missing ':'", h)
	}
	return strings.TrimRight(h[:i], " "), strings.TrimLeft(h[i:], " :")
}

// visit visits a url and times the interaction.
// If the response is a 30x, visit follows the redirect.
func visit(url *url.URL) {
	scheme := url.Scheme
	hostport := url.Host
	host, port := func() (string, string) {
		host, port, err := net.SplitHostPort(hostport)
		if err != nil {
			host = hostport
		}
		switch scheme {
		case "https":
			if port == "" {
				port = "443"
			}
		case "http":
			if port == "" {
				port = "80"
			}
		default:
			log.Fatalf("unsupported url scheme %q", scheme)
		}
		return host, port
	}()

	t0 := time.Now() // before dns resolution
	raddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%s", host, port))
	if err != nil {
		log.Fatalf("unable to resolve host: %v", err)
	}

	var conn net.Conn
	t1 := time.Now() // after dns resolution, before connect
	conn, err = net.DialTCP("tcp", nil, raddr)
	if err != nil {
		log.Fatalf("unable to connect to host %vv %v", raddr, err)
	}
	printf("\n%s%s\n", color.GreenString("Connected to "), color.CyanString(raddr.String()))

	var t2 time.Time // after connect, before TLS handshake
	if scheme == "https" {
		t2 = time.Now()
		c := tls.Client(conn, &tls.Config{
			ServerName:         host,
			InsecureSkipVerify: insecure,
		})
		if err := c.Handshake(); err != nil {
			log.Fatalf("unable to negotiate TLS handshake: %v", err)
		}
		conn = c
	}

	t3 := time.Now() // after connect, before request
	if onlyHeader {
		httpMethod = "HEAD"
	}
	req, err := http.NewRequest(httpMethod, url.String(), createBody(postBody))
	if err != nil {
		log.Fatalf("unable to create request: %v", err)
	}
	for _, h := range httpHeaders {
		req.Header.Add(headerKeyValue(h))
	}

	if err := req.Write(conn); err != nil {
		log.Fatalf("failed to write request: %v", err)
	}

	t4 := time.Now() // after request, before read response
	resp, err := http.ReadResponse(bufio.NewReader(conn), req)
	if err != nil {
		log.Fatalf("failed to read response: %v", err)
	}

	t5 := time.Now() // after read response
	bodyMsg := readResponseBody(req, resp)
	resp.Body.Close()

	t6 := time.Now() // after read body

	// print status line and headers
	printf("\n%s%s%s\n", color.GreenString("HTTP"), grayscale(14)("/"), color.CyanString("%d.%d %s", resp.ProtoMajor, resp.ProtoMinor, resp.Status))

	names := make([]string, 0, len(resp.Header))
	for k := range resp.Header {
		names = append(names, k)
	}
	sort.Sort(headers(names))
	for _, k := range names {
		printf("%s %s\n", grayscale(14)(k+":"), color.CyanString(strings.Join(resp.Header[k], ",")))
	}

	if bodyMsg != "" {
		printf("\n%s\n", bodyMsg)
	}

	fmta := func(d time.Duration) string {
		return color.CyanString("%7dms", int(d/time.Millisecond))
	}

	fmtb := func(d time.Duration) string {
		return color.CyanString("%-9s", strconv.Itoa(int(d/time.Millisecond))+"ms")
	}

	colorize := func(s string) string {
		v := strings.Split(s, "\n")
		v[0] = grayscale(16)(v[0])
		return strings.Join(v, "\n")
	}

	fmt.Println()

	switch scheme {
	case "https":
		printf(colorize(HTTPS_TEMPLATE),
			fmta(t1.Sub(t0)), // dns lookup
			fmta(t2.Sub(t1)), // tcp connection
			fmta(t3.Sub(t2)), // tls handshake
			fmta(t5.Sub(t4)), // server processing
			fmta(t6.Sub(t5)), // content transfer
			fmtb(t1.Sub(t0)), // namelookup
			fmtb(t2.Sub(t0)), // connect
			fmtb(t3.Sub(t0)), // pretransfer
			fmtb(t5.Sub(t0)), // starttransfer
			fmtb(t6.Sub(t0)), // total
		)
	case "http":
		printf(colorize(HTTP_TEMPLATE),
			fmta(t1.Sub(t0)), // dns lookup
			fmta(t3.Sub(t1)), // tcp connection
			fmta(t5.Sub(t3)), // server processing
			fmta(t6.Sub(t5)), // content transfer
			fmtb(t1.Sub(t0)), // namelookup
			fmtb(t3.Sub(t0)), // connect
			fmtb(t5.Sub(t0)), // starttransfer
			fmtb(t6.Sub(t0)), // total
		)
	}

	if followRedirects && isRedirect(resp) {
		loc, err := resp.Location()
		if err != nil {
			if err == http.ErrNoLocation {
				// 30x but no Location to follow, give up.
				return
			}
			log.Fatalf("unable to follow redirect: %v", err)
		}

		redirectsFollowed++
		if redirectsFollowed > maxRedirects {
			log.Fatalf("maximum number of redirects (%d) followed\n", maxRedirects)
		}

		visit(loc)
	}
}

func isRedirect(resp *http.Response) bool {
	return resp.StatusCode > 299 && resp.StatusCode < 400
}

func createBody(body string) io.Reader {
	if strings.HasPrefix(body, "@") {
		filename := body[1:]
		f, err := os.Open(filename)
		if err != nil {
			log.Fatalf("failed to open data file %s: %v", filename, err)
		}
		return f
	}
	return strings.NewReader(body)
}

// readResponseBody consumes the body of the response.
// readResponseBody returns an informational message about the
// disposition of the response body's contents.
func readResponseBody(req *http.Request, resp *http.Response) string {
	if isRedirect(resp) || req.Method == http.MethodHead {
		return ""
	}

	w := ioutil.Discard
	msg := color.CyanString("Body discarded")

	if saveOutput == true || outputFile != "" {
		filename := outputFile

		if saveOutput == true {
			// TODO(dfc) handle Content-Disposition: attachment
			filename = path.Base(req.URL.RequestURI())

			if filename == "/" {
				log.Fatalf("No remote filename; specify output filename with -o to save response body")
			}
		}

		f, err := os.Create(filename)
		if err != nil {
			log.Fatalf("unable to create file %s", outputFile)
		}
		defer f.Close()
		w = f
		msg = color.CyanString("Body read")
	}

	if _, err := io.Copy(w, resp.Body); err != nil {
		log.Fatalf("failed to read response body: %v", err)
	}

	return msg
}

type headers []string

func (h headers) String() string {
	var o []string
	for _, v := range h {
		o = append(o, "-H "+v)
	}
	return strings.Join(o, " ")
}

func (h *headers) Set(v string) error {
	*h = append(*h, v)
	return nil
}

func (h headers) Len() int      { return len(h) }
func (h headers) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h headers) Less(i, j int) bool {
	a, b := h[i], h[j]

	// server always sorts at the top
	if a == "Server" {
		return true
	}
	if b == "Server" {
		return false
	}

	endtoend := func(n string) bool {
		// https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1
		switch n {
		case "Connection",
			"Keep-Alive",
			"Proxy-Authenticate",
			"Proxy-Authorization",
			"TE",
			"Trailers",
			"Transfer-Encoding",
			"Upgrade":
			return false
		default:
			return true
		}
	}

	x, y := endtoend(a), endtoend(b)
	if x == y {
		// both are of the same class
		return a < b
	}
	return x
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"path"
	"path/filepath"
	"strings"
	"text/template"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/units"
	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"
)

var (
	s3Bucket    string
	s3AccessKey string
	s3SecretKey string
	s3Region    string
	port        string
	certFile    string
	keyFile     string
)

// cleanBucketName returns the bucket and prefix
// for a given s3bucket
func cleanBucketName(bucket string) (string, string) {
	bucket = strings.TrimPrefix(bucket, "s3://")
	parts := strings.SplitN(bucket, "/", 2)
	if len(parts) == 1 {
		return bucket, "/"
	}

	return parts[0], parts[1]
}

// getRegion returns the aws region that is matches a given string
func getRegion(name string) (aws.Region, error) {
	var regions = map[string]aws.Region{
		aws.APNortheast.Name:  aws.APNortheast,
		aws.APSoutheast.Name:  aws.APSoutheast,
		aws.APSoutheast2.Name: aws.APSoutheast2,
		aws.EUCentral.Name:    aws.EUCentral,
		aws.EUWest.Name:       aws.EUWest,
		aws.USEast.Name:       aws.USEast,
		aws.USWest.Name:       aws.USWest,
		aws.USWest2.Name:      aws.USWest2,
		aws.USGovWest.Name:    aws.USGovWest,
		aws.SAEast.Name:       aws.SAEast,
	}
	region, ok := regions[name]
	if !ok {
		return aws.Region{}, fmt.Errorf("No region matches %s", name)
	}
	return region, nil
}

// listFiles lists the files in a specific s3 bucket
func listFiles(prefix, delimiter, marker string, maxKeys int, b *s3.Bucket) (files []s3.Key, err error) {
	resp, err := b.List(prefix, delimiter, marker, maxKeys)
	if err != nil {
		return nil, err
	}

	// append to files
	files = append(files, resp.Contents...)

	// recursion for the recursion god
	if resp.IsTruncated && resp.NextMarker != "" {
		f, err := listFiles(resp.Prefix, resp.Delimiter, resp.NextMarker, resp.MaxKeys, b)
		if err != nil {
			return nil, err
		}

		// append to files
		files = append(files, f...)
	}

	return files, nil
}

// JSONResponse is a map[string]string
// response from the web server
type JSONResponse map[string]string

// String returns the string representation of the
// JSONResponse object
func (j JSONResponse) String() string {
	str, err := json.MarshalIndent(j, "", "  ")
	if err != nil {
		return fmt.Sprintf(`{
  "error": "%v"
}`, err)
	}

	return string(str)
}

// Handler is the object which contains data to pass to the http handler functions
type Handler struct {
	Files []s3.Key
}

func (h *Handler) serveTemplate(w http.ResponseWriter, r *http.Request) {
	templateDir := path.Join("/src", "templates")
	lp := path.Join(templateDir, "layout.html")

	// set up custom functions
	funcMap := template.FuncMap{
		"ext": func(name string) string {
			return strings.TrimPrefix(filepath.Ext(name), ".")
		},
		"base": func(name string) string {
			parts := strings.Split(name, "/")
			return parts[len(parts)-1]
		},
		"size": func(s int64) string {
			return units.HumanSize(float64(s))
		},
	}

	// parse & execute the template
	tmpl := template.Must(template.New("").Funcs(funcMap).ParseFiles(lp))
	if err := tmpl.ExecuteTemplate(w, "layout", h.Files); err != nil {
		writeError(w, fmt.Sprintf("Execute template failed: %v", err))
		return
	}
}

// writeError sends an error back to the requester
// and also logrus. the error
func writeError(w http.ResponseWriter, msg string) {
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprint(w, JSONResponse{
		"error": msg,
	})
	logrus.Printf("writing error: %s", msg)
	return
}

func init() {
	flag.StringVar(&s3Bucket, "s3bucket", "", "bucket path from which to serve files")
	flag.StringVar(&s3AccessKey, "s3key", "", "s3 access key")
	flag.StringVar(&s3SecretKey, "s3secret", "", "s3 access secret")
	flag.StringVar(&s3Region, "s3region", "us-west-2", "aws region for the bucket")
	flag.StringVar(&port, "p", "8080", "port for server to run on")

	flag.StringVar(&certFile, "cert", "", "path to ssl certificate")
	flag.StringVar(&keyFile, "key", "", "path to ssl key")
	flag.Parse()
}

func main() {
	// auth with aws
	auth, err := aws.GetAuth(s3AccessKey, s3SecretKey)
	if err != nil {
		logrus.Fatalf("Could not auth to AWS: %v", err)
	}

	// create the client
	region, err := getRegion(s3Region)
	if err != nil {
		logrus.Fatal(err)
	}
	client := s3.New(auth, region)

	// get the files in the bucket
	bucket, prefix := cleanBucketName(s3Bucket)
	// get the bucket
	b := client.Bucket(bucket)
	files, err := listFiles(prefix, prefix, "", 2000, b)
	if err != nil {
		logrus.Fatalf("Listing all files in bucket failed: %v", err)
	}

	// create mux server
	mux := http.NewServeMux()

	// static files handler
	staticHandler := http.StripPrefix("/static/", http.FileServer(http.Dir("/src/static")))
	mux.Handle("/static/", staticHandler)

	// template handler
	h := Handler{
		Files: files,
	}
	mux.HandleFunc("/", h.serveTemplate)

	// set up the server
	server := &http.Server{
		Addr:    ":" + port,
		Handler: mux,
	}
	logrus.Infof("Starting server on port %q", port)
	if certFile != "" && keyFile != "" {
		logrus.Fatal(server.ListenAndServeTLS(certFile, keyFile))
	} else {
		logrus.Fatal(server.ListenAndServe())
	}
}
<commit_msg>better linting<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"path"
	"path/filepath"
	"strings"
	"text/template"

	"github.com/Sirupsen/logrus"
	"github.com/docker/docker/pkg/units"
	"github.com/mitchellh/goamz/aws"
	"github.com/mitchellh/goamz/s3"
)

var (
	s3Bucket    string
	s3AccessKey string
	s3SecretKey string
	s3Region    string
	port        string
	certFile    string
	keyFile     string
)

// cleanBucketName returns the bucket and prefix
// for a given s3bucket.
func cleanBucketName(bucket string) (string, string) {
	bucket = strings.TrimPrefix(bucket, "s3://")
	parts := strings.SplitN(bucket, "/", 2)
	if len(parts) == 1 {
		return bucket, "/"
	}

	return parts[0], parts[1]
}

// getRegion returns the aws region that is matches a given string.
func getRegion(name string) (aws.Region, error) {
	var regions = map[string]aws.Region{
		aws.APNortheast.Name:  aws.APNortheast,
		aws.APSoutheast.Name:  aws.APSoutheast,
		aws.APSoutheast2.Name: aws.APSoutheast2,
		aws.EUCentral.Name:    aws.EUCentral,
		aws.EUWest.Name:       aws.EUWest,
		aws.USEast.Name:       aws.USEast,
		aws.USWest.Name:       aws.USWest,
		aws.USWest2.Name:      aws.USWest2,
		aws.USGovWest.Name:    aws.USGovWest,
		aws.SAEast.Name:       aws.SAEast,
	}
	region, ok := regions[name]
	if !ok {
		return aws.Region{}, fmt.Errorf("No region matches %s", name)
	}
	return region, nil
}

// listFiles lists the files in a specific s3 bucket.
func listFiles(prefix, delimiter, marker string, maxKeys int, b *s3.Bucket) (files []s3.Key, err error) {
	resp, err := b.List(prefix, delimiter, marker, maxKeys)
	if err != nil {
		return nil, err
	}

	// append to files
	files = append(files, resp.Contents...)

	// recursion for the recursion god
	if resp.IsTruncated && resp.NextMarker != "" {
		f, err := listFiles(resp.Prefix, resp.Delimiter, resp.NextMarker, resp.MaxKeys, b)
		if err != nil {
			return nil, err
		}

		// append to files
		files = append(files, f...)
	}

	return files, nil
}

// JSONResponse is a map[string]string
// response from the web server.
type JSONResponse map[string]string

// String returns the string representation of the
// JSONResponse object.
func (j JSONResponse) String() string {
	str, err := json.MarshalIndent(j, "", "  ")
	if err != nil {
		return fmt.Sprintf(`{
  "error": "%v"
}`, err)
	}

	return string(str)
}

// Handler is the object which contains data to pass to the http handler functions.
type Handler struct {
	Files []s3.Key
}

func (h *Handler) serveTemplate(w http.ResponseWriter, r *http.Request) {
	templateDir := path.Join("/src", "templates")
	lp := path.Join(templateDir, "layout.html")

	// set up custom functions
	funcMap := template.FuncMap{
		"ext": func(name string) string {
			return strings.TrimPrefix(filepath.Ext(name), ".")
		},
		"base": func(name string) string {
			parts := strings.Split(name, "/")
			return parts[len(parts)-1]
		},
		"size": func(s int64) string {
			return units.HumanSize(float64(s))
		},
	}

	// parse & execute the template
	tmpl := template.Must(template.New("").Funcs(funcMap).ParseFiles(lp))
	if err := tmpl.ExecuteTemplate(w, "layout", h.Files); err != nil {
		writeError(w, fmt.Sprintf("Execute template failed: %v", err))
		return
	}
}

// writeError sends an error back to the requester
// and also logs the error.
func writeError(w http.ResponseWriter, msg string) {
	w.Header().Set("Content-Type", "application/json")
	fmt.Fprint(w, JSONResponse{
		"error": msg,
	})
	logrus.Printf("writing error: %s", msg)
	return
}

func init() {
	flag.StringVar(&s3Bucket, "s3bucket", "", "bucket path from which to serve files")
	flag.StringVar(&s3AccessKey, "s3key", "", "s3 access key")
	flag.StringVar(&s3SecretKey, "s3secret", "", "s3 access secret")
	flag.StringVar(&s3Region, "s3region", "us-west-2", "aws region for the bucket")
	flag.StringVar(&port, "p", "8080", "port for server to run on")

	flag.StringVar(&certFile, "cert", "", "path to ssl certificate")
	flag.StringVar(&keyFile, "key", "", "path to ssl key")
	flag.Parse()
}

func main() {
	// auth with aws
	auth, err := aws.GetAuth(s3AccessKey, s3SecretKey)
	if err != nil {
		logrus.Fatalf("Could not auth to AWS: %v", err)
	}

	// create the client
	region, err := getRegion(s3Region)
	if err != nil {
		logrus.Fatal(err)
	}
	client := s3.New(auth, region)

	// get the files in the bucket
	bucket, prefix := cleanBucketName(s3Bucket)
	// get the bucket
	b := client.Bucket(bucket)
	files, err := listFiles(prefix, prefix, "", 2000, b)
	if err != nil {
		logrus.Fatalf("Listing all files in bucket failed: %v", err)
	}

	// create mux server
	mux := http.NewServeMux()

	// static files handler
	staticHandler := http.StripPrefix("/static/", http.FileServer(http.Dir("/src/static")))
	mux.Handle("/static/", staticHandler)

	// template handler
	h := Handler{
		Files: files,
	}
	mux.HandleFunc("/", h.serveTemplate)

	// set up the server
	server := &http.Server{
		Addr:    ":" + port,
		Handler: mux,
	}
	logrus.Infof("Starting server on port %q", port)
	if certFile != "" && keyFile != "" {
		logrus.Fatal(server.ListenAndServeTLS(certFile, keyFile))
	} else {
		logrus.Fatal(server.ListenAndServe())
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"bitbucket.org/kardianos/osext"
	"code.google.com/p/gcfg"
	"github.com/influxdb/influxdb/client"
	"github.com/soniah/gosnmp"
)

const layout = "2006-01-02 15:04:05"

type SnmpConfig struct {
	Host      string `gcfg:"host"`
	Public    string `gcfg:"community"`
	Port      int    `gcfg:"port"`
	Retries   int    `gcfg:"retries"`
	Timeout   int    `gcfg:"timeout"`
	Repeat    int    `gcfg:"repeat"`
	Freq      int    `gcfg:"freq"`
	PortFile  string `gcfg:"portfile"`
	Config    string `gcfg:"config"`
	labels    map[string]string
	asName    map[string]string
	asOID     map[string]string
	oids      []string
	mib       *MibConfig
	Influx    *InfluxConfig
	LastError time.Time
	Requests  int64
	Gets      int64
	Errors    int64
	debugging chan bool
	enabled   chan chan bool
}

type InfluxConfig struct {
	Host      string `gcfg:"host"`
	Port      int    `gcfg:"port"`
	DB        string `gcfg:"db"`
	User      string `gcfg:"user"`
	Password  string `gcfg:"password"`
	Retention string `gcfg:"retention"`
	iChan     chan *client.BatchPoints
	conn      *client.Client
	Sent      int64
	Errors    int64
}

type HTTPConfig struct {
	Port int `gcfg:"port"`
}

type GeneralConfig struct {
	LogDir  string `gcfg:"logdir"`
	OidFile string `gcfg:"oidfile"`
}

type MibConfig struct {
	Scalers bool     `gcfg:"scalers"`
	Name    string   `gcfg:"name"`
	Columns []string `gcfg:"column"`
}

var (
	quit          = make(chan struct{})
	verbose       bool
	startTime     = time.Now()
	testing       bool
	snmpNames     bool
	repeat        = 0
	freq          = 30
	httpPort      = 8080
	oidToName     = make(map[string]string)
	nameToOid     = make(map[string]string)
	appdir, _     = osext.ExecutableFolder()
	logDir        = filepath.Join(appdir, "log")
	oidFile       = filepath.Join(appdir, "oids.txt")
	configFile    = filepath.Join(appdir, "config.gcfg")
	errorLog      *os.File
	errorDuration = time.Duration(10 * time.Minute)
	errorPeriod   = errorDuration.String()
	errorMax      = 100
	errorName     string

	cfg = struct {
		Snmp    map[string]*SnmpConfig
		Mibs    map[string]*MibConfig
		Influx  map[string]*InfluxConfig
		HTTP    HTTPConfig
		General GeneralConfig
	}{}
)

func fatal(v ...interface{}) {
	log.SetOutput(os.Stderr)
	log.Fatalln(v...)
}

func (c *SnmpConfig) DebugAction() string {
	debug := make(chan bool)
	c.enabled <- debug
	if <-debug {
		return "disable"
	}
	return "enable"
}

func (c *SnmpConfig) LoadPorts() {
	c.labels = make(map[string]string)
	if len(c.PortFile) == 0 {
		return
	}
	data, err := ioutil.ReadFile(filepath.Join(appdir, c.PortFile))
	if err != nil {
		log.Fatal(err)
	}
	for _, line := range strings.Split(string(data), "\n") {
		// strip comments
		comment := strings.Index(line, "#")
		if comment >= 0 {
			line = line[:comment]
		}
		f := strings.Fields(line)
		if len(f) < 2 {
			continue
		}
		c.labels[f[0]] = f[1]
	}
}

func (c *SnmpConfig) incRequests() {
	atomic.AddInt64(&c.Requests, 1)
}

func (c *SnmpConfig) incGets() {
	atomic.AddInt64(&c.Gets, 1)
}

func (c *SnmpConfig) incErrors() {
	atomic.AddInt64(&c.Errors, 1)
}

func (c *InfluxConfig) incErrors() {
	atomic.AddInt64(&c.Errors, 1)
}

func (c *InfluxConfig) incSent() {
	atomic.AddInt64(&c.Sent, 1)
}

// loads [last_octet]name for device
func (c *SnmpConfig) Translate() {
	client, err := snmpClient(c)
	if err != nil {
		fatal("Client connect error:", err)
	}
	defer client.Conn.Close()
	spew("Looking up column names for:", c.Host)
	pdus, err := client.BulkWalkAll(nameOid)
	if err != nil {
		fatal("SNMP bulkwalk error", err)
	}
	c.asName = make(map[string]string)
	c.asOID = make(map[string]string)
	for _, pdu := range pdus {
		switch pdu.Type {
		case gosnmp.OctetString:
			i := strings.LastIndex(pdu.Name, ".")
			suffix := pdu.Name[i+1:]
			name := string(pdu.Value.([]byte))
			_, ok := c.labels[name]
			if len(c.PortFile) == 0 || ok {
				c.asName[name] = suffix
				c.asOID[suffix] = name
			}
		}
	}
	// make sure we got everything
	for k := range c.labels {
		if _, ok := c.asName[k]; !ok {
			fatal("No OID found for:", k)
		}
	}

}

func spew(x ...interface{}) {
	if verbose {
		fmt.Println(x...)
	}
}

func (c *SnmpConfig) OIDs() {
	if c.mib == nil {
		fatal("NO MIB!")
	}
	c.oids = []string{}
	for _, col := range c.mib.Columns {
		base, ok := nameToOid[col]
		if !ok {
			fatal("no oid for col:", col)
		}
		// just named columns
		if len(c.PortFile) > 0 {
			for k := range c.asOID {
				c.oids = append(c.oids, base+"."+k)
			}
		} else if c.mib.Scalers {
			// or plain old scaler instances
			c.oids = append(c.oids, base+".0")
		} else {
			c.oids = append(c.oids, base)
		}
	}
	if len(c.mib.Columns) > 0 {
		spew("COLUMNS", c.mib.Columns)
		spew(c.oids)
	}
}

// load oid lookup data
func init() {
	data, err := ioutil.ReadFile(oidFile)
	if err != nil {
		log.Fatal(err)
	}
	for _, line := range strings.Split(string(data), "\n") {
		f := strings.Fields(line)
		if len(f) < 2 {
			continue
		}
		nameToOid[f[0]] = f[1]
		oidToName[f[1]] = f[0]
	}
}

func flags() *flag.FlagSet {
	var f flag.FlagSet
	f.BoolVar(&testing, "testing", testing, "print data w/o saving")
	f.BoolVar(&snmpNames, "names", snmpNames, "print column names and exit")
	f.StringVar(&configFile, "config", configFile, "config file")
	f.BoolVar(&verbose, "verbose", verbose, "verbose mode")
	f.IntVar(&repeat, "repeat", repeat, "number of times to repeat")
	f.IntVar(&freq, "freq", freq, "delay (in seconds)")
	f.IntVar(&httpPort, "http", httpPort, "http port")
	f.StringVar(&logDir, "logs", logDir, "log directory")
	f.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		f.VisitAll(func(flag *flag.Flag) {
			format := "%10s: %s\n"
			fmt.Fprintf(os.Stderr, format, "-"+flag.Name, flag.Usage)
		})
		fmt.Fprintf(os.Stderr, "\nAll settings can be set in config file: %s\n", configFile)
		os.Exit(1)

	}
	return &f
}

func init() {
	// parse first time to see if config file is being specified
	f := flags()
	f.Parse(os.Args[1:])
	// now load up config settings
	if _, err := os.Stat(configFile); err != nil {
		log.Fatal(err)
	} else {
		data, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Fatal(err)
		}
		err = gcfg.ReadStringInto(&cfg, string(data))
		if err != nil {
			log.Fatalf("Failed to parse gcfg data: %s", err)
		}
		httpPort = cfg.HTTP.Port
	}

	if len(cfg.General.LogDir) > 0 {
		logDir = cfg.General.LogDir
	}
	if len(cfg.General.OidFile) > 0 {
		oidFile = cfg.General.OidFile
	}

	for _, s := range cfg.Snmp {
		s.LoadPorts()
		s.debugging = make(chan bool)
		s.enabled = make(chan chan bool)
	}
	var ok bool
	for name, c := range cfg.Snmp {
		if c.mib, ok = cfg.Mibs[name]; !ok {
			if c.mib, ok = cfg.Mibs["*"]; !ok {
				fatal("No mib data found for config:", name)
			}
		}
		c.Translate()
		c.OIDs()
		if c.Freq == 0 {
			c.Freq = freq
		}
	}

	// only run when one needs to see the interface names of the device
	if snmpNames {
		for _, c := range cfg.Snmp {
			fmt.Println("\nSNMP host:", c.Host)
			fmt.Println("=========================================")
			printSnmpNames(c)
		}
		os.Exit(0)
	}

	// re-read cmd line args to override as indicated
	f = flags()
	f.Parse(os.Args[1:])
	os.Mkdir(logDir, 0755)

	// now make sure each snmp device has a db
	for name, c := range cfg.Snmp {
		// default is to use name of snmp config, but it can be overridden
		if len(c.Config) > 0 {
			name = c.Config
		}
		if c.Influx, ok = cfg.Influx[name]; !ok {
			if c.Influx, ok = cfg.Influx["*"]; !ok {
				fatal("No influx config for snmp device:", name)
			}
		}
		c.Influx.Init()
	}

	var ferr error
	errorName = fmt.Sprintf("error.%d.log", cfg.HTTP.Port)
	errorPath := filepath.Join(logDir, errorName)
	errorLog, ferr = os.OpenFile(errorPath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0664)
	if ferr != nil {
		log.Fatal("Can't open error log:", ferr)
	}
}

func errLog(msg string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, msg, args...)
	fmt.Fprintf(errorLog, msg, args...)
}

func errMsg(msg string, err error) {
	now := time.Now()
	errLog("%s\t%s: %s\n", now.Format(layout), msg, err)
}

func ptest() {
    val := &pduValue{column: "abc", value: nil}
    pt := makePoint("localhost", val, time.Now())
    fmt.Println("PT:",pt.MarshalString())
}

func main() {
    ptest(); return
	var wg sync.WaitGroup
	defer func() {
		errorLog.Close()
	}()
	for _, c := range cfg.Snmp {
		wg.Add(1)
		go c.Gather(repeat, &wg)
	}
	if repeat > 0 {
		wg.Wait()
	} else {
		if httpPort > 0 {
			webServer(httpPort)
		} else {
			<-quit
		}
	}
}
<commit_msg>remove temp test code<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"bitbucket.org/kardianos/osext"
	"code.google.com/p/gcfg"
	"github.com/influxdb/influxdb/client"
	"github.com/soniah/gosnmp"
)

const layout = "2006-01-02 15:04:05"

type SnmpConfig struct {
	Host      string `gcfg:"host"`
	Public    string `gcfg:"community"`
	Port      int    `gcfg:"port"`
	Retries   int    `gcfg:"retries"`
	Timeout   int    `gcfg:"timeout"`
	Repeat    int    `gcfg:"repeat"`
	Freq      int    `gcfg:"freq"`
	PortFile  string `gcfg:"portfile"`
	Config    string `gcfg:"config"`
	labels    map[string]string
	asName    map[string]string
	asOID     map[string]string
	oids      []string
	mib       *MibConfig
	Influx    *InfluxConfig
	LastError time.Time
	Requests  int64
	Gets      int64
	Errors    int64
	debugging chan bool
	enabled   chan chan bool
}

type InfluxConfig struct {
	Host      string `gcfg:"host"`
	Port      int    `gcfg:"port"`
	DB        string `gcfg:"db"`
	User      string `gcfg:"user"`
	Password  string `gcfg:"password"`
	Retention string `gcfg:"retention"`
	iChan     chan *client.BatchPoints
	conn      *client.Client
	Sent      int64
	Errors    int64
}

type HTTPConfig struct {
	Port int `gcfg:"port"`
}

type GeneralConfig struct {
	LogDir  string `gcfg:"logdir"`
	OidFile string `gcfg:"oidfile"`
}

type MibConfig struct {
	Scalers bool     `gcfg:"scalers"`
	Name    string   `gcfg:"name"`
	Columns []string `gcfg:"column"`
}

var (
	quit          = make(chan struct{})
	verbose       bool
	startTime     = time.Now()
	testing       bool
	snmpNames     bool
	repeat        = 0
	freq          = 30
	httpPort      = 8080
	oidToName     = make(map[string]string)
	nameToOid     = make(map[string]string)
	appdir, _     = osext.ExecutableFolder()
	logDir        = filepath.Join(appdir, "log")
	oidFile       = filepath.Join(appdir, "oids.txt")
	configFile    = filepath.Join(appdir, "config.gcfg")
	errorLog      *os.File
	errorDuration = time.Duration(10 * time.Minute)
	errorPeriod   = errorDuration.String()
	errorMax      = 100
	errorName     string

	cfg = struct {
		Snmp    map[string]*SnmpConfig
		Mibs    map[string]*MibConfig
		Influx  map[string]*InfluxConfig
		HTTP    HTTPConfig
		General GeneralConfig
	}{}
)

func fatal(v ...interface{}) {
	log.SetOutput(os.Stderr)
	log.Fatalln(v...)
}

func (c *SnmpConfig) DebugAction() string {
	debug := make(chan bool)
	c.enabled <- debug
	if <-debug {
		return "disable"
	}
	return "enable"
}

func (c *SnmpConfig) LoadPorts() {
	c.labels = make(map[string]string)
	if len(c.PortFile) == 0 {
		return
	}
	data, err := ioutil.ReadFile(filepath.Join(appdir, c.PortFile))
	if err != nil {
		log.Fatal(err)
	}
	for _, line := range strings.Split(string(data), "\n") {
		// strip comments
		comment := strings.Index(line, "#")
		if comment >= 0 {
			line = line[:comment]
		}
		f := strings.Fields(line)
		if len(f) < 2 {
			continue
		}
		c.labels[f[0]] = f[1]
	}
}

func (c *SnmpConfig) incRequests() {
	atomic.AddInt64(&c.Requests, 1)
}

func (c *SnmpConfig) incGets() {
	atomic.AddInt64(&c.Gets, 1)
}

func (c *SnmpConfig) incErrors() {
	atomic.AddInt64(&c.Errors, 1)
}

func (c *InfluxConfig) incErrors() {
	atomic.AddInt64(&c.Errors, 1)
}

func (c *InfluxConfig) incSent() {
	atomic.AddInt64(&c.Sent, 1)
}

// loads [last_octet]name for device
func (c *SnmpConfig) Translate() {
	client, err := snmpClient(c)
	if err != nil {
		fatal("Client connect error:", err)
	}
	defer client.Conn.Close()
	spew("Looking up column names for:", c.Host)
	pdus, err := client.BulkWalkAll(nameOid)
	if err != nil {
		fatal("SNMP bulkwalk error", err)
	}
	c.asName = make(map[string]string)
	c.asOID = make(map[string]string)
	for _, pdu := range pdus {
		switch pdu.Type {
		case gosnmp.OctetString:
			i := strings.LastIndex(pdu.Name, ".")
			suffix := pdu.Name[i+1:]
			name := string(pdu.Value.([]byte))
			_, ok := c.labels[name]
			if len(c.PortFile) == 0 || ok {
				c.asName[name] = suffix
				c.asOID[suffix] = name
			}
		}
	}
	// make sure we got everything
	for k := range c.labels {
		if _, ok := c.asName[k]; !ok {
			fatal("No OID found for:", k)
		}
	}

}

func spew(x ...interface{}) {
	if verbose {
		fmt.Println(x...)
	}
}

func (c *SnmpConfig) OIDs() {
	if c.mib == nil {
		fatal("NO MIB!")
	}
	c.oids = []string{}
	for _, col := range c.mib.Columns {
		base, ok := nameToOid[col]
		if !ok {
			fatal("no oid for col:", col)
		}
		// just named columns
		if len(c.PortFile) > 0 {
			for k := range c.asOID {
				c.oids = append(c.oids, base+"."+k)
			}
		} else if c.mib.Scalers {
			// or plain old scaler instances
			c.oids = append(c.oids, base+".0")
		} else {
			c.oids = append(c.oids, base)
		}
	}
	if len(c.mib.Columns) > 0 {
		spew("COLUMNS", c.mib.Columns)
		spew(c.oids)
	}
}

// load oid lookup data
func init() {
	data, err := ioutil.ReadFile(oidFile)
	if err != nil {
		log.Fatal(err)
	}
	for _, line := range strings.Split(string(data), "\n") {
		f := strings.Fields(line)
		if len(f) < 2 {
			continue
		}
		nameToOid[f[0]] = f[1]
		oidToName[f[1]] = f[0]
	}
}

func flags() *flag.FlagSet {
	var f flag.FlagSet
	f.BoolVar(&testing, "testing", testing, "print data w/o saving")
	f.BoolVar(&snmpNames, "names", snmpNames, "print column names and exit")
	f.StringVar(&configFile, "config", configFile, "config file")
	f.BoolVar(&verbose, "verbose", verbose, "verbose mode")
	f.IntVar(&repeat, "repeat", repeat, "number of times to repeat")
	f.IntVar(&freq, "freq", freq, "delay (in seconds)")
	f.IntVar(&httpPort, "http", httpPort, "http port")
	f.StringVar(&logDir, "logs", logDir, "log directory")
	f.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		f.VisitAll(func(flag *flag.Flag) {
			format := "%10s: %s\n"
			fmt.Fprintf(os.Stderr, format, "-"+flag.Name, flag.Usage)
		})
		fmt.Fprintf(os.Stderr, "\nAll settings can be set in config file: %s\n", configFile)
		os.Exit(1)

	}
	return &f
}

func init() {
	// parse first time to see if config file is being specified
	f := flags()
	f.Parse(os.Args[1:])
	// now load up config settings
	if _, err := os.Stat(configFile); err != nil {
		log.Fatal(err)
	} else {
		data, err := ioutil.ReadFile(configFile)
		if err != nil {
			log.Fatal(err)
		}
		err = gcfg.ReadStringInto(&cfg, string(data))
		if err != nil {
			log.Fatalf("Failed to parse gcfg data: %s", err)
		}
		httpPort = cfg.HTTP.Port
	}

	if len(cfg.General.LogDir) > 0 {
		logDir = cfg.General.LogDir
	}
	if len(cfg.General.OidFile) > 0 {
		oidFile = cfg.General.OidFile
	}

	for _, s := range cfg.Snmp {
		s.LoadPorts()
		s.debugging = make(chan bool)
		s.enabled = make(chan chan bool)
	}
	var ok bool
	for name, c := range cfg.Snmp {
		if c.mib, ok = cfg.Mibs[name]; !ok {
			if c.mib, ok = cfg.Mibs["*"]; !ok {
				fatal("No mib data found for config:", name)
			}
		}
		c.Translate()
		c.OIDs()
		if c.Freq == 0 {
			c.Freq = freq
		}
	}

	// only run when one needs to see the interface names of the device
	if snmpNames {
		for _, c := range cfg.Snmp {
			fmt.Println("\nSNMP host:", c.Host)
			fmt.Println("=========================================")
			printSnmpNames(c)
		}
		os.Exit(0)
	}

	// re-read cmd line args to override as indicated
	f = flags()
	f.Parse(os.Args[1:])
	os.Mkdir(logDir, 0755)

	// now make sure each snmp device has a db
	for name, c := range cfg.Snmp {
		// default is to use name of snmp config, but it can be overridden
		if len(c.Config) > 0 {
			name = c.Config
		}
		if c.Influx, ok = cfg.Influx[name]; !ok {
			if c.Influx, ok = cfg.Influx["*"]; !ok {
				fatal("No influx config for snmp device:", name)
			}
		}
		c.Influx.Init()
	}

	var ferr error
	errorName = fmt.Sprintf("error.%d.log", cfg.HTTP.Port)
	errorPath := filepath.Join(logDir, errorName)
	errorLog, ferr = os.OpenFile(errorPath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0664)
	if ferr != nil {
		log.Fatal("Can't open error log:", ferr)
	}
}

func errLog(msg string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, msg, args...)
	fmt.Fprintf(errorLog, msg, args...)
}

func errMsg(msg string, err error) {
	now := time.Now()
	errLog("%s\t%s: %s\n", now.Format(layout), msg, err)
}

func main() {
	var wg sync.WaitGroup
	defer func() {
		errorLog.Close()
	}()
	for _, c := range cfg.Snmp {
		wg.Add(1)
		go c.Gather(repeat, &wg)
	}
	if repeat > 0 {
		wg.Wait()
	} else {
		if httpPort > 0 {
			webServer(httpPort)
		} else {
			<-quit
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	//"github.com/kisielk/whisper-go/whisper"
	whisper "github.com/robyoung/go-whisper"
	pickle "github.com/kisielk/og-rek"

	"net/http"
	"encoding/json"
	"path/filepath"
	"strings"
	"strconv"
	"math"
	"fmt"
)

var config = struct {
	WhisperData	string
}{
	WhisperData: "/var/lib/carbon/whisper",
	//WhisperData: "..",
}

type WhisperFetchResponse struct {
	Name        string      `json:"name"`
	StartTime   int         `json:"startTime"`
	StopTime    int         `json:"stopTime"`
	StepTime    int         `json:"stepTime"`
	Values      []float64   `json:"values"`
	IsAbsent    []bool      `json:"isAbsent"`
}

type WhisperGlobResponse struct {
	Name        string      `json:"name"`
	Paths       []string    `json:"paths"`
}

func findHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /metrics/find/?local=1&format=pickle&query=general.hadoop.lhr4.ha201jobtracker-01.jobtracker.NonHeapMemoryUsage.committed HTTP/1.1
//	http://localhost:8080/metrics/find/?query=test
	req.ParseForm()
	glob := req.FormValue("query")
	format := req.FormValue("format")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		return
	}

	/* things to glob:
	 * - carbon.relays  -> carbon.relays
	 * - carbon.re      -> carbon.relays, carbon.rewhatever
	 * - carbon.[rz]    -> carbon.relays, carbon.zipper
	 * - carbon.{re,zi} -> carbon.relays, carbon.zipper
	 * - implicit * at the end of each query
	 * - match is either dir or .wsp file
	 * unfortunately, filepath.Glob doesn't handle the curly brace
	 * expansion for us */
	lbrace := strings.Index(glob, "{")
	rbrace := -1
	if lbrace > -1 {
		rbrace = strings.Index(glob[lbrace:], "}")
		if rbrace > -1 {
			rbrace += lbrace
		}
	}
	files := make([]string, 0)
	if lbrace > -1 && rbrace > -1 {
		expansion := glob[lbrace + 1:rbrace]
		parts := strings.Split(expansion, ",")
		for _, sub := range parts {
			sglob := glob[:lbrace] + sub + glob[rbrace + 1:]
			path := config.WhisperData + "/" + strings.Replace(sglob, ".", "/", -1) + "*"
			nfiles, err := filepath.Glob(path)
			if err == nil {
				files = append(files, nfiles...)
			}
		}
	} else {
		path := config.WhisperData + "/" + strings.Replace(glob, ".", "/", -1) + "*"
		nfiles, err := filepath.Glob(path)
		if err != nil {
			files = append(files, nfiles...)
		}
	}

	leafs := make([]bool, len(files))
	for i, p := range files {
		p = p[len(config.WhisperData + "/"):]
		if strings.HasSuffix(p, ".wsp") {
			p = p[:len(p) - 4]
			leafs[i] = true
		} else {
			leafs[i] = false
		}
		files[i] = strings.Replace(p, "/", ".", -1)
	}

	if format == "json" {
		response := WhisperGlobResponse {
			Name:		glob,
			Paths:		make([]string, 0),
		}
		for _, p := range files {
			response.Paths = append(response.Paths, p)
		}
		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", glob, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		// [{'metric_path': 'metric', 'intervals': [(x,y)], 'isLeaf': True},]
		var metrics []map[string]interface{}
		var m map[string]interface{}

		for i, p := range files {
			m = make(map[string]interface{})
			m["metric_path"] = p
			// m["intervals"] = dunno how to do a tuple here
			m["isLeaf"] = leafs[i]
			metrics = append(metrics, m)
		}

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}
	fmt.Printf("find: %d hits for %s\n", len(files), glob)
	return
}

func fetchHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /render/?target=general.me.1.percent_time_active.pfnredis&format=pickle&from=1396008021&until=1396022421 HTTP/1.1
//	http://localhost:8080/render/?target=testmetric&format=json&from=1395961200&until=1395961800
	req.ParseForm()
	metric := req.FormValue("target")
	format := req.FormValue("format")
	from := req.FormValue("from")
	until := req.FormValue("until")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		http.Error(wr, "Bad request (unsupported format)", http.StatusBadRequest)
		return
	}

	path := config.WhisperData + "/" + strings.Replace(metric, ".", "/", -1) + ".wsp"
	w, err := whisper.Open(path)
	if err != nil {
		// the FE/carbonzipper often requests metrics we don't have
		//fmt.Printf("failed to open %s: %s\n", path, err)
		w = nil
	}

	i, err := strconv.Atoi(from)
	if err != nil {
		fmt.Printf("fromTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	fromTime := int(i)
	i, err = strconv.Atoi(until)
	if err != nil {
		fmt.Printf("untilTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	untilTime := int(i)

	if (w != nil) {
		defer w.Close()
	} else {
		http.Error(wr, "Bad request (invalid from/until time)", http.StatusBadRequest)
		return
	}

	points, err := w.Fetch(fromTime, untilTime)
	if err != nil {
		fmt.Printf("failed to getch points from %s: %s\n", path, err)
		return
	}
	values := points.Values()

	if format == "json" {
		response := WhisperFetchResponse {
			Name:		metric,
			StartTime:	points.FromTime(),
			StopTime:	points.UntilTime(),
			StepTime:	points.Step(),
			Values:		make([]float64, len(values)),
			IsAbsent:	make([]bool, len(values)),
		}

		for i, p := range values {
			if math.IsNaN(p) {
				response.Values[i] = 0
				response.IsAbsent[i] = true
			} else {
				response.Values[i] = p
				response.IsAbsent[i] = false
			}
		}

		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", path, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		//[{'start': 1396271100, 'step': 60, 'name': 'metric',
		//'values': [9.0, 19.0, None], 'end': 1396273140}
		var metrics []map[string]interface{}
		var m map[string]interface{}

		m = make(map[string]interface{})
		m["start"] = points.FromTime()
		m["step"] = points.Step()
		m["end"] = points.UntilTime()
		m["name"] = metric

		mv := make([]interface{}, len(values))
		for i, p := range values {
			if math.IsNaN(p) {
				mv[i] = nil
			} else {
				mv[i] = p
			}
		}

		m["values"] = mv
		metrics = append(metrics, m)

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}

	fmt.Printf("served %d points\n", len(values))
	return
}

func main() {
	http.HandleFunc("/metrics/find/", findHandler)
	http.HandleFunc("/render/", fetchHandler)

	http.ListenAndServe(":8080", nil)
}
<commit_msg>Fix boolean logic error<commit_after>package main

import (
	//"github.com/kisielk/whisper-go/whisper"
	whisper "github.com/robyoung/go-whisper"
	pickle "github.com/kisielk/og-rek"

	"net/http"
	"encoding/json"
	"path/filepath"
	"strings"
	"strconv"
	"math"
	"fmt"
)

var config = struct {
	WhisperData	string
}{
	WhisperData: "/var/lib/carbon/whisper",
	//WhisperData: "..",
}

type WhisperFetchResponse struct {
	Name        string      `json:"name"`
	StartTime   int         `json:"startTime"`
	StopTime    int         `json:"stopTime"`
	StepTime    int         `json:"stepTime"`
	Values      []float64   `json:"values"`
	IsAbsent    []bool      `json:"isAbsent"`
}

type WhisperGlobResponse struct {
	Name        string      `json:"name"`
	Paths       []string    `json:"paths"`
}

func findHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /metrics/find/?local=1&format=pickle&query=general.hadoop.lhr4.ha201jobtracker-01.jobtracker.NonHeapMemoryUsage.committed HTTP/1.1
//	http://localhost:8080/metrics/find/?query=test
	req.ParseForm()
	glob := req.FormValue("query")
	format := req.FormValue("format")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		return
	}

	/* things to glob:
	 * - carbon.relays  -> carbon.relays
	 * - carbon.re      -> carbon.relays, carbon.rewhatever
	 * - carbon.[rz]    -> carbon.relays, carbon.zipper
	 * - carbon.{re,zi} -> carbon.relays, carbon.zipper
	 * - implicit * at the end of each query
	 * - match is either dir or .wsp file
	 * unfortunately, filepath.Glob doesn't handle the curly brace
	 * expansion for us */
	lbrace := strings.Index(glob, "{")
	rbrace := -1
	if lbrace > -1 {
		rbrace = strings.Index(glob[lbrace:], "}")
		if rbrace > -1 {
			rbrace += lbrace
		}
	}
	files := make([]string, 0)
	if lbrace > -1 && rbrace > -1 {
		expansion := glob[lbrace + 1:rbrace]
		parts := strings.Split(expansion, ",")
		for _, sub := range parts {
			sglob := glob[:lbrace] + sub + glob[rbrace + 1:]
			path := config.WhisperData + "/" + strings.Replace(sglob, ".", "/", -1) + "*"
			nfiles, err := filepath.Glob(path)
			if err == nil {
				files = append(files, nfiles...)
			}
		}
	} else {
		path := config.WhisperData + "/" + strings.Replace(glob, ".", "/", -1) + "*"
		nfiles, err := filepath.Glob(path)
		if err == nil {
			files = append(files, nfiles...)
		}
	}

	leafs := make([]bool, len(files))
	for i, p := range files {
		p = p[len(config.WhisperData + "/"):]
		if strings.HasSuffix(p, ".wsp") {
			p = p[:len(p) - 4]
			leafs[i] = true
		} else {
			leafs[i] = false
		}
		files[i] = strings.Replace(p, "/", ".", -1)
	}

	if format == "json" {
		response := WhisperGlobResponse {
			Name:		glob,
			Paths:		make([]string, 0),
		}
		for _, p := range files {
			response.Paths = append(response.Paths, p)
		}
		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", glob, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		// [{'metric_path': 'metric', 'intervals': [(x,y)], 'isLeaf': True},]
		var metrics []map[string]interface{}
		var m map[string]interface{}

		for i, p := range files {
			m = make(map[string]interface{})
			m["metric_path"] = p
			// m["intervals"] = dunno how to do a tuple here
			m["isLeaf"] = leafs[i]
			metrics = append(metrics, m)
		}

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}
	fmt.Printf("find: %d hits for %s\n", len(files), glob)
	return
}

func fetchHandler(wr http.ResponseWriter, req *http.Request) {
//	GET /render/?target=general.me.1.percent_time_active.pfnredis&format=pickle&from=1396008021&until=1396022421 HTTP/1.1
//	http://localhost:8080/render/?target=testmetric&format=json&from=1395961200&until=1395961800
	req.ParseForm()
	metric := req.FormValue("target")
	format := req.FormValue("format")
	from := req.FormValue("from")
	until := req.FormValue("until")

	if format != "json" && format != "pickle" {
		fmt.Printf("dropping invalid uri (format=%s): %s\n",
				format, req.URL.RequestURI())
		http.Error(wr, "Bad request (unsupported format)", http.StatusBadRequest)
		return
	}

	path := config.WhisperData + "/" + strings.Replace(metric, ".", "/", -1) + ".wsp"
	w, err := whisper.Open(path)
	if err != nil {
		// the FE/carbonzipper often requests metrics we don't have
		//fmt.Printf("failed to open %s: %s\n", path, err)
		w = nil
	}

	i, err := strconv.Atoi(from)
	if err != nil {
		fmt.Printf("fromTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	fromTime := int(i)
	i, err = strconv.Atoi(until)
	if err != nil {
		fmt.Printf("untilTime (%s) invalid: %s\n", from, err)
		if w != nil {
			w.Close()
		}
		w = nil
	}
	untilTime := int(i)

	if (w != nil) {
		defer w.Close()
	} else {
		http.Error(wr, "Bad request (invalid from/until time)", http.StatusBadRequest)
		return
	}

	points, err := w.Fetch(fromTime, untilTime)
	if err != nil {
		fmt.Printf("failed to getch points from %s: %s\n", path, err)
		return
	}
	values := points.Values()

	if format == "json" {
		response := WhisperFetchResponse {
			Name:		metric,
			StartTime:	points.FromTime(),
			StopTime:	points.UntilTime(),
			StepTime:	points.Step(),
			Values:		make([]float64, len(values)),
			IsAbsent:	make([]bool, len(values)),
		}

		for i, p := range values {
			if math.IsNaN(p) {
				response.Values[i] = 0
				response.IsAbsent[i] = true
			} else {
				response.Values[i] = p
				response.IsAbsent[i] = false
			}
		}

		b, err := json.Marshal(response)
		if err != nil {
			fmt.Printf("failed to create JSON data for %s: %s\n", path, err)
			return
		}
		wr.Write(b)
	} else if format == "pickle" {
		//[{'start': 1396271100, 'step': 60, 'name': 'metric',
		//'values': [9.0, 19.0, None], 'end': 1396273140}
		var metrics []map[string]interface{}
		var m map[string]interface{}

		m = make(map[string]interface{})
		m["start"] = points.FromTime()
		m["step"] = points.Step()
		m["end"] = points.UntilTime()
		m["name"] = metric

		mv := make([]interface{}, len(values))
		for i, p := range values {
			if math.IsNaN(p) {
				mv[i] = nil
			} else {
				mv[i] = p
			}
		}

		m["values"] = mv
		metrics = append(metrics, m)

		wr.Header().Set("Content-Type", "application/pickle")
		pEnc := pickle.NewEncoder(wr)
		pEnc.Encode(metrics)
	}

	fmt.Printf("served %d points\n", len(values))
	return
}

func main() {
	http.HandleFunc("/metrics/find/", findHandler)
	http.HandleFunc("/render/", fetchHandler)

	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"turnt-octo-hipster/max"
)

func main() {
	var sets int
	_, err := fmt.Scanf("%d", &sets)
	if err != nil {
		panic("could not read sets")
	}
	for ii := 0; ii < sets; ii++ {
		var col int
		_, err := fmt.Scanf("%d", &col)
		if err != nil {
			panic("could not read number of columns")
		}
		var xx, yy []int
		for jj := 0; jj < col; jj++ {
			var val int
			_, err := fmt.Scanf("%d", &val)
			if err != nil {
				panic("could not read row")
			}
			xx = append(xx, val)
		}
		for jj := 0; jj < col; jj++ {
			var val int
			_, err := fmt.Scanf("%d", &val)
			if err != nil {
				panic("could not read row")
			}
			yy = append(yy, val)
		}
		fmt.Printf("The maximum distance is %v\n\n", max.MaximumDistance(xx, yy))
	}
}
<commit_msg>Refactor if err != nil { panic(whatever) } into functions<commit_after>package main

import (
	"fmt"
	"turnt-octo-hipster/max"
)

func main() {
	var sets int
	_, err := fmt.Scanf("%d", &sets)
	if err != nil {
		panic("could not read sets")
	}
	for ii := 0; ii < sets; ii++ {
		var col int
		_, err := fmt.Scanf("%d", &col)
		check(err, "could not read number of columns")
		var xx, yy []int
		for jj := 0; jj < col; jj++ {
			var val int
			_, err := fmt.Scanf("%d", &val)
			check(err, "could not read row")
			xx = append(xx, val)
		}
		for jj := 0; jj < col; jj++ {
			var val int
			_, err := fmt.Scanf("%d", &val)
			check(err, "could not read row")
			yy = append(yy, val)
		}
		fmt.Printf("The maximum distance is %v\n\n", max.MaximumDistance(xx, yy))
	}
}

func check(err error, str string) {
	if err != nil {
		panic(str)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/maxbrunsfeld/counterfeiter/generator"
	"github.com/maxbrunsfeld/counterfeiter/locator"
)

var usage = `
USAGE
	counterfeiter
		[-o <output-path>] [--fake-name <fake-name>]
		<source-path> <interface-name> [-]

ARGUMENTS
	source-path
		Path to the file or directory containing the interface to fake

	interface-name
		Name of the interface to fake

	'-' argument
		Write code to standard out instead of to a file

OPTIONS
	-o
		Path to the file or directory to which code should be written.
		This also determines the package name that will be used.
		By default, code will be written to a 'fakes' directory inside
		of the directory containing the original interface.

	--fake-name
		Name of the fake struct to generate. By default, 'Fake' will
		be prepended to the name of the original interface.
`

var outputPathFlag = flag.String(
	"o",
	"",
	"The file or directory to which the generated fake will be written",
)

var fakeNameFlag = flag.String(
	"fake-name",
	"",
	"The name of the fake struct",
)

func main() {
	flag.Parse()
	args := flag.Args()
	if len(args) < 2 {
		fail("%s", usage)
	}

	sourceDir := getSourceDir(args[0])
	interfaceName := args[1]
	fakeName := getFakeName(interfaceName, *fakeNameFlag)
	outputPath := getOutputPath(sourceDir, fakeName, *outputPathFlag)
	outputDir := filepath.Dir(outputPath)
	fakePackageName := filepath.Base(outputDir)
	shouldPrintToStdout := len(args) >= 3 && args[2] == "-"

	iface, err := locator.GetInterfaceFromFilePath(interfaceName, sourceDir)
	if err != nil {
		fail("%v", err)
	}

	code, err := generator.CodeGenerator{
		Model:       *iface,
		StructName:  fakeName,
		PackageName: fakePackageName,
	}.GenerateFake()

	if err != nil {
		fail("%v", err)
	}

	if shouldPrintToStdout {
		fmt.Println(code)
	} else {
		os.MkdirAll(outputDir, 0777)
		file, err := os.Create(outputPath)
		if err != nil {
			fail("Couldn't create fake file - %v", err)
		}

		_, err = file.WriteString(code)
		if err != nil {
			fail("Couldn't write to fake file - %v", err)
		}

		rel, err := filepath.Rel(cwd(), outputPath)
		if err != nil {
			fail("%v", err)
		}

		fmt.Printf("Wrote `%s` to `%s`\n", fakeName, rel)
	}
}

func getSourceDir(arg string) string {
	if !filepath.IsAbs(arg) {
		arg = filepath.Join(cwd(), arg)
	}

	arg, err := filepath.EvalSymlinks(arg)

	stat, err := os.Stat(arg)
	if err != nil {
		fail("No such file or directory '%s'", arg)
	}

	if !stat.IsDir() {
		return filepath.Dir(arg)
	} else {
		return arg
	}
}

func getOutputPath(sourceDir, fakeName, arg string) string {
	if arg == "" {
		return filepath.Join(sourceDir, "fakes", snakeCase(fakeName)+".go")
	} else {
		if !filepath.IsAbs(arg) {
			arg = filepath.Join(cwd(), arg)
		}
		return arg
	}
}

func getFakeName(interfaceName, arg string) string {
	if arg == "" {
		return "Fake" + interfaceName
	} else {
		return arg
	}
}

func snakeCase(input string) string {
	camelRegexp := regexp.MustCompile("([a-z])([A-Z])")
	return strings.ToLower(camelRegexp.ReplaceAllString(input, "${1}_${2}"))
}

func cwd() string {
	dir, err := os.Getwd()
	if err != nil {
		fail("Error - couldn't determine current working directory")
	}
	return dir
}

func fail(s string, args ...interface{}) {
	fmt.Printf(s+"\n", args...)
	os.Exit(1)
}
<commit_msg>whitespace<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/maxbrunsfeld/counterfeiter/generator"
	"github.com/maxbrunsfeld/counterfeiter/locator"
)

var usage = `
USAGE
	counterfeiter
		[-o <output-path>] [--fake-name <fake-name>]
		<source-path> <interface-name> [-]

ARGUMENTS
	source-path
		Path to the file or directory containing the interface to fake

	interface-name
		Name of the interface to fake

	'-' argument
		Write code to standard out instead of to a file

OPTIONS
	-o
		Path to the file or directory to which code should be written.
		This also determines the package name that will be used.
		By default, code will be written to a 'fakes' directory inside
		of the directory containing the original interface.

	--fake-name
		Name of the fake struct to generate. By default, 'Fake' will
		be prepended to the name of the original interface.
`

var outputPathFlag = flag.String(
	"o",
	"",
	"The file or directory to which the generated fake will be written",
)

var fakeNameFlag = flag.String(
	"fake-name",
	"",
	"The name of the fake struct",
)

func main() {
	flag.Parse()
	args := flag.Args()

	if len(args) < 2 {
		fail("%s", usage)
	}

	sourceDir := getSourceDir(args[0])
	interfaceName := args[1]
	fakeName := getFakeName(interfaceName, *fakeNameFlag)
	outputPath := getOutputPath(sourceDir, fakeName, *outputPathFlag)
	outputDir := filepath.Dir(outputPath)
	fakePackageName := filepath.Base(outputDir)
	shouldPrintToStdout := len(args) >= 3 && args[2] == "-"

	iface, err := locator.GetInterfaceFromFilePath(interfaceName, sourceDir)
	if err != nil {
		fail("%v", err)
	}

	code, err := generator.CodeGenerator{
		Model:       *iface,
		StructName:  fakeName,
		PackageName: fakePackageName,
	}.GenerateFake()

	if err != nil {
		fail("%v", err)
	}

	if shouldPrintToStdout {
		fmt.Println(code)
	} else {
		os.MkdirAll(outputDir, 0777)
		file, err := os.Create(outputPath)
		if err != nil {
			fail("Couldn't create fake file - %v", err)
		}

		_, err = file.WriteString(code)
		if err != nil {
			fail("Couldn't write to fake file - %v", err)
		}

		rel, err := filepath.Rel(cwd(), outputPath)
		if err != nil {
			fail("%v", err)
		}

		fmt.Printf("Wrote `%s` to `%s`\n", fakeName, rel)
	}
}

func getSourceDir(arg string) string {
	if !filepath.IsAbs(arg) {
		arg = filepath.Join(cwd(), arg)
	}

	arg, err := filepath.EvalSymlinks(arg)

	stat, err := os.Stat(arg)
	if err != nil {
		fail("No such file or directory '%s'", arg)
	}

	if !stat.IsDir() {
		return filepath.Dir(arg)
	} else {
		return arg
	}
}

func getOutputPath(sourceDir, fakeName, arg string) string {
	if arg == "" {
		return filepath.Join(sourceDir, "fakes", snakeCase(fakeName)+".go")
	} else {
		if !filepath.IsAbs(arg) {
			arg = filepath.Join(cwd(), arg)
		}
		return arg
	}
}

func getFakeName(interfaceName, arg string) string {
	if arg == "" {
		return "Fake" + interfaceName
	} else {
		return arg
	}
}

func snakeCase(input string) string {
	camelRegexp := regexp.MustCompile("([a-z])([A-Z])")
	return strings.ToLower(camelRegexp.ReplaceAllString(input, "${1}_${2}"))
}

func cwd() string {
	dir, err := os.Getwd()
	if err != nil {
		fail("Error - couldn't determine current working directory")
	}
	return dir
}

func fail(s string, args ...interface{}) {
	fmt.Printf(s+"\n", args...)
	os.Exit(1)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"io"
	"log"
	"os"
	"os/exec"
	"time"
)

func init() {
	f, _ := os.OpenFile("/var/log/sendmail-logger.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	log.SetOutput(f)
}

func main() {
	body := ""
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		body += scanner.Text() + "\n"
	}
	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
	defer SendMail(body)

	conf, err := LoadConfig()
	if err != nil {
		log.Print(err)
		return
	}
	file, err := os.OpenFile(conf.LogFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0664)
	if err != nil {
		log.Print(err)
		return
	}
	defer file.Close()

	header := "Sendmail Date: " + time.Now().String()
	file.Write(([]byte)(header + "\n" + body))
}

func SendMail(body string) {
	sendmail := exec.Command("sendmail", "-t")
	stdin, _ := sendmail.StdinPipe()

	err := sendmail.Start()
	if err != nil {
		log.Fatal(err)
	}
	io.WriteString(stdin, body+".\n")

	err = sendmail.Wait()
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>add -i option to sendmail command<commit_after>package main

import (
	"bufio"
	"io"
	"log"
	"os"
	"os/exec"
	"time"
)

func init() {
	f, _ := os.OpenFile("/var/log/sendmail-logger.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	log.SetOutput(f)
}

func main() {
	body := ""
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		body += scanner.Text() + "\n"
	}
	if err := scanner.Err(); err != nil {
		log.Fatal(err)
	}
	defer SendMail(body)

	conf, err := LoadConfig()
	if err != nil {
		log.Print(err)
		return
	}
	file, err := os.OpenFile(conf.LogFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0664)
	if err != nil {
		log.Print(err)
		return
	}
	defer file.Close()

	header := "Sendmail Date: " + time.Now().String()
	file.Write(([]byte)(header + "\n" + body))
}

func SendMail(body string) {
	sendmail := exec.Command("sendmail", "-t", "-i")
	stdin, _ := sendmail.StdinPipe()

	io.WriteString(stdin, body)
	stdin.Close()

	err := sendmail.Run()
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/herald-it/goncord/controllers"
	. "github.com/herald-it/goncord/utils"

	"log"
	"net/http"

	"github.com/julienschmidt/httprouter"
	"gopkg.in/mgo.v2"
)

func getSession() *mgo.Session {
	set := GetSettingInstance()
	s, err := mgo.Dial(set.Database.Host)
	LogError(err)

	return s
}

func main() {
	uc := controllers.NewUserController(getSession())
	us := controllers.NewServiceController(getSession())

	var router = httprouter.New()
	router.POST("/register", ErrWrap(uc.RegisterUser))
	router.POST("/login", ErrWrap(uc.LoginUser))
	router.POST("/validate", ErrWrap(us.IsValid))

	log.Fatal(http.ListenAndServe(":8228", router))
}
<commit_msg>Add static instance settings.<commit_after>package main

import (
	"github.com/herald-it/goncord/controllers"
	"github.com/herald-it/goncord/models"
	. "github.com/herald-it/goncord/utils"

	"log"
	"net/http"

	"github.com/julienschmidt/httprouter"
	"gopkg.in/mgo.v2"
)

func getSession() *mgo.Session {
	s, err := mgo.Dial(models.Set.Database.Host)
	LogError(err)

	return s
}

func main() {
	models.LoadSettings()

	uc := controllers.NewUserController(getSession())
	us := controllers.NewServiceController(getSession())

	var router = httprouter.New()
	router.POST("/register", ErrWrap(uc.RegisterUser))
	router.POST("/login", ErrWrap(uc.LoginUser))
	router.POST("/validate", ErrWrap(us.IsValid))

	log.Fatal(http.ListenAndServe(":8228", router))
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"

	"github.com/veandco/go-sdl2/sdl"
)

type EventRegion struct {
	Rect *sdl.Rect
}

func NewEventRegion(x, y, width, height int32) *EventRegion {
	er := EventRegion{Rect: &sdl.Rect{X: x, Y: y, W: width, H: height}}
	return &er
}

func (er *EventRegion) SDLRect() *sdl.Rect {
	return er.Rect
}

func (er *EventRegion) HitWhat(x int32, y int32) *EventRegion {
	if x < er.Rect.X || x > er.Rect.X+er.Rect.W {
		return nil
	}
	if y < er.Rect.Y || y > er.Rect.Y+er.Rect.H {
		return nil
	}
	return er
}

type RegionList []*EventRegion

func (rl RegionList) HitWhat(x int32, y int32) *EventRegion {
	for _, region := range rl {
		if what := region.HitWhat(x, y); what != nil {
			return what
		}
	}
	return nil
}

const CARD_WIDTH = 100
const CARD_HEIGHT = 180

func main() {
	res := sdl.Init(sdl.INIT_VIDEO)
	log.Println(res)

	//eventRegions := make([]*EventRegion, 0)
	eventRegions := make(RegionList, 0)
	var x int32
	var y int32 = 20
	for i := 0; i < 8; i++ {
		x = int32(80 + (i*CARD_WIDTH + i*10))
		eventRegions = append(eventRegions, NewEventRegion(x, y, CARD_WIDTH, CARD_HEIGHT))
	}

	y = 520
	for i := 0; i < 8; i++ {
		x = int32(80 + (i*CARD_WIDTH + i*10))
		eventRegions = append(eventRegions, NewEventRegion(x, y, CARD_WIDTH, CARD_HEIGHT))
	}

	y = 280
	eventRegions = append(eventRegions, NewEventRegion(30, y, CARD_WIDTH, CARD_HEIGHT))
	eventRegions = append(eventRegions, NewEventRegion(312, y, CARD_WIDTH, CARD_HEIGHT))
	eventRegions = append(eventRegions, NewEventRegion(612, y, CARD_WIDTH, CARD_HEIGHT))
	eventRegions = append(eventRegions, NewEventRegion(894, y, CARD_WIDTH, CARD_HEIGHT))

	window := sdl.CreateWindow("Speed", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, 1024, 768, sdl.WINDOW_SHOWN)

	renderer := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if renderer == nil {
		log.Println("Failed to create renderer:", sdl.GetError())
		os.Exit(1)
	}

	imgCard42 := sdl.LoadBMP("42.bmp")
	log.Println(imgCard42)

	texture := renderer.CreateTextureFromSurface(imgCard42)
	if texture == nil {
		log.Println("Failed to create texture (42):", sdl.GetError())
	}

	src := sdl.Rect{0, 0, 100, 180}
	dst := sdl.Rect{100, 50, 100, 180}

	renderer.Clear()
	renderer.Copy(texture, &src, &dst)

	renderer.SetDrawColor(255, 255, 255, 255)
	for _, region := range eventRegions {
		renderer.DrawRect(region.SDLRect())
	}
	renderer.SetDrawColor(0, 0, 0, 255)

	renderer.Present()

	var event sdl.Event
	running := true
	for running {
		for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				running = false
			/*case *sdl.MouseMotionEvent:
			fmt.Printf("[%d ms] MouseMotion\ttype:%d\tid:%d\tx:%d\ty:%d\txrel:%d\tyrel:%d\n",
				t.Timestamp, t.Type, t.Which, t.X, t.Y, t.XRel, t.YRel)*/
			case *sdl.MouseButtonEvent:
				fmt.Printf("[%d ms] MouseButton\ttype:%d\tid:%d\tx:%d\ty:%d\tbutton:%d\tstate:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y, t.Button, t.State)
				fmt.Println(eventRegions.HitWhat(t.X, t.Y))
			case *sdl.MouseWheelEvent:
				fmt.Printf("[%d ms] MouseWheel\ttype:%d\tid:%d\tx:%d\ty:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y)
			case *sdl.KeyUpEvent:
				fmt.Printf("[%d ms] Keyboard\ttype:%d\tsym:%c\tmodifiers:%d\tstate:%d\trepeat:%d\n",
					t.Timestamp, t.Type, t.Keysym.Sym, t.Keysym.Mod, t.State, t.Repeat)
			}
		}
	}

	window.Destroy()
}
<commit_msg>Drag & Drop<commit_after>package main

import (
	"fmt"
	"log"
	"os"

	"github.com/veandco/go-sdl2/sdl"
)

type EventRegion struct {
	Rect *sdl.Rect
}

func NewEventRegion(x, y, width, height int32) *EventRegion {
	er := EventRegion{Rect: &sdl.Rect{X: x, Y: y, W: width, H: height}}
	return &er
}

func (er *EventRegion) SDLRect() *sdl.Rect {
	return er.Rect
}

func (er *EventRegion) HitWhat(x int32, y int32) *EventRegion {
	if x < er.Rect.X || x > er.Rect.X+er.Rect.W {
		return nil
	}
	if y < er.Rect.Y || y > er.Rect.Y+er.Rect.H {
		return nil
	}
	return er
}

type RegionList []*EventRegion

func (rl RegionList) HitWhat(x int32, y int32) *EventRegion {
	for _, region := range rl {
		if what := region.HitWhat(x, y); what != nil {
			return what
		}
	}
	return nil
}

const CARD_WIDTH = 100
const CARD_HEIGHT = 180

const (
	INTERACTION_STATE_DEFAULT  = 0
	INTERACTION_STATE_DRAGGING = 1
)

func main() {
	interactionState := INTERACTION_STATE_DEFAULT
	fmt.Println(interactionState)
	var draggingWhat *EventRegion
	res := sdl.Init(sdl.INIT_VIDEO)
	log.Println(res)

	//eventRegions := make([]*EventRegion, 0)
	eventRegions := make(RegionList, 0)
	var x int32
	var y int32 = 20
	for i := 0; i < 8; i++ {
		x = int32(80 + (i*CARD_WIDTH + i*10))
		eventRegions = append(eventRegions, NewEventRegion(x, y, CARD_WIDTH, CARD_HEIGHT))
	}

	y = 520
	for i := 0; i < 8; i++ {
		x = int32(80 + (i*CARD_WIDTH + i*10))
		eventRegions = append(eventRegions, NewEventRegion(x, y, CARD_WIDTH, CARD_HEIGHT))
	}

	y = 280
	eventRegions = append(eventRegions, NewEventRegion(30, y, CARD_WIDTH, CARD_HEIGHT))
	eventRegions = append(eventRegions, NewEventRegion(312, y, CARD_WIDTH, CARD_HEIGHT))
	eventRegions = append(eventRegions, NewEventRegion(612, y, CARD_WIDTH, CARD_HEIGHT))
	eventRegions = append(eventRegions, NewEventRegion(894, y, CARD_WIDTH, CARD_HEIGHT))

	window := sdl.CreateWindow("Speed", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, 1024, 768, sdl.WINDOW_SHOWN)

	renderer := sdl.CreateRenderer(window, -1, sdl.RENDERER_ACCELERATED)
	if renderer == nil {
		log.Println("Failed to create renderer:", sdl.GetError())
		os.Exit(1)
	}

	imgCard42 := sdl.LoadBMP("42.bmp")
	log.Println(imgCard42)

	texture := renderer.CreateTextureFromSurface(imgCard42)
	if texture == nil {
		log.Println("Failed to create texture (42):", sdl.GetError())
	}

	src := sdl.Rect{0, 0, 100, 180}
	dst := sdl.Rect{100, 50, 100, 180}

	renderer.Clear()
	renderer.Copy(texture, &src, &dst)

	renderer.SetDrawColor(255, 255, 255, 255)
	for _, region := range eventRegions {
		renderer.DrawRect(region.SDLRect())
	}
	renderer.SetDrawColor(0, 0, 0, 255)

	renderer.Present()

	var event sdl.Event
	running := true
	for running {
		for event = sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
			switch t := event.(type) {
			case *sdl.QuitEvent:
				running = false
			/*case *sdl.MouseMotionEvent:
			fmt.Printf("[%d ms] MouseMotion\ttype:%d\tid:%d\tx:%d\ty:%d\txrel:%d\tyrel:%d\n",
				t.Timestamp, t.Type, t.Which, t.X, t.Y, t.XRel, t.YRel)*/
			case *sdl.MouseButtonEvent:
				fmt.Printf("[%d ms] MouseButton\ttype:%d\tid:%d\tx:%d\ty:%d\tbutton:%d\tstate:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y, t.Button, t.State)
				if t.Button == 1 {
					what := eventRegions.HitWhat(t.X, t.Y)
					if t.Type == 1025 {
						log.Println("MOUSE DOWN. Grab something.")
						if what != nil {
							interactionState = INTERACTION_STATE_DRAGGING
							draggingWhat = what
						}
					} else if t.Type == 1026 {
						log.Println("MOUSE UP. Drop it.")
						if draggingWhat != nil {
							log.Println("DROPPING", draggingWhat, "ON", what)
							interactionState = INTERACTION_STATE_DEFAULT
							draggingWhat = nil
						}

					}
				}
			case *sdl.MouseWheelEvent:
				fmt.Printf("[%d ms] MouseWheel\ttype:%d\tid:%d\tx:%d\ty:%d\n",
					t.Timestamp, t.Type, t.Which, t.X, t.Y)
			case *sdl.KeyUpEvent:
				fmt.Printf("[%d ms] Keyboard\ttype:%d\tsym:%c\tmodifiers:%d\tstate:%d\trepeat:%d\n",
					t.Timestamp, t.Type, t.Keysym.Sym, t.Keysym.Mod, t.State, t.Repeat)
			}
		}
	}

	window.Destroy()
}
<|endoftext|>


<commit_before>// dither project main.go
package main

import (
	"flag"
	"fmt"
	"image"
	"image/color"
	"log"
	"math"
	"os"
	"sync"

	"math/rand"

	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"

	"github.com/nfnt/resize"
	"golang.org/x/image/tiff"
)

var (
	xBlocks       int
	yBlocks       int
	seed          int64
	smooth        bool
	rescaleOutput bool
	gamma         float64
	sRGB          bool
)

const A = 0.985

func main() {
	flag.IntVar(&xBlocks, "x", 0, "Block pixels on horizontal side")
	flag.IntVar(&yBlocks, "y", 0, "Block pixels on vertical side")
	flag.Int64Var(&seed, "r", 0, "Random number seed for dithering")
	flag.BoolVar(&smooth, "s", false, "Produce smoother look")
	flag.BoolVar(&rescaleOutput, "o", false, "Output image is one pixel per block")
	flag.Float64Var(&gamma, "g", 2.2, "Gamma of input image")
	flag.BoolVar(&sRGB, "srgb", false, "Assume sRGB input image (overrides gamma)")
	flag.Parse()
	gammaInit()

	await := &sync.WaitGroup{}
	for _, fname := range flag.Args() {
		await.Add(1)
		go func(filename string) {
			defer await.Done()
			dithered := ditherImage(imgFromFName(filename))
			save(dithered, filename)
		}(fname)
	}
	await.Wait()
}

func imgFromFName(fname string) image.Image {
	f, err := os.Open(fname)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	img, _, err := image.Decode(f)
	if err != nil {
		log.Fatal(err)
	}

	return img
}

func save(i image.Image, name string) {
	var typeName string
	if smooth {
		typeName = "s"
	} else {
		typeName = "d"
	}

	var (
		sizeX int
		sizeY int
	)

	switch {
	case xBlocks != 0 && yBlocks != 0:
		sizeX = xBlocks
		sizeY = yBlocks

	case xBlocks == 0 && yBlocks != 0:
		sizeX = yBlocks * i.Bounds().Size().X / i.Bounds().Size().Y
		sizeY = yBlocks

	case xBlocks != 0 && yBlocks == 0:
		sizeX = xBlocks
		sizeY = xBlocks * i.Bounds().Size().Y / i.Bounds().Size().X

	default:
		sizeX = i.Bounds().Size().X
		sizeY = i.Bounds().Size().Y
	}

	w, err := os.Create(fmt.Sprintf("%s.%s%04dx%04d.tiff", name, typeName, sizeX, sizeY))
	if err != nil {
		log.Fatal(err)
	}
	defer w.Close()

	err = tiff.Encode(w, i, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
	if err != nil {
		log.Fatal(err)
	}
}

var white = color.Gray16{Y: 65535}
var black = color.Gray16{Y: 0}

func ditherImage(i image.Image) image.Image {
	if xBlocks == 0 && yBlocks == 0 {
		return ditherImage1to1(i)
	}

	smaller := resize.Resize(uint(xBlocks), uint(yBlocks), i, resize.Lanczos3)
	dith := ditherImage1to1(smaller)
	finalWidth := uint(i.Bounds().Size().X)
	finalHeight := uint(i.Bounds().Size().Y)
	if smooth {
		return resize.Resize(finalWidth, finalHeight, dith, resize.Lanczos3)
	} else {
		if rescaleOutput {
			return dith
		} else {
			return resize.Resize(finalWidth, finalHeight, dith, resize.NearestNeighbor)
		}
	}
}

func ditherImage1to1(i image.Image) image.Image {
	b := i.Bounds()
	d := image.NewGray16(b)
	r := rand.New(rand.NewSource(seed))

	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			value := color.Gray16Model.Convert(i.At(x, y)).(color.Gray16)
			rand := uint16(r.Uint32())
			if rand < lut[value.Y] {
				d.Set(x, y, white)
			} else {
				d.Set(x, y, black)
			}
		}
	}

	return d
}

func gammaDecode(in float64) float64 {
	return A * math.Pow(in, gamma)
}

var (
	a  = 0.055
	a1 = a + 1.0
)

func sRGBDecode(in float64) float64 {
	if in <= 0.04045 {
		return in / 12.92
	}
	return math.Pow((in+a)/a1, 2.4)
}

var lut []uint16

func gammaInit() {
	lut = make([]uint16, 65536)
	if sRGB {
		for i := 0; i < 65536; i++ {
			lut[i] = uint16(sRGBDecode(float64(i)/65536.0) * 65536.0)
		}
	} else {
		for i := 0; i < 65536; i++ {
			lut[i] = uint16(gammaDecode(float64(i)/65536.0) * 65536.0)
		}
	}
}
<commit_msg>Assume sRGB unless othewise specified.<commit_after>// dither project main.go
package main

import (
	"flag"
	"fmt"
	"image"
	"image/color"
	"log"
	"math"
	"os"
	"sync"

	"math/rand"

	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"

	"github.com/nfnt/resize"
	"golang.org/x/image/tiff"
)

var (
	xBlocks       int
	yBlocks       int
	seed          int64
	smooth        bool
	rescaleOutput bool
	gamma         float64
)

const A = 0.985

func main() {
	flag.IntVar(&xBlocks, "x", 0, "Block pixels on horizontal side")
	flag.IntVar(&yBlocks, "y", 0, "Block pixels on vertical side")
	flag.Int64Var(&seed, "r", 0, "Random number seed for dithering")
	flag.BoolVar(&smooth, "s", false, "Produce smoother look")
	flag.BoolVar(&rescaleOutput, "o", false, "Output image is one pixel per block")
	flag.Float64Var(&gamma, "g", 0.0, "Gamma of input image. If 0.0, then assume sRGB.")
	flag.Parse()
	gammaInit()

	await := &sync.WaitGroup{}
	for _, fname := range flag.Args() {
		await.Add(1)
		go func(filename string) {
			defer await.Done()
			dithered := ditherImage(imgFromFName(filename))
			save(dithered, filename)
		}(fname)
	}
	await.Wait()
}

func imgFromFName(fname string) image.Image {
	f, err := os.Open(fname)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	img, _, err := image.Decode(f)
	if err != nil {
		log.Fatal(err)
	}

	return img
}

func save(i image.Image, name string) {
	var typeName string
	if smooth {
		typeName = "s"
	} else {
		typeName = "d"
	}

	var (
		sizeX int
		sizeY int
	)

	switch {
	case xBlocks != 0 && yBlocks != 0:
		sizeX = xBlocks
		sizeY = yBlocks

	case xBlocks == 0 && yBlocks != 0:
		sizeX = yBlocks * i.Bounds().Size().X / i.Bounds().Size().Y
		sizeY = yBlocks

	case xBlocks != 0 && yBlocks == 0:
		sizeX = xBlocks
		sizeY = xBlocks * i.Bounds().Size().Y / i.Bounds().Size().X

	default:
		sizeX = i.Bounds().Size().X
		sizeY = i.Bounds().Size().Y
	}

	w, err := os.Create(fmt.Sprintf("%s.%s%04dx%04d.tiff", name, typeName, sizeX, sizeY))
	if err != nil {
		log.Fatal(err)
	}
	defer w.Close()

	err = tiff.Encode(w, i, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
	if err != nil {
		log.Fatal(err)
	}
}

var white = color.Gray16{Y: 65535}
var black = color.Gray16{Y: 0}

func ditherImage(i image.Image) image.Image {
	if xBlocks == 0 && yBlocks == 0 {
		return ditherImage1to1(i)
	}

	smaller := resize.Resize(uint(xBlocks), uint(yBlocks), i, resize.Lanczos3)
	dith := ditherImage1to1(smaller)
	finalWidth := uint(i.Bounds().Size().X)
	finalHeight := uint(i.Bounds().Size().Y)
	if smooth {
		return resize.Resize(finalWidth, finalHeight, dith, resize.Lanczos3)
	} else {
		if rescaleOutput {
			return dith
		} else {
			return resize.Resize(finalWidth, finalHeight, dith, resize.NearestNeighbor)
		}
	}
}

func ditherImage1to1(i image.Image) image.Image {
	b := i.Bounds()
	d := image.NewGray16(b)
	r := rand.New(rand.NewSource(seed))

	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			value := color.Gray16Model.Convert(i.At(x, y)).(color.Gray16)
			rand := uint16(r.Uint32())
			if rand < lut[value.Y] {
				d.Set(x, y, white)
			} else {
				d.Set(x, y, black)
			}
		}
	}

	return d
}

func gammaDecode(in float64) float64 {
	return A * math.Pow(in, gamma)
}

var (
	a  = 0.055
	a1 = a + 1.0
)

func sRGBDecode(in float64) float64 {
	if in <= 0.04045 {
		return in / 12.92
	}
	return math.Pow((in+a)/a1, 2.4)
}

var lut []uint16

func gammaInit() {
	lut = make([]uint16, 65536)
	if gamma == 0.0 {
		for i := 0; i < 65536; i++ {
			lut[i] = uint16(sRGBDecode(float64(i)/65536.0) * 65536.0)
		}
	} else {
		for i := 0; i < 65536; i++ {
			lut[i] = uint16(gammaDecode(float64(i)/65536.0) * 65536.0)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	vips "github.com/daddye/vips"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
)

var config Configuration

type Configuration struct {
	MediaServer string
}

func initConfig() {
	file, _ := os.Open("/go/src/app/config.json")
	err := json.NewDecoder(file).Decode(&config)
	if err != nil {
		panic(err)
	}
	file.Close()
}

func main() {
	initConfig()
	http.HandleFunc("/thumbnail/", thumbnailHandler)
	log.Fatal(http.ListenAndServe(":8888", nil))
}

func thumbnailHandler(w http.ResponseWriter, r *http.Request) {
	request_uri := strings.Trim(r.RequestURI, "/thumbnail/")
	request_parts := strings.Split(request_uri, "?")
	image_parts := strings.Split(request_parts[0], "/")

	aPaths := map[string]bool{
		"photos": true,
		"frames": true,
		"pubs":   true,
	}

	if !aPaths[image_parts[0]] {
		http.NotFound(w, r)
		return
	}

	file_path := "media/" + strings.Join(image_parts, "/")
	if err := getImage(file_path); err != nil {
		http.NotFound(w, r)
		return
	}

	r.ParseForm()
	width := Int(r.Form.Get("width"))
	height := Int(r.Form.Get("height"))
	quality := Int(r.Form.Get("quality"))
	crop := Bool(r.Form.Get("crop"))
	enlarge := Bool(r.Form.Get("enlarge"))

	if width == 0 && height == 0 && quality == 0 {
		http.NotFound(w, r)
		return
	}

	if width != 0 && height != 0 {
		crop = true
	}

	options := vips.Options{
		Width:        width,
		Height:       height,
		Crop:         crop,
		Extend:       vips.EXTEND_WHITE,
		Enlarge:      enlarge,
		Interpolator: vips.BILINEAR,
		Gravity:      vips.CENTRE,
		Quality:      quality,
	}

	file, file_err := os.Open(file_path)
	if err != nil {
		http.NotFound(w, r)
		return
	}

	inBuf, buff_err := ioutil.ReadAll(file)
	if err != nil {
		http.NotFound(w, r)
		return
	}

	buf, err := vips.Resize(inBuf, options)
	if err != nil {
		http.NotFound(w, r)
		return
	}

	file.Close()

	w.Header().Set("Content-Type", "image/jpeg")
	w.Header().Set("Content-Size", string(len(buf)))
	w.Write(buf)
}

func Int(v string) int {
	if v == "" {
		return 0
	}

	val, err := strconv.ParseInt(v, 0, 0)
	if err != nil {
		log.Fatal(err)
		return 0
	}
	return int(val)
}

func Bool(v string) bool {
	if v == "1" || strings.ToLower(v) == "true" {
		return true
	}
	return false
}

func getImage(file_name string) error {
	if _, err := os.Stat(file_name); err == nil {
		return err
	}

	uri := config.MediaServer + "/" + file_name
	return DownloadToFile(uri, file_name)
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func HTTPDownload(uri string) ([]byte, error) {
	fmt.Printf("HTTPDownload From: %s.\n", uri)
	res, err := http.Get(uri)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	d, err := ioutil.ReadAll(res.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("ReadFile: Size of download: %d\n", len(d))
	return d, err
}

func WriteFile(dst string, d []byte) error {
	fmt.Printf("WriteFile: Size of download: %d\n", len(d))
	os.MkdirAll(path.Dir(dst), os.ModePerm)
	err := ioutil.WriteFile(dst, d, 0444)
	if err != nil {
		log.Fatal(err)
	}
	return err
}

func DownloadToFile(uri string, dst string) error {
	fmt.Printf("DownloadToFile From: %s.\n", uri)
	d, err := HTTPDownload(uri)
	if err == nil {
		fmt.Printf("downloaded %s.\n", uri)
		if WriteFile(dst, d) == nil {
			fmt.Printf("saved %s as %s\n", uri, dst)
		}
	}
	return err
}
<commit_msg>added extra error handling for image resize<commit_after>package main

import (
	"encoding/json"
	"fmt"
	vips "github.com/daddye/vips"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
)

var config Configuration

type Configuration struct {
	MediaServer string
}

func initConfig() {
	file, _ := os.Open("/go/src/app/config.json")
	err := json.NewDecoder(file).Decode(&config)
	if err != nil {
		panic(err)
	}
	file.Close()
}

func main() {
	initConfig()
	http.HandleFunc("/thumbnail/", thumbnailHandler)
	log.Fatal(http.ListenAndServe(":8888", nil))
}

func thumbnailHandler(w http.ResponseWriter, r *http.Request) {
	request_uri := strings.Trim(r.RequestURI, "/thumbnail/")
	request_parts := strings.Split(request_uri, "?")
	image_parts := strings.Split(request_parts[0], "/")

	aPaths := map[string]bool{
		"photos": true,
		"frames": true,
		"pubs":   true,
	}

	if !aPaths[image_parts[0]] {
		http.NotFound(w, r)
		return
	}

	file_path := "media/" + strings.Join(image_parts, "/")
	if err := getImage(file_path); err != nil {
		http.NotFound(w, r)
		return
	}

	r.ParseForm()
	width := Int(r.Form.Get("width"))
	height := Int(r.Form.Get("height"))
	quality := Int(r.Form.Get("quality"))
	crop := Bool(r.Form.Get("crop"))
	enlarge := Bool(r.Form.Get("enlarge"))

	if width == 0 && height == 0 && quality == 0 {
		http.NotFound(w, r)
		return
	}

	if width != 0 && height != 0 {
		crop = true
	}

	options := vips.Options{
		Width:        width,
		Height:       height,
		Crop:         crop,
		Extend:       vips.EXTEND_WHITE,
		Enlarge:      enlarge,
		Interpolator: vips.BILINEAR,
		Gravity:      vips.CENTRE,
		Quality:      quality,
	}

	file, file_err := os.Open(file_path)
	if file_err != nil {
		http.NotFound(w, r)
		return
	}

	inBuf, buff_err := ioutil.ReadAll(file)
	if buff_err != nil {
		http.NotFound(w, r)
		return
	}

	buf, err := vips.Resize(inBuf, options)
	if err != nil {
		http.NotFound(w, r)
		return
	}

	file.Close()

	w.Header().Set("Content-Type", "image/jpeg")
	w.Header().Set("Content-Size", string(len(buf)))
	w.Write(buf)
}

func Int(v string) int {
	if v == "" {
		return 0
	}

	val, err := strconv.ParseInt(v, 0, 0)
	if err != nil {
		log.Fatal(err)
		return 0
	}
	return int(val)
}

func Bool(v string) bool {
	if v == "1" || strings.ToLower(v) == "true" {
		return true
	}
	return false
}

func getImage(file_name string) error {
	if _, err := os.Stat(file_name); err == nil {
		return err
	}

	uri := config.MediaServer + "/" + file_name
	return DownloadToFile(uri, file_name)
}

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func HTTPDownload(uri string) ([]byte, error) {
	fmt.Printf("HTTPDownload From: %s.\n", uri)
	res, err := http.Get(uri)
	if err != nil {
		log.Fatal(err)
	}
	defer res.Body.Close()
	d, err := ioutil.ReadAll(res.Body)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("ReadFile: Size of download: %d\n", len(d))
	return d, err
}

func WriteFile(dst string, d []byte) error {
	fmt.Printf("WriteFile: Size of download: %d\n", len(d))
	os.MkdirAll(path.Dir(dst), os.ModePerm)
	err := ioutil.WriteFile(dst, d, 0444)
	if err != nil {
		log.Fatal(err)
	}
	return err
}

func DownloadToFile(uri string, dst string) error {
	fmt.Printf("DownloadToFile From: %s.\n", uri)
	d, err := HTTPDownload(uri)
	if err == nil {
		fmt.Printf("downloaded %s.\n", uri)
		if WriteFile(dst, d) == nil {
			fmt.Printf("saved %s as %s\n", uri, dst)
		}
	}
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"

	"github.com/jsok/vending/http"
	"github.com/jsok/vending/machine"
)

func main() {
	var configFile *string = flag.String("config", "config.json", "Path to JSON config file")
	flag.Parse()

	log.Print("Starting vending machine")
	log.Printf("Attempting to load config from %s...\n", *configFile)

	config := &Config{}

	contents, err := ioutil.ReadFile(*configFile)
	if err != nil {
		log.Fatal(err)
	}

	err = json.Unmarshal(contents, config)
	if err != nil {
		log.Fatal(err)
	}

	vendor := machine.NewDefaultVendor()
	for choice, slot := range config.Slots {
		item := slot.Item
		vendor.Stock(choice, slot.Inventory, &machine.Item{item.Name, item.Price})
	}

	changeMaker := machine.NewGreedyChangeMaker(config.Denominations)

	machine := machine.NewMachine(vendor, changeMaker)

	fmt.Println("Vending Machine items available:")
	for _, item := range machine.Describe() {
		available := ""
		if !item.Available {
			available = "OUT OF STOCK"
		}
		fmt.Printf("[%s] -> %s %dc %s\n", item.Choice, item.Item, item.Price, available)
	}

	http.Serve(machine)
}
<commit_msg>Do int to Denomination conversion in main<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"

	"github.com/jsok/vending/http"
	"github.com/jsok/vending/machine"
)

func main() {
	var configFile *string = flag.String("config", "config.json", "Path to JSON config file")
	flag.Parse()

	log.Print("Starting vending machine")
	log.Printf("Attempting to load config from %s...\n", *configFile)

	config := &Config{}

	contents, err := ioutil.ReadFile(*configFile)
	if err != nil {
		log.Fatal(err)
	}

	err = json.Unmarshal(contents, config)
	if err != nil {
		log.Fatal(err)
	}

	vendor := machine.NewDefaultVendor()
	for choice, slot := range config.Slots {
		item := slot.Item
		vendor.Stock(choice, slot.Inventory, &machine.Item{item.Name, item.Price})
	}

	denoms := make([]machine.Denomination, len(config.Denominations))
	for i, d := range config.Denominations {
		denoms[i] = machine.Denomination(d)
	}
	changeMaker := machine.NewGreedyChangeMaker(denoms)

	machine := machine.NewMachine(vendor, changeMaker)

	fmt.Println("Vending Machine items available:")
	for _, item := range machine.Describe() {
		available := ""
		if !item.Available {
			available = "OUT OF STOCK"
		}
		fmt.Printf("[%s] -> %s %dc %s\n", item.Choice, item.Item, item.Price, available)
	}

	http.Serve(machine)
}
<|endoftext|>