<commit_before>package main

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"sync"

	"github.com/Sirupsen/logrus"
	"github.com/docker/go-plugins-helpers/volume"
)

const socketAddress = "/run/docker/plugins/sshfs.sock"

type sshfsVolume struct {
	Password string
	Sshcmd   string
	Port     string
	AllowOther  bool

	Mountpoint  string
	connections int
}

type sshfsDriver struct {
	sync.RWMutex

	root      string
	statePath string
	volumes   map[string]*sshfsVolume
}

func newSshfsDriver(root string) (*sshfsDriver, error) {
	logrus.WithField("method", "new driver").Debug(root)

	d := &sshfsDriver{
		root:      filepath.Join(root, "volumes"),
		statePath: filepath.Join(root, "state", "sshfs-state.json"),
		volumes:   map[string]*sshfsVolume{},
	}

	data, err := ioutil.ReadFile(d.statePath)
	if err != nil {
		if os.IsNotExist(err) {
			logrus.WithField("statePath", d.statePath).Debug("no state found")
		} else {
			return nil, err
		}
	} else {
		if err := json.Unmarshal(data, &d.volumes); err != nil {
			return nil, err
		}
	}

	return d, nil
}

func (d *sshfsDriver) saveState() {
	data, err := json.Marshal(d.volumes)
	if err != nil {
		logrus.WithField("statePath", d.statePath).Error(err)
		return
	}

	if err := ioutil.WriteFile(d.statePath, data, 0644); err != nil {
		logrus.WithField("savestate", d.statePath).Error(err)
	}
}

func (d *sshfsDriver) Create(r volume.Request) volume.Response {
	logrus.WithField("method", "create").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()
	v := &sshfsVolume{}

	for key, val := range r.Options {
		switch key {
		case "sshcmd":
			v.Sshcmd = val
		case "password":
			v.Password = val
		case "port":
			v.Port = val
		case "allow_other":
			v.AllowOther = true
		default:
			return responseError(fmt.Sprintf("unknown option %q=%q", key, val))
		}
	}

	if v.Sshcmd == "" {
		return responseError("'sshcmd' option required")
	}
	v.Mountpoint = filepath.Join(d.root, fmt.Sprintf("%x", md5.Sum([]byte(v.Sshcmd))))

	d.volumes[r.Name] = v

	d.saveState()

	return volume.Response{}
}

func (d *sshfsDriver) Remove(r volume.Request) volume.Response {
	logrus.WithField("method", "remove").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()

	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	if v.connections != 0 {
		return responseError(fmt.Sprintf("volume %s is currently used by a container", r.Name))
	}
	if err := os.RemoveAll(v.Mountpoint); err != nil {
		return responseError(err.Error())
	}
	delete(d.volumes, r.Name)
	d.saveState()
	return volume.Response{}
}

func (d *sshfsDriver) Path(r volume.Request) volume.Response {
	logrus.WithField("method", "path").Debugf("%#v", r)

	d.RLock()
	defer d.RUnlock()

	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	return volume.Response{Mountpoint: v.Mountpoint}
}

func (d *sshfsDriver) Mount(r volume.MountRequest) volume.Response {
	logrus.WithField("method", "mount").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()

	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	if v.connections == 0 {
		fi, err := os.Lstat(v.Mountpoint)
		if os.IsNotExist(err) {
			if err := os.MkdirAll(v.Mountpoint, 0755); err != nil {
				return responseError(err.Error())
			}
		} else if err != nil {
			return responseError(err.Error())
		}

		if fi != nil && !fi.IsDir() {
			return responseError(fmt.Sprintf("%v already exist and it's not a directory", v.Mountpoint))
		}

		if err := d.mountVolume(v); err != nil {
			return responseError(err.Error())
		}
	}

	v.connections++

	return volume.Response{Mountpoint: v.Mountpoint}
}

func (d *sshfsDriver) Unmount(r volume.UnmountRequest) volume.Response {
	logrus.WithField("method", "unmount").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()
	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	v.connections--

	if v.connections <= 0 {
		if err := d.unmountVolume(v.Mountpoint); err != nil {
			return responseError(err.Error())
		}
		v.connections = 0
	}

	return volume.Response{}
}

func (d *sshfsDriver) Get(r volume.Request) volume.Response {
	logrus.WithField("method", "get").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()

	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	return volume.Response{Volume: &volume.Volume{Name: r.Name, Mountpoint: v.Mountpoint}}
}

func (d *sshfsDriver) List(r volume.Request) volume.Response {
	logrus.WithField("method", "list").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()

	var vols []*volume.Volume
	for name, v := range d.volumes {
		vols = append(vols, &volume.Volume{Name: name, Mountpoint: v.Mountpoint})
	}
	return volume.Response{Volumes: vols}
}

func (d *sshfsDriver) Capabilities(r volume.Request) volume.Response {
	logrus.WithField("method", "capabilities").Debugf("%#v", r)

	return volume.Response{Capabilities: volume.Capability{Scope: "local"}}
}

func (d *sshfsDriver) mountVolume(v *sshfsVolume) error {
	cmd := fmt.Sprintf("sshfs -oStrictHostKeyChecking=no %s %s", v.Sshcmd, v.Mountpoint)
	if v.Port != "" {
		cmd = fmt.Sprintf("%s -p %s", cmd, v.Port)
	}
	if v.Password != "" {
		cmd = fmt.Sprintf("echo %s | %s -o workaround=rename -o password_stdin", v.Password, cmd)
	}
	if v.AllowOther {
		cmd = fmt.Sprintf("%s -o allow_other", cmd)
	}
	logrus.Debug(cmd)
	return exec.Command("sh", "-c", cmd).Run()
}

func (d *sshfsDriver) unmountVolume(target string) error {
	cmd := fmt.Sprintf("umount %s", target)
	logrus.Debug(cmd)
	return exec.Command("sh", "-c", cmd).Run()
}

func responseError(err string) volume.Response {
	logrus.Error(err)
	return volume.Response{Err: err}
}

func main() {
	debug := os.Getenv("DEBUG")
	if ok, _ := strconv.ParseBool(debug); ok {
		logrus.SetLevel(logrus.DebugLevel)
	}

	d, err := newSshfsDriver("/mnt")
	if err != nil {
		log.Fatal(err)
	}
	h := volume.NewHandler(d)
	logrus.Infof("listening on %s", socketAddress)
	logrus.Error(h.ServeUnix(socketAddress, 0))
}
<commit_msg>Fix formatting<commit_after>package main

import (
	"crypto/md5"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"sync"

	"github.com/Sirupsen/logrus"
	"github.com/docker/go-plugins-helpers/volume"
)

const socketAddress = "/run/docker/plugins/sshfs.sock"

type sshfsVolume struct {
	Password   string
	Sshcmd     string
	Port       string
	AllowOther bool

	Mountpoint  string
	connections int
}

type sshfsDriver struct {
	sync.RWMutex

	root      string
	statePath string
	volumes   map[string]*sshfsVolume
}

func newSshfsDriver(root string) (*sshfsDriver, error) {
	logrus.WithField("method", "new driver").Debug(root)

	d := &sshfsDriver{
		root:      filepath.Join(root, "volumes"),
		statePath: filepath.Join(root, "state", "sshfs-state.json"),
		volumes:   map[string]*sshfsVolume{},
	}

	data, err := ioutil.ReadFile(d.statePath)
	if err != nil {
		if os.IsNotExist(err) {
			logrus.WithField("statePath", d.statePath).Debug("no state found")
		} else {
			return nil, err
		}
	} else {
		if err := json.Unmarshal(data, &d.volumes); err != nil {
			return nil, err
		}
	}

	return d, nil
}

func (d *sshfsDriver) saveState() {
	data, err := json.Marshal(d.volumes)
	if err != nil {
		logrus.WithField("statePath", d.statePath).Error(err)
		return
	}

	if err := ioutil.WriteFile(d.statePath, data, 0644); err != nil {
		logrus.WithField("savestate", d.statePath).Error(err)
	}
}

func (d *sshfsDriver) Create(r volume.Request) volume.Response {
	logrus.WithField("method", "create").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()
	v := &sshfsVolume{}

	for key, val := range r.Options {
		switch key {
		case "sshcmd":
			v.Sshcmd = val
		case "password":
			v.Password = val
		case "port":
			v.Port = val
		case "allow_other":
			v.AllowOther = true
		default:
			return responseError(fmt.Sprintf("unknown option %q=%q", key, val))
		}
	}

	if v.Sshcmd == "" {
		return responseError("'sshcmd' option required")
	}
	v.Mountpoint = filepath.Join(d.root, fmt.Sprintf("%x", md5.Sum([]byte(v.Sshcmd))))

	d.volumes[r.Name] = v

	d.saveState()

	return volume.Response{}
}

func (d *sshfsDriver) Remove(r volume.Request) volume.Response {
	logrus.WithField("method", "remove").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()

	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	if v.connections != 0 {
		return responseError(fmt.Sprintf("volume %s is currently used by a container", r.Name))
	}
	if err := os.RemoveAll(v.Mountpoint); err != nil {
		return responseError(err.Error())
	}
	delete(d.volumes, r.Name)
	d.saveState()
	return volume.Response{}
}

func (d *sshfsDriver) Path(r volume.Request) volume.Response {
	logrus.WithField("method", "path").Debugf("%#v", r)

	d.RLock()
	defer d.RUnlock()

	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	return volume.Response{Mountpoint: v.Mountpoint}
}

func (d *sshfsDriver) Mount(r volume.MountRequest) volume.Response {
	logrus.WithField("method", "mount").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()

	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	if v.connections == 0 {
		fi, err := os.Lstat(v.Mountpoint)
		if os.IsNotExist(err) {
			if err := os.MkdirAll(v.Mountpoint, 0755); err != nil {
				return responseError(err.Error())
			}
		} else if err != nil {
			return responseError(err.Error())
		}

		if fi != nil && !fi.IsDir() {
			return responseError(fmt.Sprintf("%v already exist and it's not a directory", v.Mountpoint))
		}

		if err := d.mountVolume(v); err != nil {
			return responseError(err.Error())
		}
	}

	v.connections++

	return volume.Response{Mountpoint: v.Mountpoint}
}

func (d *sshfsDriver) Unmount(r volume.UnmountRequest) volume.Response {
	logrus.WithField("method", "unmount").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()
	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	v.connections--

	if v.connections <= 0 {
		if err := d.unmountVolume(v.Mountpoint); err != nil {
			return responseError(err.Error())
		}
		v.connections = 0
	}

	return volume.Response{}
}

func (d *sshfsDriver) Get(r volume.Request) volume.Response {
	logrus.WithField("method", "get").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()

	v, ok := d.volumes[r.Name]
	if !ok {
		return responseError(fmt.Sprintf("volume %s not found", r.Name))
	}

	return volume.Response{Volume: &volume.Volume{Name: r.Name, Mountpoint: v.Mountpoint}}
}

func (d *sshfsDriver) List(r volume.Request) volume.Response {
	logrus.WithField("method", "list").Debugf("%#v", r)

	d.Lock()
	defer d.Unlock()

	var vols []*volume.Volume
	for name, v := range d.volumes {
		vols = append(vols, &volume.Volume{Name: name, Mountpoint: v.Mountpoint})
	}
	return volume.Response{Volumes: vols}
}

func (d *sshfsDriver) Capabilities(r volume.Request) volume.Response {
	logrus.WithField("method", "capabilities").Debugf("%#v", r)

	return volume.Response{Capabilities: volume.Capability{Scope: "local"}}
}

func (d *sshfsDriver) mountVolume(v *sshfsVolume) error {
	cmd := fmt.Sprintf("sshfs -oStrictHostKeyChecking=no %s %s", v.Sshcmd, v.Mountpoint)
	if v.Port != "" {
		cmd = fmt.Sprintf("%s -p %s", cmd, v.Port)
	}
	if v.Password != "" {
		cmd = fmt.Sprintf("echo %s | %s -o workaround=rename -o password_stdin", v.Password, cmd)
	}
	if v.AllowOther {
		cmd = fmt.Sprintf("%s -o allow_other", cmd)
	}
	logrus.Debug(cmd)
	return exec.Command("sh", "-c", cmd).Run()
}

func (d *sshfsDriver) unmountVolume(target string) error {
	cmd := fmt.Sprintf("umount %s", target)
	logrus.Debug(cmd)
	return exec.Command("sh", "-c", cmd).Run()
}

func responseError(err string) volume.Response {
	logrus.Error(err)
	return volume.Response{Err: err}
}

func main() {
	debug := os.Getenv("DEBUG")
	if ok, _ := strconv.ParseBool(debug); ok {
		logrus.SetLevel(logrus.DebugLevel)
	}

	d, err := newSshfsDriver("/mnt")
	if err != nil {
		log.Fatal(err)
	}
	h := volume.NewHandler(d)
	logrus.Infof("listening on %s", socketAddress)
	logrus.Error(h.ServeUnix(socketAddress, 0))
}
<|endoftext|>


<commit_before>package main

