<commit_before>package main

import (
	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/loadimpact/speedboat/aggregate"
	"github.com/loadimpact/speedboat/loadtest"
	"github.com/loadimpact/speedboat/report"
	"github.com/loadimpact/speedboat/runner"
	"github.com/loadimpact/speedboat/runner/duktapejs"
	"github.com/loadimpact/speedboat/runner/lua"
	"github.com/loadimpact/speedboat/runner/ottojs"
	"github.com/loadimpact/speedboat/runner/simple"
	"github.com/loadimpact/speedboat/runner/v8js"
	"golang.org/x/net/context"
	"io/ioutil"
	"os"
	"os/signal"
	"path"
	"runtime/debug"
	"time"
)

func makeTest(c *cli.Context) (test loadtest.LoadTest, err error) {
	base := ""
	conf := loadtest.NewConfig()
	if len(c.Args()) > 0 {
		filename := c.Args()[0]
		base = path.Dir(filename)
		data, err := ioutil.ReadFile(filename)
		if err != nil {
			return test, err
		}

		loadtest.ParseConfig(data, &conf)
	}

	if c.IsSet("script") {
		conf.Script = c.String("script")
		base = ""
	}
	if c.IsSet("url") {
		conf.URL = c.String("url")
	}
	if c.IsSet("duration") {
		conf.Duration = c.Duration("duration").String()
	}
	if c.IsSet("vus") {
		conf.VUs = c.Int("vus")
	}

	test, err = conf.Compile()
	if err != nil {
		return test, err
	}

	if test.Script != "" {
		srcb, err := ioutil.ReadFile(path.Join(base, test.Script))
		if err != nil {
			return test, err
		}
		test.Source = string(srcb)
	}

	return test, nil
}

func run(test loadtest.LoadTest, r runner.Runner) <-chan runner.Result {
	ch := make(chan runner.Result)

	go func() {
		defer close(ch)

		timeout := time.Duration(0)
		for _, stage := range test.Stages {
			timeout += stage.Duration
		}

		ctx, _ := context.WithTimeout(context.Background(), timeout)
		scale := make(chan int, 1)
		scale <- test.Stages[0].VUs.Start

		for res := range runner.Run(ctx, r, scale) {
			ch <- res
		}
	}()

	return ch
}

func action(c *cli.Context) {
	test, err := makeTest(c)
	if err != nil {
		log.WithError(err).Fatal("Configuration error")
	}

	r := runner.Runner(nil)

	// Start the pipeline by just running requests
	if test.Script != "" {
		ext := path.Ext(test.Script)
		switch ext {
		case ".lua":
			r = lua.New(test.Script, test.Source)
		case ".js":
			switch c.String("impl") {
			case "otto":
				r = ottojs.New(test.Script, test.Source)
			case "duk":
				r = duktapejs.New(test.Script, test.Source)
			case "v8":
				r = v8js.New(test.Script, test.Source)
			case "":
				log.Fatal("No implementation specified; use --impl {otto,duk}")
			default:
				log.Fatal("Unknown implementation")
			}
		default:
			log.WithField("ext", ext).Fatal("No runner found")
		}
	} else {
		r = simple.New(test.URL)
	}
	pipeline := run(test, r)

	// Stick result aggregation onto it
	stats := aggregate.Stats{}
	stats.Time.Values = make([]time.Duration, 30000000)[:0]
	pipeline = aggregate.Aggregate(&stats, pipeline)

	// Log results to a file
	outFilename := c.String("out-file")
	if outFilename != "" {
		reporter := report.CSVReporter{}
		if outFilename != "-" {
			f, err := os.Create("results.csv")
			if err != nil {
				log.WithError(err).Fatal("Couldn't open log file")
			}
			pipeline = report.Report(reporter, f, pipeline)
		} else {
			pipeline = report.Report(reporter, os.Stdout, pipeline)
		}
	}

	// Listen for SIGINT (Ctrl+C)
	stop := make(chan os.Signal)
	signal.Notify(stop, os.Interrupt)

runLoop:
	for {
		select {
		case res, ok := <-pipeline:
			if !ok {
				break runLoop
			}

			switch {
			case res.Error != nil:
				l := log.WithError(res.Error)
				if res.Time != time.Duration(0) {
					l = l.WithField("t", res.Time)
				}
				l.Error("Error")
			case res.Text != "":
				l := log.WithField("text", res.Text)
				if res.Time != time.Duration(0) {
					l = l.WithField("t", res.Time)
				}
				l.Info("Log")
			default:
				// log.WithField("t", res.Time).Debug("Metric")
			}
		case <-stop:
			break runLoop
		}
	}

	log.WithField("results", stats.Results).Info("Finished")
	log.WithFields(log.Fields{
		"min": stats.Time.Min,
		"max": stats.Time.Max,
		"med": stats.Time.Med,
		"avg": stats.Time.Avg,
	}).Info("Time")
}

// Configure the global logger.
func configureLogging(c *cli.Context) {
	if c.GlobalBool("verbose") {
		log.SetLevel(log.DebugLevel)
	}
}

func main() {
	// Up the thread limit (default: 10.000)
	debug.SetMaxThreads(100000)

	// Free up -v and -h for our own flags
	cli.VersionFlag.Name = "version"
	cli.HelpFlag.Name = "help, ?"

	// Bootstrap using action-registered commandline flags
	app := cli.NewApp()
	app.Name = "speedboat"
	app.Usage = "A next-generation load generator"
	app.Version = "0.0.1a1"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose, v",
			Usage: "More verbose output",
		},
		cli.StringFlag{
			Name:  "script, s",
			Usage: "Script to run (do not use with --url)",
		},
		cli.StringFlag{
			Name:  "url",
			Usage: "URL to test (do not use with --script)",
		},
		cli.IntFlag{
			Name:  "vus, u",
			Usage: "Number of VUs to simulate",
			Value: 10,
		},
		cli.DurationFlag{
			Name:  "duration, d",
			Usage: "Test duration",
			Value: time.Duration(10) * time.Second,
		},
		cli.StringFlag{
			Name:  "out-file, o",
			Usage: "Output raw metrics to a file",
		},
		cli.StringFlag{
			Name:  "impl, i",
			Usage: "Specify a runner implementation",
		},
	}
	app.Before = func(c *cli.Context) error {
		configureLogging(c)
		return nil
	}
	app.Action = action
	app.Run(os.Args)
}
<commit_msg>Forcibly grow the stack too<commit_after>package main

import (
	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/loadimpact/speedboat/aggregate"
	"github.com/loadimpact/speedboat/loadtest"
	"github.com/loadimpact/speedboat/report"
	"github.com/loadimpact/speedboat/runner"
	"github.com/loadimpact/speedboat/runner/duktapejs"
	"github.com/loadimpact/speedboat/runner/lua"
	"github.com/loadimpact/speedboat/runner/ottojs"
	"github.com/loadimpact/speedboat/runner/simple"
	"github.com/loadimpact/speedboat/runner/v8js"
	"golang.org/x/net/context"
	"io/ioutil"
	"os"
	"os/signal"
	"path"
	"runtime/debug"
	"time"
)

func makeTest(c *cli.Context) (test loadtest.LoadTest, err error) {
	base := ""
	conf := loadtest.NewConfig()
	if len(c.Args()) > 0 {
		filename := c.Args()[0]
		base = path.Dir(filename)
		data, err := ioutil.ReadFile(filename)
		if err != nil {
			return test, err
		}

		loadtest.ParseConfig(data, &conf)
	}

	if c.IsSet("script") {
		conf.Script = c.String("script")
		base = ""
	}
	if c.IsSet("url") {
		conf.URL = c.String("url")
	}
	if c.IsSet("duration") {
		conf.Duration = c.Duration("duration").String()
	}
	if c.IsSet("vus") {
		conf.VUs = c.Int("vus")
	}

	test, err = conf.Compile()
	if err != nil {
		return test, err
	}

	if test.Script != "" {
		srcb, err := ioutil.ReadFile(path.Join(base, test.Script))
		if err != nil {
			return test, err
		}
		test.Source = string(srcb)
	}

	return test, nil
}

func run(test loadtest.LoadTest, r runner.Runner) <-chan runner.Result {
	ch := make(chan runner.Result)

	go func() {
		defer close(ch)

		timeout := time.Duration(0)
		for _, stage := range test.Stages {
			timeout += stage.Duration
		}

		ctx, _ := context.WithTimeout(context.Background(), timeout)
		scale := make(chan int, 1)
		scale <- test.Stages[0].VUs.Start

		for res := range runner.Run(ctx, r, scale) {
			ch <- res
		}
	}()

	return ch
}

func action(c *cli.Context) {
	test, err := makeTest(c)
	if err != nil {
		log.WithError(err).Fatal("Configuration error")
	}

	r := runner.Runner(nil)

	// Start the pipeline by just running requests
	if test.Script != "" {
		ext := path.Ext(test.Script)
		switch ext {
		case ".lua":
			r = lua.New(test.Script, test.Source)
		case ".js":
			switch c.String("impl") {
			case "otto":
				r = ottojs.New(test.Script, test.Source)
			case "duk":
				r = duktapejs.New(test.Script, test.Source)
			case "v8":
				r = v8js.New(test.Script, test.Source)
			case "":
				log.Fatal("No implementation specified; use --impl {otto,duk}")
			default:
				log.Fatal("Unknown implementation")
			}
		default:
			log.WithField("ext", ext).Fatal("No runner found")
		}
	} else {
		r = simple.New(test.URL)
	}
	pipeline := run(test, r)

	// Stick result aggregation onto it
	stats := aggregate.Stats{}
	stats.Time.Values = make([]time.Duration, 30000000)[:0]
	pipeline = aggregate.Aggregate(&stats, pipeline)

	// Log results to a file
	outFilename := c.String("out-file")
	if outFilename != "" {
		reporter := report.CSVReporter{}
		if outFilename != "-" {
			f, err := os.Create("results.csv")
			if err != nil {
				log.WithError(err).Fatal("Couldn't open log file")
			}
			pipeline = report.Report(reporter, f, pipeline)
		} else {
			pipeline = report.Report(reporter, os.Stdout, pipeline)
		}
	}

	// Listen for SIGINT (Ctrl+C)
	stop := make(chan os.Signal)
	signal.Notify(stop, os.Interrupt)

runLoop:
	for {
		select {
		case res, ok := <-pipeline:
			if !ok {
				break runLoop
			}

			switch {
			case res.Error != nil:
				l := log.WithError(res.Error)
				if res.Time != time.Duration(0) {
					l = l.WithField("t", res.Time)
				}
				l.Error("Error")
			case res.Text != "":
				l := log.WithField("text", res.Text)
				if res.Time != time.Duration(0) {
					l = l.WithField("t", res.Time)
				}
				l.Info("Log")
			default:
				// log.WithField("t", res.Time).Debug("Metric")
			}
		case <-stop:
			break runLoop
		}
	}

	log.WithField("results", stats.Results).Info("Finished")
	log.WithFields(log.Fields{
		"min": stats.Time.Min,
		"max": stats.Time.Max,
		"med": stats.Time.Med,
		"avg": stats.Time.Avg,
	}).Info("Time")
}

// Configure the global logger.
func configureLogging(c *cli.Context) {
	if c.GlobalBool("verbose") {
		log.SetLevel(log.DebugLevel)
	}
}

func main() {
	// Up the thread limit (default: 10.000)
	debug.SetMaxThreads(100000)
	// Up the stack size limit (default: 1GB)
	debug.SetMaxStack(3 * 1000000000)

	// Free up -v and -h for our own flags
	cli.VersionFlag.Name = "version"
	cli.HelpFlag.Name = "help, ?"

	// Bootstrap using action-registered commandline flags
	app := cli.NewApp()
	app.Name = "speedboat"
	app.Usage = "A next-generation load generator"
	app.Version = "0.0.1a1"
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "verbose, v",
			Usage: "More verbose output",
		},
		cli.StringFlag{
			Name:  "script, s",
			Usage: "Script to run (do not use with --url)",
		},
		cli.StringFlag{
			Name:  "url",
			Usage: "URL to test (do not use with --script)",
		},
		cli.IntFlag{
			Name:  "vus, u",
			Usage: "Number of VUs to simulate",
			Value: 10,
		},
		cli.DurationFlag{
			Name:  "duration, d",
			Usage: "Test duration",
			Value: time.Duration(10) * time.Second,
		},
		cli.StringFlag{
			Name:  "out-file, o",
			Usage: "Output raw metrics to a file",
		},
		cli.StringFlag{
			Name:  "impl, i",
			Usage: "Specify a runner implementation",
		},
	}
	app.Before = func(c *cli.Context) error {
		configureLogging(c)
		return nil
	}
	app.Action = action
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"io/ioutil"
	"log"
	"os"
	"os/exec"

	"github.com/drone/drone-plugin-go/plugin"
	"github.com/kr/pty"
)

// SSHConfig the config used on the test runner
var SSHConfig = `Host *
    StrictHostKeyChecking no`

type deployer struct {
	Task  string `json:"task"`
	Stage string `json:"stage"`
}

func main() {
	d := new(deployer)
	w := new(plugin.Workspace)

	plugin.Param("vargs", d)
	plugin.Param("workspace", w)
	plugin.MustParse()

	// Save ssh keys
	if err := os.MkdirAll("/root/.ssh", 0700); err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile("/root/.ssh/config", []byte(SSHConfig), 0644); err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile("/root/.ssh/id_rsa", []byte(w.Keys.Private), 0600); err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile("/root/.ssh/id_rsa.pub", []byte(w.Keys.Public), 0644); err != nil {
		log.Fatal(err)
	}

	c := exec.Command("/usr/bin/php", "/bin/dep", d.Task, d.Stage)
	c.Dir = w.Path

	f, err := pty.Start(c)
	if err != nil {
		log.Fatal(err)
	}

	// Seems to always return an error
	// read /dev/ptmx: input/output error
	// So no error checking
	io.Copy(os.Stdout, f)

	log.Println("Command completed successfully")
}
<commit_msg>removed depedency on pty<commit_after>package main

