<commit_before>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/mackerelio/mackerel-agent/command"
	"github.com/mackerelio/mackerel-agent/config"
	"github.com/mackerelio/mackerel-agent/logging"
	"github.com/mackerelio/mackerel-agent/version"
	"github.com/motemen/go-cli"
)

// allow options like -role=... -role=...
type roleFullnamesFlag []string

var roleFullnamePattern = regexp.MustCompile(`^[a-zA-Z0-9][-_a-zA-Z0-9]*:\s*[a-zA-Z0-9][-_a-zA-Z0-9]*$`)

func (r *roleFullnamesFlag) String() string {
	return fmt.Sprint(*r)
}

func (r *roleFullnamesFlag) Set(input string) error {
	inputRoles := strings.Split(input, ",")
	*r = append(*r, inputRoles...)
	return nil
}

var logger = logging.GetLogger("main")

func main() {
	// mackerel-agent rarely rarely panics because of race condition
	// in multi-threaded environment on some OS/Arch.
	// So fix GOMAXPROCS to 1 just to be safe.
	if os.Getenv("GOMAXPROCS") == "" {
		runtime.GOMAXPROCS(1)
	}
	cli.Run(os.Args[1:])
}

func printRetireUsage() {
	usage := fmt.Sprintf(`Usage of mackerel-agent retire:
  -conf string
        Config file path (Configs in this file are over-written by command line options)
        (default "%s")
  -force
        force retirement without prompting
  -apibase string
        API base (default "%s")
  -apikey string
        (DEPRECATED) API key from mackerel.io web site`,
		config.DefaultConfig.Conffile,
		config.DefaultConfig.Apibase)

	fmt.Fprintln(os.Stderr, usage)
	os.Exit(2)
}

func resolveConfigForRetire(fs *flag.FlagSet, argv []string) (*config.Config, bool, error) {
	var force = fs.Bool("force", false, "force retirement without prompting")
	fs.Usage = printRetireUsage
	conf, err := resolveConfig(fs, argv)
	return conf, *force, err
}

// resolveConfig parses command line arguments and loads config file to
// return config.Config information.
func resolveConfig(fs *flag.FlagSet, argv []string) (*config.Config, error) {
	conf := &config.Config{}

	var (
		conffile      = fs.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)")
		apibase       = fs.String("apibase", config.DefaultConfig.Apibase, "API base")
		pidfile       = fs.String("pidfile", config.DefaultConfig.Pidfile, "File containing PID")
		root          = fs.String("root", config.DefaultConfig.Root, "Directory containing variable state information")
		apikey        = fs.String("apikey", "", "(DEPRECATED) API key from mackerel.io web site")
		diagnostic    = fs.Bool("diagnostic", false, "Enables diagnostic features")
		verbose       bool
		roleFullnames roleFullnamesFlag
	)
	fs.BoolVar(&verbose, "verbose", config.DefaultConfig.Verbose, "Toggle verbosity")
	fs.BoolVar(&verbose, "v", config.DefaultConfig.Verbose, "Toggle verbosity (shorthand)")

	// The value of "role" option is internally "roll fullname",
	// but we call it "role" here for ease.
	fs.Var(&roleFullnames, "role", "Set this host's roles (format: <service>:<role>)")

	fs.Parse(argv)

	conf, confErr := config.LoadConfig(*conffile)
	conf.Conffile = *conffile
	if confErr != nil {
		return nil, fmt.Errorf("Failed to load the config file: %s", confErr)
	}

	// overwrite config from file by config from args
	fs.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "apibase":
			conf.Apibase = *apibase
		case "apikey":
			conf.Apikey = *apikey
		case "pidfile":
			conf.Pidfile = *pidfile
		case "root":
			conf.Root = *root
		case "diagnostic":
			conf.Diagnostic = *diagnostic
		case "verbose", "v":
			conf.Verbose = verbose
		case "role":
			conf.Roles = roleFullnames
		}
	})

	r := []string{}
	for _, roleFullName := range conf.Roles {
		if !roleFullnamePattern.MatchString(roleFullName) {
			logger.Errorf("Bad format for role fullname (expecting <service>:<role>. Alphabet, numbers, hyphens and underscores are acceptable, but the first character must not be a hyphen or an underscore.): '%s'", roleFullName)
		} else {
			r = append(r, roleFullName)
		}
	}
	conf.Roles = r

	if conf.Verbose && conf.Silent {
		logger.Warningf("both of `verbose` and `silent` option are specified. In this case, `verbose` get preference over `silent`")
	}

	if conf.Apikey == "" {
		return nil, fmt.Errorf("Apikey must be specified in the config file (or by the DEPRECATED command-line flag)")
	}
	return conf, nil
}

func createPidFile(pidfile string) error {
	if pidString, err := ioutil.ReadFile(pidfile); err == nil {
		if pid, err := strconv.Atoi(string(pidString)); err == nil {
			if existsPid(pid) {
				return fmt.Errorf("Pidfile found, try stopping another running mackerel-agent or delete %s", pidfile)
			}
			// Note mackerel-agent in windows can't remove pidfile during stoping the service
			logger.Warningf("Pidfile found, but there seems no another process of mackerel-agent. Ignoring %s", pidfile)
		} else {
			logger.Warningf("Malformed pidfile found. Ignoring %s", pidfile)
		}
	}

	err := os.MkdirAll(filepath.Dir(pidfile), 0755)
	if err != nil {
		return err
	}
	file, err := os.Create(pidfile)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = fmt.Fprintf(file, "%d", os.Getpid())
	return err
}

func removePidFile(pidfile string) {
	if err := os.Remove(pidfile); err != nil {
		logger.Errorf("Failed to remove the pidfile: %s: %s", pidfile, err)
	}
}

func start(conf *config.Config, termCh chan struct{}) error {
	if conf.Silent {
		logging.SetLogLevel(logging.ERROR)
	}
	if conf.Verbose {
		logging.SetLogLevel(logging.DEBUG)
	}
	logger.Infof("Starting mackerel-agent version:%s, rev:%s, apibase:%s", version.VERSION, version.GITCOMMIT, conf.Apibase)

	if err := createPidFile(conf.Pidfile); err != nil {
		return fmt.Errorf("createPidFile(%q) failed: %s", conf.Pidfile, err)
	}
	defer removePidFile(conf.Pidfile)

	ctx, err := command.Prepare(conf)
	if err != nil {
		return fmt.Errorf("command.Prepare failed: %s", err)
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
	go signalHandler(c, ctx, termCh)

	return command.Run(ctx, termCh)
}

var maxTerminatingInterval = 30 * time.Second

func signalHandler(c chan os.Signal, ctx *command.Context, termCh chan struct{}) {
	received := false
	for sig := range c {
		if sig == syscall.SIGHUP {
			logger.Debugf("Received signal '%v'", sig)
			// TODO reload configuration file

			ctx.UpdateHostSpecs()
		} else {
			if !received {
				received = true
				logger.Infof(
					"Received signal '%v', try graceful shutdown up to %f seconds. If you want force shutdown immediately, send a signal again.",
					sig,
					maxTerminatingInterval.Seconds())
			} else {
				logger.Infof("Received signal '%v' again, force shutdown.", sig)
			}
			termCh <- struct{}{}
			go func() {
				time.Sleep(maxTerminatingInterval)
				logger.Infof("Timed out. force shutdown.")
				termCh <- struct{}{}
			}()
		}
	}
}
<commit_msg>fix comment. thanks stefafafan.<commit_after>package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	"path/filepath"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"syscall"
	"time"

	"github.com/mackerelio/mackerel-agent/command"
	"github.com/mackerelio/mackerel-agent/config"
	"github.com/mackerelio/mackerel-agent/logging"
	"github.com/mackerelio/mackerel-agent/version"
	"github.com/motemen/go-cli"
)

// allow options like -role=... -role=...
type roleFullnamesFlag []string

var roleFullnamePattern = regexp.MustCompile(`^[a-zA-Z0-9][-_a-zA-Z0-9]*:\s*[a-zA-Z0-9][-_a-zA-Z0-9]*$`)

func (r *roleFullnamesFlag) String() string {
	return fmt.Sprint(*r)
}

func (r *roleFullnamesFlag) Set(input string) error {
	inputRoles := strings.Split(input, ",")
	*r = append(*r, inputRoles...)
	return nil
}

var logger = logging.GetLogger("main")

func main() {
	// although the possibility is very low, mackerel-agent may panic because of
	// a race condition in multi-threaded environment on some OS/Arch.
	// So fix GOMAXPROCS to 1 just to be safe.
	if os.Getenv("GOMAXPROCS") == "" {
		runtime.GOMAXPROCS(1)
	}
	cli.Run(os.Args[1:])
}

func printRetireUsage() {
	usage := fmt.Sprintf(`Usage of mackerel-agent retire:
  -conf string
        Config file path (Configs in this file are over-written by command line options)
        (default "%s")
  -force
        force retirement without prompting
  -apibase string
        API base (default "%s")
  -apikey string
        (DEPRECATED) API key from mackerel.io web site`,
		config.DefaultConfig.Conffile,
		config.DefaultConfig.Apibase)

	fmt.Fprintln(os.Stderr, usage)
	os.Exit(2)
}

func resolveConfigForRetire(fs *flag.FlagSet, argv []string) (*config.Config, bool, error) {
	var force = fs.Bool("force", false, "force retirement without prompting")
	fs.Usage = printRetireUsage
	conf, err := resolveConfig(fs, argv)
	return conf, *force, err
}

// resolveConfig parses command line arguments and loads config file to
// return config.Config information.
func resolveConfig(fs *flag.FlagSet, argv []string) (*config.Config, error) {
	conf := &config.Config{}

	var (
		conffile      = fs.String("conf", config.DefaultConfig.Conffile, "Config file path (Configs in this file are over-written by command line options)")
		apibase       = fs.String("apibase", config.DefaultConfig.Apibase, "API base")
		pidfile       = fs.String("pidfile", config.DefaultConfig.Pidfile, "File containing PID")
		root          = fs.String("root", config.DefaultConfig.Root, "Directory containing variable state information")
		apikey        = fs.String("apikey", "", "(DEPRECATED) API key from mackerel.io web site")
		diagnostic    = fs.Bool("diagnostic", false, "Enables diagnostic features")
		verbose       bool
		roleFullnames roleFullnamesFlag
	)
	fs.BoolVar(&verbose, "verbose", config.DefaultConfig.Verbose, "Toggle verbosity")
	fs.BoolVar(&verbose, "v", config.DefaultConfig.Verbose, "Toggle verbosity (shorthand)")

	// The value of "role" option is internally "roll fullname",
	// but we call it "role" here for ease.
	fs.Var(&roleFullnames, "role", "Set this host's roles (format: <service>:<role>)")

	fs.Parse(argv)

	conf, confErr := config.LoadConfig(*conffile)
	conf.Conffile = *conffile
	if confErr != nil {
		return nil, fmt.Errorf("Failed to load the config file: %s", confErr)
	}

	// overwrite config from file by config from args
	fs.Visit(func(f *flag.Flag) {
		switch f.Name {
		case "apibase":
			conf.Apibase = *apibase
		case "apikey":
			conf.Apikey = *apikey
		case "pidfile":
			conf.Pidfile = *pidfile
		case "root":
			conf.Root = *root
		case "diagnostic":
			conf.Diagnostic = *diagnostic
		case "verbose", "v":
			conf.Verbose = verbose
		case "role":
			conf.Roles = roleFullnames
		}
	})

	r := []string{}
	for _, roleFullName := range conf.Roles {
		if !roleFullnamePattern.MatchString(roleFullName) {
			logger.Errorf("Bad format for role fullname (expecting <service>:<role>. Alphabet, numbers, hyphens and underscores are acceptable, but the first character must not be a hyphen or an underscore.): '%s'", roleFullName)
		} else {
			r = append(r, roleFullName)
		}
	}
	conf.Roles = r

	if conf.Verbose && conf.Silent {
		logger.Warningf("both of `verbose` and `silent` option are specified. In this case, `verbose` get preference over `silent`")
	}

	if conf.Apikey == "" {
		return nil, fmt.Errorf("Apikey must be specified in the config file (or by the DEPRECATED command-line flag)")
	}
	return conf, nil
}

func createPidFile(pidfile string) error {
	if pidString, err := ioutil.ReadFile(pidfile); err == nil {
		if pid, err := strconv.Atoi(string(pidString)); err == nil {
			if existsPid(pid) {
				return fmt.Errorf("Pidfile found, try stopping another running mackerel-agent or delete %s", pidfile)
			}
			// Note mackerel-agent in windows can't remove pidfile during stoping the service
			logger.Warningf("Pidfile found, but there seems no another process of mackerel-agent. Ignoring %s", pidfile)
		} else {
			logger.Warningf("Malformed pidfile found. Ignoring %s", pidfile)
		}
	}

	err := os.MkdirAll(filepath.Dir(pidfile), 0755)
	if err != nil {
		return err
	}
	file, err := os.Create(pidfile)
	if err != nil {
		return err
	}
	defer file.Close()

	_, err = fmt.Fprintf(file, "%d", os.Getpid())
	return err
}