//go:generate esc -o templates.go ./templates

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/bukalapak/snowboard/adapter/drafter"
	"github.com/bukalapak/snowboard/adapter/drafterc"
	snowboard "github.com/bukalapak/snowboard/parser"
	"github.com/fsnotify/fsnotify"
	xerrors "github.com/pkg/errors"
	"github.com/urfave/cli"
)

var versionStr string
var (
	engine  snowboard.Parser
	engineC snowboard.Parser
)

func main() {
	engine = drafter.Engine{}
	engineC = drafterc.Engine{}

	cli.VersionPrinter = func(c *cli.Context) {
		fmt.Fprintf(c.App.Writer, "Snowboard version: %s\n", c.App.Version)
		fmt.Fprintf(c.App.Writer, "Drafter version: %s\n", engine.Version())
	}

	if versionStr == "" {
		versionStr = "HEAD"
	}

	app := cli.NewApp()
	app.Name = "snowboard"
	app.Usage = "API blueprint toolkit"
	app.Version = versionStr
	app.Before = func(c *cli.Context) error {
		if c.Args().Get(1) == "" {
			cli.ShowCommandHelp(c, c.Args().Get(0))
		}

		return nil
	}
	app.Commands = []cli.Command{
		{
			Name:  "lint",
			Usage: "Validate API blueprint",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "c",
					Usage: "Use character index instead of line and row number",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				if err := validate(c, c.Args().Get(0), c.Bool("c")); err != nil {
					if strings.Contains(err.Error(), "read failed") {
						return xerrors.Cause(err)
					}

					io.WriteString(c.App.Writer, err.Error())
				}

				return nil
			},
		},
		{
			Name:  "html",
			Usage: "Render HTML documentation",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "o",
					Value: "index.html",
					Usage: "HTML file",
				},
				cli.StringFlag{
					Name:  "t",
					Value: "alpha",
					Usage: "Template for HTML documentation",
				},
				cli.BoolFlag{
					Name:  "s",
					Usage: "Serve HTML via HTTP server",
				},
				cli.StringFlag{
					Name:  "b",
					Value: "127.0.0.1:8088",
					Usage: "HTTP server listen address",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				if c.Bool("s") {
					return watchHTML(c, c.Args().Get(0), c.String("o"), c.String("t"), c.String("b"))
				}

				return renderHTML(c, c.Args().Get(0), c.String("o"), c.String("t"))
			},
		},
		{
			Name:  "apib",
			Usage: "Render API blueprint",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "o",
					Usage: "API blueprint output file",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				return renderAPIB(c, c.Args().Get(0), c.String("o"))
			},
		},
		{
			Name:  "json",
			Usage: "Render API element json",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "o",
					Usage: "API element output file",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				return renderJSON(c, c.Args().Get(0), c.String("o"))
			},
		},
		{
			Name:  "mock",
			Usage: "Run Mock server",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "b",
					Value: "127.0.0.1:8087",
					Usage: "HTTP server listen address",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				return serveMock(c, c.String("b"), c.Args().Get(0))
			},
		},
		{
			Name:  "adapter",
			Usage: "Snowboard adapter",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "c",
					Usage: "Copy snowboard adapter to desired location",
				},
				cli.StringFlag{
					Name:  "p",
					Value: ".",
					Usage: "Adapter location dir",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Bool("c") {
					return installAdapters(c, c.String("p"))
				}

				return nil
			},
		},
	}
	app.Run(os.Args)
}

func readFile(fn string) ([]byte, error) {
	info, err := os.Stat(fn)
	if err != nil {
		return nil, errors.New("File is not exist")
	}

	if info.IsDir() {
		return nil, errors.New("File is a directory")
	}

	return ioutil.ReadFile(fn)
}

func readTemplate(fn string) ([]byte, error) {
	tf, err := readFile(fn)
	if err == nil {
		return tf, nil
	}

	fs := FS(false)
	ff, err := fs.Open("/templates/" + fn + ".html")
	if err != nil {
		return nil, err
	}

	defer ff.Close()
	return ioutil.ReadAll(ff)
}

func renderHTML(c *cli.Context, input, output, tplFile string) error {
	bp, err := snowboard.Load(input, engine)
	if err != nil {
		return err
	}

	of, err := os.Create(output)
	if err != nil {
		return err
	}
	defer of.Close()

	tf, err := readTemplate(tplFile)
	if err != nil {
		return err
	}

	err = snowboard.HTML(string(tf), of, bp)
	if err != nil {
		return err
	}

	fmt.Fprintln(c.App.Writer, "HTML has been generated!")
	return nil
}

func renderAPIB(c *cli.Context, input, output string) error {
	b, err := snowboard.Read(input)
	if err != nil {
		return err
	}

	of, err := os.Create(output)
	if err != nil {
		return err
	}
	defer of.Close()

	_, err = io.Copy(of, bytes.NewReader(b))
	if err != nil {
		return err
	}

	fmt.Fprintln(c.App.Writer, "API blueprint has been generated!")
	return nil
}

func renderJSON(c *cli.Context, input, output string) error {
	b, err := snowboard.LoadAsJSON(input, engine)
	if err != nil {
		return err
	}

	of, err := os.Create(output)
	if err != nil {
		return err
	}
	defer of.Close()

	_, err = io.Copy(of, bytes.NewReader(b))
	if err != nil {
		return err
	}

	fmt.Fprintln(c.App.Writer, "API element JSON has been generated!")
	return nil
}

func validate(c *cli.Context, input string, charIdx bool) error {
	b, err := readFile(input)
	if err != nil {
		return xerrors.Wrap(err, "read failed")
	}

	bf := bytes.NewReader(b)

	if charIdx {
		out, err := snowboard.Validate(bf, engine)
		if err != nil {
			return err
		}

		if out == nil {
			fmt.Fprintln(c.App.Writer, "OK")
			return nil
		}

		var buf bytes.Buffer

		s := "--------"
		w := tabwriter.NewWriter(&buf, 8, 0, 0, ' ', tabwriter.Debug)
		fmt.Fprintln(w, "Char Index\tDescription")
		fmt.Fprintf(w, "%s\t%s\n", s, strings.Repeat(s, 8))

		for _, n := range out.Annotations {
			for _, m := range n.SourceMaps {
				fmt.Fprintf(w, "%d:%d\t%s\n", m.Row, m.Col, n.Description)
			}
		}

		w.Flush()

		if len(out.Annotations) > 0 {
			return errors.New(buf.String())
		}
	} else {
		b, err := engineC.Validate(bf)
		if err != nil {
			return err
		}

		var buf bytes.Buffer

		w := tabwriter.NewWriter(&buf, 8, 0, 0, ' ', tabwriter.Debug)
		fmt.Fprintln(w, "Location\tSeverity\tDescription")

		fmt.Fprintf(w, "%s\t%s\t%s\n", dash(42), dash(16), dash(80))

		if string(b) == "" {
			fmt.Fprintln(c.App.Writer, "OK")
			return nil
		}

		ns := strings.Split(string(b), "\n")

		for _, n := range ns {
			nn := strings.SplitN(n, "; ", 2)
			mm := strings.SplitN(nn[0], "  ", 2)
			fmt.Fprintf(w, "%s\t%s\t%s\n", nn[1], mm[0], mm[1])
		}

		w.Flush()
		return errors.New(buf.String())
	}

	return nil
}

func dash(n int) string {
	return strings.Repeat("-", n)
}

func watchHTML(c *cli.Context, input, output, tplFile, bind string) error {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return err
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				if event.Op&fsnotify.Write == fsnotify.Write {
					renderHTML(c, input, output, tplFile)
				}
			case err := <-watcher.Errors:
				fmt.Fprintln(c.App.Writer, err)
			}
		}
	}()

	err = watcher.Add(input)
	if err != nil {
		return err
	}

	if _, err = os.Stat(tplFile); err == nil {
		err = watcher.Add(tplFile)
		if err != nil {
			return err
		}
	}

	renderHTML(c, input, output, tplFile)
	serveHTML(bind, output)

	<-done

	return nil
}

func serveHTML(bind, output string) error {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, output)
	})

	return http.ListenAndServe(bind, nil)
}

func serveMock(c *cli.Context, bind, input string) error {
	bp, err := snowboard.Load(input, engine)
	if err != nil {
		return err
	}

	fmt.Fprintf(c.App.Writer, "Mock server is ready. Use %s\n", bind)
	fmt.Fprintln(c.App.Writer, "Available Routes:")

	ms := snowboard.Mock(bp)
	for _, m := range ms {
		fmt.Fprintf(c.App.Writer, "%s\t%d\t%s\n", m.Method, m.StatusCode, m.Pattern)
	}

	h := snowboard.MockHandler(ms)
	return http.ListenAndServe(bind, h)
}

func installAdapters(c *cli.Context, dir string) error {
	n := drafterc.Engine{}
	name, err := n.CopyExec(dir)
	if err != nil {
		return err
	}

	fmt.Fprintln(c.App.Writer, "Snowboard adapter installed!\nLocation: "+name)
	return nil
}
<commit_msg>use stdout when no output file specified<commit_after>package main

//go:generate esc -o templates.go ./templates

import (
	"bytes"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"os"
	"strings"
	"text/tabwriter"

	"github.com/bukalapak/snowboard/adapter/drafter"
	"github.com/bukalapak/snowboard/adapter/drafterc"
	snowboard "github.com/bukalapak/snowboard/parser"
	"github.com/fsnotify/fsnotify"
	xerrors "github.com/pkg/errors"
	"github.com/urfave/cli"
)

var versionStr string
var (
	engine  snowboard.Parser
	engineC snowboard.Parser
)

func main() {
	engine = drafter.Engine{}
	engineC = drafterc.Engine{}

	cli.VersionPrinter = func(c *cli.Context) {
		fmt.Fprintf(c.App.Writer, "Snowboard version: %s\n", c.App.Version)
		fmt.Fprintf(c.App.Writer, "Drafter version: %s\n", engine.Version())
	}

	if versionStr == "" {
		versionStr = "HEAD"
	}

	app := cli.NewApp()
	app.Name = "snowboard"
	app.Usage = "API blueprint toolkit"
	app.Version = versionStr
	app.Before = func(c *cli.Context) error {
		if c.Args().Get(1) == "" {
			cli.ShowCommandHelp(c, c.Args().Get(0))
		}

		return nil
	}
	app.Commands = []cli.Command{
		{
			Name:  "lint",
			Usage: "Validate API blueprint",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "c",
					Usage: "Use character index instead of line and row number",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				if err := validate(c, c.Args().Get(0), c.Bool("c")); err != nil {
					if strings.Contains(err.Error(), "read failed") {
						return xerrors.Cause(err)
					}

					io.WriteString(c.App.Writer, err.Error())
				}

				return nil
			},
		},
		{
			Name:  "html",
			Usage: "Render HTML documentation",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "o",
					Usage: "HTML file",
				},
				cli.StringFlag{
					Name:  "t",
					Value: "alpha",
					Usage: "Template for HTML documentation",
				},
				cli.BoolFlag{
					Name:  "s",
					Usage: "Serve HTML via HTTP server",
				},
				cli.StringFlag{
					Name:  "b",
					Value: "127.0.0.1:8088",
					Usage: "HTTP server listen address",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				if c.Bool("s") {
					return watchHTML(c, c.Args().Get(0), c.String("o"), c.String("t"), c.String("b"))
				}

				return renderHTML(c, c.Args().Get(0), c.String("o"), c.String("t"))
			},
		},
		{
			Name:  "apib",
			Usage: "Render API blueprint",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "o",
					Usage: "API blueprint output file",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				return renderAPIB(c, c.Args().Get(0), c.String("o"))
			},
		},
		{
			Name:  "json",
			Usage: "Render API element json",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "o",
					Usage: "API element output file",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				return renderJSON(c, c.Args().Get(0), c.String("o"))
			},
		},
		{
			Name:  "mock",
			Usage: "Run Mock server",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "b",
					Value: "127.0.0.1:8087",
					Usage: "HTTP server listen address",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Args().Get(0) == "" {
					return nil
				}

				return serveMock(c, c.String("b"), c.Args().Get(0))
			},
		},
		{
			Name:  "adapter",
			Usage: "Snowboard adapter",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "c",
					Usage: "Copy snowboard adapter to desired location",
				},
				cli.StringFlag{
					Name:  "p",
					Value: ".",
					Usage: "Adapter location dir",
				},
			},
			Action: func(c *cli.Context) error {
				if c.Bool("c") {
					return installAdapters(c, c.String("p"))
				}

				return nil
			},
		},
	}
	app.Run(os.Args)
}

func readFile(fn string) ([]byte, error) {
	info, err := os.Stat(fn)
	if err != nil {
		return nil, errors.New("File is not exist")
	}

	if info.IsDir() {
		return nil, errors.New("File is a directory")
	}

	return ioutil.ReadFile(fn)
}

func readTemplate(fn string) ([]byte, error) {
	tf, err := readFile(fn)
	if err == nil {
		return tf, nil
	}

	fs := FS(false)
	ff, err := fs.Open("/templates/" + fn + ".html")
	if err != nil {
		return nil, err
	}

	defer ff.Close()
	return ioutil.ReadAll(ff)
}