import (
	"io/ioutil"
	"log"
	"os"
	"os/exec"

	"github.com/drone/drone-plugin-go/plugin"
)

// SSHConfig the config used on the test runner
var SSHConfig = `Host *
    StrictHostKeyChecking no`

type deployer struct {
	Task  string `json:"task"`
	Stage string `json:"stage"`
}

func main() {
	d := new(deployer)
	w := new(plugin.Workspace)

	plugin.Param("vargs", d)
	plugin.Param("workspace", w)
	plugin.MustParse()

	// Save ssh keys
	if err := os.MkdirAll("/root/.ssh", 0700); err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile("/root/.ssh/config", []byte(SSHConfig), 0644); err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile("/root/.ssh/id_rsa", []byte(w.Keys.Private), 0600); err != nil {
		log.Fatal(err)
	}

	if err := ioutil.WriteFile("/root/.ssh/id_rsa.pub", []byte(w.Keys.Public), 0644); err != nil {
		log.Fatal(err)
	}

	c := exec.Command("/usr/bin/php", "/bin/dep", d.Task, d.Stage)
	c.Dir = w.Path
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	err := c.Run()
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Command completed successfully")
}
<|endoftext|>


<commit_before>package acom

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"
)

func Logger(genLogPath func(t time.Time) string, contentFormat string, v ...interface{}) {
	var buffer bytes.Buffer

	t := time.Now()
	logFH := genLogPath(t)

	dirname := filepath.Dir(logFH)
	if _, err := os.Stat(dirname); err != nil {
		os.MkdirAll(dirname, 0755)
	}

	f, err := os.OpenFile(logFH, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		log.Fatalf("%s", err)
	}

	buffer.WriteString("[")
	buffer.WriteString(t.String())
	buffer.WriteString("] ")
	buffer.WriteString(contentFormat)

	if len(v) > 0 {
		fmt.Fprintf(f, buffer.String(), v...)
	} else {
		fmt.Fprintf(f, buffer.String())
	}
	f.Close()
}
<commit_msg>change output time string to RFC3339Nano.<commit_after>package acom

import (
	"bytes"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"
)

func Logger(genLogPath func(t time.Time) string, contentFormat string, v ...interface{}) {
	var buffer bytes.Buffer

	t := time.Now()
	logFH := genLogPath(t)

	dirname := filepath.Dir(logFH)
	if _, err := os.Stat(dirname); err != nil {
		os.MkdirAll(dirname, 0755)
	}

	f, err := os.OpenFile(logFH, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
	if err != nil {
		log.Fatalf("%s", err)
	}

	buffer.WriteString("[")
	buffer.WriteString(t.Format(time.RFC3339Nano))
	buffer.WriteString("] ")
	buffer.WriteString(contentFormat)

	if len(v) > 0 {
		fmt.Fprintf(f, buffer.String(), v...)
	} else {
		fmt.Fprintf(f, buffer.String())
	}
	f.Close()
}
<|endoftext|>


<commit_before>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"

	"github.com/golang/glog"
	"github.com/google/mtail/mtail"

	_ "net/http/pprof"
)

type seqStringFlag []string

func (f *seqStringFlag) String() string {
	return fmt.Sprint(*f)
}

func (f *seqStringFlag) Set(value string) error {
	for _, v := range strings.Split(value, ",") {
		*f = append(*f, v)
	}
	return nil
}

type seqIntFlag []int

func (f *seqIntFlag) String() string {
	return fmt.Sprint(*f)
}

func (f *seqIntFlag) Set(value string) error {
	for _, v := range strings.Split(value, ",") {
		val, err := strconv.Atoi(v)
		if err != nil {
			return err
		}
		*f = append(*f, val)
	}
	return nil
}

var logs seqStringFlag
var logFds seqIntFlag

var (
	port  = flag.String("port", "3903", "HTTP port to listen on.")
	progs = flag.String("progs", "", "Name of the directory containing mtail programs")

	// Compiler behaviour flags
	oneShot        = flag.Bool("one_shot", false, "Run the contents of the provided logs until EOF and exit.")
	oneShotMetrics = flag.Bool("one_shot_metrics", false, "Dump metrics (to stdout) after one shot mode.")
	compileOnly    = flag.Bool("compile_only", false, "Compile programs only, do not load the virtual machine.")
	dumpAst        = flag.Bool("dump_ast", false, "Dump AST of programs after parse (to INFO log).")
	dumpAstTypes   = flag.Bool("dump_ast_types", false, "Dump AST of programs with type annotation after typecheck (to INFO log).")
	dumpBytecode   = flag.Bool("dump_bytecode", false, "Dump bytecode of programs (to INFO log).")

	// Runtime behaviour flags
	syslogUseCurrentYear = flag.Bool("syslog_use_current_year", true, "Patch yearless timestamps with the present year.")
	emitProgLabel        = flag.Bool("emit_prog_label", true, "Emit the 'prog' label in variable exports.")

	// Debugging flags
	blockProfileRate     = flag.Int("block_profile_rate", 0, "Nanoseconds of block time before goroutine blocking events reported. 0 turns off.  See https://golang.org/pkg/runtime/#SetBlockProfileRate")
	mutexProfileFraction = flag.Int("mutex_profile_fraction", 0, "Fraction of mutex contention events reported.  0 turns off.  See http://golang.org/pkg/runtime/#SetMutexProfileFraction")
)

func init() {
	flag.Var(&logs, "logs", "List of log files to monitor, separated by commas.  This flag may be specified multiple times.")
	flag.Var(&logFds, "logfds", "List of file descriptor numbers to monitor, separated by commas.  This flag may be specified multiple times.")
}

var (
	// Externally supplied by the linker
	Version   string
	Revision  string
	GoVersion = runtime.Version()
)

func buildInfo() string {
	return fmt.Sprintf("mtail version %s git revision %s go version %s", Version, Revision, GoVersion)
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s\n", buildInfo())
		fmt.Fprintf(os.Stderr, "\nUsage:\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	glog.Info(buildInfo())
	if *blockProfileRate > 0 {
		glog.Infof("Setting block profile rate to %d", *blockProfileRate)
		runtime.SetBlockProfileRate(*blockProfileRate)
	}
	if *mutexProfileFraction > 0 {
		glog.Infof("Setting mutex profile fraction to %d", *mutexProfileFraction)
		SetMutexProfileFraction(*mutexProfileFraction)
	}
	if *progs == "" {
		glog.Exitf("No mtail program directory specified; use -progs")
	}
	if !(*dumpBytecode || *dumpAst || *dumpAstTypes || *compileOnly) {
		if len(logs) == 0 && len(logFds) == 0 {
			glog.Exitf("No logs specified to tail; use -logs or -logfds")
		}
	}
	if _, err := strconv.Atoi(*port); err == nil {
		// If supplied port is a bare int try prepending ":" for implicit global bind
		*port = ":" + *port
	}
	o := mtail.Options{
		Progs:                *progs,
		LogPathPatterns:      logs,
		LogFds:               logFds,
		Port:                 *port,
		OneShot:              *oneShot,
		OneShotMetrics:       *oneShotMetrics,
		CompileOnly:          *compileOnly,
		DumpAst:              *dumpAst,
		DumpAstTypes:         *dumpAstTypes,
		DumpBytecode:         *dumpBytecode,
		SyslogUseCurrentYear: *syslogUseCurrentYear,
		OmitProgLabel:        !*emitProgLabel,
		BuildInfo:            buildInfo(),
	}
	m, err := mtail.New(o)
	if err != nil {
		glog.Fatalf("couldn't start: %s", err)
	}
	m.Run()
}
<commit_msg>Updated to reflect comments on #83<commit_after>// Copyright 2011 Google Inc. All Rights Reserved.
// This file is available under the Apache license.

package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"strconv"
	"strings"

	"github.com/golang/glog"
	"github.com/google/mtail/mtail"

	_ "net/http/pprof"
)

type seqStringFlag []string

func (f *seqStringFlag) String() string {
	return fmt.Sprint(*f)
}

func (f *seqStringFlag) Set(value string) error {
	for _, v := range strings.Split(value, ",") {
		*f = append(*f, v)
	}
	return nil
}

type seqIntFlag []int

func (f *seqIntFlag) String() string {
	return fmt.Sprint(*f)
}

func (f *seqIntFlag) Set(value string) error {
	for _, v := range strings.Split(value, ",") {
		val, err := strconv.Atoi(v)
		if err != nil {
			return err
		}
		*f = append(*f, val)
	}
	return nil
}

var logs seqStringFlag
var logFds seqIntFlag

var (
	port    = flag.Int("port", 3903, "HTTP port to listen on.")
	address = flag.String("address", "", "IP address on which to bind HTTP listener")
	progs   = flag.String("progs", "", "Name of the directory containing mtail programs")

	// Compiler behaviour flags
	oneShot        = flag.Bool("one_shot", false, "Run the contents of the provided logs until EOF and exit.")
	oneShotMetrics = flag.Bool("one_shot_metrics", false, "Dump metrics (to stdout) after one shot mode.")
	compileOnly    = flag.Bool("compile_only", false, "Compile programs only, do not load the virtual machine.")
	dumpAst        = flag.Bool("dump_ast", false, "Dump AST of programs after parse (to INFO log).")
	dumpAstTypes   = flag.Bool("dump_ast_types", false, "Dump AST of programs with type annotation after typecheck (to INFO log).")
	dumpBytecode   = flag.Bool("dump_bytecode", false, "Dump bytecode of programs (to INFO log).")

	// Runtime behaviour flags
	syslogUseCurrentYear = flag.Bool("syslog_use_current_year", true, "Patch yearless timestamps with the present year.")
	emitProgLabel        = flag.Bool("emit_prog_label", true, "Emit the 'prog' label in variable exports.")

	// Debugging flags
	blockProfileRate     = flag.Int("block_profile_rate", 0, "Nanoseconds of block time before goroutine blocking events reported. 0 turns off.  See https://golang.org/pkg/runtime/#SetBlockProfileRate")
	mutexProfileFraction = flag.Int("mutex_profile_fraction", 0, "Fraction of mutex contention events reported.  0 turns off.  See http://golang.org/pkg/runtime/#SetMutexProfileFraction")
)

func init() {
	flag.Var(&logs, "logs", "List of log files to monitor, separated by commas.  This flag may be specified multiple times.")
	flag.Var(&logFds, "logfds", "List of file descriptor numbers to monitor, separated by commas.  This flag may be specified multiple times.")
}

var (
	// Externally supplied by the linker
	Version   string
	Revision  string
	GoVersion = runtime.Version()
)

func buildInfo() string {
	return fmt.Sprintf("mtail version %s git revision %s go version %s", Version, Revision, GoVersion)
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s\n", buildInfo())
		fmt.Fprintf(os.Stderr, "\nUsage:\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	glog.Info(buildInfo())
	if *blockProfileRate > 0 {
		glog.Infof("Setting block profile rate to %d", *blockProfileRate)
		runtime.SetBlockProfileRate(*blockProfileRate)
	}
	if *mutexProfileFraction > 0 {
		glog.Infof("Setting mutex profile fraction to %d", *mutexProfileFraction)
		SetMutexProfileFraction(*mutexProfileFraction)
	}
	if *progs == "" {
		glog.Exitf("No mtail program directory specified; use -progs")
	}
	if !(*dumpBytecode || *dumpAst || *dumpAstTypes || *compileOnly) {
		if len(logs) == 0 && len(logFds) == 0 {
			glog.Exitf("No logs specified to tail; use -logs or -logfds")
		}
	}
	hostport := fmt.Sprintf("%s:%d", *address, *port)
	o := mtail.Options{
		Progs:                *progs,
		LogPathPatterns:      logs,
		LogFds:               logFds,
		Port:                 hostport,
		OneShot:              *oneShot,
		OneShotMetrics:       *oneShotMetrics,
		CompileOnly:          *compileOnly,
		DumpAst:              *dumpAst,
		DumpAstTypes:         *dumpAstTypes,
		DumpBytecode:         *dumpBytecode,
		SyslogUseCurrentYear: *syslogUseCurrentYear,
		OmitProgLabel:        !*emitProgLabel,
		BuildInfo:            buildInfo(),
	}
	m, err := mtail.New(o)
	if err != nil {
		glog.Fatalf("couldn't start: %s", err)
	}
	m.Run()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"io"
	"log"
	"os"
)

var Version = "master"

var (
	input  io.Reader
	logger *log.Logger
)

var args struct {
	inputFile     string
	skipTLSVerify bool
}

func init() {
	flag.StringVar(&args.inputFile, "f", "-", "input file, defaults to stdin")
	flag.BoolVar(&args.skipTLSVerify, "S", false, "skips verification of the chain of certificate")
	flag.Parse()

	if args.inputFile == "-" {
		input = os.Stdin
	}
}

func main() {
	report, err := makeReport(input)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	if err = newReporter(args.skipTLSVerify).send(report); err != nil {
		log.Println(err)
		os.Exit(1)
	}
}
<commit_msg>dont print stack trace in error messages<commit_after>package main

import (
	"flag"
	"io"
	"log"
	"os"

	"github.com/alexkappa/errors"
)

var Version = "master"

var (
	input  io.Reader
	logger *log.Logger
)

var args struct {
	inputFile     string
	skipTLSVerify bool
}

func init() {
	flag.StringVar(&args.inputFile, "f", "-", "input file, defaults to stdin")
	flag.BoolVar(&args.skipTLSVerify, "S", false, "skips verification of the chain of certificate")
	flag.Parse()

	if args.inputFile == "-" {
		input = os.Stdin
	}

	errors.PrintTrace = false
}

func main() {
	report, err := makeReport(input)
	if err != nil {
		log.Println(err)
		os.Exit(1)
	}
	if err = newReporter(args.skipTLSVerify).send(report); err != nil {
		log.Println(err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"

	"github.com/blakesmith/ar"
)

type semaphore chan int

type Conf struct {
	ListenPort   string   `json:"listenPort"`
	RootRepoPath string   `json:"rootRepoPath"`
	SupportArch  []string `json:"supportedArch"`
	EnableSSL    bool     `json:"enableSSL"`
	SSLCert      string   `json:"SSLcert"`
	SSLKey       string   `json:"SSLkey"`
}

type DeleteObj struct {
	Filename string
	Arch     string
}

var sem = make(semaphore, 1)
var configFile = flag.String("c", "conf.json", "config file location")
var config = &Conf{}

func main() {
	flag.Parse()
	file, err := ioutil.ReadFile(*configFile)
	if err != nil {
		log.Panic("unable to read config file, exiting...")
	}
	config = &Conf{}
	if err := json.Unmarshal(file, &config); err != nil {
		log.Panic("unable to marshal config file, exiting...")
	}

	if !createDirs() {
		log.Println("error creating directory structure, exiting")
		os.Exit(1)
	}
	http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(config.RootRepoPath))))
	http.HandleFunc("/upload", uploadHandler)
	http.HandleFunc("/delete", deleteHandler)
	if config.EnableSSL {
		log.Println("running with SSL enabled")
		log.Fatal(http.ListenAndServeTLS(":"+config.ListenPort, config.SSLCert, config.SSLKey, nil))
	} else {
		log.Println("running without SSL enabled")
		log.Fatal(http.ListenAndServe(":"+config.ListenPort, nil))
	}
}