func removePidFile(pidfile string) {
	if err := os.Remove(pidfile); err != nil {
		logger.Errorf("Failed to remove the pidfile: %s: %s", pidfile, err)
	}
}

func start(conf *config.Config, termCh chan struct{}) error {
	if conf.Silent {
		logging.SetLogLevel(logging.ERROR)
	}
	if conf.Verbose {
		logging.SetLogLevel(logging.DEBUG)
	}
	logger.Infof("Starting mackerel-agent version:%s, rev:%s, apibase:%s", version.VERSION, version.GITCOMMIT, conf.Apibase)

	if err := createPidFile(conf.Pidfile); err != nil {
		return fmt.Errorf("createPidFile(%q) failed: %s", conf.Pidfile, err)
	}
	defer removePidFile(conf.Pidfile)

	ctx, err := command.Prepare(conf)
	if err != nil {
		return fmt.Errorf("command.Prepare failed: %s", err)
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGHUP)
	go signalHandler(c, ctx, termCh)

	return command.Run(ctx, termCh)
}

var maxTerminatingInterval = 30 * time.Second

func signalHandler(c chan os.Signal, ctx *command.Context, termCh chan struct{}) {
	received := false
	for sig := range c {
		if sig == syscall.SIGHUP {
			logger.Debugf("Received signal '%v'", sig)
			// TODO reload configuration file

			ctx.UpdateHostSpecs()
		} else {
			if !received {
				received = true
				logger.Infof(
					"Received signal '%v', try graceful shutdown up to %f seconds. If you want force shutdown immediately, send a signal again.",
					sig,
					maxTerminatingInterval.Seconds())
			} else {
				logger.Infof("Received signal '%v' again, force shutdown.", sig)
			}
			termCh <- struct{}{}
			go func() {
				time.Sleep(maxTerminatingInterval)
				logger.Infof("Timed out. force shutdown.")
				termCh <- struct{}{}
			}()
		}
	}
}
<|endoftext|>


<commit_before>package main

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

	log "github.com/Sirupsen/logrus"
)

func main() {
	c, err := NewContext()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Unable to load application context.")
		return
	}

	log.WithFields(log.Fields{
		"address": c.InternalListenAddr(),
	}).Info("Auth API listening.")

	// v1 routes
	http.HandleFunc("/v1/style", BindContext(c, StyleHandler))
	http.HandleFunc("/v1/validate", BindContext(c, ValidateHandler))

	http.HandleFunc("/v1/accounts", BindContext(c, AccountHandler))
	http.HandleFunc("/v1/keys", BindContext(c, KeyHandler))

	err = http.ListenAndServeTLS(c.InternalListenAddr(), c.InternalCert, c.InternalKey, nil)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Error("Unable to launch auth API.")
	}
}

// ContextHandler is an HTTP HandlerFunc that accepts an additional parameter containing the
// server context.
type ContextHandler func(c *Context, w http.ResponseWriter, r *http.Request)

// BindContext returns an http.HandlerFunc that binds a ContextHandler to a specific Context.
func BindContext(c *Context, handler ContextHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) { handler(c, w, r) }
}

// APIError consistently renders error conditions as a JSON payload.
type APIError struct {
	// If nonzero, this message will be displayed to the user in the generated response payload.
	UserMessage string `json:"message"`

	// If nonzero, this message will be displayed to operators in the process log.
	LogMessage string `json:"-"`

	// Used as both UserMessage and LogMessage if either are missing.
	Message string `json:"-"`
}

// Log emits a log message for an error.
func (err APIError) Log(username string) APIError {
	if err.LogMessage == "" {
		err.LogMessage = err.Message
	}

	f := log.Fields{}
	if username != "" {
		f["username"] = username
	}
	log.WithFields(f).Error(err.LogMessage)
	return err
}

// Report renders an error as an HTTP response with the correct content-type and HTTP status code.
func (err APIError) Report(w http.ResponseWriter, status int) APIError {
	if err.UserMessage == "" {
		err.UserMessage = err.Message
	}

	w.WriteHeader(status)
	w.Header().Set("Content-Type", "application/json")

	encodeErr := json.NewEncoder(w).Encode(err)
	if encodeErr != nil {
		fmt.Fprintf(w, `{"message":"Unable to encode error: %v"}`, encodeErr)
	}
	return err
}

// MethodOk tests the HTTP request method. If the method is correct, it does nothing and
// returns true. If it's incorrect, it generates a JSON error and returns false.
func MethodOk(w http.ResponseWriter, r *http.Request, method string) bool {
	if r.Method == method {
		return true
	}

	APIError{
		Message: fmt.Sprintf("Unsupported method %s. Only %s is accepted for this resource.",
			r.Method, method),
	}.Log("").Report(w, http.StatusMethodNotAllowed)

	return false
}

// ExtractKeyCredentials attempts to read an account name and API key from the request.
func ExtractKeyCredentials(w http.ResponseWriter, r *http.Request, requestName string) (accountName, apiKey string, ok bool) {
	return extractCredentials(w, r, requestName, "apiKey")
}

// ExtractPasswordCredentials attempts to read an account name and password from a request form.
func ExtractPasswordCredentials(w http.ResponseWriter, r *http.Request, requestName string) (accountName, password string, ok bool) {
	return extractCredentials(w, r, requestName, "password")
}

func extractCredentials(w http.ResponseWriter, r *http.Request, requestName, credentialName string) (accountName, credential string, ok bool) {
	if err := r.ParseForm(); err != nil {
		APIError{
			Message: fmt.Sprintf("Unable to parse URL parameters: %v", err),
		}.Log("").Report(w, http.StatusBadRequest)
		return "", "", false
	}

	accountName, credential = r.FormValue("accountName"), r.FormValue(credentialName)
	if accountName == "" || credential == "" {
		APIError{
			UserMessage: fmt.Sprintf(
				`Missing required parameters "accountName" and "%s".`,
				credentialName,
			),
			LogMessage: fmt.Sprintf(
				"%s request missing required query parameters.",
				requestName,
			),
		}.Log("").Report(w, http.StatusBadRequest)
		return "", "", false
	}
	return accountName, credential, true
}
<commit_msg>Listen on two interfaces.<commit_after>package main

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

	log "github.com/Sirupsen/logrus"
)

func main() {
	c, err := NewContext()
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Unable to load application context.")
		return
	}

	go ServeInternal(c)
	ServeExternal(c)
}

// ServeInternal configures and launches the internal API.
func ServeInternal(c *Context) {
	mux := http.NewServeMux()

	mux.HandleFunc("/v1/style", BindContext(c, StyleHandler))
	mux.HandleFunc("/v1/validate", BindContext(c, ValidateHandler))

	server := &http.Server{
		Addr:    c.InternalListenAddr(),
		Handler: mux,
	}

	log.WithFields(log.Fields{
		"address": c.InternalListenAddr(),
	}).Info("Internal auth API listening.")

	err := server.ListenAndServeTLS(c.InternalCert, c.InternalKey)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Unable to launch internal auth API.")
	}
}

// ServeExternal configures and launches the external API.
func ServeExternal(c *Context) {
	mux := http.NewServeMux()

	mux.HandleFunc("/v1/accounts", BindContext(c, AccountHandler))
	mux.HandleFunc("/v1/keys", BindContext(c, KeyHandler))

	server := &http.Server{
		Addr:    c.ExternalListenAddr(),
		Handler: mux,
	}

	log.WithFields(log.Fields{
		"address": c.ExternalListenAddr(),
	}).Info("External auth API listening.")

	err := server.ListenAndServeTLS(c.ExternalCert, c.ExternalKey)
	if err != nil {
		log.WithFields(log.Fields{
			"error": err,
		}).Fatal("Unable to launch external auth API.")
	}
}

// ContextHandler is an HTTP HandlerFunc that accepts an additional parameter containing the
// server context.
type ContextHandler func(c *Context, w http.ResponseWriter, r *http.Request)

// BindContext returns an http.HandlerFunc that binds a ContextHandler to a specific Context.
func BindContext(c *Context, handler ContextHandler) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) { handler(c, w, r) }
}

// APIError consistently renders error conditions as a JSON payload.
type APIError struct {
	// If nonzero, this message will be displayed to the user in the generated response payload.
	UserMessage string `json:"message"`

	// If nonzero, this message will be displayed to operators in the process log.
	LogMessage string `json:"-"`

	// Used as both UserMessage and LogMessage if either are missing.
	Message string `json:"-"`
}

// Log emits a log message for an error.
func (err APIError) Log(username string) APIError {
	if err.LogMessage == "" {
		err.LogMessage = err.Message
	}

	f := log.Fields{}
	if username != "" {
		f["username"] = username
	}
	log.WithFields(f).Error(err.LogMessage)
	return err
}

// Report renders an error as an HTTP response with the correct content-type and HTTP status code.
func (err APIError) Report(w http.ResponseWriter, status int) APIError {
	if err.UserMessage == "" {
		err.UserMessage = err.Message
	}

	w.WriteHeader(status)
	w.Header().Set("Content-Type", "application/json")

	encodeErr := json.NewEncoder(w).Encode(err)
	if encodeErr != nil {
		fmt.Fprintf(w, `{"message":"Unable to encode error: %v"}`, encodeErr)
	}
	return err
}

// MethodOk tests the HTTP request method. If the method is correct, it does nothing and
// returns true. If it's incorrect, it generates a JSON error and returns false.
func MethodOk(w http.ResponseWriter, r *http.Request, method string) bool {
	if r.Method == method {
		return true
	}

	APIError{
		Message: fmt.Sprintf("Unsupported method %s. Only %s is accepted for this resource.",
			r.Method, method),
	}.Log("").Report(w, http.StatusMethodNotAllowed)

	return false
}

// ExtractKeyCredentials attempts to read an account name and API key from the request.
func ExtractKeyCredentials(w http.ResponseWriter, r *http.Request, requestName string) (accountName, apiKey string, ok bool) {
	return extractCredentials(w, r, requestName, "apiKey")
}

// ExtractPasswordCredentials attempts to read an account name and password from a request form.
func ExtractPasswordCredentials(w http.ResponseWriter, r *http.Request, requestName string) (accountName, password string, ok bool) {
	return extractCredentials(w, r, requestName, "password")
}

func extractCredentials(w http.ResponseWriter, r *http.Request, requestName, credentialName string) (accountName, credential string, ok bool) {
	if err := r.ParseForm(); err != nil {
		APIError{
			Message: fmt.Sprintf("Unable to parse URL parameters: %v", err),
		}.Log("").Report(w, http.StatusBadRequest)
		return "", "", false
	}

	accountName, credential = r.FormValue("accountName"), r.FormValue(credentialName)
	if accountName == "" || credential == "" {
		APIError{
			UserMessage: fmt.Sprintf(
				`Missing required parameters "accountName" and "%s".`,
				credentialName,
			),
			LogMessage: fmt.Sprintf(
				"%s request missing required query parameters.",
				requestName,
			),
		}.Log("").Report(w, http.StatusBadRequest)
		return "", "", false
	}
	return accountName, credential, true
}
<|endoftext|>


<commit_before>// Package main defines a command line interface for the sqlboiler package
package main

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

	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var (
	cmdState  *State
	cmdConfig *Config
)

func main() {
	var err error

	viper.SetConfigName("sqlboiler")

	configHome := os.Getenv("XDG_CONFIG_HOME")
	homePath := os.Getenv("HOME")
	wd, err := os.Getwd()
	if err != nil {
		wd = "./"
	}

	configPaths := []string{wd}
	if len(configHome) > 0 {
		configPaths = append(configPaths, filepath.Join(configHome, "sqlboiler"))
	} else {
		configPaths = append(configPaths, filepath.Join(homePath, ".config/sqlboiler"))
	}

	for _, p := range configPaths {
		viper.AddConfigPath(p)
	}

	// Find and read config
	err = viper.ReadInConfig()

	// Set up the cobra root command
	var rootCmd = &cobra.Command{
		Use:   "sqlboiler <driver>",
		Short: "SQL Boiler generates boilerplate structs and statements",
		Long: "SQL Boiler generates boilerplate structs and statements from template files.\n" +
			`Complete documentation is available at http://github.com/nullbio/sqlboiler`,
		Example:  `sqlboiler postgres -o models -p models`,
		PreRunE:  preRun,
		RunE:     run,
		PostRunE: postRun,
	}

	// Set up the cobra root command flags
	rootCmd.PersistentFlags().StringSliceP("tables", "t", nil, "Tables to generate models for, all tables if empty")
	rootCmd.PersistentFlags().StringP("output", "o", "models", "The name of the folder to output to")
	rootCmd.PersistentFlags().StringP("pkgname", "p", "models", "The name you wish to assign to your generated package")

	viper.BindPFlags(rootCmd.PersistentFlags())

	if err := rootCmd.Execute(); err != nil {
		fmt.Printf("\n%+v\n", err)
		os.Exit(1)
	}
}