func renderHTML(c *cli.Context, input, output, tplFile string) error {
	bp, err := snowboard.Load(input, engine)
	if err != nil {
		return err
	}

	tf, err := readTemplate(tplFile)
	if err != nil {
		return err
	}

	if output == "" {
		var bf bytes.Buffer

		if err := snowboard.HTML(string(tf), &bf, bp); err != nil {
			return err
		}

		fmt.Fprintln(c.App.Writer, bf.String())
		return nil
	}

	of, err := os.Create(output)
	if err != nil {
		return err
	}
	defer of.Close()

	err = snowboard.HTML(string(tf), of, bp)
	if err != nil {
		return err
	}

	fmt.Fprintln(c.App.Writer, "HTML has been generated!")
	return nil
}

func renderAPIB(c *cli.Context, input, output string) error {
	b, err := snowboard.Read(input)
	if err != nil {
		return err
	}

	if output == "" {
		fmt.Fprintln(c.App.Writer, string(b))
		return nil
	}

	of, err := os.Create(output)
	if err != nil {
		return err
	}
	defer of.Close()

	_, err = io.Copy(of, bytes.NewReader(b))
	if err != nil {
		return err
	}

	fmt.Fprintln(c.App.Writer, "API blueprint has been generated!")
	return nil
}

func renderJSON(c *cli.Context, input, output string) error {
	b, err := snowboard.LoadAsJSON(input, engine)
	if err != nil {
		return err
	}

	if output == "" {
		fmt.Fprintln(c.App.Writer, string(b))
		return nil
	}

	of, err := os.Create(output)
	if err != nil {
		return err
	}
	defer of.Close()

	_, err = io.Copy(of, bytes.NewReader(b))
	if err != nil {
		return err
	}

	fmt.Fprintln(c.App.Writer, "API element JSON has been generated!")
	return nil
}

func validate(c *cli.Context, input string, charIdx bool) error {
	b, err := readFile(input)
	if err != nil {
		return xerrors.Wrap(err, "read failed")
	}

	bf := bytes.NewReader(b)

	if charIdx {
		out, err := snowboard.Validate(bf, engine)
		if err != nil {
			return err
		}

		if out == nil {
			fmt.Fprintln(c.App.Writer, "OK")
			return nil
		}

		var buf bytes.Buffer

		s := "--------"
		w := tabwriter.NewWriter(&buf, 8, 0, 0, ' ', tabwriter.Debug)
		fmt.Fprintln(w, "Char Index\tDescription")
		fmt.Fprintf(w, "%s\t%s\n", s, strings.Repeat(s, 8))

		for _, n := range out.Annotations {
			for _, m := range n.SourceMaps {
				fmt.Fprintf(w, "%d:%d\t%s\n", m.Row, m.Col, n.Description)
			}
		}

		w.Flush()

		if len(out.Annotations) > 0 {
			return errors.New(buf.String())
		}
	} else {
		b, err := engineC.Validate(bf)
		if err != nil {
			return err
		}

		var buf bytes.Buffer

		w := tabwriter.NewWriter(&buf, 8, 0, 0, ' ', tabwriter.Debug)
		fmt.Fprintln(w, "Location\tSeverity\tDescription")

		fmt.Fprintf(w, "%s\t%s\t%s\n", dash(42), dash(16), dash(80))

		if string(b) == "" {
			fmt.Fprintln(c.App.Writer, "OK")
			return nil
		}

		ns := strings.Split(string(b), "\n")

		for _, n := range ns {
			nn := strings.SplitN(n, "; ", 2)
			mm := strings.SplitN(nn[0], "  ", 2)
			fmt.Fprintf(w, "%s\t%s\t%s\n", nn[1], mm[0], mm[1])
		}

		w.Flush()
		return errors.New(buf.String())
	}

	return nil
}

func dash(n int) string {
	return strings.Repeat("-", n)
}

func watchHTML(c *cli.Context, input, output, tplFile, bind string) error {
	if output == "" {
		output = "index.html"
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		return err
	}
	defer watcher.Close()

	done := make(chan bool)
	go func() {
		for {
			select {
			case event := <-watcher.Events:
				if event.Op&fsnotify.Write == fsnotify.Write {
					renderHTML(c, input, output, tplFile)
				}
			case err := <-watcher.Errors:
				fmt.Fprintln(c.App.Writer, err)
			}
		}
	}()

	err = watcher.Add(input)
	if err != nil {
		return err
	}

	if _, err = os.Stat(tplFile); err == nil {
		err = watcher.Add(tplFile)
		if err != nil {
			return err
		}
	}

	renderHTML(c, input, output, tplFile)
	serveHTML(bind, output)

	<-done

	return nil
}

func serveHTML(bind, output string) error {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, output)
	})

	return http.ListenAndServe(bind, nil)
}

func serveMock(c *cli.Context, bind, input string) error {
	bp, err := snowboard.Load(input, engine)
	if err != nil {
		return err
	}

	fmt.Fprintf(c.App.Writer, "Mock server is ready. Use %s\n", bind)
	fmt.Fprintln(c.App.Writer, "Available Routes:")

	ms := snowboard.Mock(bp)
	for _, m := range ms {
		fmt.Fprintf(c.App.Writer, "%s\t%d\t%s\n", m.Method, m.StatusCode, m.Pattern)
	}

	h := snowboard.MockHandler(ms)
	return http.ListenAndServe(bind, h)
}

func installAdapters(c *cli.Context, dir string) error {
	n := drafterc.Engine{}
	name, err := n.CopyExec(dir)
	if err != nil {
		return err
	}

	fmt.Fprintln(c.App.Writer, "Snowboard adapter installed!\nLocation: "+name)
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"sync"

	"github.com/fatih/color"
	"github.com/jmks/uristat/options"
)

func main() {
	opts := options.Parse()

	if !opts.IsValid() {
		opts.PrintError()
		os.Exit(1)
	}

	existingSrc := filepathProducer(opts.Filepaths)
	uriSrc := uriProducer(existingSrc)

	if opts.ListOnly() {
		for uri := range uriSrc {
			fmt.Println(uri)
		}
	} else {
		printStatuses(uriSrc)
	}
}

func filepathProducer(filepaths []string) <-chan string {
	dest := make(chan string, 100)

	go func() {
		for _, filepath := range filepaths {
			if len(filepath) == 0 {
				continue
			}

			if _, err := os.Stat(filepath); !os.IsNotExist(err) {
				dest <- filepath
			}
		}
		close(dest)
	}()

	return dest
}

func uriProducer(filepathSrc <-chan string) <-chan string {
	dest := make(chan string, 100)

	go func() {
		wg := sync.WaitGroup{}

		for filepath := range filepathSrc {
			wg.Add(1)

			go func(path string) {
				defer wg.Done()

				if uris := urisIn(path); len(uris) > 0 {
					for _, uri := range uris {
						dest <- uri
					}
				}
			}(filepath)
		}

		wg.Wait()
		close(dest)
	}()

	return dest
}

func urisIn(filepath string) (uris []string) {
	file, err := os.Open(filepath)
	if err != nil {
		fmt.Printf("Error '%v': %v\n", filepath, err)
		return uris
	}

	// https://github.com/matthewrudy/regexpert/blob/master/lib/regexpert.rb
	uriRe := regexp.MustCompile(`(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)`)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if matches := uriRe.FindAllString(line, -1); matches != nil {
			uris = append(uris, matches...)
		}
	}

	return uris
}

func printStatuses(uriSrc <-chan string) {
	wg := sync.WaitGroup{}

	for uri := range uriSrc {
		wg.Add(1)

		go func(uri string) {
			if resp, err := http.Head(uri); err != nil {
				color.Red("%v error: %v\n", uri, err)
			} else {
				defer resp.Body.Close()
				colorize := statusCodePrinterFunc(resp.StatusCode)
				fmt.Printf("%v : %v\n", colorize(resp.Status), uri)
			}

			wg.Done()
		}(uri)
	}

	wg.Wait()
}

func statusCodePrinterFunc(code int) func(...interface{}) string {
	switch code {
	case 200:
		return color.New(color.FgGreen).SprintFunc()
	case 404:
		return color.New(color.FgYellow).SprintFunc()
	default:
		return color.New(color.FgRed).SprintFunc()
	}
}
<commit_msg>Made HTTP error printing more consistent<commit_after>package main

import (
	"bufio"
	"fmt"
	"net/http"
	"os"
	"regexp"
	"sync"

	"github.com/fatih/color"
	"github.com/jmks/uristat/options"
)

func main() {
	opts := options.Parse()

	if !opts.IsValid() {
		opts.PrintError()
		os.Exit(1)
	}

	existingSrc := filepathProducer(opts.Filepaths)
	uriSrc := uriProducer(existingSrc)

	if opts.ListOnly() {
		for uri := range uriSrc {
			fmt.Println(uri)
		}
	} else {
		printStatuses(uriSrc)
	}
}

func filepathProducer(filepaths []string) <-chan string {
	dest := make(chan string, 100)

	go func() {
		for _, filepath := range filepaths {
			if len(filepath) == 0 {
				continue
			}

			if _, err := os.Stat(filepath); !os.IsNotExist(err) {
				dest <- filepath
			}
		}
		close(dest)
	}()

	return dest
}

func uriProducer(filepathSrc <-chan string) <-chan string {
	dest := make(chan string, 100)

	go func() {
		wg := sync.WaitGroup{}

		for filepath := range filepathSrc {
			wg.Add(1)

			go func(path string) {
				defer wg.Done()

				if uris := urisIn(path); len(uris) > 0 {
					for _, uri := range uris {
						dest <- uri
					}
				}
			}(filepath)
		}

		wg.Wait()
		close(dest)
	}()

	return dest
}

func urisIn(filepath string) (uris []string) {
	file, err := os.Open(filepath)
	if err != nil {
		fmt.Printf("Error '%v': %v\n", filepath, err)
		return uris
	}

	// https://github.com/matthewrudy/regexpert/blob/master/lib/regexpert.rb
	uriRe := regexp.MustCompile(`(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)`)

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		if matches := uriRe.FindAllString(line, -1); matches != nil {
			uris = append(uris, matches...)
		}
	}

	return uris
}

func printStatuses(uriSrc <-chan string) {
	wg := sync.WaitGroup{}

	for uri := range uriSrc {
		wg.Add(1)

		go func(uri string) {
			if resp, err := http.Head(uri); err != nil {
				redden := color.New(color.FgRed).SprintFunc()
				fmt.Printf("%v : %v\n", redden("HTTP ERROR"), uri)
			} else {
				defer resp.Body.Close()
				colorize := statusCodePrinterFunc(resp.StatusCode)
				fmt.Printf("%v : %v\n", colorize(resp.Status), uri)
			}

			wg.Done()
		}(uri)
	}

	wg.Wait()
}

func statusCodePrinterFunc(code int) func(...interface{}) string {
	switch code {
	case 200:
		return color.New(color.FgGreen).SprintFunc()
	case 404:
		return color.New(color.FgYellow).SprintFunc()
	default:
		return color.New(color.FgRed).SprintFunc()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"golang.org/x/net/websocket"
)

var token string

func init() {
	if token = os.Getenv("TOKEN"); token == "" {
		log.Fatal("TOKEN not specified")
	}
}

//{"type":"message","channel":"D04FLBCPZ","user":"U02D58RR5","text":"howdy ho","ts":"1429561458.000015","team":"T02D58RR3"}
type Message struct {
	Type    string
	Channel string
	User    string
	Text    string
	Ts      string
	Team    string
}

func webSocketUrl() (url string, err error) {
	resp, err := http.Get("https://slack.com/api/rtm.start?token=" + token)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	buf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var body map[string]interface{}
	if err = json.Unmarshal(buf, &body); err != nil {
		return
	}
	url, ok := body["url"].(string)
	if !ok {
		err = errors.New("unable to parse rtm url")
	}
	return
}

func main() {
	url, err := webSocketUrl()
	if err != nil {
		log.Fatal(err)
	}
	origin := "http://localhost/"
	ws, err := websocket.Dial(url, "", origin)
	if err != nil {
		log.Fatal(err)
	}
	defer ws.Close()

	input := make(chan []byte)
	go func() {
		for {
			var buf []byte
			if err := websocket.Message.Receive(ws, &buf); err != nil {
				log.Println(ws)
				log.Fatal(err)
			}
			if len(buf) > 0 {
				input <- buf
			}
		}
	}()

	output := make(chan map[string]interface{})
	go func() {
		id := 0
		for {
			msg := <-output
			msg["id"] = id
			buf, _ := json.MarshalIndent(msg, "", "  ")
			log.Println("sending message")
			fmt.Println(string(buf))
			if err := websocket.JSON.Send(ws, msg); err != nil {
				log.Fatal(err)
			}
			id++
		}
	}()

	messages := make(chan Message)
	go func() {
		for {
			select {
			case buf := <-input:
				var msg Message
				if err := json.Unmarshal(buf, &msg); err != nil {
					log.Fatal("unable to parse rtm message")
				}
				switch msg.Type {
				case "message":
					if len(msg.Channel) > 0 && msg.Channel[0] == 'D' {
						messages <- msg
					}
				default:
					log.Println("ignoring", msg.Type)
				}
			case <-time.After(5 * time.Second):
				log.Println("timeout, pinging")
				output <- map[string]interface{}{"type": "ping"}
			}
		}
	}()
	for m := range messages {
		fmt.Println(m)
		output <- map[string]interface{}{
			"type":    m.Type,
			"channel": m.Channel,
			"text":    m.Text,
		}
	}
}
<commit_msg>refactor and add reconnecting<commit_after>package main

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"golang.org/x/net/websocket"
)