func createDirs() bool {
	for _, archDir := range config.SupportArch {
		if _, err := os.Stat(config.RootRepoPath + "/dists/stable/main/binary-" + archDir); err != nil {
			if os.IsNotExist(err) {
				log.Printf("Directory for %s does not exist, creating", archDir)
				dirErr := os.MkdirAll(config.RootRepoPath+"/dists/stable/main/binary-"+archDir, 0755)
				if dirErr != nil {
					log.Printf("error creating directory for %s: %s\n", archDir, dirErr)
					return false
				}
			} else {
				log.Printf("error inspecting %s: %s\n", archDir, err)
				return false
			}
		}
	}
	return true
}

func inspectPackage(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		log.Printf("error opening package file %s: %s\n", filename, err)
		return ""
	}
	defer f.Close()

	arReader := ar.NewReader(f)
	var controlBuf bytes.Buffer

	for {
		header, err := arReader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			log.Println("error in inspectPackage loop: ", err)
			return ""
		}

		if header.Name == "control.tar.gz" {
			io.Copy(&controlBuf, arReader)
			return inspectPackageControl(controlBuf)

		}

	}
	return ""
}

func inspectPackageControl(filename bytes.Buffer) string {
	gzf, err := gzip.NewReader(bytes.NewReader(filename.Bytes()))
	if err != nil {
		log.Println("error creating gzip reader: ", err)
		return ""
	}

	tarReader := tar.NewReader(gzf)
	var controlBuf bytes.Buffer
	for {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			log.Println("error in inspectPackage loop: ", err)
			return ""
		}

		name := header.Name

		switch header.Typeflag {
		case tar.TypeDir:
			continue
		case tar.TypeReg:
			if name == "./control" {
				io.Copy(&controlBuf, tarReader)
				log.Printf("control file: %s\n", controlBuf.String())
				return controlBuf.String()
			}
		default:
			log.Printf("%s : %c %s %s\n",
				"Yikes! Unable to figure out type",
				header.Typeflag,
				"in file",
				name,
			)
		}
	}
	return ""
}

func createPackagesGz(arch string) bool {
	var packBuf bytes.Buffer
	// loop through each directory
	// run inspectPackage
	dirList, err := ioutil.ReadDir(config.RootRepoPath + "/dists/stable/main/binary-" + arch)
	if err != nil {
		log.Printf("error scanning %s: %s\n", config.RootRepoPath+"/dists/stable/main/binary-"+arch, err)
		return false
	}
	for _, debFile := range dirList {
		if strings.HasSuffix(debFile.Name(), "deb") {
			tempCtlData := inspectPackage(config.RootRepoPath + "/dists/stable/main/binary-" + arch + "/" + debFile.Name())
			packBuf.WriteString(tempCtlData)
			packBuf.WriteString("Filename: " + "dists/stable/main/binary-" + arch + "/" + debFile.Name() + "\n")
			packBuf.WriteString("Size: " + strconv.FormatInt(debFile.Size(), 10) + "\n")
			f, _ := ioutil.ReadFile(config.RootRepoPath + "/dists/stable/main/binary-" + arch + "/" + debFile.Name())
			md5hash := md5.New()
			io.WriteString(md5hash, string(f[:]))
			md5sum := hex.EncodeToString(md5hash.Sum(nil))
			packBuf.WriteString("MD5sum: " + md5sum + "\n")
			sha1hash := sha1.New()
			io.WriteString(sha1hash, string(f[:]))
			sha1sum := hex.EncodeToString(sha1hash.Sum(nil))
			packBuf.WriteString("SHA1: " + sha1sum + "\n")
			sha256hash := sha256.New()
			io.WriteString(sha256hash, string(f[:]))
			sha256sum := hex.EncodeToString(sha256hash.Sum(nil))
			packBuf.WriteString("SHA256: " + sha256sum + "\n")
			packBuf.WriteString("\n\n")
		}
	}

	outfile, err := os.Create(config.RootRepoPath + "/dists/stable/main/binary-" + arch + "/Packages.gz")
	if err != nil {
		log.Println("error creating packages.gz file")
		return false
	}
	defer outfile.Close()
	gzOut := gzip.NewWriter(outfile)
	defer gzOut.Close()
	gzOut.Write(packBuf.Bytes())
	gzOut.Flush()
	return true
}

func uploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "POST" {
		archType := r.FormValue("arch")
		if archType == "" {
			archType = "all"
		}
		log.Println("archType is: ", archType)
		file, header, err := r.FormFile("file")
		if err != nil {
			log.Println("error parsing file: ", err)
		}
		log.Println("filename is: ", header.Filename)
		out, err := os.Create(config.RootRepoPath + "/dists/stable/main/binary-" + archType + "/" + header.Filename)
		if err != nil {
			log.Println("error creating file: ", err)
		}
		hash := md5.New()
		_, err = io.Copy(out, io.TeeReader(file, hash))
		defer file.Close()
		if err != nil {
			log.Println("error saving file: ", err)
		}
		md5sum := hex.EncodeToString(hash.Sum(nil))
		log.Println("md5sum = ", md5sum)
		log.Println("grabbing lock...")
		sem.Lock()
		log.Println("got lock, updating package list...")
		if !createPackagesGz(archType) {
			log.Println("unable to create Packages.gz")
		}
		sem.Unlock()
		log.Println("lock returned")
	} else {
		log.Println("not a POST")
	}
}

func deleteHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method == "DELETE" {
		decoder := json.NewDecoder(r.Body)
		var toDelete DeleteObj
		err := decoder.Decode(&toDelete)
		if err != nil {
			log.Println("error decoding DELETE json: ", err)
		}
		err = os.Remove(config.RootRepoPath + "/dists/stable/main/binary-" + toDelete.Arch + "/" + toDelete.Filename)
		log.Println("grabbing lock...")
		sem.Lock()
		log.Println("got lock, updating package list...")
		if !createPackagesGz(toDelete.Arch) {
			log.Println("unable to create Packages.gz")
		}
		sem.Unlock()
		log.Println("lock returned")
	} else {
		log.Println("not a DELETE")
	}
}

func (s semaphore) Lock() {
	s <- 1
}

func (s semaphore) Unlock() {
	<-s
}
<commit_msg>add DI in prep for tests<commit_after>package main

import (
	"archive/tar"
	"bytes"
	"compress/gzip"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"flag"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"

	"github.com/blakesmith/ar"
)

type semaphore chan int

type Conf struct {
	ListenPort   string   `json:"listenPort"`
	RootRepoPath string   `json:"rootRepoPath"`
	SupportArch  []string `json:"supportedArch"`
	EnableSSL    bool     `json:"enableSSL"`
	SSLCert      string   `json:"SSLcert"`
	SSLKey       string   `json:"SSLkey"`
}

type DeleteObj struct {
	Filename string
	Arch     string
}

var sem = make(semaphore, 1)
var configFile = flag.String("c", "conf.json", "config file location")
var parsedConfig = &Conf{}

func main() {
	flag.Parse()
	file, err := ioutil.ReadFile(*configFile)
	if err != nil {
		log.Panic("unable to read config file, exiting...")
	}
	//config = &Conf{}
	if err := json.Unmarshal(file, &parsedConfig); err != nil {
		log.Panic("unable to marshal config file, exiting...")
	}

	if !createDirs(*parsedConfig) {
		log.Println("error creating directory structure, exiting")
		os.Exit(1)
	}
	http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(parsedConfig.RootRepoPath))))
	http.Handle("/upload", uploadHandler(*parsedConfig))
	http.Handle("/delete", deleteHandler(*parsedConfig))
	if parsedConfig.EnableSSL {
		log.Println("running with SSL enabled")
		log.Fatal(http.ListenAndServeTLS(":"+parsedConfig.ListenPort, parsedConfig.SSLCert, parsedConfig.SSLKey, nil))
	} else {
		log.Println("running without SSL enabled")
		log.Fatal(http.ListenAndServe(":"+parsedConfig.ListenPort, nil))
	}
}

func createDirs(config Conf) bool {
	for _, archDir := range config.SupportArch {
		if _, err := os.Stat(config.RootRepoPath + "/dists/stable/main/binary-" + archDir); err != nil {
			if os.IsNotExist(err) {
				log.Printf("Directory for %s does not exist, creating", archDir)
				dirErr := os.MkdirAll(config.RootRepoPath+"/dists/stable/main/binary-"+archDir, 0755)
				if dirErr != nil {
					log.Printf("error creating directory for %s: %s\n", archDir, dirErr)
					return false
				}
			} else {
				log.Printf("error inspecting %s: %s\n", archDir, err)
				return false
			}
		}
	}
	return true
}

func inspectPackage(filename string) string {
	f, err := os.Open(filename)
	if err != nil {
		log.Printf("error opening package file %s: %s\n", filename, err)
		return ""
	}
	defer f.Close()

	arReader := ar.NewReader(f)
	var controlBuf bytes.Buffer

	for {
		header, err := arReader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			log.Println("error in inspectPackage loop: ", err)
			return ""
		}

		if header.Name == "control.tar.gz" {
			io.Copy(&controlBuf, arReader)
			return inspectPackageControl(controlBuf)

		}

	}
	return ""
}

func inspectPackageControl(filename bytes.Buffer) string {
	gzf, err := gzip.NewReader(bytes.NewReader(filename.Bytes()))
	if err != nil {
		log.Println("error creating gzip reader: ", err)
		return ""
	}

	tarReader := tar.NewReader(gzf)
	var controlBuf bytes.Buffer
	for {
		header, err := tarReader.Next()

		if err == io.EOF {
			break
		}

		if err != nil {
			log.Println("error in inspectPackage loop: ", err)
			return ""
		}

		name := header.Name

		switch header.Typeflag {
		case tar.TypeDir:
			continue
		case tar.TypeReg:
			if name == "./control" {
				io.Copy(&controlBuf, tarReader)
				log.Printf("control file: %s\n", controlBuf.String())
				return controlBuf.String()
			}
		default:
			log.Printf("%s : %c %s %s\n",
				"Yikes! Unable to figure out type",
				header.Typeflag,
				"in file",
				name,
			)
		}
	}
	return ""
}

func createPackagesGz(config *Conf, arch string) bool {
	var packBuf bytes.Buffer
	// loop through each directory
	// run inspectPackage
	dirList, err := ioutil.ReadDir(config.RootRepoPath + "/dists/stable/main/binary-" + arch)
	if err != nil {
		log.Printf("error scanning %s: %s\n", config.RootRepoPath+"/dists/stable/main/binary-"+arch, err)
		return false
	}
	for _, debFile := range dirList {
		if strings.HasSuffix(debFile.Name(), "deb") {
			tempCtlData := inspectPackage(config.RootRepoPath + "/dists/stable/main/binary-" + arch + "/" + debFile.Name())
			packBuf.WriteString(tempCtlData)
			packBuf.WriteString("Filename: " + "dists/stable/main/binary-" + arch + "/" + debFile.Name() + "\n")
			packBuf.WriteString("Size: " + strconv.FormatInt(debFile.Size(), 10) + "\n")
			f, _ := ioutil.ReadFile(config.RootRepoPath + "/dists/stable/main/binary-" + arch + "/" + debFile.Name())
			md5hash := md5.New()
			io.WriteString(md5hash, string(f[:]))
			md5sum := hex.EncodeToString(md5hash.Sum(nil))
			packBuf.WriteString("MD5sum: " + md5sum + "\n")
			sha1hash := sha1.New()
			io.WriteString(sha1hash, string(f[:]))
			sha1sum := hex.EncodeToString(sha1hash.Sum(nil))
			packBuf.WriteString("SHA1: " + sha1sum + "\n")
			sha256hash := sha256.New()
			io.WriteString(sha256hash, string(f[:]))
			sha256sum := hex.EncodeToString(sha256hash.Sum(nil))
			packBuf.WriteString("SHA256: " + sha256sum + "\n")
			packBuf.WriteString("\n\n")
		}
	}

	outfile, err := os.Create(config.RootRepoPath + "/dists/stable/main/binary-" + arch + "/Packages.gz")
	if err != nil {
		log.Println("error creating packages.gz file")
		return false
	}
	defer outfile.Close()
	gzOut := gzip.NewWriter(outfile)
	defer gzOut.Close()
	gzOut.Write(packBuf.Bytes())
	gzOut.Flush()
	return true
}