func preRun(cmd *cobra.Command, args []string) error {
	var err error

	if len(args) == 0 {
		return errors.New("must provide a driver name")
	}

	cmdConfig = &Config{
		DriverName: args[0],
		OutFolder:  viper.GetString("output"),
		PkgName:    viper.GetString("pkgname"),
	}

	// BUG: https://github.com/spf13/viper/issues/200
	// Look up the value of TableNames directly from PFlags in Cobra if we
	// detect a malformed value coming out of viper.
	// Once the bug is fixed we'll be able to move this into the init above
	cmdConfig.TableNames = viper.GetStringSlice("tables")
	if len(cmdConfig.TableNames) == 1 && strings.HasPrefix(cmdConfig.TableNames[0], "[") {
		cmdConfig.TableNames, err = cmd.PersistentFlags().GetStringSlice("tables")
		if err != nil {
			return err
		}
	}

	if len(cmdConfig.DriverName) == 0 {
		return errors.New("Must supply a driver flag.")
	}
	if len(cmdConfig.OutFolder) == 0 {
		return fmt.Errorf("No output folder specified.")
	}

	if viper.IsSet("postgres.dbname") {
		cmdConfig.Postgres = PostgresConfig{
			User:   viper.GetString("postgres.user"),
			Pass:   viper.GetString("postgres.pass"),
			Host:   viper.GetString("postgres.host"),
			Port:   viper.GetInt("postgres.port"),
			DBName: viper.GetString("postgres.dbname"),
		}
	}

	cmdState, err = New(cmdConfig)
	return err
}

func run(cmd *cobra.Command, args []string) error {
	return cmdState.Run(true)
}

func postRun(cmd *cobra.Command, args []string) error {
	return cmdState.Cleanup()
}
<commit_msg>Correct main help output<commit_after>// Package main defines a command line interface for the sqlboiler package
package main

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

	"github.com/pkg/errors"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var (
	cmdState  *State
	cmdConfig *Config
)

func main() {
	var err error

	viper.SetConfigName("sqlboiler")

	configHome := os.Getenv("XDG_CONFIG_HOME")
	homePath := os.Getenv("HOME")
	wd, err := os.Getwd()
	if err != nil {
		wd = "./"
	}

	configPaths := []string{wd}
	if len(configHome) > 0 {
		configPaths = append(configPaths, filepath.Join(configHome, "sqlboiler"))
	} else {
		configPaths = append(configPaths, filepath.Join(homePath, ".config/sqlboiler"))
	}

	for _, p := range configPaths {
		viper.AddConfigPath(p)
	}

	// Find and read config
	err = viper.ReadInConfig()

	// Set up the cobra root command
	var rootCmd = &cobra.Command{
		Use:   "sqlboiler [flags] <driver>",
		Short: "SQL Boiler generates boilerplate structs and statements",
		Long: "SQL Boiler generates boilerplate structs and statements from template files.\n" +
			`Complete documentation is available at http://github.com/nullbio/sqlboiler`,
		Example:  `sqlboiler -o models -p models postgres`,
		PreRunE:  preRun,
		RunE:     run,
		PostRunE: postRun,
	}

	// Set up the cobra root command flags
	rootCmd.PersistentFlags().StringSliceP("tables", "t", nil, "Tables to generate models for, all tables if empty")
	rootCmd.PersistentFlags().StringP("output", "o", "models", "The name of the folder to output to")
	rootCmd.PersistentFlags().StringP("pkgname", "p", "models", "The name you wish to assign to your generated package")

	viper.BindPFlags(rootCmd.PersistentFlags())

	if err := rootCmd.Execute(); err != nil {
		fmt.Printf("\n%+v\n", err)
		os.Exit(1)
	}
}

func preRun(cmd *cobra.Command, args []string) error {
	var err error

	if len(args) == 0 {
		return errors.New("must provide a driver name")
	}

	cmdConfig = &Config{
		DriverName: args[0],
		OutFolder:  viper.GetString("output"),
		PkgName:    viper.GetString("pkgname"),
	}

	// BUG: https://github.com/spf13/viper/issues/200
	// Look up the value of TableNames directly from PFlags in Cobra if we
	// detect a malformed value coming out of viper.
	// Once the bug is fixed we'll be able to move this into the init above
	cmdConfig.TableNames = viper.GetStringSlice("tables")
	if len(cmdConfig.TableNames) == 1 && strings.HasPrefix(cmdConfig.TableNames[0], "[") {
		cmdConfig.TableNames, err = cmd.PersistentFlags().GetStringSlice("tables")
		if err != nil {
			return err
		}
	}

	if len(cmdConfig.DriverName) == 0 {
		return errors.New("Must supply a driver flag.")
	}
	if len(cmdConfig.OutFolder) == 0 {
		return fmt.Errorf("No output folder specified.")
	}

	if viper.IsSet("postgres.dbname") {
		cmdConfig.Postgres = PostgresConfig{
			User:   viper.GetString("postgres.user"),
			Pass:   viper.GetString("postgres.pass"),
			Host:   viper.GetString("postgres.host"),
			Port:   viper.GetInt("postgres.port"),
			DBName: viper.GetString("postgres.dbname"),
		}
	}

	cmdState, err = New(cmdConfig)
	return err
}

func run(cmd *cobra.Command, args []string) error {
	return cmdState.Run(true)
}

func postRun(cmd *cobra.Command, args []string) error {
	return cmdState.Cleanup()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"net/http"
	"text/template"
	"time"
	mw "github.com/EthanG78/golang_chat/middleware"
	"github.com/EthanG78/golang_chat/lib"
	"golang.org/x/crypto/bcrypt"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
)

//Ethan Zaat is a cool dude;)

type User struct {
	Username 		string		`json:"username"`
	Pass     		[]byte		`json:"pass"`
}

var dbUsers = map[string]User{}

func home (c echo.Context) error{
	return c.String(http.StatusOK, "home")
}

func four_o_one (c echo.Context) error{
	return c.String(http.StatusUnauthorized, "Nice try buster, you are unauthorized!")
}

func sign_up (c echo.Context) error{
	var u User
	if c.Request().Method == http.MethodPost{
		un := c.Request().FormValue("username")
		p := c.Request().FormValue("password")

		//TODO: Make an individual way of handling when users do not insert anything into the fields..
		if un == "" {
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}
		if p == ""{
			time.Sleep(3000)
			RedirectError:= c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}
		pByte := []byte(p)
		finalP, err := bcrypt.GenerateFromPassword(pByte, 0)
		if err != nil{
			log.Fatalf("Error encrypting password: %v", err)
			//This is probably really bad, should find a better way to handle it lmao
		}

		u = User{un, finalP}

		dbUsers[un] = u
		RedirectError := c.Redirect(http.StatusFound, "/login")
		//Error checking for testing
		if RedirectError != nil{
			log.Printf("Error: %v", RedirectError)
		}

		//FOR DEBUGGING
		log.Println(dbUsers)

		return c.String(http.StatusOK, "you have successfully signed up!")

	}

	return c.String(http.StatusBadRequest, "You could not be signed up")

}

func login (c echo.Context) error{
	if c.Request().Method == http.MethodPost{
		un := c.Request().FormValue("username")
		p := c.Request().FormValue("password")

		if un == "" {
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}
		if p == "" {
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}

		u, ok := dbUsers[un]
		if !ok {
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}

		inputPass := []byte(p)
		userPass := u.Pass
		err := bcrypt.CompareHashAndPassword(userPass, inputPass)
		if err != nil{
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//This is in the case that they input the incorrect password
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}

		cookie := &http.Cookie{}
		cookie.Name = "session_id"
		cookie.Value = mw.CookieVal

		c.SetCookie(cookie)

		RedirectError := c.Redirect(http.StatusFound, "/chat")
		//Error checking for testing
		if RedirectError != nil{
			log.Printf("Error: %v", RedirectError)
		}

		return c.String(http.StatusOK, "You have successfully logged in!")

	}

	return c.String(http.StatusBadRequest, "You could not log in")
}

func homeHandler(tpl *template.Template) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		tpl.Execute(w, r)
	})
}

//////
//MAIN
//////
func main() {

	e := echo.New()

	e.File("/favicon.ico", "static/styling/favicon.ico")

	//TODO: Find a way to store cookies
	//TODO: Assign groups, use logger, auth, server info and such
	//TODO: How can I store users without using a DB?????
	//TODO: Maybe generate cookie during login? Then ask for it within the chat!
	//TODO: I also really need to re-style the web pages... They are garbage

	//TODO: COOKIES IN LOGIN!!!!!! (please don't forget this)

	//TODO: I also have to use echo's websockets... That's going to be brutal

	//TODO: Create admin group and page

	//GROUPS
	admin := e.Group("/admin")

	//MIDDLEWARE
	admin.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
		Format: `[${time_rfc3339}] ${status} ${method} ${host}${path} ${latency}` + "\n",
	}))

	admin.Use(middleware.BasicAuth(func (username, password string, c echo.Context) (bool, error) {
		//placeholders for now
		if username == mw.AdminLogin && password == mw.AdminPassword{
			return true, nil
		}

		return false, nil
	}))

	//ENDPOINTS
	e.GET("/", home)
	e.File("/", "static/home.html")
	e.GET("/401", four_o_one)
	e.File("/401", "static/forbidden.html")
	e.POST("/signup", sign_up)
	e.File("/signup", "static/signup.html")
	e.POST("/login", login)
	e.File("/login", "static/login.html")

	//CREATE SERVER
	e.Logger.Fatal(e.Start(":8080"))

	//OLD CODE
	flag.Parse()
	tpl := template.Must(template.ParseFiles("static/chat.html"))
	H := lib.NewHub()
	router := http.NewServeMux()
	router.Handle("/styling/", http.StripPrefix("/styling/", http.FileServer(http.Dir("styling/"))))
	router.Handle("/chat", homeHandler(tpl))
	router.Handle("/ws", lib.WsHandler{H: H})
}

//TODO Current build is beta v1.0, it was released on 1/29/2017
//This version is not user friendly, this will change:)
<commit_msg>Now generate user specific cookies<commit_after>package main

import (
	"flag"
	"log"
	"net/http"
	"text/template"
	"time"
	mw "github.com/EthanG78/golang_chat/middleware"
	"github.com/EthanG78/golang_chat/lib"
	"golang.org/x/crypto/bcrypt"
	"github.com/labstack/echo"
	"github.com/labstack/echo/middleware"
	"github.com/satori/go.uuid"
)

//Ethan Zaat is a cool dude;)

type User struct {
	Username 		string		`json:"username"`
	Pass     		[]byte		`json:"pass"`
	Cookie			string		`json:"cookie"`
}

var dbUsers = map[string]User{}

func home (c echo.Context) error{
	return c.String(http.StatusOK, "home")
}

func four_o_one (c echo.Context) error{
	return c.String(http.StatusUnauthorized, "Nice try buster, you are unauthorized!")
}

func sign_up (c echo.Context) error{
	cookie := &http.Cookie{}
	cookie.Name = "user_id"
	cookieID := uuid.NewV4()
	cookie.Value = cookieID.String()

	c.SetCookie(cookie)

	var u User
	if c.Request().Method == http.MethodPost{
		un := c.Request().FormValue("username")
		p := c.Request().FormValue("password")

		//TODO: Make an individual way of handling when users do not insert anything into the fields..
		if un == "" {
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}
		if p == ""{
			time.Sleep(3000)
			RedirectError:= c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}
		pByte := []byte(p)
		finalP, err := bcrypt.GenerateFromPassword(pByte, 0)
		if err != nil{
			log.Fatalf("Error encrypting password: %v", err)
			//This is probably really bad, should find a better way to handle it lmao
		}

		u = User{un, finalP, cookie.Value}

		dbUsers[un] = u
		RedirectError := c.Redirect(http.StatusFound, "/login")
		//Error checking for testing
		if RedirectError != nil{
			log.Printf("Error: %v", RedirectError)
		}

		//FOR DEBUGGING
		log.Println(dbUsers)

		return c.String(http.StatusOK, "you have successfully signed up!")

	}

	return c.String(http.StatusBadRequest, "You could not be signed up")

}

func login (c echo.Context) error{
	if c.Request().Method == http.MethodPost{
		un := c.Request().FormValue("username")
		p := c.Request().FormValue("password")

		if un == "" {
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}
		if p == "" {
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}

		u, ok := dbUsers[un]
		if !ok {
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}

		inputPass := []byte(p)
		userPass := u.Pass
		err := bcrypt.CompareHashAndPassword(userPass, inputPass)
		if err != nil{
			time.Sleep(3000)
			RedirectError := c.Redirect(http.StatusFound, "/401")
			//This is in the case that they input the incorrect password
			//Error checking for testing
			if RedirectError != nil{
				log.Printf("Error: %v", RedirectError)
			}
		}

		RedirectError := c.Redirect(http.StatusFound, "/chat")
		//Error checking for testing
		if RedirectError != nil{
			log.Printf("Error: %v", RedirectError)
		}

		log.Printf("SERVER: User %v has logged in\n", u.Username )
		return c.String(http.StatusOK, "You have successfully logged in!")

	}

	return c.String(http.StatusBadRequest, "You could not log in")
}

func homeHandler(tpl *template.Template) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		tpl.Execute(w, r)
	})
}