type Message map[string]interface{}

func (m Message) Type() string    { return m["type"].(string) }
func (m Message) Channel() string { return m["channel"].(string) }
func (m Message) User() string    { return m["user"].(string) }
func (m Message) Text() string    { return m["text"].(string) }

func (m Message) DirectMessage() bool {
	if _, ok := m["reply_to"]; ok {
		return false
	}
	msgType, ok := m["type"].(string)
	if !ok {
		return false
	}
	channel, ok := m["channel"].(string)
	if !ok {
		return false
	}
	if _, ok := m["user"].(string); !ok {
		return false
	}
	if _, ok := m["text"].(string); !ok {
		return false
	}
	return msgType == "message" && len(channel) > 0 && channel[0] == 'D'
}

func (m Message) String() string {
	buf, _ := json.Marshal(m)
	return string(buf)
}

var token string

func init() {
	if token = os.Getenv("TOKEN"); token == "" {
		log.Fatal("TOKEN not specified")
	}
}

func webSocketUrl() (url string, err error) {
	log.Println("authenticating with rtm")
	resp, err := http.Get("https://slack.com/api/rtm.start?token=" + token)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	buf, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	var body map[string]interface{}
	if err = json.Unmarshal(buf, &body); err != nil {
		return
	}
	url, ok := body["url"].(string)
	if !ok {
		err = errors.New("unable to parse rtm url")
	}
	return
}

func connectToRtm() (ws *websocket.Conn, input, output chan Message, err error) {
	var url string
	url, err = webSocketUrl()
	if err != nil {
		return
	}

	log.Println("connecting to rtm")
	origin := "http://localhost/"
	ws, err = websocket.Dial(url, "", origin)
	if err != nil {
		return
	}

	input = make(chan Message)
	go func() {
		for {
			var msg Message
			if err := websocket.JSON.Receive(ws, &msg); err != nil {
				close(input)
				return
			}
			if msg != nil {
				input <- msg
			}
		}
	}()

	output = make(chan Message)
	go func() {
		id := 0
		for {
			msg := <-output
			msg["id"] = id
			if err := websocket.JSON.Send(ws, msg); err != nil {
				close(output)
				return
			}
			id++
		}
	}()

	return
}

func main() {
	ws, input, output, err := connectToRtm()
	if err != nil {
		log.Fatal(err)
	}
	defer ws.Close()

	messages := make(chan Message)
	go func() {
		for {
			select {
			case msg, ok := <-input:
				// Handle disconects.
				if !ok {
					log.Println("disconnected from rtm")
					ws, input, output, err = connectToRtm()
					if err != nil {
						log.Fatal(err)
					}
					defer ws.Close()
					continue
				}
				if msg.DirectMessage() {
					messages <- msg
				}
			case <-time.After(5 * time.Second):
				output <- Message{"type": "ping"}
			}
		}
	}()

	for m := range messages {
		log.Println(m)
		output <- Message{
			"type":    m.Type(),
			"channel": m.Channel(),
			"text":    m.Text(),
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	_ "net/http/pprof"
	"strconv"
	"strings"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"github.com/prometheus/common/version"
	"gopkg.in/alecthomas/kingpin.v2"
)

const (
	namespace       = "solr"
	pidFileHelpText = `Path to Solr pid file.

	If provided, the standard process metrics get exported for the Solr
	process, prefixed with 'solr_process_...'. The solr_process exporter
	needs to have read access to files owned by the Solr process. Depends on
	the availability of /proc.

	https://prometheus.io/docs/instrumenting/writing_clientlibs/#process-metrics.`
)

var (
	listenAddress    = kingpin.Flag("web.listen-address", "Address to listen on for web interface and telemetry.").Default(":9231").String()
	metricsPath      = kingpin.Flag("web.telemetry-path", "Path under which to expose metrics.").Default("/metrics").String()
	solrURI          = kingpin.Flag("solr.address", "URI on which to scrape Solr.").Default("http://localhost:8983").String()
	solrContextPath  = kingpin.Flag("solr.context-path", "Solr webapp context path.").Default("/solr").String()
	solrExcludedCore = kingpin.Flag("solr.excluded-core", "Regex to exclude core from monitoring").Default("").String()
	solrTimeout      = kingpin.Flag("solr.timeout", "Timeout for trying to get stats from Solr.").Default("5s").Duration()
	solrPidFile      = kingpin.Flag("solr.pid-file", "").Default(pidFileHelpText).String()
)

var landingPage = []byte(`
<title>Solr exporter</title>

Solr exporter

<a href='` + *metricsPath + `'>Metrics

`)

func main() {
	log.AddFlags(kingpin.CommandLine)
	kingpin.Version(version.Print("solr_exporter"))
	kingpin.HelpFlag.Short('h')
	kingpin.Parse()

	log.Infoln("Starting solr_exporter", version.Info())
	log.Infoln("Build context", version.BuildContext())

	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				c, err := net.DialTimeout(netw, addr, *solrTimeout)
				if err != nil {
					return nil, err
				}
				if err := c.SetDeadline(time.Now().Add(*solrTimeout)); err != nil {
					return nil, err
				}
				return c, nil
			},
		},
	}

	solrBaseURL := fmt.Sprintf("%s%s", *solrURI, *solrContextPath)

	exporter := NewExporter(solrBaseURL, *solrTimeout, *solrExcludedCore, *client)
	prometheus.MustRegister(exporter)
	prometheus.MustRegister(version.NewCollector("solr_exporter"))

	jvmExporter, err := NewJVMCollector(*client, solrBaseURL)
	if err != nil {
		log.Errorf("Failed to create JVM metrics collector: %v", err)
	}
	prometheus.MustRegister(jvmExporter)

	if *solrPidFile != "" {
		procExporter := prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{
			PidFn: func() (int, error) {
				content, err := ioutil.ReadFile(*solrPidFile)
				if err != nil {
					return 0, fmt.Errorf("Can't read pid file: %s", err)
				}
				value, err := strconv.Atoi(strings.TrimSpace(string(content)))
				if err != nil {
					return 0, fmt.Errorf("Can't parse pid file: %s", err)
				}
				return value, nil
			},
			Namespace: "solr",
		})
		prometheus.MustRegister(procExporter)
	}

	log.Infoln("Listening on", *listenAddress)
	http.Handle(*metricsPath, prometheus.Handler())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write(landingPage)
	})
	log.Fatal(http.ListenAndServe(*listenAddress, nil))
}
<commit_msg>Fix metric path<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	_ "net/http/pprof"
	"strconv"
	"strings"
	"time"

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/common/log"
	"github.com/prometheus/common/version"
	"gopkg.in/alecthomas/kingpin.v2"
)

const (
	namespace       = "solr"
	pidFileHelpText = `Path to Solr pid file.

	If provided, the standard process metrics get exported for the Solr
	process, prefixed with 'solr_process_...'. The solr_process exporter
	needs to have read access to files owned by the Solr process. Depends on
	the availability of /proc.

	https://prometheus.io/docs/instrumenting/writing_clientlibs/#process-metrics.`
)

var (
	listenAddress    = kingpin.Flag("web.listen-address", "Address to listen on for web interface and telemetry.").Default(":9231").String()
	metricsPath      = kingpin.Flag("web.telemetry-path", "Path under which to expose metrics.").Default("/metrics").String()
	solrURI          = kingpin.Flag("solr.address", "URI on which to scrape Solr.").Default("http://localhost:8983").String()
	solrContextPath  = kingpin.Flag("solr.context-path", "Solr webapp context path.").Default("/solr").String()
	solrExcludedCore = kingpin.Flag("solr.excluded-core", "Regex to exclude core from monitoring").Default("").String()
	solrTimeout      = kingpin.Flag("solr.timeout", "Timeout for trying to get stats from Solr.").Default("5s").Duration()
	solrPidFile      = kingpin.Flag("solr.pid-file", "").Default(pidFileHelpText).String()
)

func main() {
	log.AddFlags(kingpin.CommandLine)
	kingpin.Version(version.Print("solr_exporter"))
	kingpin.HelpFlag.Short('h')
	kingpin.Parse()

	log.Infoln("Starting solr_exporter", version.Info())
	log.Infoln("Build context", version.BuildContext())

	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(netw, addr string) (net.Conn, error) {
				c, err := net.DialTimeout(netw, addr, *solrTimeout)
				if err != nil {
					return nil, err
				}
				if err := c.SetDeadline(time.Now().Add(*solrTimeout)); err != nil {
					return nil, err
				}
				return c, nil
			},
		},
	}

	solrBaseURL := fmt.Sprintf("%s%s", *solrURI, *solrContextPath)

	exporter := NewExporter(solrBaseURL, *solrTimeout, *solrExcludedCore, *client)
	prometheus.MustRegister(exporter)
	prometheus.MustRegister(version.NewCollector("solr_exporter"))

	jvmExporter, err := NewJVMCollector(*client, solrBaseURL)
	if err != nil {
		log.Errorf("Failed to create JVM metrics collector: %v", err)
	}
	prometheus.MustRegister(jvmExporter)

	if *solrPidFile != "" {
		procExporter := prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{
			PidFn: func() (int, error) {
				content, err := ioutil.ReadFile(*solrPidFile)
				if err != nil {
					return 0, fmt.Errorf("Can't read pid file: %s", err)
				}
				value, err := strconv.Atoi(strings.TrimSpace(string(content)))
				if err != nil {
					return 0, fmt.Errorf("Can't parse pid file: %s", err)
				}
				return value, nil
			},
			Namespace: "solr",
		})
		prometheus.MustRegister(procExporter)
	}

	log.Infoln("Listening on", *listenAddress)
	http.Handle(*metricsPath, prometheus.Handler())
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(`
             <title>Solr Exporter</title>

Solr Exporter

<a href='` + *metricsPath + `'>Metrics

             `))
	})
	log.Fatal(http.ListenAndServe(*listenAddress, nil))
}
<|endoftext|>


<commit_before>package main

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

	"github.com/gorilla/mux"
	"github.com/rubyist/circuitbreaker"
)

var breaker = circuit.NewConsecutiveBreaker(5)

// DriverLocation models response from LocationService
type DriverLocation struct {
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	UpdatedAt string  `json:"updated_at"`
}

// APIResponse models the response to know if a driver is active
type APIResponse struct {
	ID     int  `json:"id"`
	Zombie bool `json:"zombie"`
}

func main() {
	r := mux.NewRouter().StrictSlash(true)
	r.HandleFunc("/drivers/{id:[0-9]+}", ZombieDriverHandler).Methods("GET")
	http.Handle("/", r)
	log.Printf("Server started and listening on port %d.", 1338)
	log.Fatal(http.ListenAndServe(":1338", nil))
}