func uploadHandler(config Conf) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "POST" {
			archType := r.FormValue("arch")
			if archType == "" {
				archType = "all"
			}
			log.Println("archType is: ", archType)
			file, header, err := r.FormFile("file")
			if err != nil {
				log.Println("error parsing file: ", err)
			}
			log.Println("filename is: ", header.Filename)
			out, err := os.Create(config.RootRepoPath + "/dists/stable/main/binary-" + archType + "/" + header.Filename)
			if err != nil {
				log.Println("error creating file: ", err)
			}
			hash := md5.New()
			_, err = io.Copy(out, io.TeeReader(file, hash))
			defer file.Close()
			if err != nil {
				log.Println("error saving file: ", err)
			}
			md5sum := hex.EncodeToString(hash.Sum(nil))
			log.Println("md5sum = ", md5sum)
			log.Println("grabbing lock...")
			sem.Lock()
			log.Println("got lock, updating package list...")
			if !createPackagesGz(&config, archType) {
				log.Println("unable to create Packages.gz")
			}
			sem.Unlock()
			log.Println("lock returned")
		} else {
			log.Println("not a POST")
		}
	})
}

func deleteHandler(config Conf) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "DELETE" {
			decoder := json.NewDecoder(r.Body)
			var toDelete DeleteObj
			err := decoder.Decode(&toDelete)
			if err != nil {
				log.Println("error decoding DELETE json: ", err)
			}
			err = os.Remove(config.RootRepoPath + "/dists/stable/main/binary-" + toDelete.Arch + "/" + toDelete.Filename)
			log.Println("grabbing lock...")
			sem.Lock()
			log.Println("got lock, updating package list...")
			if !createPackagesGz(&config, toDelete.Arch) {
				log.Println("unable to create Packages.gz")
			}
			sem.Unlock()
			log.Println("lock returned")
		} else {
			log.Println("not a DELETE")
		}
	})
}

func (s semaphore) Lock() {
	s <- 1
}

func (s semaphore) Unlock() {
	<-s
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"flag"
	"fmt"
	"github.com/franela/goreq"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

var dir *string
var host *string
var port *string
var iport int
var burpBuddyURL *string
var localURL string

var count int

func init() {
	host = flag.String("host", "localhost", "host for the file server to listen on")
	port = flag.String("port", "9999", "port for the file server to listen on")
	dir = flag.String("dir", "", "directory with code to scan")
	burpBuddyURL = flag.String("burpbuddy", "http://localhost:8001", "HTTP API URL for burpbuddy")
	flag.Parse()

	if *dir == "" {
		log.Fatal("dir is required")
	}

	d, err := filepath.Abs(*dir)
	if err != nil {
		log.Fatalf("Error getting absolute path of dir: %s", err.Error())
	}
	dir = &d

	iport, err = strconv.Atoi(*port)
	if err != nil {
		log.Fatalf("Error converting port to int: %s", err.Error())
	}
	count = 0
	localURL = fmt.Sprintf("http://%s:%s", *host, *port)
}

func main() {

	go func() {
		log.Fatal(http.ListenAndServe(*host+":"+*port, http.FileServer(http.Dir(*dir))))
	}()

	log.Printf("Static file server listening on %s, serving %s", localURL, *dir)
	log.Printf("Adding %s to scope", localURL)

	s := ScopeRequest{URL: localURL + "/"}
	resp, err := goreq.Request{
		Method: "POST",
		Uri:    *burpBuddyURL + "/scope",
		Body:   s,
	}.Do()

	if err != nil {
		log.Fatalf("Error adding site to scope: %s", err.Error())
	}
	if resp.StatusCode != 201 {
		log.Fatal("Non 201 status code when adding to scope")
	}
	resp.Body.Close()

	log.Println("Walking directory, each file sent to burp's passive scan")

	if err := filepath.Walk(*dir, walker); err != nil {
		log.Printf("Error during directory walk: %s", err.Error())
	}

	log.Printf("%d file sent to burp", count)

	sresp, err := goreq.Request{
		Method: "DELETE",
		Uri:    *burpBuddyURL + "/scope/" + base64.StdEncoding.EncodeToString([]byte(localURL)),
	}.Do()

	if err != nil || sresp.StatusCode != 204 {
		log.Printf("Error removing %s from scope", localURL)
	} else {
		log.Printf("%s removed from scope", localURL)
	}

}

func walker(path string, info os.FileInfo, err error) error {
	parts := strings.Split(path, *dir)
	if parts[1] == "" {
		return nil
	}

	resp, err := http.Get(localURL + parts[1])

	if err != nil {
		log.Printf("Error getting %s from go http server: %s", parts[1], err.Error())
		return nil
	}
	if resp.StatusCode != 200 {
		log.Printf("Non 200 status code from go for %s", parts[1])
		return nil
	}

	rawResponse, err := httputil.DumpResponse(resp, true)
	if err != nil {
		log.Printf("Error dumping response: %s", err.Error())
		return nil
	}
	rawRequest, err := httputil.DumpRequest(resp.Request, true)
	if err != nil {
		log.Printf("Error dumping request: %s", err.Error())
		return nil
	}

	r := PassivScanRequest{
		Host:     *host,
		Port:     iport,
		UseHTTPS: false,
		Request:  base64.StdEncoding.EncodeToString(rawRequest),
		Response: base64.StdEncoding.EncodeToString(rawResponse),
	}

	presp, err := goreq.Request{
		Method: "POST",
		Uri:    *burpBuddyURL + "/scan/passive",
		Body:   r,
	}.Do()

	if err != nil {
		log.Printf("Error during passive scan request to burpbuddy: %s", err.Error())
		return nil
	}

	if presp.StatusCode != 201 {
		log.Println("Non 201 status code during passive scan request to burpbuddy")
		return nil
	}

	defer resp.Body.Close()
	defer presp.Body.Close()
	count += 1

	return nil
}
<commit_msg>Fix typos<commit_after>package main

import (
	"encoding/base64"
	"flag"
	"fmt"
	"github.com/franela/goreq"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
)

var dir *string
var host *string
var port *string
var iport int
var burpBuddyURL *string
var localURL string

var count int

func init() {
	host = flag.String("host", "localhost", "host for the file server to listen on")
	port = flag.String("port", "9999", "port for the file server to listen on")
	dir = flag.String("dir", "", "directory with code to scan")
	burpBuddyURL = flag.String("burpbuddy", "http://localhost:8001", "HTTP API URL for burpbuddy")
	flag.Parse()

	if *dir == "" {
		log.Fatal("dir is required")
	}

	d, err := filepath.Abs(*dir)
	if err != nil {
		log.Fatalf("Error getting absolute path of dir: %s", err.Error())
	}
	dir = &d

	iport, err = strconv.Atoi(*port)
	if err != nil {
		log.Fatalf("Error converting port to int: %s", err.Error())
	}
	count = 0
	localURL = fmt.Sprintf("http://%s:%s", *host, *port)
}

func main() {

	go func() {
		log.Fatal(http.ListenAndServe(*host+":"+*port, http.FileServer(http.Dir(*dir))))
	}()

	log.Printf("Static file server listening on %s, serving %s", localURL, *dir)
	log.Printf("Adding %s to scope", localURL)

	s := ScopeRequest{URL: localURL + "/"}
	resp, err := goreq.Request{
		Method: "POST",
		Uri:    *burpBuddyURL + "/scope",
		Body:   s,
	}.Do()

	if err != nil {
		log.Fatalf("Error adding site to scope: %s", err.Error())
	}
	if resp.StatusCode != 201 {
		log.Fatal("Non 201 status code when adding to scope")
	}
	resp.Body.Close()

	log.Println("Walking directory, each file will be sent to burp's passive scan")

	if err := filepath.Walk(*dir, walker); err != nil {
		log.Printf("Error during directory walk: %s", err.Error())
	}

	log.Printf("%d files sent to burp", count)

	sresp, err := goreq.Request{
		Method: "DELETE",
		Uri:    *burpBuddyURL + "/scope/" + base64.StdEncoding.EncodeToString([]byte(localURL)),
	}.Do()

	if err != nil || sresp.StatusCode != 204 {
		log.Printf("Error removing %s from scope", localURL)
	} else {
		log.Printf("%s removed from scope", localURL)
	}

}

func walker(path string, info os.FileInfo, err error) error {
	parts := strings.Split(path, *dir)
	if parts[1] == "" {
		return nil
	}

	resp, err := http.Get(localURL + parts[1])

	if err != nil {
		log.Printf("Error getting %s from go http server: %s", parts[1], err.Error())
		return nil
	}
	if resp.StatusCode != 200 {
		log.Printf("Non 200 status code from go for %s", parts[1])
		return nil
	}

	rawResponse, err := httputil.DumpResponse(resp, true)
	if err != nil {
		log.Printf("Error dumping response: %s", err.Error())
		return nil
	}
	rawRequest, err := httputil.DumpRequest(resp.Request, true)
	if err != nil {
		log.Printf("Error dumping request: %s", err.Error())
		return nil
	}

	r := PassivScanRequest{
		Host:     *host,
		Port:     iport,
		UseHTTPS: false,
		Request:  base64.StdEncoding.EncodeToString(rawRequest),
		Response: base64.StdEncoding.EncodeToString(rawResponse),
	}

	presp, err := goreq.Request{
		Method: "POST",
		Uri:    *burpBuddyURL + "/scan/passive",
		Body:   r,
	}.Do()

	if err != nil {
		log.Printf("Error during passive scan request to burpbuddy: %s", err.Error())
		return nil
	}

	if presp.StatusCode != 201 {
		log.Println("Non 201 status code during passive scan request to burpbuddy")
		return nil
	}

	defer resp.Body.Close()
	defer presp.Body.Close()
	count += 1

	return nil
}
<|endoftext|>


<commit_before>//go:generate fileb0x ./b0x.json
package main

import (
	"os"

	"io/ioutil"

	"github.com/FederationOfFathers/dashboard/api"
	"github.com/FederationOfFathers/dashboard/bot"
	"github.com/FederationOfFathers/dashboard/bridge"
	"github.com/FederationOfFathers/dashboard/config"
	"github.com/FederationOfFathers/dashboard/db"
	"github.com/FederationOfFathers/dashboard/environment"
	"github.com/FederationOfFathers/dashboard/events"
	"github.com/FederationOfFathers/dashboard/messaging"
	"github.com/FederationOfFathers/dashboard/metrics"
	"github.com/FederationOfFathers/dashboard/store"
	"github.com/FederationOfFathers/dashboard/streams"
	"github.com/apokalyptik/cfg"
	"github.com/bearcherian/rollzap"
	rollbar "github.com/rollbar/rollbar-go"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/yaml.v2"
)

var twitchClientID = ""
var slackAPIKey = "xox...."
var slackMessagingKey = ""
var discordCfg = bot.DiscordCfg{}
var rollbarCfg = metrics.RollbarConfig{}
var logger *zap.Logger
var devPort = 0
var DB *db.DB
var mysqlURI string
var streamChannel = "-fof-dashboard"
var mindStreams bool

func init() {

	if environment.IsProd {
		logger, _ = zap.NewProduction()
	} else {
		logger, _ = zap.NewDevelopment()
	}
	logger = logger.Named("main")

	// ROLLBAR
	rollbarCore := rollzap.NewRollbarCore(zapcore.WarnLevel)
	if err := unmarshalConfig("cfg-rollbar.yml", &rollbarCfg); err != nil {
		logger.Error("Unable to unmarshal rollbar config", zap.Error(err))
	} else if rollbarCfg.Token != "" {
		rollbarCfg.Init()
		logger.Info("Rollbar initialized")
		logger = logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
			return zapcore.NewTee(core, rollbarCore)
		}))
	}

	bot.Logger = logger.Named("bot")
	api.Logger = logger.Named("api")
	config.Logger = logger.Named("config")
	events.Logger = logger.Named("events")
	streams.Logger = logger.Named("streams")
	db.Logger = logger.Named("db")
	bridge.Logger = logger.Named("bridge")
	messaging.Logger = logger.Named("messaging")

	scfg := cfg.New("cfg-slack")
	scfg.StringVar(&slackAPIKey, "apiKey", slackAPIKey, "Slack API Key (env: SLACK_APIKEY)")
	scfg.StringVar(&slackMessagingKey, "messagingKey", slackMessagingKey, "Slack Messaging API Key (env: SLACK_MESSAGINGAPIKEY)")
	scfg.BoolVar(&bot.StartupNotice, "startupNotice", bot.StartupNotice, "send a start-up notice to slack")
	scfg.StringVar(&streamChannel, "streamChannel", streamChannel, "where to send streaming notices")
	scfg.BoolVar(&mindStreams, "mindStreams", mindStreams, "should we mind streaming?")

	err := unmarshalConfig("cfg-discord.yml", &discordCfg)
	if err != nil {
		logger.Error("Unable to load discord config", zap.Error(err))
	}

	acfg := cfg.New("cfg-api")
	acfg.StringVar(&api.ListenOn, "listen", api.ListenOn, "API bind address (env: API_LISTEN)")
	acfg.StringVar(&api.AuthSecret, "secret", api.AuthSecret, "Authentication secret for use in generating login tokens")
	acfg.StringVar(&api.JWTSecret, "hmac", api.JWTSecret, "Authentication secret used for JWT tokens")

	ecfg := cfg.New("cfg-events")
	ecfg.StringVar(&events.SaveFile, "savefile", events.SaveFile, "path to the file in which events should be persisted")
	ecfg.DurationVar(&events.SaveInterval, "saveinterval", events.SaveInterval, "how often to check and see if we need to save data")
	ecfg.StringVar(&events.OldEventLinkHMAC, "hmackey", events.OldEventLinkHMAC, "hmac key for generating team tool login links")

	dcfg := cfg.New("cfg-db")
	dcfg.StringVar(&mysqlURI, "mysql", mysqlURI, "MySQL Connection URI")
	dcfg.StringVar(&store.DBPath, "path", store.DBPath, "Path to the database file")

	tcfg := cfg.New("cfg-twitch")
	tcfg.StringVar(&twitchClientID, "clientID", "", "Twitch OAuth key")
}