//////
//MAIN
//////
func main() {

	e := echo.New()

	e.File("/favicon.ico", "static/styling/favicon.ico")

	//TODO: Find a way to store cookies
	//TODO: Assign groups, use logger, auth, server info and such
	//TODO: How can I store users without using a DB?????
	//TODO: I also really need to re-style the web pages... They are garbage

	//TODO: ADD SESSION COOKIES, so no random dude can access chat without logging in

	//TODO: I also have to use echo's websockets... That's going to be brutal

	//TODO: Create admin group and page

	//GROUPS
	admin := e.Group("/admin")

	//MIDDLEWARE
	admin.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
		Format: `[${time_rfc3339}] ${status} ${method} ${host}${path} ${latency}` + "\n",
	}))

	admin.Use(middleware.BasicAuth(func (username, password string, c echo.Context) (bool, error) {
		//placeholders for now
		if username == mw.AdminLogin && password == mw.AdminPassword{
			return true, nil
		}

		return false, nil
	}))

	//ENDPOINTS
	e.GET("/", home)
	e.File("/", "static/home.html")
	e.GET("/401", four_o_one)
	e.File("/401", "static/forbidden.html")
	e.POST("/signup", sign_up)
	e.File("/signup", "static/signup.html")
	e.POST("/login", login)
	e.File("/login", "static/login.html")

	//CREATE SERVER
	e.Logger.Fatal(e.Start(":8080"))

	//OLD CODE
	flag.Parse()
	tpl := template.Must(template.ParseFiles("static/chat.html"))
	H := lib.NewHub()
	router := http.NewServeMux()
	router.Handle("/styling/", http.StripPrefix("/styling/", http.FileServer(http.Dir("styling/"))))
	router.Handle("/chat", homeHandler(tpl))
	router.Handle("/ws", lib.WsHandler{H: H})
}

//TODO Current build is beta v1.0, it was released on 1/29/2017
//This version is not user friendly, this will change:)
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/xackery/discordeq/applog"
	"github.com/xackery/discordeq/discord"
	"github.com/xackery/discordeq/listener"
	"github.com/xackery/eqemuconfig"
	"log"
	"os"
	"strings"
	"time"
)

func main() {
	applog.StartupInteractive()
	log.SetOutput(applog.DefaultOutput)
	startService()
}

func startService() {
	log.Println("Starting DiscordEQ v0.4")
	var option string
	//Load config
	config, err := eqemuconfig.GetConfig()
	if err != nil {
		applog.Error.Println("Error while loading eqemu_config.xml to start:", err.Error())
		fmt.Println("press a key then enter to exit.")

		fmt.Scan(&option)
		os.Exit(1)
	}
	if config.Discord.RefreshRate == 0 {
		config.Discord.RefreshRate = 10
	}
	if strings.ToLower(config.World.Tcp.Telnet) != "enabled" {
		log.Println("Telnet must be enabled for this tool to work. Check your eqemuconfig.xml, and please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}

	if config.Discord.Username == "" {
		applog.Error.Println("I don't see a username set in your <discord><username> section of eqemu_config.xml, please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}

	if config.Discord.Password == "" {
		applog.Error.Println("I don't see a password set in your <discord><password> section of eqemu_config.xml, please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}

	if config.Discord.ServerID == "" {
		applog.Error.Println("I don't see a serverid set in your <discord><serverid> section of eqemuconfig.xml, please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}

	if config.Discord.ChannelID == "" {
		applog.Error.Println("I don't see a channelid set in your <discord><channelid> section of eqemuconfig.xml, please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}
	disco := discord.Discord{}
	err = disco.Connect(config.Discord.Username, config.Discord.Password)
	if err != nil {
		applog.Error.Println("Error connecting to discord:", err.Error())
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}
	go listenToDiscord(config, &disco)
	go listenToOOC(config, &disco)
	select {}
}

func listenToDiscord(config *eqemuconfig.Config, disco *discord.Discord) (err error) {
	for {
		applog.Info.Println("[Discord] Connecting as", config.Discord.Username, "...")
		if err = listener.ListenToDiscord(config, disco); err != nil {
			applog.Error.Println("[Discord] Disconnected with error:", err.Error())
		}

		applog.Info.Println("[Discord] Reconnecting in 5 seconds...")
		time.Sleep(5 * time.Second)
		err = disco.Connect(config.Discord.Username, config.Discord.Password)
		if err != nil {
			applog.Error.Println("[Discord] Error connecting to discord:", err.Error())
		}
	}
}

func listenToOOC(config *eqemuconfig.Config, disco *discord.Discord) (err error) {
	for {
		applog.Info.Println("[OOC] Connecting to ", config.Database.Host, "...")
		listener.ListenToOOC(config, disco)
		applog.Info.Println("[OOC] Reconnecting in 5 seconds...")
		time.Sleep(5 * time.Second)
	}
}
<commit_msg>fixed OOC echo to go to telnet ip instead of database<commit_after>package main

import (
	"fmt"
	"github.com/xackery/discordeq/applog"
	"github.com/xackery/discordeq/discord"
	"github.com/xackery/discordeq/listener"
	"github.com/xackery/eqemuconfig"
	"log"
	"os"
	"strings"
	"time"
)

func main() {
	applog.StartupInteractive()
	log.SetOutput(applog.DefaultOutput)
	startService()
}

func startService() {
	log.Println("Starting DiscordEQ v0.4")
	var option string
	//Load config
	config, err := eqemuconfig.GetConfig()
	if err != nil {
		applog.Error.Println("Error while loading eqemu_config.xml to start:", err.Error())
		fmt.Println("press a key then enter to exit.")

		fmt.Scan(&option)
		os.Exit(1)
	}
	if config.Discord.RefreshRate == 0 {
		config.Discord.RefreshRate = 10
	}
	if strings.ToLower(config.World.Tcp.Telnet) != "enabled" {
		log.Println("Telnet must be enabled for this tool to work. Check your eqemuconfig.xml, and please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}

	if config.Discord.Username == "" {
		applog.Error.Println("I don't see a username set in your <discord><username> section of eqemu_config.xml, please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}

	if config.Discord.Password == "" {
		applog.Error.Println("I don't see a password set in your <discord><password> section of eqemu_config.xml, please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}

	if config.Discord.ServerID == "" {
		applog.Error.Println("I don't see a serverid set in your <discord><serverid> section of eqemuconfig.xml, please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}

	if config.Discord.ChannelID == "" {
		applog.Error.Println("I don't see a channelid set in your <discord><channelid> section of eqemuconfig.xml, please adjust.")
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}
	disco := discord.Discord{}
	err = disco.Connect(config.Discord.Username, config.Discord.Password)
	if err != nil {
		applog.Error.Println("Error connecting to discord:", err.Error())
		fmt.Println("press a key then enter to exit.")
		fmt.Scan(&option)
		os.Exit(1)
	}
	go listenToDiscord(config, &disco)
	go listenToOOC(config, &disco)
	select {}
}

func listenToDiscord(config *eqemuconfig.Config, disco *discord.Discord) (err error) {
	for {
		applog.Info.Println("[Discord] Connecting as", config.Discord.Username, "...")
		if err = listener.ListenToDiscord(config, disco); err != nil {
			applog.Error.Println("[Discord] Disconnected with error:", err.Error())
		}

		applog.Info.Println("[Discord] Reconnecting in 5 seconds...")
		time.Sleep(5 * time.Second)
		err = disco.Connect(config.Discord.Username, config.Discord.Password)
		if err != nil {
			applog.Error.Println("[Discord] Error connecting to discord:", err.Error())
		}
	}
}

func listenToOOC(config *eqemuconfig.Config, disco *discord.Discord) (err error) {
	for {
		applog.Info.Println("[OOC] Connecting to ", config.World.Tcp.Ip, "...")
		listener.ListenToOOC(config, disco)
		applog.Info.Println("[OOC] Reconnecting in 5 seconds...")
		time.Sleep(5 * time.Second)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"runtime"
	"strings"

    "github.com/daaku/go.httpgzip"
)

var templates = template.Must(template.New("").Funcs(template.FuncMap{"add": func(a, b int) int { return a + b }}).ParseGlob("./views/*.tmpl"))

type Config struct {
	DBConn   string
	CertFile string
	KeyFile  string
}

func getFiles(folder, fileType string) []string {
	files, err := ioutil.ReadDir(folder)
	if err != nil {
		panic(err)
	}
	var templateList []string
	for _, file := range files {
		if strings.HasSuffix(file.Name(), fileType) {
			templateList = append(templateList, folder+file.Name())
		}
	}
	return templateList
}

type Keyboards struct {
	Keyboards map[string]string
}

func keyboardHandler(w http.ResponseWriter, r *http.Request) {
	keyboards := getFiles("./static/keyboards/", ".jpg")
	matchedBoards := Keyboards{make(map[string]string)}
	for _, keyboard := range keyboards {
		dir, file := path.Split(keyboard)
		matchedBoards.Keyboards[path.Join("/", dir, file)] = path.Join("/", dir, "thumbs", file)
	}
	if err := templates.ExecuteTemplate(w, "keyboards.tmpl", matchedBoards); err != nil {
		log.Println(err)
	}
}

func serveStatic(filename string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Cache-Control", "max-age=31536000")
		http.ServeFile(w, r, filename)
	}
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Cache-Control", "max-age=120")

		ForwardedFor := r.Header.Get("X-Forwarded-For")
		if ForwardedFor == "" {
			log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL)
		} else {
			log.Printf("%s %s %s", ForwardedFor, r.Method, r.URL)
		}
		handler.ServeHTTP(w, r)
	})
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	configfile, err := os.Open("config.json")
	if err != nil {
		log.Fatal(err)
	}
	var config Config
	err = json.NewDecoder(configfile).Decode(&config)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Starting sadbox.org")

	geekhack, err := NewGeekhack(config)
	if err != nil {
		log.Fatal(err)
	}
	defer geekhack.db.Close()

	// These files have to be here
	http.HandleFunc("/favicon.ico", serveStatic("./static/favicon.ico"))
	http.HandleFunc("/sitemap.xml", serveStatic("./static/sitemap.xml"))
	http.HandleFunc("/robots.txt", serveStatic("./static/robots.txt"))
	http.HandleFunc("/humans.txt", serveStatic("./static/humans.txt"))
	http.HandleFunc("/static/jquery.min.js", serveStatic("./vendor/jquery.min.js"))
	http.HandleFunc("/static/highcharts.js", serveStatic("./vendor/highcharts.js"))
	http.HandleFunc("/static/bootstrap.min.css", serveStatic("./vendor/bootstrap.min.css"))
	http.HandleFunc("/mu-fea81392-5746180a-5e50de1d-fb4a7b05.txt", serveStatic("./static/blitz.txt"))

	// The plain-jane stuff I serve up
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			return
		}

		if err := templates.ExecuteTemplate(w, "main.tmpl", nil); err != nil {
			log.Println(err)
		}
	})
	http.HandleFunc("/keyboards", keyboardHandler)

	// Geekhack stats! the geekhack struct will handle the routing to sub-things
	http.Handle("/geekhack/", geekhack)
	// Redirects to the right URL so I don't break old links
	http.Handle("/ghstats", http.RedirectHandler("/geekhack/", http.StatusMovedPermanently))
	http.Handle("/geekhack", http.RedirectHandler("/geekhack/", http.StatusMovedPermanently))

	// The rest of the static files
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))

	http.Handle("/znc", http.RedirectHandler("https://sadbox.org:6697", http.StatusMovedPermanently))

	go func() { log.Fatal(http.ListenAndServe(":http", Log(http.DefaultServeMux))) }()

	log.Fatal(http.ListenAndServeTLS(":https", config.CertFile,
		config.KeyFile, httpgzip.NewHandler(Log(http.DefaultServeMux))))
}
<commit_msg>use openssl again, maybe fixed<commit_after>package main

import (
	"encoding/json"
	"html/template"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"path"
	"runtime"
	"strings"

	"github.com/daaku/go.httpgzip"
	"github.com/sadbox/openssl"
)

var templates = template.Must(template.New("").Funcs(template.FuncMap{"add": func(a, b int) int { return a + b }}).ParseGlob("./views/*.tmpl"))

type Config struct {
	DBConn   string
	CertFile string
	KeyFile  string
}

func getFiles(folder, fileType string) []string {
	files, err := ioutil.ReadDir(folder)
	if err != nil {
		panic(err)
	}
	var templateList []string
	for _, file := range files {
		if strings.HasSuffix(file.Name(), fileType) {
			templateList = append(templateList, folder+file.Name())
		}
	}
	return templateList
}

type Keyboards struct {
	Keyboards map[string]string
}

func keyboardHandler(w http.ResponseWriter, r *http.Request) {
	keyboards := getFiles("./static/keyboards/", ".jpg")
	matchedBoards := Keyboards{make(map[string]string)}
	for _, keyboard := range keyboards {
		dir, file := path.Split(keyboard)
		matchedBoards.Keyboards[path.Join("/", dir, file)] = path.Join("/", dir, "thumbs", file)
	}
	if err := templates.ExecuteTemplate(w, "keyboards.tmpl", matchedBoards); err != nil {
		log.Println(err)
	}
}

func serveStatic(filename string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Cache-Control", "max-age=31536000")
		http.ServeFile(w, r, filename)
	}
}

func Log(handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Cache-Control", "max-age=120")

		ForwardedFor := r.Header.Get("X-Forwarded-For")
		if ForwardedFor == "" {
			log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL)
		} else {
			log.Printf("%s %s %s", ForwardedFor, r.Method, r.URL)
		}
		handler.ServeHTTP(w, r)
	})
}

func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	configfile, err := os.Open("config.json")
	if err != nil {
		log.Fatal(err)
	}
	var config Config
	err = json.NewDecoder(configfile).Decode(&config)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Starting sadbox.org")

	geekhack, err := NewGeekhack(config)
	if err != nil {
		log.Fatal(err)
	}
	defer geekhack.db.Close()

	// These files have to be here
	http.HandleFunc("/favicon.ico", serveStatic("./static/favicon.ico"))
	http.HandleFunc("/sitemap.xml", serveStatic("./static/sitemap.xml"))
	http.HandleFunc("/robots.txt", serveStatic("./static/robots.txt"))
	http.HandleFunc("/humans.txt", serveStatic("./static/humans.txt"))
	http.HandleFunc("/static/jquery.min.js", serveStatic("./vendor/jquery.min.js"))
	http.HandleFunc("/static/highcharts.js", serveStatic("./vendor/highcharts.js"))
	http.HandleFunc("/static/bootstrap.min.css", serveStatic("./vendor/bootstrap.min.css"))
	http.HandleFunc("/mu-fea81392-5746180a-5e50de1d-fb4a7b05.txt", serveStatic("./static/blitz.txt"))

	// The plain-jane stuff I serve up
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			return
		}

		if err := templates.ExecuteTemplate(w, "main.tmpl", nil); err != nil {
			log.Println(err)
		}
	})
	http.HandleFunc("/keyboards", keyboardHandler)

	// Geekhack stats! the geekhack struct will handle the routing to sub-things
	http.Handle("/geekhack/", geekhack)
	// Redirects to the right URL so I don't break old links
	http.Handle("/ghstats", http.RedirectHandler("/geekhack/", http.StatusMovedPermanently))
	http.Handle("/geekhack", http.RedirectHandler("/geekhack/", http.StatusMovedPermanently))

	// The rest of the static files
	http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("./static/"))))

	http.Handle("/znc", http.RedirectHandler("https://sadbox.org:6697", http.StatusMovedPermanently))

	go func() { log.Fatal(http.ListenAndServe(":http", Log(http.DefaultServeMux))) }()

	log.Fatal(openssl.ListenAndServeTLS(":https", config.CertFile,
		config.KeyFile, httpgzip.NewHandler(Log(http.DefaultServeMux))))
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
	"strings"

	. "github.com/candid82/joker/core"
	_ "github.com/candid82/joker/std/base64"
	_ "github.com/candid82/joker/std/html"
	_ "github.com/candid82/joker/std/http"
	_ "github.com/candid82/joker/std/json"
	_ "github.com/candid82/joker/std/math"
	_ "github.com/candid82/joker/std/os"
	_ "github.com/candid82/joker/std/string"
	_ "github.com/candid82/joker/std/time"
	_ "github.com/candid82/joker/std/url"
	_ "github.com/candid82/joker/std/yaml"
	"github.com/chzyer/readline"
)