// ZombieDriverHandler handles a user's request to know if a driver is active
func ZombieDriverHandler(w http.ResponseWriter, r *http.Request) {
	log.Printf("\t%s",
		r.RequestURI)
	// Read route parameter
	vars := mux.Vars(r)
	param := vars["id"]
	driverID, err := strconv.Atoi(param)
	if err != nil {
		log.Printf("Received bad request with driver id %s.", param)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	locationURL := fmt.Sprintf("http://172.17.0.1:8001/drivers/%d/coordinates?minutes=5", driverID)
	locations, err := getDriverLocations(breaker, locationURL)
	if err != nil {
		log.Printf(err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	isZombie := isDriverZombie(locations)
	result := APIResponse{ID: driverID, Zombie: isZombie}
	w.Header().Set("Content-Type", "application/json")
	response, err := json.Marshal(result)
	if err != nil {
		log.Printf(err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Write(response)
	return
}

func getDriverLocations(breaker *circuit.Breaker, serviceURL string) ([]*DriverLocation, error) {
	var response *http.Response
	var err error
	err = breaker.Call(func() error {
		var httpErr error
		response, httpErr = http.Get(serviceURL)
		return httpErr
	}, time.Second*1)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	decoder := json.NewDecoder(response.Body)
	var locations []*DriverLocation
	if err := decoder.Decode(&locations); err != nil {
		return nil, err
	}
	return locations, nil
}

//isDriverZombie
func isDriverZombie(locations []*DriverLocation) bool {
	var meters float64
	var prev DriverLocation
	for i, loc := range locations {
		if i > 0 {
			meters = Distance(prev.Latitude, prev.Longitude, loc.Latitude, loc.Longitude) + meters
		}
		prev.Latitude = loc.Latitude
		prev.Longitude = loc.Longitude
	}

	if meters < 500 {
		return true
	}
	return false
}
<commit_msg>add consul client<commit_after>package main

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

	"github.com/gorilla/mux"
	consul "github.com/hashicorp/consul/api"
	"github.com/rubyist/circuitbreaker"
)

var breaker = circuit.NewConsecutiveBreaker(5)

// DriverLocation models response from LocationService
type DriverLocation struct {
	Latitude  float64 `json:"latitude"`
	Longitude float64 `json:"longitude"`
	UpdatedAt string  `json:"updated_at"`
}

// APIResponse models the response to know if a driver is active
type APIResponse struct {
	ID     int  `json:"id"`
	Zombie bool `json:"zombie"`
}

func main() {
	consulConfig := consul.DefaultConfig()
	consulClient, err := consul.NewClient(consulConfig)
	if err != nil {
		log.Fatal(err)
	}
	err = Register(consulClient, "zombie", "172.17.0.1", 1338)
	if err != nil {
		log.Fatal(err)
	}

	r := mux.NewRouter().StrictSlash(true)
	r.HandleFunc("/drivers/{id:[0-9]+}", ZombieDriverHandler).Methods("GET")
	http.Handle("/", r)
	log.Printf("Server started and listening on port %d.", 1338)
	log.Fatal(http.ListenAndServe(":1338", nil))
}

// Register a service with consul local agent
func Register(client *consul.Client, name, address string, port int) error {
	reg := &consul.AgentServiceRegistration{
		ID:      name,
		Name:    name,
		Address: address,
		Port:    port,
	}
	return client.Agent().ServiceRegister(reg)
}

// ZombieDriverHandler handles a user's request to know if a driver is active
func ZombieDriverHandler(w http.ResponseWriter, r *http.Request) {
	log.Printf("\t%s",
		r.RequestURI)
	// Read route parameter
	vars := mux.Vars(r)
	param := vars["id"]
	driverID, err := strconv.Atoi(param)
	if err != nil {
		log.Printf("Received bad request with driver id %s.", param)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	locationURL := fmt.Sprintf("http://172.17.0.1:8001/drivers/%d/coordinates?minutes=5", driverID)
	locations, err := getDriverLocations(breaker, locationURL)
	if err != nil {
		log.Printf(err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	isZombie := isDriverZombie(locations)
	result := APIResponse{ID: driverID, Zombie: isZombie}
	w.Header().Set("Content-Type", "application/json")
	response, err := json.Marshal(result)
	if err != nil {
		log.Printf(err.Error())
		w.WriteHeader(http.StatusInternalServerError)
		return
	}

	w.Write(response)
	return
}

func getDriverLocations(breaker *circuit.Breaker, serviceURL string) ([]*DriverLocation, error) {
	var response *http.Response
	var err error
	err = breaker.Call(func() error {
		var httpErr error
		response, httpErr = http.Get(serviceURL)
		return httpErr
	}, time.Second*1)
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()
	decoder := json.NewDecoder(response.Body)
	var locations []*DriverLocation
	if err := decoder.Decode(&locations); err != nil {
		return nil, err
	}
	return locations, nil
}

//isDriverZombie
func isDriverZombie(locations []*DriverLocation) bool {
	var meters float64
	var prev DriverLocation
	for i, loc := range locations {
		if i > 0 {
			meters = Distance(prev.Latitude, prev.Longitude, loc.Latitude, loc.Longitude) + meters
		}
		prev.Latitude = loc.Latitude
		prev.Longitude = loc.Longitude
	}

	if meters < 500 {
		return true
	}
	return false
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"time"
)

const (
	SunSyncDaysPast = 5
)

func main() {
	// Flag setup
	verbose := flag.Bool("verbose", false, "Verbose processing (default false)")
	randomize := flag.Bool("randomize", false, "Random input (default false)")
	deviceName := flag.String("device", "/dev/ttyAMA0", "Device or filename (default ttyAMA0)")
	baudRate := flag.Int("baud", 4800, "Baudrate of serial device (default 4800)")
	influxHost := flag.String("influxhost", "localhost", "Influxdb hostname")
	influxPort := flag.Int("influxport", 8086, "Influxdb port")
	influxDBName := flag.String("influxdbname", "weather", "Influxdb DB name")
	latitude := flag.Float64("latitude", 48.137222, "Geographic latitude (default 48.137222, munich)")
	longitude := flag.Float64("longitude", 11.575556, "Geographic latitude (default 11.575556, munich)")
	location := flag.String("location", "munich", "Geographic location (default 'munich')")

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

	// Logging setup
	logFilename := "wcollector.log"

	logfile, err := os.OpenFile(logFilename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Panicf("Failed to open logfile %s for writing: %v\n", logFilename, err)
	}
	defer logfile.Close()

	var logWriter io.Writer = logfile
	if *verbose {
		logWriter = io.MultiWriter(logfile, os.Stdout)
	}

	var logger *log.Logger = log.New(logWriter, "[wcollector] ", log.LstdFlags)
	log.Println("Starting up")

	// TSDB client
	tsdb := NewInfluxDBClient(*influxHost, *influxPort, *influxDBName)
	if *verbose {
		tsdb.SetDebug(true)
	}

	// Input source
	var in Input
	if *randomize {
		in = NewRandomInput()
	} else {
		err, in = OpenUART(*deviceName, *baudRate)
		if err != nil {
			logger.Fatal(err)
		}
	}
	defer in.Close()

	// Sun rise and set calculation
	go func() {
		for {
			logger.Println("Sun rise/set calculation")
			for i := 0; i < 2*SunSyncDaysPast; i++ { // For -5 to +5 days from now
				day := time.Now().AddDate(0, 0, (-SunSyncDaysPast + i))
				err := EnsureSunRiseAndSet(tsdb, day, *latitude, *longitude, *location)
				if err != nil {
					logger.Printf("Error: Failed ensuring sun information: %v\n", err)
				}
			}

			time.Sleep(30 * time.Minute)
		}
	}()

	// Loop over input, process data, store in TSDB
	Consume(in, tsdb, logger)
}
<commit_msg>Change logfile name.<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path"
	"time"
)

const (
	SunSyncDaysPast = 5
)

func main() {
	// Flag setup
	verbose := flag.Bool("verbose", false, "Verbose processing (default false)")
	randomize := flag.Bool("randomize", false, "Random input (default false)")
	deviceName := flag.String("device", "/dev/ttyAMA0", "Device or filename (default ttyAMA0)")
	baudRate := flag.Int("baud", 4800, "Baudrate of serial device (default 4800)")
	influxHost := flag.String("influxhost", "localhost", "Influxdb hostname")
	influxPort := flag.Int("influxport", 8086, "Influxdb port")
	influxDBName := flag.String("influxdbname", "weather", "Influxdb DB name")
	latitude := flag.Float64("latitude", 48.137222, "Geographic latitude (default 48.137222, munich)")
	longitude := flag.Float64("longitude", 11.575556, "Geographic latitude (default 11.575556, munich)")
	location := flag.String("location", "munich", "Geographic location (default 'munich')")

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

	// Logging setup
	logFilename := "weather-collector.log"

	logfile, err := os.OpenFile(logFilename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		log.Panicf("Failed to open logfile %s for writing: %v\n", logFilename, err)
	}
	defer logfile.Close()

	var logWriter io.Writer = logfile
	if *verbose {
		logWriter = io.MultiWriter(logfile, os.Stdout)
	}

	var logger *log.Logger = log.New(logWriter, "[wcollector] ", log.LstdFlags)
	log.Println("Starting up")

	// TSDB client
	tsdb := NewInfluxDBClient(*influxHost, *influxPort, *influxDBName)
	if *verbose {
		tsdb.SetDebug(true)
	}

	// Input source
	var in Input
	if *randomize {
		in = NewRandomInput()
	} else {
		err, in = OpenUART(*deviceName, *baudRate)
		if err != nil {
			logger.Fatal(err)
		}
	}
	defer in.Close()

	// Sun rise and set calculation
	go func() {
		for {
			logger.Println("Sun rise/set calculation")
			for i := 0; i < 2*SunSyncDaysPast; i++ { // For -5 to +5 days from now
				day := time.Now().AddDate(0, 0, (-SunSyncDaysPast + i))
				err := EnsureSunRiseAndSet(tsdb, day, *latitude, *longitude, *location)
				if err != nil {
					logger.Printf("Error: Failed ensuring sun information: %v\n", err)
				}
			}

			time.Sleep(30 * time.Minute)
		}
	}()

	// Loop over input, process data, store in TSDB
	Consume(in, tsdb, logger)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/skelterjohn/go.matrix" // daa59528eefd43623a4c8e36373a86f9eef870a2
	"github.com/youpy/go-wav"
	"io"
	"log"
	"os"
)

func main() {
	// I have no idea what I am doing
	fmt.Println("Bop")
	if len(os.Args) <= 1 {
		log.Fatal("You need to tell me what file to encode.")
	}
	file, _ := os.Open(os.Args[1])

	output, _ := os.OpenFile("./out.wav", os.O_CREATE, 600)
	outputpac, _ := os.OpenFile("./out.pac", os.O_CREATE, 600)

	reader := wav.NewReader(file)

	// Settings for output
	var numSamples uint32 = 999999
	var numChannels uint16 = 2
	var sampleRate uint32 = 44100
	var bitsPerSample uint16 = 16
	writer := wav.NewWriter(output, numSamples, numChannels, sampleRate, bitsPerSample)
	BlockesProcessed := 0
	// End of settings for output
	var SampleBlock []float64
	SampleBlock = make([]float64, 8)
	for {
		samplez := make([]wav.Sample, 0)
		samples, err := reader.ReadSamples()
		// Samples will return (usally) 2048 samples in a single sitting

		log.Println(BlockesProcessed)
		if err == io.EOF {
			break
		}

		BlockesProcessed++
		var SamplePointer int = 0 // max is 8
		for _, sample := range samples {
			sam := wav.Sample{}
			L := reader.IntValue(sample, 0)
			R := reader.IntValue(sample, 1)
			MonoVal := (L + R) / 2

			// Now we add it to the staging array
			SampleBlock[SamplePointer] = float64(MonoVal)
			SamplePointer++
			if SamplePointer == 8 {
				out := GetPolyResults([]float64{0, 1, 2, 3, 4, 5, 6, 7}, SampleBlock)
				Line := fmt.Sprintf("%f,%f,%f,%f,%f\n", out[0], out[1], out[2], out[3], out[4])
				outputpac.Write([]byte(Line))
				SamplePointer = 0
			}
			sam.Values[0] = L
			sam.Values[0] = R
			samplez = append(samplez, sam)
		}

		// fmt.Println(len(samplez), len(samples))
		writer.WriteSamples(samplez)
	}

}

var degree = 5

func GetPolyResults(xGiven []float64, yGiven []float64) []float64 {
	m := len(yGiven)
	if m != len(xGiven) {
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	if m < 5 {
		// Prevent the processing of really small datasets, This is becauase there
		// appears to be a bug in the libary that will trigger a crash in the go.matrix
		// if some (small) amount of values are entered. I don't know why this happens
		// (Otherwise I would have fixed it) but the URL for the github issue is:
		// https://github.com/skelterjohn/go.matrix/issues/11
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	n := degree + 1
	y := matrix.MakeDenseMatrix(yGiven, m, 1)
	x := matrix.Zeros(m, n)
	for i := 0; i < m; i++ {
		ip := float64(1)
		for j := 0; j < n; j++ {
			x.Set(i, j, ip)
			ip *= xGiven[i]
		}
	}

	q, r := x.QR()
	qty, err := q.Transpose().Times(y)
	if err != nil {
		log.Println(err)
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	c := make([]float64, n)
	for i := n - 1; i >= 0; i-- {
		c[i] = qty.Get(i, 0)
		for j := i + 1; j < n; j++ {
			c[i] -= c[j] * r.Get(i, j)
		}
		c[i] /= r.Get(i, i)
	}
	// log.Println(c)
	return c
}
<commit_msg>Added cmd prams for encode and decode<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/skelterjohn/go.matrix" // daa59528eefd43623a4c8e36373a86f9eef870a2
	"github.com/youpy/go-wav"
	"io"
	"log"
	"os"
)

func main() {
	// I have no idea what I am doing
	Encoding := flag.Bool("encode", false, "true if you want to encode")
	Decoding := flag.Bool("decode", false, "true if you want to decode")
	Filename := flag.String("in", "", "What file the output sould be read from")
	OutputFile := flag.String("out", "", "What file the output sould be written to")
	flag.Parse()

	if *Encoding && *Decoding {
		log.Fatal("You can't do both!")
	}
	if *Filename == "" || *OutputFile == "" {
		log.Fatal("Please give both input and output.")
	}

	fmt.Println("Bop")
	if len(os.Args) <= 1 {
		log.Fatal("You need to tell me what file to encode.")
	}
	if *Encoding {
		Encode(*Filename, *OutputFile)
	}

}

func Encode(filename, OutputFile string) {
	// I have no idea what I am doing
	fmt.Println("Bop")
	if len(os.Args) <= 1 {
		log.Fatal("You need to tell me what file to encode.")
	}
	file, _ := os.Open(filename)

	outputpac, _ := os.OpenFile(OutputFile, os.O_CREATE, 600)

	reader := wav.NewReader(file)

	BlockesProcessed := 0
	// End of settings for output
	var SampleBlock []float64
	SampleBlock = make([]float64, 8)
	for {
		samplez := make([]wav.Sample, 0)
		samples, err := reader.ReadSamples()
		// Samples will return (usally) 2048 samples in a single sitting

		log.Println(BlockesProcessed)
		if err == io.EOF {
			break
		}

		BlockesProcessed++
		var SamplePointer int = 0 // max is 8
		for _, sample := range samples {
			sam := wav.Sample{}
			L := reader.IntValue(sample, 0)
			R := reader.IntValue(sample, 1)
			MonoVal := (L + R) / 2

			// Now we add it to the staging array
			SampleBlock[SamplePointer] = float64(MonoVal)
			SamplePointer++
			if SamplePointer == 8 {
				out := GetPolyResults([]float64{0, 1, 2, 3, 4, 5, 6, 7}, SampleBlock)
				Line := fmt.Sprintf("%f,%f,%f,%f,%f\n", out[0], out[1], out[2], out[3], out[4])
				outputpac.Write([]byte(Line))
				SamplePointer = 0
			}
			sam.Values[0] = L
			sam.Values[0] = R
			samplez = append(samplez, sam)
		}

		// fmt.Println(len(samplez), len(samples))
	}

}

var degree = 5

func GetPolyResults(xGiven []float64, yGiven []float64) []float64 {
	m := len(yGiven)
	if m != len(xGiven) {
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	if m < 5 {
		// Prevent the processing of really small datasets, This is becauase there
		// appears to be a bug in the libary that will trigger a crash in the go.matrix
		// if some (small) amount of values are entered. I don't know why this happens
		// (Otherwise I would have fixed it) but the URL for the github issue is:
		// https://github.com/skelterjohn/go.matrix/issues/11
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	n := degree + 1
	y := matrix.MakeDenseMatrix(yGiven, m, 1)
	x := matrix.Zeros(m, n)
	for i := 0; i < m; i++ {
		ip := float64(1)
		for j := 0; j < n; j++ {
			x.Set(i, j, ip)
			ip *= xGiven[i]
		}
	}

	q, r := x.QR()
	qty, err := q.Transpose().Times(y)
	if err != nil {
		log.Println(err)
		return []float64{0, 0, 0, 0, 0} // Send it back, There is nothing sane here.
	}
	c := make([]float64, n)
	for i := n - 1; i >= 0; i-- {
		c[i] = qty.Get(i, 0)
		for j := i + 1; j < n; j++ {
			c[i] -= c[j] * r.Get(i, j)
		}
		c[i] /= r.Get(i, i)
	}
	// log.Println(c)
	return c
}
<|endoftext|>


<commit_before>package main

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

func renderTemplate(filename string, tmplFile string, data interface{}) (err error) {
	tmpl, err := template.ParseFiles("rep.tmpl")
	if err != nil {
		return
	}
	fd, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer fd.Close()
	err = tmpl.Execute(fd, data)
	return
}

func dumpFile(filename string, data interface{}) (err error) {
	fd, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer fd.Close()
	err = json.NewEncoder(fd).Encode(data)
	return
}

func loadFile(filename string, data interface{}) (err error) {
	fd, err := os.Open(filename)
	if err != nil {
		return
	}
	defer fd.Close()
	err = json.NewDecoder(fd).Decode(data)
	return
}

func renderJson(filename string, data interface{}) (err error) {
	fd, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer fd.Close()
	err = json.NewEncoder(fd).Encode(data)
	return
}

//func saveText(filename string,

func ignore(info os.FileInfo) bool {
	if info.IsDir() {
		if info.Name() != "." && info.Name() != ".." &&
			strings.HasPrefix(info.Name(), ".") { // ignore hidden dir
			return true
		}
	} else {
		return strings.HasPrefix(info.Name(), ".")
	}
	return false
}

func pathWalk(path string, depth int) (files []string, err error) {
	files = make([]string, 0)
	baseNumSeps := strings.Count(path, string(os.PathSeparator))
	err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			pathDepth := strings.Count(path, string(os.PathSeparator)) - baseNumSeps
			if pathDepth > depth {
				return filepath.SkipDir
			}
			if ignore(info) {
				return filepath.SkipDir
			}
		} else if info.Mode().IsRegular() && !ignore(info) {
			if matched, _ := regexp.Match(*include, []byte(info.Name())); matched {
				files = append(files, path)
			}
		}
		return nil
	})
	return
}

var (
	depth      = flag.Int("depth", 0, "depth of dir search")
	path       = flag.String("path", "./", "root path")
	replacer   = flag.String("r", "{}", "filename replacer")
	command    = flag.String("c", "./{}", "spec how to run command")
	resultHtml = flag.String("html", "test.html", "output html")
	verbose    = flag.Bool("v", false, "show verbose info")
	resultJson = flag.String("json", ".out.json", "output json")

	include = flag.String("I", ".*", "regex to match include file")
	//exclude = flag.String("x", "\\.*", "regex to exclude file")
	reload = flag.Bool("reload", false, "reload failed file, and run again")
)

type TaskConfig struct {
	Replacer string
	Command  string
	Files    []string
}

type TaskResult struct {
	StartTime string
	TimeCost  time.Duration
	Command   string
	Filename  string
	Output    string // console out
	Source    string // source code
	Error     error
}

func work(cfg *TaskConfig) (results []TaskResult) {
	var err error
	results = []TaskResult{}
	for i, file := range cfg.Files {
		start := time.Now()
		r := TaskResult{
			StartTime: start.Format("15:04:05"),
		}
		c := strings.Replace(cfg.Command, cfg.Replacer, file, -1)

		prefix := fmt.Sprintf("\r\033[36m>>>\033[0m %-5d", i)
		format := fmt.Sprintf(prefix+"%%-14v %-24s\n", c) //file) //file)
		// show current exec file
		fmt.Printf(prefix+"exec %s ...", strconv.Quote(file))
		if *verbose {
			fmt.Printf("\n")
		}

		output := bytes.NewBuffer(nil)
		cmd := exec.Command("/bin/bash", "-c", c)
		if *verbose {
			cmd.Stdout = io.MultiWriter(os.Stdout, output)
			cmd.Stderr = io.MultiWriter(os.Stderr, output)
		} else {
			cmd.Stdout = output
			cmd.Stderr = output
		}
		err = cmd.Run()
		if err != nil {
			r.Error = err
			fmt.Printf(format, fmt.Sprintf("\033[33m"+"err: %s"+"\033[0m", err))
		} else {
			fmt.Printf(format, "\033[32m"+"success"+"\033[0m")
		}
		r.Command = c
		r.Filename = file
		r.TimeCost = time.Now().Sub(start)
		r.Output = string(output.Bytes())
		r.Source = "unfinished(todo)"
		results = append(results, r)
	}
	return
}

func init() {
	flag.Parse()
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func fileExists(filename string) bool {
	fi, err := os.Stat(filename)
	return err == nil && fi.Mode().IsRegular()
}

func selfPath() string {
	return filepath.Dir(os.Args[0])
}

func main() {
	var err error
	var taskcfg = &TaskConfig{}
	if *reload && fileExists(*resultJson) {
		err = loadFile(*resultJson, taskcfg)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		files, err := pathWalk(*path, *depth)
		if err != nil {
			log.Fatal(err)
		}
		taskcfg.Command = *command
		taskcfg.Replacer = *replacer
		taskcfg.Files = files
	}

	results := work(taskcfg)
	errfiles := []string{}
	errCnt := 0
	for _, r := range results {
		if r.Error != nil {
			errCnt++
			errfiles = append(errfiles, r.Filename)
		}
	}
	// save to restart again
	taskcfg.Files = errfiles
	err = dumpFile(*resultJson, taskcfg)
	if err != nil {
		log.Fatal(err)
	}

	// reder html
	startTime := time.Now()
	data := map[string]interface{}{}
	data["StartTime"] = startTime.Format("2006-01-02 15:04:05")
	endTime := time.Now()
	data["TimeCost"] = endTime.Sub(startTime)
	data["Tasks"] = results
	hostname, _ := os.Hostname()
	data["Host"] = hostname
	data["Total"] = len(taskcfg.Files)
	data["FailCount"] = errCnt

	tmplPath := filepath.Join(selfPath(), ".rep.tmpl")
	if !fileExists(tmplPath) {
		log.Println("create .rep.tmpl")
		ioutil.WriteFile(tmplPath, []byte(defaultTemplate), 0644)
	}
	err = renderTemplate(*resultHtml, tmplPath, data)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>fix page show bug<commit_after>package main

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

func renderTemplate(filename string, tmplFile string, data interface{}) (err error) {
	tmpl, err := template.ParseFiles("rep.tmpl")
	if err != nil {
		return
	}
	fd, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer fd.Close()
	err = tmpl.Execute(fd, data)
	return
}

func dumpFile(filename string, data interface{}) (err error) {
	fd, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer fd.Close()
	err = json.NewEncoder(fd).Encode(data)
	return
}

func loadFile(filename string, data interface{}) (err error) {
	fd, err := os.Open(filename)
	if err != nil {
		return
	}
	defer fd.Close()
	err = json.NewDecoder(fd).Decode(data)
	return
}

func renderJson(filename string, data interface{}) (err error) {
	fd, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer fd.Close()
	err = json.NewEncoder(fd).Encode(data)
	return
}

//func saveText(filename string,

func ignore(info os.FileInfo) bool {
	if info.IsDir() {
		if info.Name() != "." && info.Name() != ".." &&
			strings.HasPrefix(info.Name(), ".") { // ignore hidden dir
			return true
		}
	} else {
		return strings.HasPrefix(info.Name(), ".")
	}
	return false
}

func pathWalk(path string, depth int) (files []string, err error) {
	files = make([]string, 0)
	baseNumSeps := strings.Count(path, string(os.PathSeparator))
	err = filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			pathDepth := strings.Count(path, string(os.PathSeparator)) - baseNumSeps
			if pathDepth > depth {
				return filepath.SkipDir
			}
			if ignore(info) {
				return filepath.SkipDir
			}
		} else if info.Mode().IsRegular() && !ignore(info) {
			if matched, _ := regexp.Match(*include, []byte(info.Name())); matched {
				files = append(files, path)
			}
		}
		return nil
	})
	return
}

var (
	depth      = flag.Int("depth", 0, "depth of dir search")
	path       = flag.String("path", "./", "root path")
	replacer   = flag.String("r", "{}", "filename replacer")
	command    = flag.String("c", "./{}", "spec how to run command")
	resultHtml = flag.String("html", "test.html", "output html")
	verbose    = flag.Bool("v", false, "show verbose info")
	resultJson = flag.String("json", ".out.json", "output json")

	include = flag.String("I", ".*", "regex to match include file")
	//exclude = flag.String("x", "\\.*", "regex to exclude file")
	reload = flag.Bool("reload", false, "reload failed file, and run again")
)

type TaskConfig struct {
	Replacer string
	Command  string
	Files    []string
}

type TaskResult struct {
	StartTime string
	TimeCost  time.Duration
	Command   string
	Filename  string
	Output    string // console out
	Source    string // source code
	Error     error
}

func work(cfg *TaskConfig) (results []TaskResult) {
	var err error
	results = []TaskResult{}
	for i, file := range cfg.Files {
		start := time.Now()
		r := TaskResult{
			StartTime: start.Format("15:04:05"),
		}
		c := strings.Replace(cfg.Command, cfg.Replacer, file, -1)

		prefix := fmt.Sprintf("\r\033[36m>>>\033[0m %-5d", i)
		format := fmt.Sprintf(prefix+"%%-14v %-24s\n", c) //file) //file)
		// show current exec file
		fmt.Printf(prefix+"exec %s ...", strconv.Quote(file))
		if *verbose {
			fmt.Printf("\n")
		}

		output := bytes.NewBuffer(nil)
		cmd := exec.Command("/bin/bash", "-c", c)
		if *verbose {
			cmd.Stdout = io.MultiWriter(os.Stdout, output)
			cmd.Stderr = io.MultiWriter(os.Stderr, output)
		} else {
			cmd.Stdout = output
			cmd.Stderr = output
		}
		err = cmd.Run()
		if err != nil {
			r.Error = err
			fmt.Printf(format, fmt.Sprintf("\033[33m"+"err: %s"+"\033[0m", err))
		} else {
			fmt.Printf(format, "\033[32m"+"success"+"\033[0m")
		}
		r.Command = c
		r.Filename = file
		r.TimeCost = time.Now().Sub(start)
		r.Output = string(output.Bytes())
		r.Source = "unfinished(todo)"
		results = append(results, r)
	}
	return
}

func init() {
	flag.Parse()
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func fileExists(filename string) bool {
	fi, err := os.Stat(filename)
	return err == nil && fi.Mode().IsRegular()
}

func selfPath() string {
	return filepath.Dir(os.Args[0])
}

func main() {
	var err error
	var taskcfg = &TaskConfig{}
	var startTime = time.Now()
	if *reload && fileExists(*resultJson) {
		err = loadFile(*resultJson, taskcfg)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		files, err := pathWalk(*path, *depth)
		if err != nil {
			log.Fatal(err)
		}
		taskcfg.Command = *command
		taskcfg.Replacer = *replacer
		taskcfg.Files = files
	}

	results := work(taskcfg)
	errfiles := []string{}
	errCnt := 0
	for _, r := range results {
		if r.Error != nil {
			errCnt++
			errfiles = append(errfiles, r.Filename)
		}
	}

	// reder html
	data := map[string]interface{}{}
	data["StartTime"] = startTime.Format("2006-01-02 15:04:05")
	endTime := time.Now()
	data["TimeCost"] = endTime.Sub(startTime)
	data["Tasks"] = results
	hostname, _ := os.Hostname()
	data["Host"] = hostname
	data["Total"] = len(taskcfg.Files)
	data["FailCount"] = errCnt

	tmplPath := filepath.Join(selfPath(), ".rep.tmpl")
	if !fileExists(tmplPath) {
		log.Println("create .rep.tmpl")
		ioutil.WriteFile(tmplPath, []byte(defaultTemplate), 0644)
	}
	err = renderTemplate(*resultHtml, tmplPath, data)
	if err != nil {
		log.Fatal(err)
	}

	// save to restart again
	taskcfg.Files = errfiles
	err = dumpFile(*resultJson, taskcfg)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"go/build"
	"log"
	"os"
	"sort"
	"strings"
)

var (
	pkgs map[string]*build.Package
	ids  map[string]string

	ignored = map[string]bool{
		"C": true,
	}
	ignoredPrefixes []string
	onlyPrefixes    []string

	ignoreStdlib   = flag.Bool("nostdlib", false, "ignore packages in the Go standard library")
	ignoreVendor   = flag.Bool("novendor", false, "ignore packages in the vendor directory")
	stopOnError    = flag.Bool("stoponerror", true, "stop on package import errors")
	withGoroot     = flag.Bool("withgoroot", false, "show dependencies of packages in the Go standard library")
	ignorePrefixes = flag.String("ignoreprefixes", "", "a comma-separated list of prefixes to ignore")
	ignorePackages = flag.String("ignorepackages", "", "a comma-separated list of packages to ignore")
	onlyPrefix     = flag.String("onlyprefixes", "", "a comma-separated list of prefixes to include")
	tagList        = flag.String("tags", "", "a comma-separated list of build tags to consider satisfied during the build")
	horizontal     = flag.Bool("horizontal", false, "lay out the dependency graph horizontally instead of vertically")
	withTests      = flag.Bool("withtests", false, "include test packages")
	maxLevel       = flag.Int("maxlevel", 256, "max level of go dependency graph")

	buildTags    []string
	buildContext = build.Default
)

func init() {
	flag.BoolVar(ignoreStdlib, "s", false, "(alias for -nostdlib) ignore packages in the Go standard library")
	flag.StringVar(ignorePrefixes, "p", "", "(alias for -ignoreprefixes) a comma-separated list of prefixes to ignore")
	flag.StringVar(ignorePackages, "i", "", "(alias for -ignorepackages) a comma-separated list of packages to ignore")
	flag.StringVar(onlyPrefix, "o", "", "(alias for -onlyprefixes) a comma-separated list of prefixes to include")
	flag.BoolVar(withTests, "t", false, "(alias for -withtests) include test packages")
	flag.IntVar(maxLevel, "l", 256, "(alias for -maxlevel) maximum level of the go dependency graph")
	flag.BoolVar(withGoroot, "d", false, "(alias for -withgoroot) show dependencies of packages in the Go standard library")
}

func main() {
	pkgs = make(map[string]*build.Package)
	ids = make(map[string]string)
	flag.Parse()

	args := flag.Args()

	if len(args) < 1 {
		log.Fatal("need one package name to process")
	}

	if *ignorePrefixes != "" {
		ignoredPrefixes = strings.Split(*ignorePrefixes, ",")
	}
	if *onlyPrefix != "" {
		onlyPrefixes = strings.Split(*onlyPrefix, ",")
	}
	if *ignorePackages != "" {
		for _, p := range strings.Split(*ignorePackages, ",") {
			ignored[p] = true
		}
	}
	if *tagList != "" {
		buildTags = strings.Split(*tagList, ",")
	}
	buildContext.BuildTags = buildTags

	cwd, err := os.Getwd()
	if err != nil {
		log.Fatalf("failed to get cwd: %s", err)
	}
	for _, a := range args {
		if err := processPackage(cwd, a, 0, "", *stopOnError); err != nil {
			log.Fatal(err)
		}
	}

	fmt.Println("digraph godep {")
	if *horizontal {
		fmt.Println(`rankdir="LR"`)
	}
	fmt.Print(`splines=ortho
nodesep=0.4
ranksep=0.8
node [shape="box",style="rounded,filled"]
edge [arrowsize="0.5"]
`)

	// sort packages
	pkgKeys := []string{}
	for k := range pkgs {
		pkgKeys = append(pkgKeys, k)
	}
	sort.Strings(pkgKeys)

	for _, pkgName := range pkgKeys {
		pkg := pkgs[pkgName]
		pkgId := getId(pkgName)

		if isIgnored(pkg) {
			continue
		}

		var color string
		switch {
		case pkg.Goroot:
			color = "palegreen"
		case len(pkg.CgoFiles) > 0:
			color = "darkgoldenrod1"
		case isVendored(pkg.ImportPath):
			color = "palegoldenrod"
		default:
			color = "paleturquoise"
		}

		fmt.Printf("%s [label=\"%s\" color=\"%s\"];\n", pkgId, pkgName, color)

		// Don't render imports from packages in Goroot
		if pkg.Goroot && !*withGoroot {
			continue
		}

		for _, imp := range getImports(pkg) {
			impPkg := pkgs[imp]
			if impPkg == nil || isIgnored(impPkg) {
				continue
			}

			impId := getId(imp)
			fmt.Printf("%s -> %s;\n", pkgId, impId)
		}
	}
	fmt.Println("}")
}

func processPackage(root string, pkgName string, level int, importedBy string, stopOnError bool) error {
	if level++; level > *maxLevel {
		return nil
	}
	if ignored[pkgName] {
		return nil
	}

	pkg, err := buildContext.Import(pkgName, root, 0)
	if err != nil {
		if stopOnError {
			return fmt.Errorf("failed to import %s (imported at level %d by %s): %s", pkgName, level, importedBy, err)
		} else {
			// TODO: mark the package so that it is rendered with a different color
		}
	}

	if isIgnored(pkg) {
		return nil
	}

	pkgs[normalizeVendor(pkg.ImportPath)] = pkg

	// Don't worry about dependencies for stdlib packages
	if pkg.Goroot && !*withGoroot {
		return nil
	}

	for _, imp := range getImports(pkg) {
		if _, ok := pkgs[imp]; !ok {
			if err := processPackage(pkg.Dir, imp, level, pkgName, stopOnError); err != nil {
				return err
			}
		}
	}
	return nil
}

func getImports(pkg *build.Package) []string {
	allImports := pkg.Imports
	if *withTests {
		allImports = append(allImports, pkg.TestImports...)
		allImports = append(allImports, pkg.XTestImports...)
	}
	var imports []string
	found := make(map[string]struct{})
	for _, imp := range allImports {
		if imp == normalizeVendor(pkg.ImportPath) {
			// Don't draw a self-reference when foo_test depends on foo.
			continue
		}
		if _, ok := found[imp]; ok {
			continue
		}
		found[imp] = struct{}{}
		imports = append(imports, imp)
	}
	return imports
}

func deriveNodeID(packageName string) string {
	//TODO: improve implementation?
	id := "\"" + packageName + "\""
	return id
}

func getId(name string) string {
	id, ok := ids[name]
	if !ok {
		id = deriveNodeID(name)
		ids[name] = id
	}
	return id
}

func hasPrefixes(s string, prefixes []string) bool {
	for _, p := range prefixes {
		if strings.HasPrefix(s, p) {
			return true
		}
	}
	return false
}

func isIgnored(pkg *build.Package) bool {
	if len(onlyPrefixes) > 0 && !hasPrefixes(normalizeVendor(pkg.ImportPath), onlyPrefixes) {
		return true
	}

	if *ignoreVendor && isVendored(pkg.ImportPath) {
		return true
	}
	return ignored[normalizeVendor(pkg.ImportPath)] || (pkg.Goroot && *ignoreStdlib) || hasPrefixes(normalizeVendor(pkg.ImportPath), ignoredPrefixes)
}

func debug(args ...interface{}) {
	fmt.Fprintln(os.Stderr, args...)
}

func debugf(s string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, s, args...)
}

func isVendored(path string) bool {
	return strings.Contains(path, "/vendor/")
}

func normalizeVendor(path string) string {
	pieces := strings.Split(path, "vendor/")
	return pieces[len(pieces)-1]
}
<commit_msg>Link package nodes to godoc. Works for SVG output.<commit_after>package main

import (
	"flag"
	"fmt"
	"go/build"
	"log"
	"os"
	"sort"
	"strings"
)

var (
	pkgs map[string]*build.Package
	ids  map[string]string

	ignored = map[string]bool{
		"C": true,
	}
	ignoredPrefixes []string
	onlyPrefixes    []string

	ignoreStdlib   = flag.Bool("nostdlib", false, "ignore packages in the Go standard library")
	ignoreVendor   = flag.Bool("novendor", false, "ignore packages in the vendor directory")
	stopOnError    = flag.Bool("stoponerror", true, "stop on package import errors")
	withGoroot     = flag.Bool("withgoroot", false, "show dependencies of packages in the Go standard library")
	ignorePrefixes = flag.String("ignoreprefixes", "", "a comma-separated list of prefixes to ignore")
	ignorePackages = flag.String("ignorepackages", "", "a comma-separated list of packages to ignore")
	onlyPrefix     = flag.String("onlyprefixes", "", "a comma-separated list of prefixes to include")
	tagList        = flag.String("tags", "", "a comma-separated list of build tags to consider satisfied during the build")
	horizontal     = flag.Bool("horizontal", false, "lay out the dependency graph horizontally instead of vertically")
	withTests      = flag.Bool("withtests", false, "include test packages")
	maxLevel       = flag.Int("maxlevel", 256, "max level of go dependency graph")

	buildTags    []string
	buildContext = build.Default
)

func init() {
	flag.BoolVar(ignoreStdlib, "s", false, "(alias for -nostdlib) ignore packages in the Go standard library")
	flag.StringVar(ignorePrefixes, "p", "", "(alias for -ignoreprefixes) a comma-separated list of prefixes to ignore")
	flag.StringVar(ignorePackages, "i", "", "(alias for -ignorepackages) a comma-separated list of packages to ignore")
	flag.StringVar(onlyPrefix, "o", "", "(alias for -onlyprefixes) a comma-separated list of prefixes to include")
	flag.BoolVar(withTests, "t", false, "(alias for -withtests) include test packages")
	flag.IntVar(maxLevel, "l", 256, "(alias for -maxlevel) maximum level of the go dependency graph")
	flag.BoolVar(withGoroot, "d", false, "(alias for -withgoroot) show dependencies of packages in the Go standard library")
}

func main() {
	pkgs = make(map[string]*build.Package)
	ids = make(map[string]string)
	flag.Parse()

	args := flag.Args()

	if len(args) < 1 {
		log.Fatal("need one package name to process")
	}

	if *ignorePrefixes != "" {
		ignoredPrefixes = strings.Split(*ignorePrefixes, ",")
	}
	if *onlyPrefix != "" {
		onlyPrefixes = strings.Split(*onlyPrefix, ",")
	}
	if *ignorePackages != "" {
		for _, p := range strings.Split(*ignorePackages, ",") {
			ignored[p] = true
		}
	}
	if *tagList != "" {
		buildTags = strings.Split(*tagList, ",")
	}
	buildContext.BuildTags = buildTags

	cwd, err := os.Getwd()
	if err != nil {
		log.Fatalf("failed to get cwd: %s", err)
	}
	for _, a := range args {
		if err := processPackage(cwd, a, 0, "", *stopOnError); err != nil {
			log.Fatal(err)
		}
	}

	fmt.Println("digraph godep {")
	if *horizontal {
		fmt.Println(`rankdir="LR"`)
	}
	fmt.Print(`splines=ortho
nodesep=0.4
ranksep=0.8
node [shape="box",style="rounded,filled"]
edge [arrowsize="0.5"]
`)

	// sort packages
	pkgKeys := []string{}
	for k := range pkgs {
		pkgKeys = append(pkgKeys, k)
	}
	sort.Strings(pkgKeys)

	for _, pkgName := range pkgKeys {
		pkg := pkgs[pkgName]
		pkgId := getId(pkgName)

		if isIgnored(pkg) {
			continue
		}

		var color string
		switch {
		case pkg.Goroot:
			color = "palegreen"
		case len(pkg.CgoFiles) > 0:
			color = "darkgoldenrod1"
		case isVendored(pkg.ImportPath):
			color = "palegoldenrod"
		default:
			color = "paleturquoise"
		}

		fmt.Printf("%s [label=\"%s\" color=\"%s\" URL=\"%s\" target=\"_blank\"];\n", pkgId, pkgName, color, pkgURL(pkgName))

		// Don't render imports from packages in Goroot
		if pkg.Goroot && !*withGoroot {
			continue
		}

		for _, imp := range getImports(pkg) {
			impPkg := pkgs[imp]
			if impPkg == nil || isIgnored(impPkg) {
				continue
			}

			impId := getId(imp)
			fmt.Printf("%s -> %s;\n", pkgId, impId)
		}
	}
	fmt.Println("}")
}

func pkgURL(pkgName string) string {
	return "https://godoc.org/" + pkgName
}

func processPackage(root string, pkgName string, level int, importedBy string, stopOnError bool) error {
	if level++; level > *maxLevel {
		return nil
	}
	if ignored[pkgName] {
		return nil
	}

	pkg, err := buildContext.Import(pkgName, root, 0)
	if err != nil {
		if stopOnError {
			return fmt.Errorf("failed to import %s (imported at level %d by %s): %s", pkgName, level, importedBy, err)
		} else {
			// TODO: mark the package so that it is rendered with a different color
		}
	}

	if isIgnored(pkg) {
		return nil
	}

	pkgs[normalizeVendor(pkg.ImportPath)] = pkg

	// Don't worry about dependencies for stdlib packages
	if pkg.Goroot && !*withGoroot {
		return nil
	}

	for _, imp := range getImports(pkg) {
		if _, ok := pkgs[imp]; !ok {
			if err := processPackage(pkg.Dir, imp, level, pkgName, stopOnError); err != nil {
				return err
			}
		}
	}
	return nil
}

func getImports(pkg *build.Package) []string {
	allImports := pkg.Imports
	if *withTests {
		allImports = append(allImports, pkg.TestImports...)
		allImports = append(allImports, pkg.XTestImports...)
	}
	var imports []string
	found := make(map[string]struct{})
	for _, imp := range allImports {
		if imp == normalizeVendor(pkg.ImportPath) {
			// Don't draw a self-reference when foo_test depends on foo.
			continue
		}
		if _, ok := found[imp]; ok {
			continue
		}
		found[imp] = struct{}{}
		imports = append(imports, imp)
	}
	return imports
}

func deriveNodeID(packageName string) string {
	//TODO: improve implementation?
	id := "\"" + packageName + "\""
	return id
}

func getId(name string) string {
	id, ok := ids[name]
	if !ok {
		id = deriveNodeID(name)
		ids[name] = id
	}
	return id
}

func hasPrefixes(s string, prefixes []string) bool {
	for _, p := range prefixes {
		if strings.HasPrefix(s, p) {
			return true
		}
	}
	return false
}

func isIgnored(pkg *build.Package) bool {
	if len(onlyPrefixes) > 0 && !hasPrefixes(normalizeVendor(pkg.ImportPath), onlyPrefixes) {
		return true
	}

	if *ignoreVendor && isVendored(pkg.ImportPath) {
		return true
	}
	return ignored[normalizeVendor(pkg.ImportPath)] || (pkg.Goroot && *ignoreStdlib) || hasPrefixes(normalizeVendor(pkg.ImportPath), ignoredPrefixes)
}

func debug(args ...interface{}) {
	fmt.Fprintln(os.Stderr, args...)
}

func debugf(s string, args ...interface{}) {
	fmt.Fprintf(os.Stderr, s, args...)
}

func isVendored(path string) bool {
	return strings.Contains(path, "/vendor/")
}

func normalizeVendor(path string) string {
	pieces := strings.Split(path, "vendor/")
	return pieces[len(pieces)-1]
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"os"

	"github.com/ian-kent/Go-MailHog/MailHog-Server/config"
	"github.com/ian-kent/Go-MailHog/MailHog-UI/assets"
	"github.com/ian-kent/Go-MailHog/MailHog-UI/http/web"
	"github.com/ian-kent/Go-MailHog/http"
	"github.com/ian-kent/go-log/log"
	gotcha "github.com/ian-kent/gotcha/app"
)

var conf *config.Config
var exitCh chan int

func configure() {
	config.RegisterFlags()
	flag.Parse()
	conf = config.Configure()
}

func main() {
	configure()

	// FIXME need to make API URL configurable

	exitCh = make(chan int)
	cb := func(app *gotcha.App) {
		web.CreateWeb(conf, app)
	}
	go http.Listen(conf, assets.Asset, exitCh, cb)

	for {
		select {
		case <-exitCh:
			log.Printf("Received exit signal")
			os.Exit(0)
		}
	}
}
<commit_msg>Remove old tests, fix import<commit_after>package main

import (
	"flag"
	"os"

	"github.com/ian-kent/Go-MailHog/MailHog-Server/config"
	"github.com/ian-kent/Go-MailHog/MailHog-UI/assets"
	"github.com/ian-kent/Go-MailHog/MailHog-UI/web"
	"github.com/ian-kent/Go-MailHog/http"
	"github.com/ian-kent/go-log/log"
	gotcha "github.com/ian-kent/gotcha/app"
)

var conf *config.Config
var exitCh chan int

func configure() {
	config.RegisterFlags()
	flag.Parse()
	conf = config.Configure()
}

func main() {
	configure()

	// FIXME need to make API URL configurable

	exitCh = make(chan int)
	cb := func(app *gotcha.App) {
		web.CreateWeb(conf, app)
	}
	go http.Listen(conf, assets.Asset, exitCh, cb)

	for {
		select {
		case <-exitCh:
			log.Printf("Received exit signal")
			os.Exit(0)
		}
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	yaml "gopkg.in/yaml.v2"
)

const (
	defaultSpiderTime = 30 * time.Second
	defaultTimeout    = 20 * time.Second
)

var (
	configFile = flag.String("config", "./config.yml", "config file")
	listen     = flag.String("listen", ":8080", "listen address")
	verbose    = flag.Bool("v", false, "verbose")

	reqHist = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: "http",
			Name:      "time",
			Help:      "end-to-end time of requests",
			Buckets:   prometheus.ExponentialBuckets(0.001, 2, 16), // 0.001 -> 32 seconds
		},
		[]string{"name", "result"},
	)
)

func init() {
	prometheus.MustRegister(reqHist)
}

func main() {
	flag.Parse()

	b, err := ioutil.ReadFile(*configFile)
	if err != nil {
		fmt.Printf("%s\n", err)
		os.Exit(1)
	}

	c := Config{}
	if err := yaml.Unmarshal(b, &c); err != nil {
		fmt.Printf("%s\n", err)
		os.Exit(1)
	}

	for name, t := range c.Targets {
		st := t.SpiderTime
		if st == 0 {
			st = c.SpiderTime
		}
		if st == 0 {
			st = defaultSpiderTime
		}

		timeout := t.Timeout
		if timeout == 0 {
			timeout = c.Timeout
		}
		if timeout == 0 {
			timeout = defaultTimeout
		}

		// sanity check
		if u, err := url.Parse(t.URL); err != nil {
			panic(fmt.Sprintf("invalid target %q: %s\n", name, err))
		} else {
			switch u.Scheme {
			case "http", "https":
			default:
				fmt.Printf("invalid target %q: unsupported scheme %q\n", name, u.Scheme)
				os.Exit(1)
			}
		}

		go spider(name, t, st, timeout)
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		fmt.Fprintf(w, `see <a href="/metrics">/metrics</a>`)
	})
	http.Handle("/metrics", promhttp.Handler())
	fmt.Printf("listening on %s...\n", *listen)
	http.ListenAndServe(*listen, nil)
}

func spider(name string, target Target, spiderTime, timeout time.Duration) {
	client := &http.Client{
		Timeout: timeout,
		CheckRedirect: func(_ *http.Request, _ []*http.Request) error {
			return http.ErrUseLastResponse
		},
		Transport: &http.Transport{
			DisableKeepAlives:   true,
			TLSHandshakeTimeout: timeout,
			DialContext: (&net.Dialer{
				Timeout: timeout,
			}).DialContext,
		},
	}

	if *verbose {
		fmt.Printf("starting %q spider:%s timeout:%s\n", name, spiderTime, timeout)
	}

	for {
		var (
			t       = time.Now()
			success = false
		)
		req, err := http.NewRequest(target.Method, target.URL, nil)
		if err != nil {
			fmt.Printf("%s: %s\n", name, err)
		} else {
			resp, err := client.Do(req)
			if err == nil {
				if _, err := ioutil.ReadAll(resp.Body); err == nil {
					resp.Body.Close()
					if resp.StatusCode == 200 {
						success = true
					} else {
						if *verbose {
							fmt.Printf("%s: status code %d\n", name, resp.StatusCode)
						}
					}
				}
			} else {
				if *verbose {
					fmt.Printf("%s: %s\n", name, err)
				}
			}
		}

		dt := time.Since(t)
		sv := "error"
		if success {
			sv = "ok"
		}
		if *verbose {
			fmt.Printf("- %s: dt:%s success:%s\n", name, dt, sv)
		}
		reqHist.WithLabelValues(name, sv).Observe(dt.Seconds())

		time.Sleep(spiderTime)
	}
}
<commit_msg>different default port<commit_after>package main

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

	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	yaml "gopkg.in/yaml.v2"
)

const (
	defaultSpiderTime = 30 * time.Second
	defaultTimeout    = 20 * time.Second
)

var (
	configFile = flag.String("config", "./config.yml", "config file")
	listen     = flag.String("listen", ":9414", "listen address")
	verbose    = flag.Bool("v", false, "verbose")

	reqHist = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Namespace: "http",
			Name:      "time",
			Help:      "end-to-end time of requests",
			Buckets:   prometheus.ExponentialBuckets(0.001, 2, 16), // 0.001 -> 32 seconds
		},
		[]string{"name", "result"},
	)
)

func init() {
	prometheus.MustRegister(reqHist)
}

func main() {
	flag.Parse()

	b, err := ioutil.ReadFile(*configFile)
	if err != nil {
		fmt.Printf("%s\n", err)
		os.Exit(1)
	}

	c := Config{}
	if err := yaml.Unmarshal(b, &c); err != nil {
		fmt.Printf("%s\n", err)
		os.Exit(1)
	}

	for name, t := range c.Targets {
		st := t.SpiderTime
		if st == 0 {
			st = c.SpiderTime
		}
		if st == 0 {
			st = defaultSpiderTime
		}

		timeout := t.Timeout
		if timeout == 0 {
			timeout = c.Timeout
		}
		if timeout == 0 {
			timeout = defaultTimeout
		}

		// sanity check
		if u, err := url.Parse(t.URL); err != nil {
			panic(fmt.Sprintf("invalid target %q: %s\n", name, err))
		} else {
			switch u.Scheme {
			case "http", "https":
			default:
				fmt.Printf("invalid target %q: unsupported scheme %q\n", name, u.Scheme)
				os.Exit(1)
			}
		}

		go spider(name, t, st, timeout)
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/html")
		fmt.Fprintf(w, `see <a href="/metrics">/metrics</a>`)
	})
	http.Handle("/metrics", promhttp.Handler())
	fmt.Printf("listening on %s...\n", *listen)
	http.ListenAndServe(*listen, nil)
}