func main() {
	cfg.Parse()

	store.Mind()

	DB = db.New("mysql", mysqlURI)
	streams.DB = DB
	api.DB = DB
	bot.DB = DB
	events.DB = DB

	bridge.DiscordCoreDataUpdated = bot.DiscordCoreDataUpdated
	bridge.OldEventToolLink = events.OldEventToolLink
	bridge.OldEventToolAuthorization = events.OldEventToolAuthorization

	// start discord bot
	if discordCfg.Token != "" {
		logger.Info("Starting discord")
		discordApi := bot.StartDiscord(discordCfg)
		discordApi.MindGuild()
		defer discordApi.Shutdown()

		messaging.AddMsgAPI(discordApi)
	}

	streams.Init(streamChannel)
	if mindStreams {
		logger.Info("Minding streams", zap.String("channel", streamChannel))
		streams.MustTwitch(twitchClientID)
		streams.Mind()
	} else {
		streams.MindList()
		logger.Info("Not minding streams")
	}

	events.Start() //TODO still needed? old events?
	events.MindEvents()

	rollbar.Info("starting up")
	api.Run()

}

// unmarshal a config YML file into an interface
func unmarshalConfig(fileName string, cfgObject interface{}) error {
	// exit quietly if no file. assume we are not configuring that portion
	if _, err := os.Stat(fileName); err != nil {
		logger.Info("File does not exist", zap.String("file", fileName))
		return nil
	}

	// read file data
	fileData, err := ioutil.ReadFile(fileName)
	if err != nil {
		return err
	}

	// unmarshal into interface object
	err2 := yaml.Unmarshal(fileData, cfgObject)
	if err2 != nil {
		return err2
	}

	return nil
}
<commit_msg>Sending info level logs to rollbar<commit_after>//go:generate fileb0x ./b0x.json
package main

import (
	"os"

	"io/ioutil"

	"github.com/FederationOfFathers/dashboard/api"
	"github.com/FederationOfFathers/dashboard/bot"
	"github.com/FederationOfFathers/dashboard/bridge"
	"github.com/FederationOfFathers/dashboard/config"
	"github.com/FederationOfFathers/dashboard/db"
	"github.com/FederationOfFathers/dashboard/environment"
	"github.com/FederationOfFathers/dashboard/events"
	"github.com/FederationOfFathers/dashboard/messaging"
	"github.com/FederationOfFathers/dashboard/metrics"
	"github.com/FederationOfFathers/dashboard/store"
	"github.com/FederationOfFathers/dashboard/streams"
	"github.com/apokalyptik/cfg"
	"github.com/bearcherian/rollzap"
	rollbar "github.com/rollbar/rollbar-go"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/yaml.v2"
)

var twitchClientID = ""
var slackAPIKey = "xox...."
var slackMessagingKey = ""
var discordCfg = bot.DiscordCfg{}
var rollbarCfg = metrics.RollbarConfig{}
var logger *zap.Logger
var devPort = 0
var DB *db.DB
var mysqlURI string
var streamChannel = "-fof-dashboard"
var mindStreams bool

func init() {

	if environment.IsProd {
		logger, _ = zap.NewProduction()
	} else {
		logger, _ = zap.NewDevelopment()
	}
	logger = logger.Named("main")

	// ROLLBAR
	rollbarCore := rollzap.NewRollbarCore(zapcore.InfoLevel)
	if err := unmarshalConfig("cfg-rollbar.yml", &rollbarCfg); err != nil {
		logger.Error("Unable to unmarshal rollbar config", zap.Error(err))
	} else if rollbarCfg.Token != "" {
		rollbarCfg.Init()
		logger.Info("Rollbar initialized")
		logger = logger.WithOptions(zap.WrapCore(func(core zapcore.Core) zapcore.Core {
			return zapcore.NewTee(core, rollbarCore)
		}))
	}

	bot.Logger = logger.Named("bot")
	api.Logger = logger.Named("api")
	config.Logger = logger.Named("config")
	events.Logger = logger.Named("events")
	streams.Logger = logger.Named("streams")
	db.Logger = logger.Named("db")
	bridge.Logger = logger.Named("bridge")
	messaging.Logger = logger.Named("messaging")

	scfg := cfg.New("cfg-slack")
	scfg.StringVar(&slackAPIKey, "apiKey", slackAPIKey, "Slack API Key (env: SLACK_APIKEY)")
	scfg.StringVar(&slackMessagingKey, "messagingKey", slackMessagingKey, "Slack Messaging API Key (env: SLACK_MESSAGINGAPIKEY)")
	scfg.BoolVar(&bot.StartupNotice, "startupNotice", bot.StartupNotice, "send a start-up notice to slack")
	scfg.StringVar(&streamChannel, "streamChannel", streamChannel, "where to send streaming notices")
	scfg.BoolVar(&mindStreams, "mindStreams", mindStreams, "should we mind streaming?")

	err := unmarshalConfig("cfg-discord.yml", &discordCfg)
	if err != nil {
		logger.Error("Unable to load discord config", zap.Error(err))
	}

	acfg := cfg.New("cfg-api")
	acfg.StringVar(&api.ListenOn, "listen", api.ListenOn, "API bind address (env: API_LISTEN)")
	acfg.StringVar(&api.AuthSecret, "secret", api.AuthSecret, "Authentication secret for use in generating login tokens")
	acfg.StringVar(&api.JWTSecret, "hmac", api.JWTSecret, "Authentication secret used for JWT tokens")

	ecfg := cfg.New("cfg-events")
	ecfg.StringVar(&events.SaveFile, "savefile", events.SaveFile, "path to the file in which events should be persisted")
	ecfg.DurationVar(&events.SaveInterval, "saveinterval", events.SaveInterval, "how often to check and see if we need to save data")
	ecfg.StringVar(&events.OldEventLinkHMAC, "hmackey", events.OldEventLinkHMAC, "hmac key for generating team tool login links")

	dcfg := cfg.New("cfg-db")
	dcfg.StringVar(&mysqlURI, "mysql", mysqlURI, "MySQL Connection URI")
	dcfg.StringVar(&store.DBPath, "path", store.DBPath, "Path to the database file")

	tcfg := cfg.New("cfg-twitch")
	tcfg.StringVar(&twitchClientID, "clientID", "", "Twitch OAuth key")
}

func main() {
	cfg.Parse()

	store.Mind()

	DB = db.New("mysql", mysqlURI)
	streams.DB = DB
	api.DB = DB
	bot.DB = DB
	events.DB = DB

	bridge.DiscordCoreDataUpdated = bot.DiscordCoreDataUpdated
	bridge.OldEventToolLink = events.OldEventToolLink
	bridge.OldEventToolAuthorization = events.OldEventToolAuthorization

	// start discord bot
	if discordCfg.Token != "" {
		logger.Info("Starting discord")
		discordApi := bot.StartDiscord(discordCfg)
		discordApi.MindGuild()
		defer discordApi.Shutdown()

		messaging.AddMsgAPI(discordApi)
	}

	streams.Init(streamChannel)
	if mindStreams {
		logger.Info("Minding streams", zap.String("channel", streamChannel))
		streams.MustTwitch(twitchClientID)
		streams.Mind()
	} else {
		streams.MindList()
		logger.Info("Not minding streams")
	}

	events.Start() //TODO still needed? old events?
	events.MindEvents()

	rollbar.Info("starting up")
	api.Run()

}

// unmarshal a config YML file into an interface
func unmarshalConfig(fileName string, cfgObject interface{}) error {
	// exit quietly if no file. assume we are not configuring that portion
	if _, err := os.Stat(fileName); err != nil {
		logger.Info("File does not exist", zap.String("file", fileName))
		return nil
	}

	// read file data
	fileData, err := ioutil.ReadFile(fileName)
	if err != nil {
		return err
	}

	// unmarshal into interface object
	err2 := yaml.Unmarshal(fileData, cfgObject)
	if err2 != nil {
		return err2
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "time"
  "os"
  "bufio"
  "log"
  "regexp"
  "errors"
  "math/rand"
)

type Posicao struct {
  linha  int
  coluna int
}

type PacGo struct {
  posicao Posicao
  figura  string // emoji
  pilula  bool
  pontos int
}

type Fantasma struct {
  posicao Posicao
  figura  string // emoji
}

type Labirinto struct {
  largura int
  altura  int
  mapa    []string
  figura string
}

type Movimento int

const (
        Cima = iota
        Baixo
        Esquerda
        Direita
        Nenhum
        Sai
)

var labirinto *Labirinto
var pacgo     *PacGo
var lista_de_fantasmas []*Fantasma
var mapaSinais map[int]string

func construirLabirinto(nomeArquivo string) (*Labirinto, *PacGo, []*Fantasma, error) {

  var ErrMapNotFound = errors.New("Não conseguiu ler o arquivo do mapa")

  var arquivo string
  if nomeArquivo == "" {
    arquivo = "./data/mapa.txt"
  } else {
    arquivo = nomeArquivo
  }

  if file, err := os.Open(arquivo); err == nil {

    // fecha depois de ler o arquivo
    defer file.Close()

    // inicializa o mapa vazio
    var pacgo *PacGo
    fantasmas := []*Fantasma{}
    mapa := []string{}

    r, _ := regexp.Compile("[^ #.]")

    // cria um leitor para ler linha a linha o arquivo
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
      linha := scanner.Text()

      for indice , caracter := range linha {
        switch caracter {
          case 'F': {
            fantasma := &Fantasma{ posicao: Posicao{len(mapa), indice}, figura: "\xF0\x9F\x91\xBB"}
            fantasmas = append(fantasmas, fantasma)
          }
          case 'G': pacgo = &PacGo{ posicao: Posicao{len(mapa), indice}, figura: "\xF0\x9F\x98\x83", pontos : 0 }
        }
      }

      linha = r.ReplaceAllString(linha, " ")
      mapa = append(mapa, linha)
    }

    // verifica se teve erro o leitor
    if err = scanner.Err(); err != nil {
      log.Fatal(err)
      return nil, nil, nil, ErrMapNotFound
    }

    l := &Labirinto{largura: len(mapa[0]), altura: len(mapa), mapa : mapa, figura: "\x1b[44m \x1b[0m"}
    return l, pacgo, fantasmas, nil

  } else {
    log.Fatal(err)
    return nil, nil, nil, ErrMapNotFound
  }
}

func atualizarLabirinto() {
  limpaTela()

    // Imprime os pontos
  moveCursor(Posicao{0,0})
  fmt.Printf("Pontos: ", pacgo.pontos)

  posicaoInicial := Posicao{2,0}
  moveCursor(posicaoInicial)
  for _, linha := range labirinto.mapa {
    for _, char := range linha {
      if char == '#' {
        fmt.Print(labirinto.figura)
      } else if char == '.'{
        fmt.Print(".")
      } else {
        fmt.Print(" ")
      }
      //fmt.Println(linha)
    }
    fmt.Println("")
  }

  // Imprime PacGo
  moveCursor(posicaoInicial.adiciona(&pacgo.posicao))
  fmt.Printf("%s", pacgo.figura)

  // Imprime fantasmas
  for _, fantasma := range lista_de_fantasmas {
    moveCursor(posicaoInicial.adiciona(&fantasma.posicao))
    fmt.Printf("%s", fantasma.figura)
  }

  // Move o cursor para fora do labirinto
  moveCursor(posicaoInicial.adiciona(&Posicao{labirinto.altura + 2, 1}))
}

func detectarColisao() bool {
  for _, fantasma := range lista_de_fantasmas {
    if fantasma.posicao == pacgo.posicao {
      return true
    }
  }
  return false
}

func moverPacGo(m Movimento) {

  var valorDaPosicaoAtualDaPacgo = labirinto.mapa[pacgo.posicao.linha][pacgo.posicao.coluna]
  var linhaAtualDaPacgo = pacgo.posicao.linha
  var colunaAtualDaPacgo = pacgo.posicao.coluna

  switch m {
    case Cima:
      if linhaAtualDaPacgo == 0 {
        if valorDaPosicaoAtualDaPacgo == ' ' {
          pacgo.posicao.linha = labirinto.altura - 1
        }
      } else {
        var posicaoAcimaDaPacgo = labirinto.mapa[pacgo.posicao.linha - 1][pacgo.posicao.coluna]
        if posicaoAcimaDaPacgo != '#' {
          pacgo.posicao.linha = pacgo.posicao.linha - 1
        }
      }
    case Baixo:
      if linhaAtualDaPacgo == labirinto.altura - 1{
        if valorDaPosicaoAtualDaPacgo == ' '{
          pacgo.posicao.linha = 0
        }
      } else {
        var posicaoAbaixoDaPacgo = labirinto.mapa[pacgo.posicao.linha + 1][pacgo.posicao.coluna]
        if posicaoAbaixoDaPacgo != '#'{
          pacgo.posicao.linha = pacgo.posicao.linha + 1
        }
      }
    case Direita:
      if colunaAtualDaPacgo == labirinto.largura-1{
        if valorDaPosicaoAtualDaPacgo == ' '{
          pacgo.posicao.coluna = 0
        }
      } else {
        var posicaoDireitaDaPacgo = labirinto.mapa[pacgo.posicao.linha][pacgo.posicao.coluna + 1]
        if posicaoDireitaDaPacgo != '#'{
          pacgo.posicao.coluna = pacgo.posicao.coluna + 1
        }
      }
    case Esquerda:
      if colunaAtualDaPacgo == 0 {
        if valorDaPosicaoAtualDaPacgo == ' ' {
          pacgo.posicao.coluna = labirinto.largura - 1
        }
      } else {
        var posicaoEsquerdaDaPacgo = labirinto.mapa[pacgo.posicao.linha][pacgo.posicao.coluna - 1]
        if posicaoEsquerdaDaPacgo != '#'{
          pacgo.posicao.coluna = pacgo.posicao.coluna - 1
        }
      }
  }
}