type (
	ReplContext struct {
		first  *Var
		second *Var
		third  *Var
		exc    *Var
	}
)

func NewReplContext(env *Env) *ReplContext {
	first, _ := env.Resolve(MakeSymbol("joker.core/*1"))
	second, _ := env.Resolve(MakeSymbol("joker.core/*2"))
	third, _ := env.Resolve(MakeSymbol("joker.core/*3"))
	exc, _ := env.Resolve(MakeSymbol("joker.core/*e"))
	first.Value = NIL
	second.Value = NIL
	third.Value = NIL
	exc.Value = NIL
	return &ReplContext{
		first:  first,
		second: second,
		third:  third,
		exc:    exc,
	}
}

func (ctx *ReplContext) PushValue(obj Object) {
	ctx.third.Value = ctx.second.Value
	ctx.second.Value = ctx.first.Value
	ctx.first.Value = obj
}

func (ctx *ReplContext) PushException(exc Object) {
	ctx.exc.Value = exc
}

func processFile(filename string, phase Phase) error {
	var reader *Reader
	if filename == "-" || filename == "--" {
		reader = NewReader(bufio.NewReader(os.Stdin), "<stdin>")
		filename = ""
	} else {
		var err error
		reader, err = NewReaderFromFile(filename)
		if err != nil {
			return err
		}
	}
	return ProcessReader(reader, filename, phase)
}

func skipRestOfLine(reader *Reader) {
	for {
		switch reader.Get() {
		case EOF, '\n':
			return
		}
	}
}

func processReplCommand(reader *Reader, phase Phase, parseContext *ParseContext, replContext *ReplContext) (exit bool) {

	defer func() {
		if r := recover(); r != nil {
			switch r := r.(type) {
			case *ParseError:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			case *EvalError:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			case Error:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			// case *runtime.TypeAssertionError:
			// 	fmt.Fprintln(os.Stderr, r)
			default:
				panic(r)
			}
		}
	}()

	obj, err := TryRead(reader)
	if err == io.EOF {
		return true
	}
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		skipRestOfLine(reader)
		return
	}

	if phase == READ {
		fmt.Println(obj.ToString(true))
		return false
	}

	expr := Parse(obj, parseContext)
	if phase == PARSE {
		fmt.Println(expr)
		return false
	}

	res := Eval(expr, nil)
	replContext.PushValue(res)
	fmt.Println(res.ToString(true))
	return false
}

func repl(phase Phase) {
	fmt.Printf("Welcome to joker %s. Use ctrl-c to exit.\n", VERSION)
	parseContext := &ParseContext{GlobalEnv: GLOBAL_ENV}
	replContext := NewReplContext(parseContext.GlobalEnv)

	rl, err := readline.New("")
	if err != nil {
		fmt.Println("Error: " + err.Error())
	}
	defer rl.Close()

	reader := NewReader(NewLineRuneReader(rl), "<repl>")

	for {
		rl.SetPrompt(GLOBAL_ENV.CurrentNamespace().Name.ToString(false) + "=> ")
		if processReplCommand(reader, phase, parseContext, replContext) {
			return
		}
	}
}

func makeDialectKeyword(dialect Dialect) Keyword {
	switch dialect {
	case EDN:
		return MakeKeyword("clj")
	case CLJ:
		return MakeKeyword("clj")
	case CLJS:
		return MakeKeyword("cljs")
	default:
		return MakeKeyword("joker ")
	}
}

func configureLinterMode(dialect Dialect, filename string, workingDir string) {
	ProcessLinterFiles(dialect, filename, workingDir)
	LINTER_MODE = true
	DIALECT = dialect
	lm, _ := GLOBAL_ENV.Resolve(MakeSymbol("joker.core/*linter-mode*"))
	lm.Value = Bool{B: true}
	GLOBAL_ENV.Features = GLOBAL_ENV.Features.Disjoin(MakeKeyword("joker")).Conj(makeDialectKeyword(dialect)).(Set)
	ProcessLinterData(dialect)
}

func detectDialect(filename string) Dialect {
	switch {
	case strings.HasSuffix(filename, ".edn"):
		return EDN
	case strings.HasSuffix(filename, ".cljs"):
		return CLJS
	case strings.HasSuffix(filename, ".joke"):
		return JOKER
	}
	return CLJ
}

func lintFile(filename string, dialect Dialect, workingDir string) {
	phase := PARSE
	if dialect == EDN {
		phase = READ
	}
	ReadConfig(filename, workingDir)
	configureLinterMode(dialect, filename, workingDir)
	if processFile(filename, phase) == nil {
		WarnOnUnusedNamespaces()
		WarnOnUnusedVars()
	}
}

func dialectFromArg(arg string) Dialect {
	switch strings.ToLower(arg) {
	case "clj":
		return CLJ
	case "cljs":
		return CLJS
	case "joker":
		return JOKER
	case "edn":
		return EDN
	}
	return UNKNOWN
}

func main() {
	GLOBAL_ENV.FindNamespace(MakeSymbol("user")).ReferAll(GLOBAL_ENV.CoreNamespace)
	if len(os.Args) == 1 {
		repl(EVAL)
		return
	}
	if len(os.Args) == 2 {
		if os.Args[1] == "-v" || os.Args[1] == "--version" {
			println(VERSION)
			return
		}
		processFile(os.Args[1], EVAL)
		return
	}
	workingDir := ""
	phase := EVAL
	lint := false
	dialect := UNKNOWN
	expr := ""
	length := len(os.Args) - 1
	for i := 1; i < length; i++ {
		switch os.Args[i] {
		case "--read":
			phase = READ
		case "--parse":
			phase = PARSE
		case "--working-dir":
			if i < length-1 {
				workingDir = os.Args[i+1]
			}
		case "--lint":
			lint = true
		case "--lintclj":
			lint = true
			dialect = CLJ
		case "--lintcljs":
			lint = true
			dialect = CLJS
		case "--lintjoker":
			lint = true
			dialect = JOKER
		case "--lintedn":
			lint = true
			dialect = EDN
		case "--dialect":
			if i < length-1 {
				dialect = dialectFromArg(os.Args[i+1])
			}
		case "-e":
			if i < length {
				expr = os.Args[i+1]
			}
		case "--hashmap-threshold":
			if i < length {
				i, err := strconv.Atoi(os.Args[i+1])
				if err != nil {
					fmt.Fprintln(os.Stderr, "Error: ", err)
					return
				}
				if i < 0 {
					HASHMAP_THRESHOLD = math.MaxInt64
				} else {
					HASHMAP_THRESHOLD = i
				}
			}
		}
	}
	filename := os.Args[length]
	if lint {
		if dialect == UNKNOWN {
			dialect = detectDialect(filename)
		}
		lintFile(filename, dialect, workingDir)
		if PROBLEM_COUNT > 0 {
			os.Exit(1)
		}
		return
	}
	if phase == EVAL {
		if expr == "" {
			// First argument is a filename, subsequent arguments are script arguments.
			processFile(os.Args[1], phase)
		} else {
			reader := NewReader(strings.NewReader(expr), "<expr>")
			ProcessReader(reader, "", phase)
		}
	} else {
		processFile(filename, phase)
	}
}
<commit_msg>Warn if '--' is used for a filename<commit_after>package main

import (
	"bufio"
	"fmt"
	"io"
	"math"
	"os"
	"strconv"
	"strings"

	. "github.com/candid82/joker/core"
	_ "github.com/candid82/joker/std/base64"
	_ "github.com/candid82/joker/std/html"
	_ "github.com/candid82/joker/std/http"
	_ "github.com/candid82/joker/std/json"
	_ "github.com/candid82/joker/std/math"
	_ "github.com/candid82/joker/std/os"
	_ "github.com/candid82/joker/std/string"
	_ "github.com/candid82/joker/std/time"
	_ "github.com/candid82/joker/std/url"
	_ "github.com/candid82/joker/std/yaml"
	"github.com/chzyer/readline"
)

type (
	ReplContext struct {
		first  *Var
		second *Var
		third  *Var
		exc    *Var
	}
)

func NewReplContext(env *Env) *ReplContext {
	first, _ := env.Resolve(MakeSymbol("joker.core/*1"))
	second, _ := env.Resolve(MakeSymbol("joker.core/*2"))
	third, _ := env.Resolve(MakeSymbol("joker.core/*3"))
	exc, _ := env.Resolve(MakeSymbol("joker.core/*e"))
	first.Value = NIL
	second.Value = NIL
	third.Value = NIL
	exc.Value = NIL
	return &ReplContext{
		first:  first,
		second: second,
		third:  third,
		exc:    exc,
	}
}

func (ctx *ReplContext) PushValue(obj Object) {
	ctx.third.Value = ctx.second.Value
	ctx.second.Value = ctx.first.Value
	ctx.first.Value = obj
}

func (ctx *ReplContext) PushException(exc Object) {
	ctx.exc.Value = exc
}

func processFile(filename string, phase Phase) error {
	var reader *Reader
	if filename == "-" || filename == "--" {
		if filename == "--" {
			fmt.Fprintln(os.Stderr, "Warning: '--' indicating standard input (stdin) to Joker is deprecated; please use '-' instead");
		}
		reader = NewReader(bufio.NewReader(os.Stdin), "<stdin>")
		filename = ""
	} else {
		var err error
		reader, err = NewReaderFromFile(filename)
		if err != nil {
			return err
		}
	}
	return ProcessReader(reader, filename, phase)
}

func skipRestOfLine(reader *Reader) {
	for {
		switch reader.Get() {
		case EOF, '\n':
			return
		}
	}
}

func processReplCommand(reader *Reader, phase Phase, parseContext *ParseContext, replContext *ReplContext) (exit bool) {

	defer func() {
		if r := recover(); r != nil {
			switch r := r.(type) {
			case *ParseError:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			case *EvalError:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			case Error:
				replContext.PushException(r)
				fmt.Fprintln(os.Stderr, r)
			// case *runtime.TypeAssertionError:
			// 	fmt.Fprintln(os.Stderr, r)
			default:
				panic(r)
			}
		}
	}()

	obj, err := TryRead(reader)
	if err == io.EOF {
		return true
	}
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		skipRestOfLine(reader)
		return
	}

	if phase == READ {
		fmt.Println(obj.ToString(true))
		return false
	}

	expr := Parse(obj, parseContext)
	if phase == PARSE {
		fmt.Println(expr)
		return false
	}

	res := Eval(expr, nil)
	replContext.PushValue(res)
	fmt.Println(res.ToString(true))
	return false
}