func spider(name string, target Target, spiderTime, timeout time.Duration) {
	client := &http.Client{
		Timeout: timeout,
		CheckRedirect: func(_ *http.Request, _ []*http.Request) error {
			return http.ErrUseLastResponse
		},
		Transport: &http.Transport{
			DisableKeepAlives:   true,
			TLSHandshakeTimeout: timeout,
			DialContext: (&net.Dialer{
				Timeout: timeout,
			}).DialContext,
		},
	}

	if *verbose {
		fmt.Printf("starting %q spider:%s timeout:%s\n", name, spiderTime, timeout)
	}

	for {
		var (
			t       = time.Now()
			success = false
		)
		req, err := http.NewRequest(target.Method, target.URL, nil)
		if err != nil {
			fmt.Printf("%s: %s\n", name, err)
		} else {
			resp, err := client.Do(req)
			if err == nil {
				if _, err := ioutil.ReadAll(resp.Body); err == nil {
					resp.Body.Close()
					if resp.StatusCode == 200 {
						success = true
					} else {
						if *verbose {
							fmt.Printf("%s: status code %d\n", name, resp.StatusCode)
						}
					}
				}
			} else {
				if *verbose {
					fmt.Printf("%s: %s\n", name, err)
				}
			}
		}

		dt := time.Since(t)
		sv := "error"
		if success {
			sv = "ok"
		}
		if *verbose {
			fmt.Printf("- %s: dt:%s success:%s\n", name, dt, sv)
		}
		reqHist.WithLabelValues(name, sv).Observe(dt.Seconds())

		time.Sleep(spiderTime)
	}
}
<|endoftext|>