func random(min, max int) int {
    return rand.Intn(max - min) + min
}

func move(fantasma *Fantasma, valorDaPosicaoAtualDoFantasma byte, linhaAtualDoFantasma int, colunaAtualDoFantasma int){

  var direcao = random(0, 4)
  var sinal = mapaSinais[direcao]
  //fmt.Println(sinal)
  switch sinal {
  case "Cima":
              if linhaAtualDoFantasma == 0{
                if valorDaPosicaoAtualDoFantasma == ' '{
                   fantasma.posicao.linha = labirinto.altura - 1
                 }
             }else{
               var posicaoAcimaDoFantasma = labirinto.mapa[fantasma.posicao.linha - 1][fantasma.posicao.coluna]
               if posicaoAcimaDoFantasma != '#'{
                 fantasma.posicao.linha = fantasma.posicao.linha - 1
               }
             }
  case "Baixo":
              if linhaAtualDoFantasma == labirinto.altura - 1{
                 if valorDaPosicaoAtualDoFantasma == ' '{
                   fantasma.posicao.linha = 0
                 }
              }else{
                var posicaoAbaixoDoFantasma = labirinto.mapa[fantasma.posicao.linha + 1][fantasma.posicao.coluna]
                if posicaoAbaixoDoFantasma != '#'{
                  fantasma.posicao.linha = fantasma.posicao.linha + 1
                }
              }
  case "Direita":
                if colunaAtualDoFantasma == labirinto.largura-1{
                  if valorDaPosicaoAtualDoFantasma == ' '{
                    fantasma.posicao.coluna = 0
                  }
                }else{
                  var posicaoDireitaDofantasma = labirinto.mapa[fantasma.posicao.linha][fantasma.posicao.coluna + 1]
                  if posicaoDireitaDofantasma != '#'{
                    fantasma.posicao.coluna = fantasma.posicao.coluna + 1
                  }
                }
  case "Esquerda":
                 if colunaAtualDoFantasma == 0{
                   if valorDaPosicaoAtualDoFantasma == ' '{
                     fantasma.posicao.coluna = labirinto.largura - 1
                   }
                 }else{
                   var posicaoEsquerdaDoFantasma = labirinto.mapa[fantasma.posicao.linha][fantasma.posicao.coluna - 1]
                   if posicaoEsquerdaDoFantasma != '#'{
                     fantasma.posicao.coluna = fantasma.posicao.coluna - 1
                   }
                 }
  }
}

func moverFantasmas() {

  for {
    for i := 0; i < len(lista_de_fantasmas); i++{
        var valorDaPosicaoAtualDoFantasma = labirinto.mapa[lista_de_fantasmas[i].posicao.linha][lista_de_fantasmas[i].posicao.coluna]
        var linhaAtualDoFantasma = lista_de_fantasmas[i].posicao.linha
        var colunaAtualDoFantasma = lista_de_fantasmas[i].posicao.coluna
        //fmt.Println(valorDaPosicaoAtualDoFantasma, linhaAtualDoFantasma, colunaAtualDoFantasma)
        move(lista_de_fantasmas[i], valorDaPosicaoAtualDoFantasma, linhaAtualDoFantasma, colunaAtualDoFantasma)
    }
    dorme(200)
  }
}

func dorme(milisegundos time.Duration) {
  time.Sleep(time.Millisecond * milisegundos)
}

func entradaDoUsuario(canal chan<- Movimento) {
  array := make([]byte, 10)

  for {
    lido, _ := os.Stdin.Read(array)

    if lido == 1 && array[0] == 0x1b {
      canal <- Sai;
    } else if lido == 3 {
      if array[0] == 0x1b && array[1] == '[' {
        switch array[2] {
        case 'A': canal <- Cima
        case 'B': canal <- Baixo
        case 'C': canal <- Direita
        case 'D': canal <- Esquerda
        }
      }
    }
  }
}

func ativarPilula() {
  pacgo.pilula = true
  go desativarPilula(3000)
}

func desativarPilula(milisegundos time.Duration) {
  dorme(milisegundos)
  pacgo.pilula = false
}

func terminarJogo() {
  // pacgo morreu :(
  moveCursor( Posicao{labirinto.altura + 2, 0} )
  fmt.Println("Fim de jogo! Os fantasmas venceram... \xF0\x9F\x98\xAD")
}

func main() {
  inicializa()
  defer finaliza()

  mapaSinais = make(map[int]string)
  mapaSinais[0] = "Cima"
  mapaSinais[1] = "Baixo"
  mapaSinais[2] = "Direita"
  mapaSinais[3] = "Esquerda"

  args    := os.Args[1:]
  var arquivo string
  if len(args) >= 1 {
    arquivo = args[0]
  } else {
    arquivo = ""
  }

  labirinto, pacgo, lista_de_fantasmas, _ = construirLabirinto(arquivo)

  canal := make(chan Movimento, 10)

  // Processos assincronos
  go entradaDoUsuario(canal)
  go moverFantasmas()

  var tecla Movimento
  for  {
    atualizarLabirinto()

    // canal não-bloqueador
    select {
    case tecla = <-canal:
        moverPacGo(tecla)
    default:
    }
    if tecla == Sai { break }

    if detectarColisao() {
      terminarJogo()
      break;
    }

    dorme(100)
  }
}
<commit_msg>muda o placar para vermelho<commit_after>package main

import (
  "fmt"
  "time"
  "os"
  "bufio"
  "log"
  "regexp"
  "errors"
  "math/rand"
)

type Posicao struct {
  linha  int
  coluna int
}

type PacGo struct {
  posicao Posicao
  figura  string // emoji
  pilula  bool
  pontos int
}

type Fantasma struct {
  posicao Posicao
  figura  string // emoji
}

type Labirinto struct {
  largura int
  altura  int
  mapa    []string
  figura string
}

type Movimento int

const (
        Cima = iota
        Baixo
        Esquerda
        Direita
        Nenhum
        Sai
)

var labirinto *Labirinto
var pacgo     *PacGo
var lista_de_fantasmas []*Fantasma
var mapaSinais map[int]string

func construirLabirinto(nomeArquivo string) (*Labirinto, *PacGo, []*Fantasma, error) {

  var ErrMapNotFound = errors.New("Não conseguiu ler o arquivo do mapa")

  var arquivo string
  if nomeArquivo == "" {
    arquivo = "./data/mapa.txt"
  } else {
    arquivo = nomeArquivo
  }

  if file, err := os.Open(arquivo); err == nil {

    // fecha depois de ler o arquivo
    defer file.Close()

    // inicializa o mapa vazio
    var pacgo *PacGo
    fantasmas := []*Fantasma{}
    mapa := []string{}

    r, _ := regexp.Compile("[^ #.]")

    // cria um leitor para ler linha a linha o arquivo
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
      linha := scanner.Text()

      for indice , caracter := range linha {
        switch caracter {
          case 'F': {
            fantasma := &Fantasma{ posicao: Posicao{len(mapa), indice}, figura: "\xF0\x9F\x91\xBB"}
            fantasmas = append(fantasmas, fantasma)
          }
          case 'G': pacgo = &PacGo{ posicao: Posicao{len(mapa), indice}, figura: "\xF0\x9F\x98\x83", pontos : 0 }
        }
      }

      linha = r.ReplaceAllString(linha, " ")
      mapa = append(mapa, linha)
    }

    // verifica se teve erro o leitor
    if err = scanner.Err(); err != nil {
      log.Fatal(err)
      return nil, nil, nil, ErrMapNotFound
    }

    l := &Labirinto{largura: len(mapa[0]), altura: len(mapa), mapa : mapa, figura: "\x1b[44m \x1b[0m"}
    return l, pacgo, fantasmas, nil

  } else {
    log.Fatal(err)
    return nil, nil, nil, ErrMapNotFound
  }
}

func atualizarLabirinto() {
  limpaTela()

  // Imprime os pontos
  moveCursor(Posicao{0,0})
  fmt.Printf("%s%d%s\n", "\x1b[31;1m", pacgo.pontos, "\x1b[0m")

  posicaoInicial := Posicao{2,0}
  moveCursor(posicaoInicial)
  for _, linha := range labirinto.mapa {
    for _, char := range linha {
      if char == '#' {
        fmt.Print(labirinto.figura)
      } else if char == '.'{
        fmt.Print(".")
      } else {
        fmt.Print(" ")
      }
      //fmt.Println(linha)
    }
    fmt.Println("")
  }

  // Imprime PacGo
  moveCursor(posicaoInicial.adiciona(&pacgo.posicao))
  fmt.Printf("%s", pacgo.figura)

  // Imprime fantasmas
  for _, fantasma := range lista_de_fantasmas {
    moveCursor(posicaoInicial.adiciona(&fantasma.posicao))
    fmt.Printf("%s", fantasma.figura)
  }

  // Move o cursor para fora do labirinto
  moveCursor(posicaoInicial.adiciona(&Posicao{labirinto.altura + 2, 1}))
}

func detectarColisao() bool {
  for _, fantasma := range lista_de_fantasmas {
    if fantasma.posicao == pacgo.posicao {
      return true
    }
  }
  return false
}

func moverPacGo(m Movimento) {

  var valorDaPosicaoAtualDaPacgo = labirinto.mapa[pacgo.posicao.linha][pacgo.posicao.coluna]
  var linhaAtualDaPacgo = pacgo.posicao.linha
  var colunaAtualDaPacgo = pacgo.posicao.coluna

  switch m {
    case Cima:
      if linhaAtualDaPacgo == 0 {
        if valorDaPosicaoAtualDaPacgo == ' ' {
          pacgo.posicao.linha = labirinto.altura - 1
        }
      } else {
        var posicaoAcimaDaPacgo = labirinto.mapa[pacgo.posicao.linha - 1][pacgo.posicao.coluna]
        if posicaoAcimaDaPacgo != '#' {
          pacgo.posicao.linha = pacgo.posicao.linha - 1
        }
      }
    case Baixo:
      if linhaAtualDaPacgo == labirinto.altura - 1{
        if valorDaPosicaoAtualDaPacgo == ' '{
          pacgo.posicao.linha = 0
        }
      } else {
        var posicaoAbaixoDaPacgo = labirinto.mapa[pacgo.posicao.linha + 1][pacgo.posicao.coluna]
        if posicaoAbaixoDaPacgo != '#'{
          pacgo.posicao.linha = pacgo.posicao.linha + 1
        }
      }
    case Direita:
      if colunaAtualDaPacgo == labirinto.largura-1{
        if valorDaPosicaoAtualDaPacgo == ' '{
          pacgo.posicao.coluna = 0
        }
      } else {
        var posicaoDireitaDaPacgo = labirinto.mapa[pacgo.posicao.linha][pacgo.posicao.coluna + 1]
        if posicaoDireitaDaPacgo != '#'{
          pacgo.posicao.coluna = pacgo.posicao.coluna + 1
        }
      }
    case Esquerda:
      if colunaAtualDaPacgo == 0 {
        if valorDaPosicaoAtualDaPacgo == ' ' {
          pacgo.posicao.coluna = labirinto.largura - 1
        }
      } else {
        var posicaoEsquerdaDaPacgo = labirinto.mapa[pacgo.posicao.linha][pacgo.posicao.coluna - 1]
        if posicaoEsquerdaDaPacgo != '#'{
          pacgo.posicao.coluna = pacgo.posicao.coluna - 1
        }
      }
  }
}

func random(min, max int) int {
    return rand.Intn(max - min) + min
}

func move(fantasma *Fantasma, valorDaPosicaoAtualDoFantasma byte, linhaAtualDoFantasma int, colunaAtualDoFantasma int){

  var direcao = random(0, 4)
  var sinal = mapaSinais[direcao]
  //fmt.Println(sinal)
  switch sinal {
  case "Cima":
              if linhaAtualDoFantasma == 0{
                if valorDaPosicaoAtualDoFantasma == ' '{
                   fantasma.posicao.linha = labirinto.altura - 1
                 }
             }else{
               var posicaoAcimaDoFantasma = labirinto.mapa[fantasma.posicao.linha - 1][fantasma.posicao.coluna]
               if posicaoAcimaDoFantasma != '#'{
                 fantasma.posicao.linha = fantasma.posicao.linha - 1
               }
             }
  case "Baixo":
              if linhaAtualDoFantasma == labirinto.altura - 1{
                 if valorDaPosicaoAtualDoFantasma == ' '{
                   fantasma.posicao.linha = 0
                 }
              }else{
                var posicaoAbaixoDoFantasma = labirinto.mapa[fantasma.posicao.linha + 1][fantasma.posicao.coluna]
                if posicaoAbaixoDoFantasma != '#'{
                  fantasma.posicao.linha = fantasma.posicao.linha + 1
                }
              }
  case "Direita":
                if colunaAtualDoFantasma == labirinto.largura-1{
                  if valorDaPosicaoAtualDoFantasma == ' '{
                    fantasma.posicao.coluna = 0
                  }
                }else{
                  var posicaoDireitaDofantasma = labirinto.mapa[fantasma.posicao.linha][fantasma.posicao.coluna + 1]
                  if posicaoDireitaDofantasma != '#'{
                    fantasma.posicao.coluna = fantasma.posicao.coluna + 1
                  }
                }
  case "Esquerda":
                 if colunaAtualDoFantasma == 0{
                   if valorDaPosicaoAtualDoFantasma == ' '{
                     fantasma.posicao.coluna = labirinto.largura - 1
                   }
                 }else{
                   var posicaoEsquerdaDoFantasma = labirinto.mapa[fantasma.posicao.linha][fantasma.posicao.coluna - 1]
                   if posicaoEsquerdaDoFantasma != '#'{
                     fantasma.posicao.coluna = fantasma.posicao.coluna - 1
                   }
                 }
  }
}