func repl(phase Phase) {
	fmt.Printf("Welcome to joker %s. Use ctrl-c to exit.\n", VERSION)
	parseContext := &ParseContext{GlobalEnv: GLOBAL_ENV}
	replContext := NewReplContext(parseContext.GlobalEnv)

	rl, err := readline.New("")
	if err != nil {
		fmt.Println("Error: " + err.Error())
	}
	defer rl.Close()

	reader := NewReader(NewLineRuneReader(rl), "<repl>")

	for {
		rl.SetPrompt(GLOBAL_ENV.CurrentNamespace().Name.ToString(false) + "=> ")
		if processReplCommand(reader, phase, parseContext, replContext) {
			return
		}
	}
}

func makeDialectKeyword(dialect Dialect) Keyword {
	switch dialect {
	case EDN:
		return MakeKeyword("clj")
	case CLJ:
		return MakeKeyword("clj")
	case CLJS:
		return MakeKeyword("cljs")
	default:
		return MakeKeyword("joker ")
	}
}

func configureLinterMode(dialect Dialect, filename string, workingDir string) {
	ProcessLinterFiles(dialect, filename, workingDir)
	LINTER_MODE = true
	DIALECT = dialect
	lm, _ := GLOBAL_ENV.Resolve(MakeSymbol("joker.core/*linter-mode*"))
	lm.Value = Bool{B: true}
	GLOBAL_ENV.Features = GLOBAL_ENV.Features.Disjoin(MakeKeyword("joker")).Conj(makeDialectKeyword(dialect)).(Set)
	ProcessLinterData(dialect)
}

func detectDialect(filename string) Dialect {
	switch {
	case strings.HasSuffix(filename, ".edn"):
		return EDN
	case strings.HasSuffix(filename, ".cljs"):
		return CLJS
	case strings.HasSuffix(filename, ".joke"):
		return JOKER
	}
	return CLJ
}

func lintFile(filename string, dialect Dialect, workingDir string) {
	phase := PARSE
	if dialect == EDN {
		phase = READ
	}
	ReadConfig(filename, workingDir)
	configureLinterMode(dialect, filename, workingDir)
	if processFile(filename, phase) == nil {
		WarnOnUnusedNamespaces()
		WarnOnUnusedVars()
	}
}

func dialectFromArg(arg string) Dialect {
	switch strings.ToLower(arg) {
	case "clj":
		return CLJ
	case "cljs":
		return CLJS
	case "joker":
		return JOKER
	case "edn":
		return EDN
	}
	return UNKNOWN
}