func moverFantasmas() {

  for {
    for i := 0; i < len(lista_de_fantasmas); i++{
        var valorDaPosicaoAtualDoFantasma = labirinto.mapa[lista_de_fantasmas[i].posicao.linha][lista_de_fantasmas[i].posicao.coluna]
        var linhaAtualDoFantasma = lista_de_fantasmas[i].posicao.linha
        var colunaAtualDoFantasma = lista_de_fantasmas[i].posicao.coluna
        //fmt.Println(valorDaPosicaoAtualDoFantasma, linhaAtualDoFantasma, colunaAtualDoFantasma)
        move(lista_de_fantasmas[i], valorDaPosicaoAtualDoFantasma, linhaAtualDoFantasma, colunaAtualDoFantasma)
    }
    dorme(200)
  }
}

func dorme(milisegundos time.Duration) {
  time.Sleep(time.Millisecond * milisegundos)
}

func entradaDoUsuario(canal chan<- Movimento) {
  array := make([]byte, 10)

  for {
    lido, _ := os.Stdin.Read(array)

    if lido == 1 && array[0] == 0x1b {
      canal <- Sai;
    } else if lido == 3 {
      if array[0] == 0x1b && array[1] == '[' {
        switch array[2] {
        case 'A': canal <- Cima
        case 'B': canal <- Baixo
        case 'C': canal <- Direita
        case 'D': canal <- Esquerda
        }
      }
    }
  }
}

func ativarPilula() {
  pacgo.pilula = true
  go desativarPilula(3000)
}

func desativarPilula(milisegundos time.Duration) {
  dorme(milisegundos)
  pacgo.pilula = false
}

func terminarJogo() {
  // pacgo morreu :(
  moveCursor( Posicao{labirinto.altura + 2, 0} )
  fmt.Println("Fim de jogo! Os fantasmas venceram... \xF0\x9F\x98\xAD")
}

func main() {
  inicializa()
  defer finaliza()

  mapaSinais = make(map[int]string)
  mapaSinais[0] = "Cima"
  mapaSinais[1] = "Baixo"
  mapaSinais[2] = "Direita"
  mapaSinais[3] = "Esquerda"

  args    := os.Args[1:]
  var arquivo string
  if len(args) >= 1 {
    arquivo = args[0]
  } else {
    arquivo = ""
  }

  labirinto, pacgo, lista_de_fantasmas, _ = construirLabirinto(arquivo)

  canal := make(chan Movimento, 10)

  // Processos assincronos
  go entradaDoUsuario(canal)
  go moverFantasmas()

  var tecla Movimento
  for  {
    atualizarLabirinto()

    // canal não-bloqueador
    select {
    case tecla = <-canal:
        moverPacGo(tecla)
    default:
    }
    if tecla == Sai { break }

    if detectarColisao() {
      terminarJogo()
      break;
    }

    dorme(100)
  }
}
<|endoftext|>


<commit_before>//go:generate go get -v github.com/josephspurrier/goversioninfo/...
//go:generate goversioninfo -icon=res/app-portable.ico

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"syscall"

	logging "github.com/op/go-logging"
)

const (
	NAME = "discord-portable"
)

var (
	log       = logging.MustGetLogger(NAME)
	logFormat = logging.MustStringFormatter(`%{time:2006-01-02 15:04:05} %{level:.4s} - %{message}`)
)

func main() {
	// Current path
	currentPath, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		log.Error("Current path:", err)
	}

	// Log file
	logfile, err := os.OpenFile(path.Join(currentPath, NAME+".log"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Error("Log file:", err)
	}

	// Init logger
	logBackendStdout := logging.NewBackendFormatter(logging.NewLogBackend(os.Stdout, "", 0), logFormat)
	logBackendFile := logging.NewBackendFormatter(logging.NewLogBackend(logfile, "", 0), logFormat)
	logging.SetBackend(logBackendStdout, logBackendFile)
	log.Info("--------")
	log.Info("Starting " + NAME + "...")
	log.Info("Current path:", currentPath)

	// Init vars
	discordExe := path.Join(currentPath, "Update.exe")
	dataPath := path.Join(currentPath, "data")
	symlinkPath := path.Clean(path.Join(os.Getenv("APPDATA"), "discord"))
	//var symlinkPath = path.Join(currentPath, "data2")
	log.Info("Discord executable:", discordExe)
	log.Info("Data path:", dataPath)
	log.Info("Symlink path:", symlinkPath)

	// Find app folder
	log.Info("Lookup app folder in:", currentPath)
	appPath := ""
	rootFiles, _ := ioutil.ReadDir(currentPath)
	for _, f := range rootFiles {
		if strings.HasPrefix(f.Name(), "app-") && f.IsDir() {
			log.Info("App folder found:", f.Name())
			appPath = path.Join(currentPath, f.Name())
			break
		}
	}
	if _, err := os.Stat(appPath); err == nil {
		log.Info("App path:", appPath)
	} else {
		log.Error("App path does not exist")
	}

	// Create data folder
	if _, err := os.Stat(dataPath); os.IsNotExist(err) {
		log.Info("Create data folder...", dataPath)
		err = os.Mkdir(dataPath, 777)
		if err != nil {
			log.Error("Create data folder:", err)
		}
	}

	// Check old data folder
	if _, err := os.Stat(symlinkPath); err == nil {
		fi, err := os.Lstat(symlinkPath)
		if err != nil {
			log.Error("Symlink lstat:", err)
		}
		if fi.Mode()&os.ModeSymlink != os.ModeSymlink {
			// Copy old data folder
			log.Info("Copy old data from", symlinkPath)
			err = copyDir(symlinkPath, dataPath)
			if err != nil {
				log.Error("Copying old data folder:", err)
			}

			// Rename old data folder
			log.Info("Chmod old data folder...")
			err = os.Chmod(symlinkPath, 0777)
			if err != nil {
				log.Error("Chmod old data folder:", err)
			}

			log.Info("Rename old data folder to", symlinkPath+"_old")
			err = os.Rename(symlinkPath, symlinkPath+"_old")
			if err != nil {
				log.Error("Renaming old data folder:", err)
			}
		}
	}

	// Create symlink
	log.Info("Create symlink:", symlinkPath)
	os.Remove(symlinkPath)
	cmd := exec.Command("cmd", "/c", "mklink", "/J", strings.Replace(symlinkPath, "/", "\\", -1), strings.Replace(dataPath, "/", "\\", -1))
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
	if err := cmd.Run(); err != nil {
		log.Error("Symlink:", err)
	}
	/*err = os.Symlink(dataPath, symlinkPath)
	  if err != nil {
	    log.Error(err)
	  }*/

	// Launch Discord
	log.Info("Launch Discord...")
	cmd = exec.Command(discordExe, "--processStart", "Discord.exe")
	cmd.Dir = appPath

	defer logfile.Close()
	cmd.Stdout = logfile
	cmd.Stderr = logfile

	if err := cmd.Start(); err != nil {
		log.Error("Cmd Start:", err)
	}

	cmd.Wait()
}

// src: https://gist.github.com/m4ng0squ4sh/92462b38df26839a3ca324697c8cba04
func copyFile(src, dst string) (err error) {
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	out, err := os.Create(dst)
	if err != nil {
		return
	}
	defer func() {
		if e := out.Close(); e != nil {
			err = e
		}
	}()

	_, err = io.Copy(out, in)
	if err != nil {
		return
	}

	err = out.Sync()
	if err != nil {
		return
	}

	si, err := os.Stat(src)
	if err != nil {
		return
	}

	err = os.Chmod(dst, si.Mode())
	if err != nil {
		return
	}

	return
}

// src: https://gist.github.com/m4ng0squ4sh/92462b38df26839a3ca324697c8cba04
func copyDir(src string, dst string) (err error) {
	src = filepath.Clean(src)
	dst = filepath.Clean(dst)

	si, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !si.IsDir() {
		return fmt.Errorf("source is not a directory: %s", src)
	}

	_, err = os.Stat(dst)
	if err != nil && !os.IsNotExist(err) {
		return
	}

	err = os.MkdirAll(dst, si.Mode())
	if err != nil {
		return
	}

	entries, err := ioutil.ReadDir(src)
	if err != nil {
		return
	}

	for _, entry := range entries {
		srcPath := filepath.Join(src, entry.Name())
		dstPath := filepath.Join(dst, entry.Name())
		if entry.IsDir() {
			err = copyDir(srcPath, dstPath)
			if err != nil {
				return
			}
		} else {
			err = copyFile(srcPath, dstPath)
			if err != nil {
				return
			}
		}
	}

	return
}
<commit_msg>Discord voice error (Issue #4) Heuristic detection (Issue #3)<commit_after>//go:generate go get -v github.com/josephspurrier/goversioninfo/...
//go:generate goversioninfo -icon=res/app-portable.ico

package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"syscall"

	logging "github.com/op/go-logging"
)

const (
	NAME            = "discord-portable"
	APP_NAME        = "Discord"
	APP_DATA_FOLDER = "discord"
	APP_PROCESS     = "Update.exe"
)

var (
	log       = logging.MustGetLogger(NAME)
	logFormat = logging.MustStringFormatter(`%{time:2006-01-02 15:04:05} %{level:.4s} - %{message}`)
)

func main() {
	// Current path
	currentPath, err := filepath.Abs(filepath.Dir(os.Args[0]))
	if err != nil {
		log.Error("Current path:", err)
	}

	// Log file
	logfile, err := os.OpenFile(path.Join(currentPath, NAME+".log"), os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Error("Log file:", err)
	}

	// Init logger
	logBackendStdout := logging.NewBackendFormatter(logging.NewLogBackend(os.Stdout, "", 0), logFormat)
	logBackendFile := logging.NewBackendFormatter(logging.NewLogBackend(logfile, "", 0), logFormat)
	logging.SetBackend(logBackendStdout, logBackendFile)
	log.Info("--------")
	log.Info("Starting " + NAME + "...")
	log.Info("Current path:", currentPath)

	// Find app folder
	log.Info("Lookup app folder in:", currentPath)
	appPath := ""
	rootFiles, _ := ioutil.ReadDir(currentPath)
	for _, f := range rootFiles {
		if strings.HasPrefix(f.Name(), "app-") && f.IsDir() {
			log.Info("App folder found:", f.Name())
			appPath = path.Join(currentPath, f.Name())
			break
		}
	}
	if _, err := os.Stat(appPath); err == nil {
		log.Info("App path:", appPath)
	} else {
		log.Error("App path does not exist")
	}

	// Init vars
	appExe := path.Join(currentPath, APP_PROCESS)
	dataPath := path.Join(currentPath, "data")
	symlinkPath := path.Clean(path.Join(os.Getenv("APPDATA"), APP_DATA_FOLDER))
	log.Info("App executable:", appExe)
	log.Info("Data path:", dataPath)
	log.Info("Symlink path:", symlinkPath)

	// Create data folder
	if _, err := os.Stat(dataPath); os.IsNotExist(err) {
		log.Info("Create data folder...", dataPath)
		err = os.Mkdir(dataPath, 777)
		if err != nil {
			log.Error("Create data folder:", err)
		}
	}

	// Check old data folder
	if _, err := os.Stat(symlinkPath); err == nil {
		fi, err := os.Lstat(symlinkPath)
		if err != nil {
			log.Error("Symlink lstat:", err)
		}
		if fi.Mode()&os.ModeSymlink != os.ModeSymlink {
			// Copy old data folder
			log.Info("Copy old data from", symlinkPath)
			err = copyDir(symlinkPath, dataPath)
			if err != nil {
				log.Error("Copying old data folder:", err)
			}

			// Rename old data folder
			log.Info("Chmod old data folder...")
			err = os.Chmod(symlinkPath, 0777)
			if err != nil {
				log.Error("Chmod old data folder:", err)
			}

			log.Info("Rename old data folder to", symlinkPath+"_old")
			err = os.Rename(symlinkPath, symlinkPath+"_old")
			if err != nil {
				log.Error("Renaming old data folder:", err)
			}
		}
	}

	// Create symlink
	log.Info("Create symlink", symlinkPath)
	os.Remove(symlinkPath)
	cmd := exec.Command("cmd", "/c", "mklink", "/J", strings.Replace(symlinkPath, "/", "\\", -1), strings.Replace(dataPath, "/", "\\", -1))
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
	if err := cmd.Run(); err != nil {
		log.Error("Symlink:", err)
	}
	/*err = os.Symlink(dataPath, symlinkPath)
	if err != nil {
	  log.Error(err)
	}*/

	// Launch Discord
	log.Infof("Launch %s...", APP_NAME)
	cmd = exec.Command(appExe, "--processStart", "Discord.exe")
	cmd.Dir = appPath

	defer logfile.Close()
	cmd.Stdout = logfile
	cmd.Stderr = logfile

	if err := cmd.Start(); err != nil {
		log.Error("Cmd Start:", err)
	}

	cmd.Wait()
}

// src : https://gist.github.com/crazy-max/e50ee72138bb184baf8d1b6e81983f13
func copyDir(src string, dst string) (err error) {
	src = filepath.Clean(src)
	dst = filepath.Clean(dst)

	si, err := os.Stat(src)
	if err != nil {
		return err
	}
	if !si.IsDir() {
		return fmt.Errorf("src is not a directory: %s", src)
	}

	_, err = os.Stat(dst)
	if err != nil && !os.IsNotExist(err) {
		return
	}

	err = os.MkdirAll(dst, si.Mode())
	if err != nil {
		return
	}

	entries, err := ioutil.ReadDir(src)
	if err != nil {
		return
	}

	for _, entry := range entries {
		srcPath := filepath.Join(src, entry.Name())
		dstPath := filepath.Join(dst, entry.Name())
		if entry.IsDir() {
			err = copyDir(srcPath, dstPath)
			if err != nil {
				return
			}
		} else {
			err = copyFile(srcPath, dstPath)
			if err != nil {
				return
			}
		}
	}

	return
}

func copyFile(src, dst string) (err error) {
	in, err := os.Open(src)
	if err != nil {
		return
	}
	defer in.Close()

	out, err := os.Create(dst)
	if err != nil {
		return
	}
	defer func() {
		if e := out.Close(); e != nil {
			err = e
		}
	}()

	_, err = io.Copy(out, in)
	if err != nil {
		return
	}

	err = out.Sync()
	if err != nil {
		return
	}

	si, err := os.Stat(src)
	if err != nil {
		return
	}

	err = os.Chmod(dst, si.Mode())
	if err != nil {
		return
	}

	return
}
<|endoftext|>


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

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"

	"github.com/nmiyake/pkg/dirs"
	"github.com/nmiyake/pkg/errorstringer"
	"github.com/pkg/errors"

	"github.com/palantir/godel/framework/builtintasks"
	"github.com/palantir/godel/framework/godel"
	"github.com/palantir/godel/framework/godel/config"
	"github.com/palantir/godel/framework/godellauncher"
	"github.com/palantir/godel/framework/godellauncher/defaulttasks"
	"github.com/palantir/godel/framework/plugins"
)

func main() {
	if err := dirs.SetGoEnvVariables(); err != nil {
		printErrAndExit(errors.Wrapf(err, "failed to set Go environment variables"), false)
	}
	os.Exit(runGodelApp(os.Args))
}

func runGodelApp(osArgs []string) int {
	os.Args = osArgs

	global, err := godellauncher.ParseAppArgs(os.Args)
	tasksCfgInfo := config.TasksConfigInfo{
		BuiltinPluginsConfig: defaulttasks.BuiltinPluginsConfig(),
	}
	if err != nil {
		// match invalid flag output with that provided by Cobra CLI
		printErrAndExit(fmt.Errorf(err.Error()+"\n"+godellauncher.UsageString(createTasks(nil, nil, nil, tasksCfgInfo))), false)
	}

	var allUpgradeConfigTasks []godellauncher.UpgradeConfigTask
	var defaultTasks, pluginTasks []godellauncher.Task
	if global.Wrapper != "" {
		godelCfg, err := config.ReadGodelConfigFromProjectDir(path.Dir(global.Wrapper))
		if err != nil {
			printErrAndExit(err, global.Debug)
		}

		taskCfgProviders := config.TasksConfigProvidersConfig(godelCfg.TasksConfigProviders)
		configProvidersParam, err := taskCfgProviders.ToParam()
		if err != nil {
			printErrAndExit(err, global.Debug)
		}
		providedConfigs, err := plugins.LoadProvidedConfigurations(configProvidersParam, os.Stdout)
		if err != nil {
			printErrAndExit(err, global.Debug)
		}
		// combine base configuration with resolved configurations
		tasksConfig := config.TasksConfig(godelCfg.TasksConfig)
		tasksConfig.Combine(providedConfigs...)
		tasksCfgInfo.TasksConfig = tasksConfig

		// add default tasks
		defaultTasksCfg, err := defaulttasks.PluginsConfig(config.DefaultTasksConfig(tasksConfig.DefaultTasks))
		if err != nil {
			printErrAndExit(err, global.Debug)
		}
		defaultTasksParam, err := defaultTasksCfg.ToParam()
		if err != nil {
			printErrAndExit(err, global.Debug)
		}

		var defaultUpgradeConfigTasks, pluginUpgradeConfigTasks []godellauncher.UpgradeConfigTask

		tasksCfgInfo.DefaultTasksPluginsConfig = defaultTasksCfg
		defaultTasks, defaultUpgradeConfigTasks, err = plugins.LoadPluginsTasks(defaultTasksParam, os.Stdout)
		if err != nil {
			printErrAndExit(err, global.Debug)
		}

		// add tasks provided by plugins
		pluginsCfg := config.PluginsConfig(tasksConfig.Plugins)
		pluginsParam, err := pluginsCfg.ToParam()
		if err != nil {
			printErrAndExit(err, global.Debug)
		}
		pluginTasks, pluginUpgradeConfigTasks, err = plugins.LoadPluginsTasks(pluginsParam, os.Stdout)
		if err != nil {
			printErrAndExit(err, global.Debug)
		}

		if len(defaultTasksCfg.Plugins) != 0 && len(tasksConfig.Plugins.Plugins) != 0 {
			// verify that there are no conflicts
			combinedCfg := config.PluginsConfig(tasksConfig.Plugins)
			combinedCfg.DefaultResolvers = append(combinedCfg.DefaultResolvers, tasksConfig.Plugins.DefaultResolvers...)
			combinedCfg.Plugins = append(combinedCfg.Plugins, tasksConfig.Plugins.Plugins...)
			combinedParam, err := combinedCfg.ToParam()
			if err != nil {
				printErrAndExit(err, global.Debug)
			}
			if _, _, err := plugins.LoadPluginsTasks(combinedParam, ioutil.Discard); err != nil {
				printErrAndExit(err, global.Debug)
			}
		}

		// add all upgrade tasks
		allUpgradeConfigTasks = append(allUpgradeConfigTasks, defaulttasks.BuiltinUpgradeConfigTasks()...)
		allUpgradeConfigTasks = append(allUpgradeConfigTasks, defaultUpgradeConfigTasks...)
		allUpgradeConfigTasks = append(allUpgradeConfigTasks, pluginUpgradeConfigTasks...)
	}
	task, err := godellauncher.TaskForInput(global, createTasks(defaultTasks, pluginTasks, allUpgradeConfigTasks, tasksCfgInfo))
	if err != nil {
		// match missing command output with that provided by Cobra CLI
		errTmpl := "%s\nRun '%s --help' for usage."
		printErrAndExit(fmt.Errorf(errTmpl, err.Error(), godel.AppName), false)
	}

	if err := task.Run(global, os.Stdout); err != nil {
		// note that only app/amalgomated tasks will never reach this point, as they return an exit code and then
		// pass through an empty error. Those tasks are expected to handle their own error output.
		printErrAndExit(err, global.Debug)
	}
	return 0
}

func createTasks(defaultTasks, pluginTasks []godellauncher.Task, upgradeConfigTasks []godellauncher.UpgradeConfigTask, tasksCfgInfo config.TasksConfigInfo) []godellauncher.Task {
	var allTasks []godellauncher.Task
	allTasks = append(allTasks, builtintasks.Tasks(tasksCfgInfo)...)
	allTasks = append(allTasks, defaultTasks...)
	allTasks = append(allTasks, builtintasks.VerifyTask(append(allTasks, pluginTasks...)))
	allTasks = append(allTasks, builtintasks.UpgradeConfigTask(upgradeConfigTasks))
	allTasks = append(allTasks, pluginTasks...)
	return allTasks
}

func printErrAndExit(err error, debug bool) {
	if errStr := err.Error(); errStr != "" {
		if debug {
			errStr = errorstringer.StackWithInterleavedMessages(err)
		}
		fmt.Println("Error:", errStr)
	}
	os.Exit(1)
}
<commit_msg>Fix task config resolution precedence (#368)<commit_after>// Copyright 2016 Palantir Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"

	"github.com/nmiyake/pkg/dirs"
	"github.com/nmiyake/pkg/errorstringer"
	"github.com/pkg/errors"

	"github.com/palantir/godel/framework/builtintasks"
	"github.com/palantir/godel/framework/godel"
	"github.com/palantir/godel/framework/godel/config"
	"github.com/palantir/godel/framework/godellauncher"
	"github.com/palantir/godel/framework/godellauncher/defaulttasks"
	"github.com/palantir/godel/framework/plugins"
)

func main() {
	if err := dirs.SetGoEnvVariables(); err != nil {
		printErrAndExit(errors.Wrapf(err, "failed to set Go environment variables"), false)
	}
	os.Exit(runGodelApp(os.Args))
}

func runGodelApp(osArgs []string) int {
	os.Args = osArgs

	global, err := godellauncher.ParseAppArgs(os.Args)
	tasksCfgInfo := config.TasksConfigInfo{
		BuiltinPluginsConfig: defaulttasks.BuiltinPluginsConfig(),
	}
	if err != nil {
		// match invalid flag output with that provided by Cobra CLI
		printErrAndExit(fmt.Errorf(err.Error()+"\n"+godellauncher.UsageString(createTasks(nil, nil, nil, tasksCfgInfo))), false)
	}

	var allUpgradeConfigTasks []godellauncher.UpgradeConfigTask
	var defaultTasks, pluginTasks []godellauncher.Task
	if global.Wrapper != "" {
		godelCfg, err := config.ReadGodelConfigFromProjectDir(path.Dir(global.Wrapper))
		if err != nil {
			printErrAndExit(err, global.Debug)
		}

		taskCfgProviders := config.TasksConfigProvidersConfig(godelCfg.TasksConfigProviders)
		configProvidersParam, err := taskCfgProviders.ToParam()
		if err != nil {
			printErrAndExit(err, global.Debug)
		}
		providedConfigs, err := plugins.LoadProvidedConfigurations(configProvidersParam, os.Stdout)
		if err != nil {
			printErrAndExit(err, global.Debug)
		}
		tasksConfig := config.TasksConfig{}
		// add resolved configurations
		tasksConfig.Combine(providedConfigs...)
		// add configuration specified in config file (overrides any provided config)
		tasksConfig.Combine(config.TasksConfig(godelCfg.TasksConfig))
		tasksCfgInfo.TasksConfig = tasksConfig

		// add default tasks
		defaultTasksCfg, err := defaulttasks.PluginsConfig(config.DefaultTasksConfig(tasksConfig.DefaultTasks))
		if err != nil {
			printErrAndExit(err, global.Debug)
		}
		defaultTasksParam, err := defaultTasksCfg.ToParam()
		if err != nil {
			printErrAndExit(err, global.Debug)
		}

		var defaultUpgradeConfigTasks, pluginUpgradeConfigTasks []godellauncher.UpgradeConfigTask

		tasksCfgInfo.DefaultTasksPluginsConfig = defaultTasksCfg
		defaultTasks, defaultUpgradeConfigTasks, err = plugins.LoadPluginsTasks(defaultTasksParam, os.Stdout)
		if err != nil {
			printErrAndExit(err, global.Debug)
		}

		// add tasks provided by plugins
		pluginsCfg := config.PluginsConfig(tasksConfig.Plugins)
		pluginsParam, err := pluginsCfg.ToParam()
		if err != nil {
			printErrAndExit(err, global.Debug)
		}
		pluginTasks, pluginUpgradeConfigTasks, err = plugins.LoadPluginsTasks(pluginsParam, os.Stdout)
		if err != nil {
			printErrAndExit(err, global.Debug)
		}

		if len(defaultTasksCfg.Plugins) != 0 && len(tasksConfig.Plugins.Plugins) != 0 {
			// verify that there are no conflicts
			combinedCfg := config.PluginsConfig(tasksConfig.Plugins)
			combinedCfg.DefaultResolvers = append(combinedCfg.DefaultResolvers, tasksConfig.Plugins.DefaultResolvers...)
			combinedCfg.Plugins = append(combinedCfg.Plugins, tasksConfig.Plugins.Plugins...)
			combinedParam, err := combinedCfg.ToParam()
			if err != nil {
				printErrAndExit(err, global.Debug)
			}
			if _, _, err := plugins.LoadPluginsTasks(combinedParam, ioutil.Discard); err != nil {
				printErrAndExit(err, global.Debug)
			}
		}

		// add all upgrade tasks
		allUpgradeConfigTasks = append(allUpgradeConfigTasks, defaulttasks.BuiltinUpgradeConfigTasks()...)
		allUpgradeConfigTasks = append(allUpgradeConfigTasks, defaultUpgradeConfigTasks...)
		allUpgradeConfigTasks = append(allUpgradeConfigTasks, pluginUpgradeConfigTasks...)
	}
	task, err := godellauncher.TaskForInput(global, createTasks(defaultTasks, pluginTasks, allUpgradeConfigTasks, tasksCfgInfo))
	if err != nil {
		// match missing command output with that provided by Cobra CLI
		errTmpl := "%s\nRun '%s --help' for usage."
		printErrAndExit(fmt.Errorf(errTmpl, err.Error(), godel.AppName), false)
	}

	if err := task.Run(global, os.Stdout); err != nil {
		// note that only app/amalgomated tasks will never reach this point, as they return an exit code and then
		// pass through an empty error. Those tasks are expected to handle their own error output.
		printErrAndExit(err, global.Debug)
	}
	return 0
}

func createTasks(defaultTasks, pluginTasks []godellauncher.Task, upgradeConfigTasks []godellauncher.UpgradeConfigTask, tasksCfgInfo config.TasksConfigInfo) []godellauncher.Task {
	var allTasks []godellauncher.Task
	allTasks = append(allTasks, builtintasks.Tasks(tasksCfgInfo)...)
	allTasks = append(allTasks, defaultTasks...)
	allTasks = append(allTasks, builtintasks.VerifyTask(append(allTasks, pluginTasks...)))
	allTasks = append(allTasks, builtintasks.UpgradeConfigTask(upgradeConfigTasks))
	allTasks = append(allTasks, pluginTasks...)
	return allTasks
}

func printErrAndExit(err error, debug bool) {
	if errStr := err.Error(); errStr != "" {
		if debug {
			errStr = errorstringer.StackWithInterleavedMessages(err)
		}
		fmt.Println("Error:", errStr)
	}
	os.Exit(1)
}
<|endoftext|>