func main() {
	GLOBAL_ENV.FindNamespace(MakeSymbol("user")).ReferAll(GLOBAL_ENV.CoreNamespace)
	if len(os.Args) == 1 {
		repl(EVAL)
		return
	}
	if len(os.Args) == 2 {
		if os.Args[1] == "-v" || os.Args[1] == "--version" {
			println(VERSION)
			return
		}
		processFile(os.Args[1], EVAL)
		return
	}
	workingDir := ""
	phase := EVAL
	lint := false
	dialect := UNKNOWN
	expr := ""
	length := len(os.Args) - 1
	for i := 1; i < length; i++ {
		switch os.Args[i] {
		case "--read":
			phase = READ
		case "--parse":
			phase = PARSE
		case "--working-dir":
			if i < length-1 {
				workingDir = os.Args[i+1]
			}
		case "--lint":
			lint = true
		case "--lintclj":
			lint = true
			dialect = CLJ
		case "--lintcljs":
			lint = true
			dialect = CLJS
		case "--lintjoker":
			lint = true
			dialect = JOKER
		case "--lintedn":
			lint = true
			dialect = EDN
		case "--dialect":
			if i < length-1 {
				dialect = dialectFromArg(os.Args[i+1])
			}
		case "-e":
			if i < length {
				expr = os.Args[i+1]
			}
		case "--hashmap-threshold":
			if i < length {
				i, err := strconv.Atoi(os.Args[i+1])
				if err != nil {
					fmt.Fprintln(os.Stderr, "Error: ", err)
					return
				}
				if i < 0 {
					HASHMAP_THRESHOLD = math.MaxInt64
				} else {
					HASHMAP_THRESHOLD = i
				}
			}
		}
	}
	filename := os.Args[length]
	if lint {
		if dialect == UNKNOWN {
			dialect = detectDialect(filename)
		}
		lintFile(filename, dialect, workingDir)
		if PROBLEM_COUNT > 0 {
			os.Exit(1)
		}
		return
	}
	if phase == EVAL {
		if expr == "" {
			// First argument is a filename, subsequent arguments are script arguments.
			processFile(os.Args[1], phase)
		} else {
			reader := NewReader(strings.NewReader(expr), "<expr>")
			ProcessReader(reader, "", phase)
		}
	} else {
		processFile(filename, phase)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/md5"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"sort"

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

const CacheDir = "/cache"

type Cache struct {
	Mount []string `json:"mount"`
}

func main() {
	workspace := plugin.Workspace{}
	repo := plugin.Repo{}
	build := plugin.Build{}
	job := plugin.Job{}
	vargs := Cache{}

	plugin.Param("workspace", &workspace)
	plugin.Param("repo", &repo)
	plugin.Param("build", &build)
	plugin.Param("job", &job)
	plugin.Param("vargs", &vargs)
	plugin.MustParse()

	// mount paths are relative to the workspace.
	// if the workspace doesn't exist, create it
	os.MkdirAll(workspace.Path, 0755)
	os.Chdir(workspace.Path)

	// if the job is running we should restore
	// the cache
	if isRunning(&job) {

		for _, mount := range vargs.Mount {
			// unique hash for the file
			hash_ := hash(mount, build.Branch, job.Environment)
			fmt.Println("Restoring cache", mount)

			// restore
			err := restore(hash_, mount)
			if err != nil {
				fmt.Printf("Unable to restore %s. %s\n", mount, err)
			}

			// restore from repository default branch if possible
			if err != nil && build.Branch != repo.Branch {

				// recalulate the hash using the default branch
				hash_ = hash(mount, repo.Branch, job.Environment)
				fmt.Printf("Attempting to restore from %s branch\n", repo.Branch)

				err = restore(hash_, mount) // second time is the charm
				if err != nil {
					fmt.Printf("Unable to restore %s from %s branch.\n", mount, repo.Branch)
				}
			}
		}
	}

	// if the job is complete and is NOT a pull
	// request we should re-build the cache.
	if isSuccess(&job) && build.Event == plugin.EventPush {

		for _, mount := range vargs.Mount {
			// unique hash for the file
			hash_ := hash(mount, build.Branch, job.Environment)
			fmt.Println("Building cache", mount)

			// rebuild
			err := rebuild(hash_, mount)
			if err != nil {
				fmt.Printf("Unable to rebuild cache for %s. %s\n", mount, err)
			}
			// purges previously cached files
			purge(hash_)
		}
	}
}

func restore(hash, dir string) error {
	tar := fmt.Sprintf("%s/cache.%s.tar.gz", CacheDir, hash)
	_, err := os.Stat(tar)
	if err != nil {
		return fmt.Errorf("Cache does not exist")
	}

	cmd := exec.Command("tar", "-xzf", tar, "-C", "/")
	return cmd.Run()
}

// rebuild will rebuild the cache
func rebuild(hash, dir string) (err error) {
	dir = filepath.Clean(dir)
	dir, err = filepath.Abs(dir)
	if err != nil {
		return err
	}
	_, err = os.Stat(dir)
	if err != nil {
		return fmt.Errorf("File or directory %s does not exist", dir)
	}

	out := fmt.Sprintf("%s/cache.%s.tar.gz", CacheDir, hash)
	cmd := exec.Command("tar", "-czf", out, dir)
	return cmd.Run()
}

// purge will purge stale data in the cache
// to avoid a large buildup that could waste
// disk space on the host machine.
func purge(hash string) error {
	files, err := list(hash)
	if err != nil {
		return err
	}

	// we should only keep the latest
	// file in the cache
	for i := 1; i < len(files); i++ {
		err = os.Remove(files[i])
		if err != nil {
			return err
		}
	}
	return nil
}

func hash(mount, branch string, matrix map[string]string) string {
	parts := []string{mount, branch}

	// concatinate all matrix values
	// with the branch
	for val := range matrix {
		parts = append(parts, val)
	}

	// sort the strings to ensure ordering
	// is maintained prior to hashing
	sort.Strings(parts)

	// calculate the hash using the branch
	// and matrix combined.
	h := md5.New()
	for _, part := range parts {
		io.WriteString(h, part)
	}
	return fmt.Sprintf("%x", h.Sum(nil))
}

// list returns a list of items in the cache.
func list(hash string) ([]string, error) {
	glob := fmt.Sprintf("%s/cache.%s.tar.gz", CacheDir, hash)
	tars, err := filepath.Glob(glob)
	if err != nil {
		return tars, err
	}
	sort.Strings(tars) // sort by date instead?
	return tars, err
}

func isRunning(job *plugin.Job) bool {
	return job.Status == plugin.StatePending ||
		job.Status == plugin.StateRunning
}

func isSuccess(job *plugin.Job) bool {
	return job.Status == plugin.StateSuccess
}
<commit_msg>adjust wording when restoring from default branch<commit_after>package main

import (
	"crypto/md5"
	"fmt"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"sort"

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

const CacheDir = "/cache"

type Cache struct {
	Mount []string `json:"mount"`
}

func main() {
	workspace := plugin.Workspace{}
	repo := plugin.Repo{}
	build := plugin.Build{}
	job := plugin.Job{}
	vargs := Cache{}

	plugin.Param("workspace", &workspace)
	plugin.Param("repo", &repo)
	plugin.Param("build", &build)
	plugin.Param("job", &job)
	plugin.Param("vargs", &vargs)
	plugin.MustParse()

	// mount paths are relative to the workspace.
	// if the workspace doesn't exist, create it
	os.MkdirAll(workspace.Path, 0755)
	os.Chdir(workspace.Path)

	// if the job is running we should restore
	// the cache
	if isRunning(&job) {

		for _, mount := range vargs.Mount {
			// unique hash for the file
			hash_ := hash(mount, build.Branch, job.Environment)
			fmt.Println("Restoring cache", mount)

			// restore
			err := restore(hash_, mount)
			if err != nil {
				fmt.Printf("Unable to restore %s. %s\n", mount, err)
			}

			// restore from repository default branch if possible
			if err != nil && build.Branch != repo.Branch {

				// recalulate the hash using the default branch
				hash_ = hash(mount, repo.Branch, job.Environment)
				fmt.Printf("Restoring cache from %s branch\n", repo.Branch)

				err = restore(hash_, mount) // second time is the charm
				if err != nil {
					fmt.Printf("Unable to restore %s from %s branch.\n", mount, repo.Branch)
				}
			}
		}
	}

	// if the job is complete and is NOT a pull
	// request we should re-build the cache.
	if isSuccess(&job) && build.Event == plugin.EventPush {

		for _, mount := range vargs.Mount {
			// unique hash for the file
			hash_ := hash(mount, build.Branch, job.Environment)
			fmt.Println("Building cache", mount)

			// rebuild
			err := rebuild(hash_, mount)
			if err != nil {
				fmt.Printf("Unable to rebuild cache for %s. %s\n", mount, err)
			}
			// purges previously cached files
			purge(hash_)
		}
	}
}

func restore(hash, dir string) error {
	tar := fmt.Sprintf("%s/cache.%s.tar.gz", CacheDir, hash)
	_, err := os.Stat(tar)
	if err != nil {
		return fmt.Errorf("Cache does not exist")
	}

	cmd := exec.Command("tar", "-xzf", tar, "-C", "/")
	return cmd.Run()
}

// rebuild will rebuild the cache
func rebuild(hash, dir string) (err error) {
	dir = filepath.Clean(dir)
	dir, err = filepath.Abs(dir)
	if err != nil {
		return err
	}
	_, err = os.Stat(dir)
	if err != nil {
		return fmt.Errorf("File or directory %s does not exist", dir)
	}

	out := fmt.Sprintf("%s/cache.%s.tar.gz", CacheDir, hash)
	cmd := exec.Command("tar", "-czf", out, dir)
	return cmd.Run()
}

// purge will purge stale data in the cache
// to avoid a large buildup that could waste
// disk space on the host machine.
func purge(hash string) error {
	files, err := list(hash)
	if err != nil {
		return err
	}

	// we should only keep the latest
	// file in the cache
	for i := 1; i < len(files); i++ {
		err = os.Remove(files[i])
		if err != nil {
			return err
		}
	}
	return nil
}

func hash(mount, branch string, matrix map[string]string) string {
	parts := []string{mount, branch}

	// concatinate all matrix values
	// with the branch
	for val := range matrix {
		parts = append(parts, val)
	}

	// sort the strings to ensure ordering
	// is maintained prior to hashing
	sort.Strings(parts)

	// calculate the hash using the branch
	// and matrix combined.
	h := md5.New()
	for _, part := range parts {
		io.WriteString(h, part)
	}
	return fmt.Sprintf("%x", h.Sum(nil))
}

// list returns a list of items in the cache.
func list(hash string) ([]string, error) {
	glob := fmt.Sprintf("%s/cache.%s.tar.gz", CacheDir, hash)
	tars, err := filepath.Glob(glob)
	if err != nil {
		return tars, err
	}
	sort.Strings(tars) // sort by date instead?
	return tars, err
}

func isRunning(job *plugin.Job) bool {
	return job.Status == plugin.StatePending ||
		job.Status == plugin.StateRunning
}

func isSuccess(job *plugin.Job) bool {
	return job.Status == plugin.StateSuccess
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/glycerine/zygomys/repl"
	"os"
)

func usage(myflags *flag.FlagSet) {
	fmt.Printf("zygo command line help:\n")
	myflags.PrintDefaults()
	os.Exit(1)
}

func main() {
	cfg := zygo.NewGlispConfig("zygo")
	cfg.DefineFlags()
	err := cfg.Flags.Parse(os.Args[1:])
	if err == flag.ErrHelp {
		usage(cfg.Flags)
	}

	if err != nil {
		panic(err)
	}
	err = cfg.ValidateConfig()
	if err != nil {
		fmt.Fprintf(os.Stderr, "zygo command line error: '%v'\n", err)
		usage(cfg.Flags)
	}

	registerExts := func(env *zygo.Glisp) {
		// this mechanism not used at the moment, but the
		// syntax would be: zygoext.ImportRandom(env)
	}
	//cfg.ExtensionsVersion = zygoext.Version()
	zygo.ReplMain(cfg, registerExts)
}
<commit_msg>v1.1.7 zygomys<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/glycerine/zygomys/repl"
	"os"
)

func usage(myflags *flag.FlagSet) {
	fmt.Printf("zygo command line help:\n")
	myflags.PrintDefaults()
	os.Exit(1)
}

func main() {
	cfg := zygo.NewGlispConfig("zygo")
	cfg.DefineFlags()
	err := cfg.Flags.Parse(os.Args[1:])
	if err == flag.ErrHelp {
		usage(cfg.Flags)
	}

	if err != nil {
		panic(err)
	}
	err = cfg.ValidateConfig()
	if err != nil {
		fmt.Fprintf(os.Stderr, "zygo command line error: '%v'\n", err)
		usage(cfg.Flags)
	}

	// the library does all the heavy lifting.
	zygo.ReplMain(cfg, registerExts)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"os"
)

func shortUsage() {
	os.Stderr.WriteString(`
Usage: alita [OPTION]... [FILE]...
Try 'alita --help' for more information.
`[1:])
}

func longUsage() {
	os.Stderr.WriteString(`
Usage: alita [OPTION]... [FILE]...
Align FILE(s), or standard input.

Delimiter control:
  -c, --count=COUNT        delimit line COUNT times
  -r, --regexp             DELIM is a regular expression
  -d, --delimiter=DELIM    delimit line by DELIM

Output control:
  -m, --margin=FORMAT      join cells by FORMAT
  -j, --justfy=SEQUENCE    justfy cells by SEQUENCE

Miscellaneous:
  -h, --help               show this help message
      --version            print the version
`[1:])
}

func version() {
	os.Stderr.WriteString(`
v0.6.0
`[1:])
}

func do(a *Aligner, r io.Reader) error {
	if err := a.ReadAll(r); err != nil {
		return err
	}
	return a.Flush()
}

func _main() int {
	a := NewAligner(os.Stdout)
	flag.IntVar(&a.Delimiter.Count, "c", -1, "")
	flag.IntVar(&a.Delimiter.Count, "count", -1, "")
	flag.BoolVar(&a.Delimiter.UseRegexp, "r", false, "")
	flag.BoolVar(&a.Delimiter.UseRegexp, "regexp", false, "")
	flag.Var(a.Delimiter, "d", "")
	flag.Var(a.Delimiter, "delimiter", "")
	flag.Var(a.Margin, "m", "")
	flag.Var(a.Margin, "margin", "")
	flag.Var(a.Padding, "j", "")
	flag.Var(a.Padding, "justfy", "")

	var isHelp, isVersion bool
	flag.BoolVar(&isHelp, "h", false, "")
	flag.BoolVar(&isHelp, "help", false, "")
	flag.BoolVar(&isVersion, "version", false, "")
	flag.Usage = shortUsage
	flag.Parse()
	switch {
	case isHelp:
		longUsage()
		return 0
	case isVersion:
		version()
		return 0
	}

	if flag.NArg() < 1 {
		if err := do(a, os.Stdin); err != nil {
			fmt.Fprintln(os.Stderr, "alita:", err)
			return 1
		}
		return 0
	}

	var input []io.Reader
	for _, fname := range flag.Args() {
		f, err := os.Open(fname)
		if err != nil {
			fmt.Fprintln(os.Stderr, "alita:", err)
			return 1
		}
		defer f.Close()
		input = append(input, f)
	}
	if err := do(a, io.MultiReader(input...)); err != nil {
		fmt.Fprintln(os.Stderr, "alita:", err)
		return 1
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<commit_msg>Summarize routine for error output<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"os"
)

func shortUsage() {
	os.Stderr.WriteString(`
Usage: alita [OPTION]... [FILE]...
Try 'alita --help' for more information.
`[1:])
}

func longUsage() {
	os.Stderr.WriteString(`
Usage: alita [OPTION]... [FILE]...
Align FILE(s), or standard input.

Delimiter control:
  -c, --count=COUNT        delimit line COUNT times
  -r, --regexp             DELIM is a regular expression
  -d, --delimiter=DELIM    delimit line by DELIM

Output control:
  -m, --margin=FORMAT      join cells by FORMAT
  -j, --justfy=SEQUENCE    justfy cells by SEQUENCE

Miscellaneous:
  -h, --help               show this help message
      --version            print the version
`[1:])
}

func version() {
	os.Stderr.WriteString(`
v0.6.0
`[1:])
}

func printErr(err error) {
	fmt.Fprintln(os.Stderr, "alita:", err)
}

func do(a *Aligner, r io.Reader) error {
	if err := a.ReadAll(r); err != nil {
		return err
	}
	return a.Flush()
}

func _main() int {
	a := NewAligner(os.Stdout)
	flag.IntVar(&a.Delimiter.Count, "c", -1, "")
	flag.IntVar(&a.Delimiter.Count, "count", -1, "")
	flag.BoolVar(&a.Delimiter.UseRegexp, "r", false, "")
	flag.BoolVar(&a.Delimiter.UseRegexp, "regexp", false, "")
	flag.Var(a.Delimiter, "d", "")
	flag.Var(a.Delimiter, "delimiter", "")
	flag.Var(a.Margin, "m", "")
	flag.Var(a.Margin, "margin", "")
	flag.Var(a.Padding, "j", "")
	flag.Var(a.Padding, "justfy", "")

	var isHelp, isVersion bool
	flag.BoolVar(&isHelp, "h", false, "")
	flag.BoolVar(&isHelp, "help", false, "")
	flag.BoolVar(&isVersion, "version", false, "")
	flag.Usage = shortUsage
	flag.Parse()
	switch {
	case isHelp:
		longUsage()
		return 0
	case isVersion:
		version()
		return 0
	}

	if flag.NArg() < 1 {
		if err := do(a, os.Stdin); err != nil {
			printErr(err)
			return 1
		}
		return 0
	}

	var input []io.Reader
	for _, fname := range flag.Args() {
		f, err := os.Open(fname)
		if err != nil {
			printErr(err)
			return 1
		}
		defer f.Close()
		input = append(input, f)
	}
	if err := do(a, io.MultiReader(input...)); err != nil {
		printErr(err)
		return 1
	}
	return 0
}

func main() {
	e := _main()
	os.Exit(e)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/go-martini/martini"
	"github.com/wmbest2/rats_server/rats"
	"github.com/wmbest2/rats_server/test"
	"io"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"time"
)

func uuid() (string, error) {
	uuid := make([]byte, 16)
	n, err := rand.Read(uuid)
	if n != len(uuid) || err != nil {
		return "", err
	}
	// TODO: verify the two lines implement RFC 4122 correctly
	uuid[8] = 0x80 // variant bits see page 5
	uuid[4] = 0x40 // version 4 Pseudo Random, see page 7

	return hex.EncodeToString(uuid), nil
}

func Mongo(db string) martini.Handler {
	session, err := mgo.Dial(db)
	if err != nil {
		panic(err)
	}

	return func(c martini.Context) {
		reqSession := session.Clone()
		c.Map(reqSession.DB("rats"))
		defer reqSession.Close()

		c.Next()
	}
}

func RunTests(w http.ResponseWriter, r *http.Request, db *mgo.Database) (int, []byte) {
    //file, err := os.Create("memprof")
    //if err != nil { log.Fatal(err) }

	uuid, err := uuid()
	if err != nil {
		panic(err)
	}

	dir := fmt.Sprintf("test_runs/%s", uuid)
	os.MkdirAll(dir, os.ModeDir|os.ModePerm|os.ModeTemporary)

	apk, _, _ := r.FormFile("apk")
	if apk != nil {
		defer apk.Close()
		f := fmt.Sprintf("%s/main.apk", dir)
		apk_file, err := os.Create(f)

		if err != nil {
			panic(err)
		}

		_, err = io.Copy(apk_file, apk)
        apk.Close()
		apk_file.Close()

		if err != nil {
			panic(err)
		}

		rats.Install(f)
	}

	test_apk, _, err := r.FormFile("test-apk")

	if err != nil {
		panic("A Test Apk must be supplied")
	}

	f := fmt.Sprintf("%s/test.apk", dir)
	test_apk_file, err := os.Create(f)

	if err != nil {
		panic(err)
	}

	_, err = io.Copy(test_apk_file, test_apk)
	test_apk.Close()
	test_apk_file.Close()

	if err != nil {
		panic(err)
	}
	rats.Install(f)
	manifest := rats.GetManifest(f)

    for _,device := range <-rats.GetDevices() {
        device.SetScreenOn(true)
        device.Unlock()
    }

	s := test.RunTests(manifest)

	s.Name = uuid
	s.Timestamp = time.Now()
	s.Project = manifest.Instrument.Target

	if dbErr := db.C("runs").Insert(&s); dbErr != nil {
		return http.StatusConflict, []byte(dbErr.Error())
	}

	rats.Uninstall(manifest.Package)
	rats.Uninstall(manifest.Instrument.Target)
	os.RemoveAll(dir)

	str, err := json.Marshal(s)
	if err != nil {
		panic(err)
	}

    //pprof.WriteHeapProfile(file)
    //file.Close()
	return http.StatusOK, str
}

func GetRunDevice(r *http.Request, parms martini.Params, db *mgo.Database) (int, string) {
	var runs test.TestSuites
    q := bson.M{"name": parms["id"]}
    fmt.Printf("%#v\n", q)
    query := db.C("runs").Find(q).Limit(1)
	query.One(&runs)
    for _, run := range runs.TestSuites {
        if run.Hostname == parms["device"] {
            b, _ := json.Marshal(run)
            return http.StatusOK, string(b)
        }
    }
    return http.StatusNotFound, fmt.Sprintf("Run on Device %s Not Found", parms["device"])
}

func GetRun(r *http.Request, parms martini.Params, db *mgo.Database) (int, string) {
	var runs test.TestSuites
    query := db.C("runs").Find(bson.M{"name": parms["id"]}).Limit(1)
	query.One(&runs)
	b, _ := json.Marshal(runs)
	return http.StatusOK, string(b)
}

func GetRuns(r *http.Request, parms martini.Params, db *mgo.Database) (int, string) {
	page := 0
	p := r.URL.Query().Get("page")
	if p != "" {
		page, _ = strconv.Atoi(p)
	}

	size := 25
	s := r.URL.Query().Get("count")
	if s != "" {
		size, _ = strconv.Atoi(s)
	}

	var runs []*test.TestSuites
	query := db.C("runs").Find(bson.M{}).Limit(size).Skip(page * size)
	//query.Select(bson.M{"name": 1, "project": 1, "timestamp": 1, "time": 1, "success": 1})
	query.Sort("-timestamp")
	query.All(&runs)
	b, _ := json.Marshal(runs)
	return http.StatusOK, string(b)
}

func GetDevices(parms martini.Params) (int, string) {
	b, _ := json.Marshal(<-rats.GetDevices())
	return http.StatusOK, string(b)
}

func serveStatic(m *martini.Martini) {
	_, file, _, _ := runtime.Caller(0)
	here := filepath.Dir(file)
	static := filepath.Join(here, "/public")
	m.Use(martini.Static(string(static)))
}

func main() {
	go rats.UpdateAdb(5)

	m := martini.New()
	m.Use(martini.Recovery())
	m.Use(martini.Logger())
	m.Use(Mongo("localhost/rats"))
	serveStatic(m)
	r := martini.NewRouter()
	r.Get(`/api/devices`, GetDevices)
	r.Post("/api/run", RunTests)
	r.Get("/api/runs", GetRuns)
    r.Get("/api/runs/:id", GetRun)
    r.Get("/api/runs/:id/:device", GetRunDevice)

	m.Action(r.Handle)
	m.Run()
}
<commit_msg>Go Fmt<commit_after>package main

import (
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/go-martini/martini"
	"github.com/wmbest2/rats_server/rats"
	"github.com/wmbest2/rats_server/test"
	"io"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strconv"
	"time"
)

func uuid() (string, error) {
	uuid := make([]byte, 16)
	n, err := rand.Read(uuid)
	if n != len(uuid) || err != nil {
		return "", err
	}
	// TODO: verify the two lines implement RFC 4122 correctly
	uuid[8] = 0x80 // variant bits see page 5
	uuid[4] = 0x40 // version 4 Pseudo Random, see page 7

	return hex.EncodeToString(uuid), nil
}

func Mongo(db string) martini.Handler {
	session, err := mgo.Dial(db)
	if err != nil {
		panic(err)
	}

	return func(c martini.Context) {
		reqSession := session.Clone()
		c.Map(reqSession.DB("rats"))
		defer reqSession.Close()

		c.Next()
	}
}

func RunTests(w http.ResponseWriter, r *http.Request, db *mgo.Database) (int, []byte) {
	//file, err := os.Create("memprof")
	//if err != nil { log.Fatal(err) }

	uuid, err := uuid()
	if err != nil {
		panic(err)
	}

	dir := fmt.Sprintf("test_runs/%s", uuid)
	os.MkdirAll(dir, os.ModeDir|os.ModePerm|os.ModeTemporary)

	apk, _, _ := r.FormFile("apk")
	if apk != nil {
		defer apk.Close()
		f := fmt.Sprintf("%s/main.apk", dir)
		apk_file, err := os.Create(f)

		if err != nil {
			panic(err)
		}

		_, err = io.Copy(apk_file, apk)
		apk.Close()
		apk_file.Close()

		if err != nil {
			panic(err)
		}

		rats.Install(f)
	}

	test_apk, _, err := r.FormFile("test-apk")

	if err != nil {
		panic("A Test Apk must be supplied")
	}

	f := fmt.Sprintf("%s/test.apk", dir)
	test_apk_file, err := os.Create(f)

	if err != nil {
		panic(err)
	}

	_, err = io.Copy(test_apk_file, test_apk)
	test_apk.Close()
	test_apk_file.Close()

	if err != nil {
		panic(err)
	}
	rats.Install(f)
	manifest := rats.GetManifest(f)

	for _, device := range <-rats.GetDevices() {
		device.SetScreenOn(true)
		device.Unlock()
	}

	s := test.RunTests(manifest)

	s.Name = uuid
	s.Timestamp = time.Now()
	s.Project = manifest.Instrument.Target

	if dbErr := db.C("runs").Insert(&s); dbErr != nil {
		return http.StatusConflict, []byte(dbErr.Error())
	}

	rats.Uninstall(manifest.Package)
	rats.Uninstall(manifest.Instrument.Target)
	os.RemoveAll(dir)

	str, err := json.Marshal(s)
	if err != nil {
		panic(err)
	}

	//pprof.WriteHeapProfile(file)
	//file.Close()
	return http.StatusOK, str
}

func GetRunDevice(r *http.Request, parms martini.Params, db *mgo.Database) (int, string) {
	var runs test.TestSuites
	q := bson.M{"name": parms["id"]}
	fmt.Printf("%#v\n", q)
	query := db.C("runs").Find(q).Limit(1)
	query.One(&runs)
	for _, run := range runs.TestSuites {
		if run.Hostname == parms["device"] {
			b, _ := json.Marshal(run)
			return http.StatusOK, string(b)
		}
	}
	return http.StatusNotFound, fmt.Sprintf("Run on Device %s Not Found", parms["device"])
}

func GetRun(r *http.Request, parms martini.Params, db *mgo.Database) (int, string) {
	var runs test.TestSuites
	query := db.C("runs").Find(bson.M{"name": parms["id"]}).Limit(1)
	query.One(&runs)
	b, _ := json.Marshal(runs)
	return http.StatusOK, string(b)
}

func GetRuns(r *http.Request, parms martini.Params, db *mgo.Database) (int, string) {
	page := 0
	p := r.URL.Query().Get("page")
	if p != "" {
		page, _ = strconv.Atoi(p)
	}

	size := 25
	s := r.URL.Query().Get("count")
	if s != "" {
		size, _ = strconv.Atoi(s)
	}

	var runs []*test.TestSuites
	query := db.C("runs").Find(bson.M{}).Limit(size).Skip(page * size)
	//query.Select(bson.M{"name": 1, "project": 1, "timestamp": 1, "time": 1, "success": 1})
	query.Sort("-timestamp")
	query.All(&runs)
	b, _ := json.Marshal(runs)
	return http.StatusOK, string(b)
}

func GetDevices(parms martini.Params) (int, string) {
	b, _ := json.Marshal(<-rats.GetDevices())
	return http.StatusOK, string(b)
}

func serveStatic(m *martini.Martini) {
	_, file, _, _ := runtime.Caller(0)
	here := filepath.Dir(file)
	static := filepath.Join(here, "/public")
	m.Use(martini.Static(string(static)))
}

func main() {
	go rats.UpdateAdb(5)

	m := martini.New()
	m.Use(martini.Recovery())
	m.Use(martini.Logger())
	m.Use(Mongo("localhost/rats"))
	serveStatic(m)
	r := martini.NewRouter()
	r.Get(`/api/devices`, GetDevices)
	r.Post("/api/run", RunTests)
	r.Get("/api/runs", GetRuns)
	r.Get("/api/runs/:id", GetRun)
	r.Get("/api/runs/:id/:device", GetRunDevice)

	m.Action(r.Handle)
	m.Run()
}
<|endoftext|>


<commit_before>package main

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

	"github.com/bosh-ops/bosh-install/aws-cli"
	"github.com/bosh-ops/bosh-install/azure-cli"
	"github.com/bosh-ops/bosh-install/plugin/registry"
	"github.com/codegangsta/cli"
	"github.com/xchapter7x/lo"
)

var Version string
var CloudConfigPluginsDir = "./.plugins/cloudconfig"
var ProductPluginsDir = "./.plugins/product"
var cloudConfigCommands []cli.Command
var productCommands []cli.Command
var productList []string
var cloudconfigList []string

func main() {
	app := cli.NewApp()
	app.Version = Version
	app.Commands = []cli.Command{
		{
			Name:   "azure",
			Usage:  "azure [--flags] - deploy a bosh to azure",
			Action: azurecli.GetAction(BoshInitDeploy),
			Flags:  azurecli.GetFlags(),
		},
		{
			Name:   "aws",
			Usage:  "aws [--flags] - deploy a bosh to aws",
			Action: awscli.GetAction(BoshInitDeploy),
			Flags:  awscli.GetFlags(),
		},
		{
			Name: "list-cloudconfigs",
			Action: func(c *cli.Context) error {
				fmt.Println("Cloud Configs:")
				for _, plgn := range registry.ListCloudConfigs() {
					fmt.Println(plgn.Name, " - ", plgn.Path, " - ", plgn.Properties)
				}
				return nil
			},
		},
		{
			Name: "list-products",
			Action: func(c *cli.Context) error {
				fmt.Println("Products:")
				return nil
			},
		},
		{
			Name:        "deploy-cloudconfig",
			Usage:       "deploy-cloudconfig <cloudconfig-name> [--flags] - deploy a cloudconfig to bosh",
			Flags:       getBoshAuthFlags(),
			Subcommands: cloudConfigCommands,
		},
		{
			Name:        "deploy-product",
			Usage:       "deploy-product <prod-name> [--flags] - deploy a product via bosh",
			Flags:       getBoshAuthFlags(),
			Subcommands: productCommands,
		},
	}
	app.Run(os.Args)
}

func init() {

	if strings.ToLower(os.Getenv("LOG_LEVEL")) != "debug" {
		log.SetOutput(ioutil.Discard)
	}
	registerCloudConfig()
}

func registerCloudConfig() {
	files, _ := ioutil.ReadDir(CloudConfigPluginsDir)
	for _, f := range files {
		lo.G.Debug("registering: ", f.Name())
		pluginPath := path.Join(CloudConfigPluginsDir, f.Name())
		flags, _ := registry.RegisterCloudConfig(pluginPath)

		cloudConfigCommands = append(cloudConfigCommands, cli.Command{
			Name:  f.Name(),
			Usage: "deploy the " + f.Name() + " cloud config",
			Flags: flags,
			Action: func(c *cli.Context) error {
				client, cc := registry.GetCloudConfigReference(pluginPath)
				defer client.Kill()
				manifest := cc.GetCloudConfig(c)
				fmt.Println("TODO: do something with my manifest here", manifest)
				return nil
			},
		})
	}
	lo.G.Debug("registered cloud configs: ", registry.ListCloudConfigs())
}

func getBoshAuthFlags() []cli.Flag {
	return []cli.Flag{
		cli.StringFlag{Name: "bosh-url", Value: "https://mybosh.com", Usage: "this is the url or ip of your bosh director"},
		cli.StringFlag{Name: "bosh-user", Value: "bosh", Usage: "this is the username for your bosh director"},
		cli.StringFlag{Name: "bosh-pass", Value: "", Usage: "this is the pasword for your bosh director"},
	}
}
<commit_msg>[#119868047] adding print manifest flag for immediate value add<commit_after>package main

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

	"github.com/bosh-ops/bosh-install/aws-cli"
	"github.com/bosh-ops/bosh-install/azure-cli"
	"github.com/bosh-ops/bosh-install/plugin/registry"
	"github.com/codegangsta/cli"
	"github.com/xchapter7x/enaml"
	"github.com/xchapter7x/lo"
)

var Version string
var CloudConfigPluginsDir = "./.plugins/cloudconfig"
var ProductPluginsDir = "./.plugins/product"
var cloudConfigCommands []cli.Command
var productCommands []cli.Command
var productList []string
var cloudconfigList []string

func main() {
	app := cli.NewApp()
	app.Version = Version
	app.Commands = []cli.Command{
		{
			Name:   "azure",
			Usage:  "azure [--flags] - deploy a bosh to azure",
			Action: azurecli.GetAction(BoshInitDeploy),
			Flags:  azurecli.GetFlags(),
		},
		{
			Name:   "aws",
			Usage:  "aws [--flags] - deploy a bosh to aws",
			Action: awscli.GetAction(BoshInitDeploy),
			Flags:  awscli.GetFlags(),
		},
		{
			Name: "list-cloudconfigs",
			Action: func(c *cli.Context) error {
				fmt.Println("Cloud Configs:")
				for _, plgn := range registry.ListCloudConfigs() {
					fmt.Println(plgn.Name, " - ", plgn.Path, " - ", plgn.Properties)
				}
				return nil
			},
		},
		{
			Name: "list-products",
			Action: func(c *cli.Context) error {
				fmt.Println("Products:")
				return nil
			},
		},
		{
			Name:        "deploy-cloudconfig",
			Usage:       "deploy-cloudconfig <cloudconfig-name> [--flags] - deploy a cloudconfig to bosh",
			Flags:       getBoshAuthFlags(),
			Subcommands: cloudConfigCommands,
		},
		{
			Name:        "deploy-product",
			Usage:       "deploy-product <prod-name> [--flags] - deploy a product via bosh",
			Flags:       getBoshAuthFlags(),
			Subcommands: productCommands,
		},
	}
	app.Run(os.Args)
}

func init() {

	if strings.ToLower(os.Getenv("LOG_LEVEL")) != "debug" {
		log.SetOutput(ioutil.Discard)
	}
	registerCloudConfig()
}

func registerCloudConfig() {
	files, _ := ioutil.ReadDir(CloudConfigPluginsDir)
	for _, f := range files {
		lo.G.Debug("registering: ", f.Name())
		pluginPath := path.Join(CloudConfigPluginsDir, f.Name())
		flags, _ := registry.RegisterCloudConfig(pluginPath)

		cloudConfigCommands = append(cloudConfigCommands, cli.Command{
			Name:  f.Name(),
			Usage: "deploy the " + f.Name() + " cloud config",
			Flags: flags,
			Action: func(c *cli.Context) error {
				client, cc := registry.GetCloudConfigReference(pluginPath)
				defer client.Kill()
				manifest := cc.GetCloudConfig(c)
				processManifest(c, manifest)
				return nil
			},
		})
	}
	lo.G.Debug("registered cloud configs: ", registry.ListCloudConfigs())
}

func getBoshAuthFlags() []cli.Flag {
	return []cli.Flag{
		cli.StringFlag{Name: "bosh-url", Value: "https://mybosh.com", Usage: "this is the url or ip of your bosh director"},
		cli.StringFlag{Name: "bosh-user", Value: "bosh", Usage: "this is the username for your bosh director"},
		cli.StringFlag{Name: "bosh-pass", Value: "", Usage: "this is the pasword for your bosh director"},
		cli.BoolFlag{Name: "print-manifest", Usage: "if you would simply like to output a manifest the set this flag as true."},
	}
}

func processManifest(c *cli.Context, manifest enaml.CloudConfigManifest) (e error) {
	if yamlString, err := enaml.Cloud(&manifest); err == nil {

		if c.Bool("print-manifest") {
			fmt.Println(yamlString)

		} else {
			fmt.Println("TODO: do something with my manifest here", manifest)
		}
	} else {
		e = err
	}
	return
}
<|endoftext|>