<commit_before>package unpuzzled

import (
	"fmt"
	"html/template"
	"os"

	"reflect"

	"github.com/fatih/color"
	"github.com/olekukonko/tablewriter"
	log "github.com/sirupsen/logrus"
)

type App struct {
	Name            string
	Usage           string
	LongDescription string
	Copyright       string
	ParsingOrder    []ParsingType
	Command         *Command
	Authors         []Author
	HelpCommands    map[string]bool
	Action          func()
	ConfigFlag      string
	RemoveColor     bool
	args            []string
	activeCommands  []*Command
}

type ParsingType int

const (
	EnvironmentVariables ParsingType = iota
	JsonConfig
	TomlConfig
	CliFlags
)

var ParingTypeStringMap = map[ParsingType]string{
	EnvironmentVariables: "Environment",
	JsonConfig:           "JSON Config",
	TomlConfig:           "Toml Config",
	CliFlags:             "CLI Flag",
}

// Create a new application with default values set.
func NewApp() *App {
	return &App{
		Name:    "cli",
		Authors: make([]Author, 0),
		HelpCommands: map[string]bool{
			"--help": true,
			"-h":     true,
			"help":   true,
		},
		ParsingOrder: []ParsingType{
			EnvironmentVariables,
			JsonConfig,
			TomlConfig,
			CliFlags,
		},
	}
}

// Run the app. Should be called with:
// app := cli.NewApp()
// app.Run(os.Args)
func (a *App) Run(args []string) {
	if len(args) < 1 {
		log.Fatal("Arguments must be at least 1, please run with app.Run(os.Args).")
	}
	a.args = args[1:]
	a.parseCommands()

	finalCommand := a.activeCommands[len(a.activeCommands)-1]
	if finalCommand.Action != nil {
		finalCommand.Action()
	}
}

func (a *App) parseCommands() {
	if a.Command == nil {
		log.Fatal("No command attached to the app!")
	}
	a.Command.buildTree(nil)
	a.Command.assignArguments(a.args)

	if helpCommand, isHelp := a.Command.isHelpCommand(a.HelpCommands); isHelp {
		fmt.Println("help.", helpCommand.Name)
		return
	}

	if err := a.Command.parseFlags(); err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("error parsing flags.")
		return
	}

	a.activeCommands = a.Command.GetActiveCommands()
	a.Command.findConfigVars()
	a.Command.parseConfigVars()
	settingsMap := a.parseByOrder()
	a.applySettingsMap(settingsMap)
}

func (a *App) parseByOrder() *mappedSettings {
	settingsMap := newMappedSettings()

	for _, order := range a.ParsingOrder {
		switch order {
		case EnvironmentVariables:
			settingsMap.addParsedArray(a.Command.parseEnvVars())

		case JsonConfig:
			vars := a.Command.getConfigVarsByType(JsonConfig)
			if len(vars) == 0 {
				continue
			}
			setValues := a.Command.parseConfigValues(vars)
			settingsMap.addParsedArray(setValues)

		case TomlConfig:
			vars := a.Command.getConfigVarsByType(TomlConfig)
			if len(vars) == 0 {
				continue
			}
			setValues := a.Command.parseConfigValues(vars)
			settingsMap.addParsedArray(setValues)

		case CliFlags:
			settingsMap.addParsedArray(a.Command.getSetFlags())
		}
	}
	settingsMap.PrintDuplicates(a.activeCommands)
	settingsMap.PrintDuplicatesStdout(a.RemoveColor)
	return settingsMap
}

func (a *App) applySettingsMap(settingsMap *mappedSettings) {
	commandMap := a.Command.GetExpandedActiveCommmands()
	// loop through commands, ensure that the order of settings are constantly applied,
	// instead of looping through MainMap, which is not a consistent order.
	for _, command := range a.activeCommands {
		path := command.GetExpandedName()
		variableSettingsMap := settingsMap.MainMap[path]
		currCommand := commandMap[path]
		variableMap := currCommand.GetVariableMap()

		for _, setting := range variableSettingsMap {
			activeSetting := setting[len(setting)-1]
			currVariable := variableMap[activeSetting.VariableName]
			if _, ok := currVariable.(*ConfigVariable); ok {
				continue
			}
			currVariable.apply(activeSetting.Value)
		}
	}
}

type mappedSettings struct {
	MainMap map[string]map[string][]activeSetting `json:"main_map"`
}

func newMappedSettings() *mappedSettings {
	return &mappedSettings{
		MainMap: make(map[string]map[string][]activeSetting),
	}
}

func (m *mappedSettings) addParsedArray(settings []activeSetting) {
	for _, setting := range settings {
		if m.MainMap[setting.CommandPath] == nil {
			m.MainMap[setting.CommandPath] = make(map[string][]activeSetting)
		}
		if m.MainMap[setting.CommandPath][setting.VariableName] == nil {
			m.MainMap[setting.CommandPath][setting.VariableName] = make([]activeSetting, 0)
		}
		m.MainMap[setting.CommandPath][setting.VariableName] = append(m.MainMap[setting.CommandPath][setting.VariableName], setting)
	}
}

// Helper to print duplciates in table format to Stdout.
func (m *mappedSettings) PrintDuplicates(commands []*Command) {
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Command", "Variable", "Source", "Value", "Type", "Status"})
	for _, command := range commands {
		expandedName := command.GetExpandedName()
		if m.MainMap[expandedName] == nil {
			continue
		}
		for _, settings := range m.MainMap[expandedName] {
			length := len(settings)
			for i, setting := range settings {
				var status string
				if i == length-1 {
					status = "✔ Used"
				} else {
					status = "x Ignored"
				}
				row := []string{
					expandedName,
					setting.VariableName,
					ParingTypeStringMap[setting.Source],
					fmt.Sprintf("%s", setting.Value),
					reflect.TypeOf(setting.Value).String(),
					status,
				}
				if setting.Source == EnvironmentVariables {
					row[1] += " (" + convertNameToOS(setting.VariableName) + ")"
				}
				table.Append(row)
			}
		}
	}
	table.Render()
}

// Use a custom formatted string to print duplicates on Stdout.
func (m *mappedSettings) PrintDuplicatesStdout(noColor bool) {
	t := template.New("duplicates")
	funcMap := template.FuncMap{
		"blue":  color.BlueString,
		"red":   color.RedString,
		"green": color.GreenString,
		"bold":  color.New(color.Bold).Sprint,
		"sourceString": func(setting activeSetting) string {
			if setting.Source == EnvironmentVariables {
				return fmt.Sprintf("%s (%s)", ParingTypeStringMap[setting.Source], convertNameToOS(setting.VariableName))
			} else if setting.Source == TomlConfig || setting.Source == JsonConfig {
				return fmt.Sprintf("%s (%s)", ParingTypeStringMap[setting.Source], setting.SettingName)
			} else {
				return ParingTypeStringMap[setting.Source]
			}
		},
		"plus1": func(x int) int {
			return x + 1
		},
	}
	if noColor {
		funcMap["blue"] = identityString
		funcMap["red"] = identityString
		funcMap["green"] = identityString
		funcMap["bold"] = identityString
	}
	t.Funcs(funcMap)
	t.Parse(`{{ range $command, $variables := . -}}
-------------------------------------
{{ blue "Configuration:"}} {{ bold $command }}
{{ range $key, $vars := $variables -}}
-------------
{{ range $k, $var := $vars }}{{ $length := len $vars -}}
	{{ if eq $length (plus1 $k) -}}
		{{ green $key }} = {{ green $var.Value }}
	{{ green "set from" }} {{ sourceString $var -}}
	{{ else -}}
		{{ red $key }} = {{ red $var.Value }}
	{{ red "ignored from" }} {{ sourceString $var -}}
	{{ end }}
{{ end -}}
{{ end }}
{{ end }}`)
	t.Execute(os.Stdout, m.MainMap)
}

func identityString(s string) string {
	return s
}
<commit_msg>exit if no parsing order, move printing out of parseByOrder<commit_after>package unpuzzled

import (
	"fmt"
	"html/template"
	"os"

	"reflect"

	"github.com/fatih/color"
	"github.com/olekukonko/tablewriter"
	log "github.com/sirupsen/logrus"
)

type App struct {
	Name            string
	Usage           string
	LongDescription string
	Copyright       string
	ParsingOrder    []ParsingType
	Command         *Command
	Authors         []Author
	HelpCommands    map[string]bool
	Action          func()
	ConfigFlag      string
	RemoveColor     bool
	args            []string
	activeCommands  []*Command
}

type ParsingType int

const (
	EnvironmentVariables ParsingType = iota
	JsonConfig
	TomlConfig
	CliFlags
)

var ParingTypeStringMap = map[ParsingType]string{
	EnvironmentVariables: "Environment",
	JsonConfig:           "JSON Config",
	TomlConfig:           "Toml Config",
	CliFlags:             "CLI Flag",
}

// Create a new application with default values set.
func NewApp() *App {
	return &App{
		Name:    "cli",
		Authors: make([]Author, 0),
		HelpCommands: map[string]bool{
			"--help": true,
			"-h":     true,
			"help":   true,
		},
		ParsingOrder: []ParsingType{
			EnvironmentVariables,
			JsonConfig,
			TomlConfig,
			CliFlags,
		},
	}
}

// Run the app. Should be called with:
// app := cli.NewApp()
// app.Run(os.Args)
func (a *App) Run(args []string) {
	if len(args) < 1 {
		log.Fatal("Arguments must be at least 1, please run with app.Run(os.Args).")
	}
	a.args = args[1:]
	a.parseCommands()

	finalCommand := a.activeCommands[len(a.activeCommands)-1]
	if finalCommand.Action != nil {
		finalCommand.Action()
	}
}

func (a *App) parseCommands() {
	if a.Command == nil {
		log.Fatal("No command attached to the app!")
	}
	a.Command.buildTree(nil)
	a.Command.assignArguments(a.args)

	if helpCommand, isHelp := a.Command.isHelpCommand(a.HelpCommands); isHelp {
		fmt.Println("help.", helpCommand.Name)
		return
	}

	if err := a.Command.parseFlags(); err != nil {
		log.WithFields(log.Fields{"err": err}).Fatal("error parsing flags.")
		return
	}

	a.activeCommands = a.Command.GetActiveCommands()
	a.Command.findConfigVars()
	a.Command.parseConfigVars()
	settingsMap := a.parseByOrder()
	a.applySettingsMap(settingsMap)
	settingsMap.PrintDuplicates(a.activeCommands)
	settingsMap.PrintDuplicatesStdout(a.RemoveColor)
}

func (a *App) parseByOrder() *mappedSettings {
	settingsMap := newMappedSettings()
	if a.ParsingOrder == nil {
		log.Fatal("No parsing order! Use unpuzzled.NewApp when creating an application.")
	}

	for _, order := range a.ParsingOrder {
		switch order {
		case EnvironmentVariables:
			settingsMap.addParsedArray(a.Command.parseEnvVars())

		case JsonConfig:
			vars := a.Command.getConfigVarsByType(JsonConfig)
			if len(vars) == 0 {
				continue
			}
			setValues := a.Command.parseConfigValues(vars)
			settingsMap.addParsedArray(setValues)

		case TomlConfig:
			vars := a.Command.getConfigVarsByType(TomlConfig)
			if len(vars) == 0 {
				continue
			}
			setValues := a.Command.parseConfigValues(vars)
			settingsMap.addParsedArray(setValues)

		case CliFlags:
			settingsMap.addParsedArray(a.Command.getSetFlags())
		}
	}
	return settingsMap
}

func (a *App) applySettingsMap(settingsMap *mappedSettings) {
	commandMap := a.Command.GetExpandedActiveCommmands()
	// loop through commands, ensure that the order of settings are constantly applied,
	// instead of looping through MainMap, which is not a consistent order.
	for _, command := range a.activeCommands {
		path := command.GetExpandedName()
		variableSettingsMap := settingsMap.MainMap[path]
		currCommand := commandMap[path]
		variableMap := currCommand.GetVariableMap()

		for _, setting := range variableSettingsMap {
			activeSetting := setting[len(setting)-1]
			currVariable := variableMap[activeSetting.VariableName]
			if _, ok := currVariable.(*ConfigVariable); ok {
				continue
			}
			currVariable.apply(activeSetting.Value)
		}
	}
}

type mappedSettings struct {
	MainMap map[string]map[string][]activeSetting `json:"main_map"`
}

func newMappedSettings() *mappedSettings {
	return &mappedSettings{
		MainMap: make(map[string]map[string][]activeSetting),
	}
}

func (m *mappedSettings) addParsedArray(settings []activeSetting) {
	for _, setting := range settings {
		if m.MainMap[setting.CommandPath] == nil {
			m.MainMap[setting.CommandPath] = make(map[string][]activeSetting)
		}
		if m.MainMap[setting.CommandPath][setting.VariableName] == nil {
			m.MainMap[setting.CommandPath][setting.VariableName] = make([]activeSetting, 0)
		}
		m.MainMap[setting.CommandPath][setting.VariableName] = append(m.MainMap[setting.CommandPath][setting.VariableName], setting)
	}
}

// Helper to print duplciates in table format to Stdout.
func (m *mappedSettings) PrintDuplicates(commands []*Command) {
	table := tablewriter.NewWriter(os.Stdout)
	table.SetHeader([]string{"Command", "Variable", "Source", "Value", "Type", "Status"})
	for _, command := range commands {
		expandedName := command.GetExpandedName()
		if m.MainMap[expandedName] == nil {
			continue
		}
		for _, settings := range m.MainMap[expandedName] {
			length := len(settings)
			for i, setting := range settings {
				var status string
				if i == length-1 {
					status = "✔ Used"
				} else {
					status = "x Ignored"
				}
				row := []string{
					expandedName,
					setting.VariableName,
					ParingTypeStringMap[setting.Source],
					fmt.Sprintf("%s", setting.Value),
					reflect.TypeOf(setting.Value).String(),
					status,
				}
				if setting.Source == EnvironmentVariables {
					row[1] += " (" + convertNameToOS(setting.VariableName) + ")"
				}
				table.Append(row)
			}
		}
	}
	table.Render()
}

// Use a custom formatted string to print duplicates on Stdout.
func (m *mappedSettings) PrintDuplicatesStdout(noColor bool) {
	t := template.New("duplicates")
	funcMap := template.FuncMap{
		"blue":  color.BlueString,
		"red":   color.RedString,
		"green": color.GreenString,
		"bold":  color.New(color.Bold).Sprint,
		"sourceString": func(setting activeSetting) string {
			if setting.Source == EnvironmentVariables {
				return fmt.Sprintf("%s (%s)", ParingTypeStringMap[setting.Source], convertNameToOS(setting.VariableName))
			} else if setting.Source == TomlConfig || setting.Source == JsonConfig {
				return fmt.Sprintf("%s (%s)", ParingTypeStringMap[setting.Source], setting.SettingName)
			} else {
				return ParingTypeStringMap[setting.Source]
			}
		},
		"plus1": func(x int) int {
			return x + 1
		},
	}
	if noColor {
		funcMap["blue"] = identityString
		funcMap["red"] = identityString
		funcMap["green"] = identityString
		funcMap["bold"] = identityString
	}
	t.Funcs(funcMap)
	t.Parse(`{{ range $command, $variables := . -}}
-------------------------------------
{{ blue "Configuration:"}} {{ bold $command }}
{{ range $key, $vars := $variables -}}
-------------
{{ range $k, $var := $vars }}{{ $length := len $vars -}}
	{{ if eq $length (plus1 $k) -}}
		{{ green $key }} = {{ green $var.Value }}
	{{ green "set from" }} {{ sourceString $var -}}
	{{ else -}}
		{{ red $key }} = {{ red $var.Value }}
	{{ red "ignored from" }} {{ sourceString $var -}}
	{{ end }}
{{ end -}}
{{ end }}
{{ end }}`)
	t.Execute(os.Stdout, m.MainMap)
}

func identityString(s string) string {
	return s
}
<|endoftext|>


<commit_before>package server

import (
	"errors"
	"launchpad.net/gnuflag"
	"launchpad.net/juju-core/cmd"
	"launchpad.net/juju-core/log"
	"strings"
)

// JujuLogCommand implements the juju-log command.
type JujuLogCommand struct {
	*HookContext
	Message string
	Debug   bool
}

func NewJujuLogCommand(ctx *HookContext) (cmd.Command, error) {
	return &JujuLogCommand{HookContext: ctx}, nil
}

func (c *JujuLogCommand) Info() *cmd.Info {
	return &cmd.Info{"juju-log", "<message>", "write a message to the juju log", ""}
}

func (c *JujuLogCommand) Init(f *gnuflag.FlagSet, args []string) error {
	f.BoolVar(&c.Debug, "debug", false, "log at debug level")
	if err := f.Parse(true, args); err != nil {
		return err
	}
	args = f.Args()
	if args == nil {
		return errors.New("no message specified")
	}
	c.Message = strings.Join(args, " ")
	return nil
}

func (c *JujuLogCommand) Run(_ *cmd.Context) error {
	s := []string{c.Unit.Name()}
	if c.RelationId != -1 {
		s = append(s, c.envRelationId())
	}
	msg := strings.Join(s, " ") + ": " + c.Message
	if c.Debug {
		log.Debugf("%s", msg)
	} else {
		log.Printf("%s", msg)
	}
	return nil
}
<commit_msg>parse -l<commit_after>package server

import (
	"errors"
	"launchpad.net/gnuflag"
	"launchpad.net/juju-core/cmd"
	"launchpad.net/juju-core/log"
	"strings"
)

// JujuLogCommand implements the juju-log command.
type JujuLogCommand struct {
	*HookContext
	Message string
	Debug   bool
	Level   string // unused
}

func NewJujuLogCommand(ctx *HookContext) (cmd.Command, error) {
	return &JujuLogCommand{HookContext: ctx}, nil
}

func (c *JujuLogCommand) Info() *cmd.Info {
	return &cmd.Info{"juju-log", "<message>", "write a message to the juju log", ""}
}

func (c *JujuLogCommand) Init(f *gnuflag.FlagSet, args []string) error {
	f.BoolVar(&c.Debug, "debug", false, "log at debug level")
	f.StringVar(&c.Level, "l", "INFO", "Send log message at the given level")
	if err := f.Parse(true, args); err != nil {
		return err
	}
	args = f.Args()
	if args == nil {
		return errors.New("no message specified")
	}
	c.Message = strings.Join(args, " ")
	return nil
}

func (c *JujuLogCommand) Run(_ *cmd.Context) error {
	s := []string{c.Unit.Name()}
	if c.RelationId != -1 {
		s = append(s, c.envRelationId())
	}
	msg := strings.Join(s, " ") + ": " + c.Message
	if c.Debug {
		log.Debugf("%s", msg)
	} else {
		log.Printf("%s", msg)
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kubeadm

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"os/exec"
)

// Forked from test/e2e/framework because the e2e framework is quite bloated
// for our purposes here, and modified to remove undesired logging.
func RunCmd(command string, args ...string) (string, string, error) {
	var bout, berr bytes.Buffer
	cmd := exec.Command(command, args...)
	cmd.Stdout = io.MultiWriter(os.Stdout, &bout)
	cmd.Stderr = io.MultiWriter(os.Stderr, &berr)
	err := cmd.Run()
	stdout, stderr := bout.String(), berr.String()
	if err != nil {
		return "", "", fmt.Errorf("error running %s %v; got error %v, stdout %q, stderr %q",
			command, args, err, stdout, stderr)
	}
	return stdout, stderr, nil
}
<commit_msg>kubeadm: only print stderr/stdout if failed test<commit_after>/*
Copyright 2016 The Kubernetes Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kubeadm

import (
	"bytes"
	"fmt"
	"os/exec"
)

// Forked from test/e2e/framework because the e2e framework is quite bloated
// for our purposes here, and modified to remove undesired logging.
func RunCmd(command string, args ...string) (string, string, error) {
	var bout, berr bytes.Buffer
	cmd := exec.Command(command, args...)
	cmd.Stdout = &bout
	cmd.Stderr = &berr
	err := cmd.Run()
	stdout, stderr := bout.String(), berr.String()
	if err != nil {
		return "", "", fmt.Errorf("error running %s %v; \ngot error %v, \nstdout %q, \nstderr %q",
			command, args, err, stdout, stderr)
	}
	return stdout, stderr, nil
}
<|endoftext|>


<commit_before>// The magnacarto command converts CartoCSS to Mapnik/MapServer styles.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime/pprof"

	"github.com/omniscale/magnacarto"
	"github.com/omniscale/magnacarto/builder"
	"github.com/omniscale/magnacarto/builder/mapnik"
	"github.com/omniscale/magnacarto/builder/mapserver"
	"github.com/omniscale/magnacarto/config"
)

type files []string

func (f *files) String() string {
	return fmt.Sprintf("%v", *f)
}

func (f *files) Set(value string) error {
	*f = append(*f, value)
	return nil
}

func main() {
	mmlFilename := flag.String("mml", "", "mml file")
	var mssFilenames files

	flag.Var(&mssFilenames, "mss", "mss file")
	confFile := flag.String("config", "", "config")
	sqliteDir := flag.String("sqlite-dir", "", "sqlite directory")
	shapeDir := flag.String("shape-dir", "", "shapefile directory")
	imageDir := flag.String("image-dir", "", "image/marker directory")
	fontDir := flag.String("font-dir", "", "fonts directory")
	dumpRules := flag.Bool("dumprules", false, "print calculated rules to stderr")
	mapfile := flag.Bool("mapfile", false, "output as MapServer mapfile")
	outFile := flag.String("out", "", "out file")
	deferEval := flag.Bool("deferred-eval", false, "defer variable/expression evaluation to the end")
	version := flag.Bool("version", false, "print version and exit")
	noCheckFiles := flag.Bool("no-check-files", false, "do not check if images/shps/etc exists")

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

	flag.Parse()

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *version {
		fmt.Println(magnacarto.Version)
		os.Exit(0)
	}

	conf := config.Magnacarto{}
	if *confFile != "" {
		if err := conf.Load(*confFile); err != nil {
			log.Fatal(err)
		}
	}

	// overwrite config with command line args
	if *sqliteDir != "" {
		conf.Datasources.SQLiteDirs = []string{*sqliteDir}
	}
	if *fontDir != "" {
		conf.Mapnik.FontDirs = []string{*fontDir}
	}
	if *shapeDir != "" {
		conf.Datasources.ShapefileDirs = []string{*shapeDir}
	}
	if *imageDir != "" {
		conf.Datasources.ImageDirs = []string{*imageDir}
	}

	if *noCheckFiles {
		conf.Datasources.NoCheckFiles = true
	}

	locator := conf.Locator()

	var m builder.MapWriter

	if *mapfile {
		m = mapserver.New(locator)
	} else {
		m = mapnik.New(locator)
	}

	b := builder.New(m)
	if *deferEval || conf.DeferEval {
		b.EnableDeferredEval()
	}
	b.SetMML(*mmlFilename)
	for _, mss := range mssFilenames {
		b.AddMSS(mss)
	}
	if *dumpRules {
		b.SetDumpRulesDest(os.Stderr)
	}

	if err := b.Build(); err != nil {
		log.Fatal("error building map: ", err)
	}

	if *outFile == "" || *outFile == "-" {
		if err := m.Write(os.Stdout); err != nil {
			log.Fatal("error writing map to stdout: ", err)
		}
	} else {
		if err := m.WriteFiles(*outFile); err != nil {
			log.Fatal("error writing map: ", err)
		}
	}
}
<commit_msg>add -builder option to switch between mapnik/mapserver<commit_after>// The magnacarto command converts CartoCSS to Mapnik/MapServer styles.
package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime/pprof"

	"github.com/omniscale/magnacarto"
	"github.com/omniscale/magnacarto/builder"
	"github.com/omniscale/magnacarto/builder/mapnik"
	"github.com/omniscale/magnacarto/builder/mapserver"
	"github.com/omniscale/magnacarto/config"
)

type files []string

func (f *files) String() string {
	return fmt.Sprintf("%v", *f)
}

func (f *files) Set(value string) error {
	*f = append(*f, value)
	return nil
}

func main() {
	mmlFilename := flag.String("mml", "", "mml file")
	var mssFilenames files

	flag.Var(&mssFilenames, "mss", "mss file")
	confFile := flag.String("config", "", "config")
	sqliteDir := flag.String("sqlite-dir", "", "sqlite directory")
	shapeDir := flag.String("shape-dir", "", "shapefile directory")
	imageDir := flag.String("image-dir", "", "image/marker directory")
	fontDir := flag.String("font-dir", "", "fonts directory")
	dumpRules := flag.Bool("dumprules", false, "print calculated rules to stderr")
	builderType := flag.String("builder", "mapnik", "builder type {mapnik,mapserver}")
	outFile := flag.String("out", "", "out file")
	deferEval := flag.Bool("deferred-eval", false, "defer variable/expression evaluation to the end")
	version := flag.Bool("version", false, "print version and exit")
	noCheckFiles := flag.Bool("no-check-files", false, "do not check if images/shps/etc exists")

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

	flag.Parse()

	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	if *version {
		fmt.Println(magnacarto.Version)
		os.Exit(0)
	}

	conf := config.Magnacarto{}
	if *confFile != "" {
		if err := conf.Load(*confFile); err != nil {
			log.Fatal(err)
		}
	}

	// overwrite config with command line args
	if *sqliteDir != "" {
		conf.Datasources.SQLiteDirs = []string{*sqliteDir}
	}
	if *fontDir != "" {
		conf.Mapnik.FontDirs = []string{*fontDir}
	}
	if *shapeDir != "" {
		conf.Datasources.ShapefileDirs = []string{*shapeDir}
	}
	if *imageDir != "" {
		conf.Datasources.ImageDirs = []string{*imageDir}
	}

	if *noCheckFiles {
		conf.Datasources.NoCheckFiles = true
	}

	locator := conf.Locator()

	var m builder.MapWriter

	switch *builderType {
	case "mapserver":
		m = mapserver.New(locator)
	case "mapnik":
		m = mapnik.New(locator)
	default:
		log.Fatal("unknown -builder ", *builderType)
	}

	b := builder.New(m)
	if *deferEval || conf.DeferEval {
		b.EnableDeferredEval()
	}
	b.SetMML(*mmlFilename)
	for _, mss := range mssFilenames {
		b.AddMSS(mss)
	}
	if *dumpRules {
		b.SetDumpRulesDest(os.Stderr)
	}

	if err := b.Build(); err != nil {
		log.Fatal("error building map: ", err)
	}

	if *outFile == "" || *outFile == "-" {
		if err := m.Write(os.Stdout); err != nil {
			log.Fatal("error writing map to stdout: ", err)
		}
	} else {
		if err := m.WriteFiles(*outFile); err != nil {
			log.Fatal("error writing map: ", err)
		}
	}
}
<|endoftext|>


<commit_before>package upload

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

	"github.com/codegangsta/cli"
	"github.com/materials-commons/gohandy/file"
	"github.com/materials-commons/mcstore/cmd/pkg/project"
	"github.com/materials-commons/mcstore/pkg/app"
	"github.com/materials-commons/mcstore/pkg/files"
	"github.com/materials-commons/mcstore/server/mcstored/service/rest/upload"
	"github.com/parnurzeal/gorequest"
)

// Command contains the arguments and functions for the cli upload command.
var Command = cli.Command{
	Name:    "upload",
	Aliases: []string{"up", "u"},
	Usage:   "Upload data to MaterialsCommons",
	Flags: []cli.Flag{
		cli.IntFlag{
			Name:  "parallel, n",
			Value: 3,
			Usage: "Number of simultaneous uploads to perform, defaults to 3",
		},
	},
	Action: uploadCLI,
}

const oneMeg = 1024 * 1024
const twoMeg = oneMeg * 2
const largeFileSize = oneMeg * 25
const maxSimultaneous = 5

var proj *project.MCProject

//var pbPool = &pb.Pool{}

// uploadCLI implements the cli command upload.
func uploadCLI(c *cli.Context) {
	fmt.Println("upload: ", c.Args())
	if len(c.Args()) != 1 {
		fmt.Println("You must give the directory to walk")
		os.Exit(1)
	}
	dir := c.Args()[0]
	numThreads := getNumThreads(c)

	if !file.IsDir(dir) {
		fmt.Printf("Invalid directory: %s\n", dir)
		os.Exit(1)
	}

	uploadToServer(dir, numThreads)
}

// getNumThreads ensures that the number of parallel downloads is valid.
func getNumThreads(c *cli.Context) int {
	numThreads := c.Int("parallel")

	if numThreads < 1 {
		fmt.Println("Simultaneous downloads must be positive: ", numThreads)
		os.Exit(1)
	} else if numThreads > maxSimultaneous {
		fmt.Printf("You may not set simultaneous downloads greater than %d: %d\n", maxSimultaneous, numThreads)
		os.Exit(1)
	}

	return numThreads
}

// uploadToServer
func uploadToServer(dir string, numThreads int) {
	var err error
	proj, err = project.Find(dir)
	if err != nil {
		fmt.Println("Unable to locate project dir is in.")
		os.Exit(1)
	}
	fmt.Printf("project = '%s'\n", proj.ID)
	// _, errc := files.PWalk(dir, numThreads, processFiles)
	// if err := <-errc; err != nil {
	// 	fmt.Println("Got error: ", err)
	// }
}

// findDotMCProject will walk up from directory looking for the .mcproject
// directory. If it cannot find it, then the directory isn't in a
// known project. findProject will call os.Exit on any errors or if
// it cannot find a .mcproject directory.
func findDotMCProject(dir string) string {
	// Normalize the directory path, and convert all path separators to a
	// forward slash (/).
	dirPath, err := filepath.Abs(dir)
	if err != nil {
		fmt.Printf("Bad directory %s: %s", dir, err)
		os.Exit(1)
	}

	dirPath = filepath.ToSlash(dirPath)
	for {
		if dirPath == "/" {
			// Projects at root level not allowed
			fmt.Println("Your directory is not in a project.")
			fmt.Println("Upload a directory in a project or create a project by running the create-project command.")
			os.Exit(1)
		}

		mcprojectDir := filepath.Join(dirPath, ".mcproject")
		if file.IsDir(mcprojectDir) {
			// found it
			return mcprojectDir
		}
		dirPath = filepath.Dir(dirPath)
	}
}

// processFiles is the callback passed into PWalk. It processes each file, determines
// if it should be uploaded, and if so uploads the file. There can be a maxSimultaneous
// processFiles routines running.
func processFiles(done <-chan struct{}, entries <-chan files.TreeEntry, result chan<- string) {
	fmt.Println("processFiles")
	u := &uploader{
		client: gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true}),
	}
	for entry := range entries {
		select {
		case result <- u.sendFile(entry):
		case <-done:
			// Received done, so stop processing requests.
			return
		}
	}
}

type uploader struct {
	client *gorequest.SuperAgent
}

// sendFile logic:
// if file has changed || file not in local database then
//       compute hash
//       if hash is on server then
//          tell server to create a new entry pointing to
//          the already uploaded file
//       else
//          upload the file
//       end
//  end
//
func (u *uploader) sendFile(fileEntry files.TreeEntry) string {
	u.createUploadRequest()
	//s1 := file.ExInfoFrom(20, time.Now(), time.Now(), time.Now(), file.FID{})
	//fileChanged(s1, s1)
	// buf := make([]byte, twoMeg)
	// f, err := os.Open(fileEntry.Path)
	// if err != nil {
	// 	return ""
	// }
	// fileHash := ""
	// // For small files just transfer the bytes. For
	// // large files compute the file hash.
	// if fileEntry.Finfo.Size() > largeFileSize {
	// 	fileHash, _ = file.HashStr(md5.New(), fileEntry.Path)
	// }
	// for {
	// 	read, err := f.Read(buf)
	// 	sendFlowChunk(buf)
	// }
	return fileEntry.Path
}

func fileChanged(oinfo, ninfo file.ExFileInfo) bool {
	switch {
	case oinfo.Size() != ninfo.Size():
		return true
	case oinfo.CTime().Before(ninfo.CTime()):
		return true
	case oinfo.ModTime().Before(ninfo.ModTime()):
		return true
	default:
		return false
	}
}

func (u *uploader) createUploadRequest() {
	fmt.Println("createUploadRequest")
	req := upload.CreateRequest{
		ProjectID:   "9ead5bbf-f7eb-4010-bc1f-e4a063f56226",
		DirectoryID: "c54a77d6-cd6d-4cd1-8f19-44facc761da6",
		FileName:    "abc.txt",
		FileSize:    10,
		FileMTime:   "Thu, 30 Apr 2015 13:10:04 EST",
	}

	var resp upload.CreateResponse
	fmt.Println("url =", app.MCApi.APIUrl("/upload"))
	r, body, errs := u.client.Post(app.MCApi.APIUrl("/upload")).Send(req).End()
	if err := app.MCApi.APIError(r, errs); err != nil {
		fmt.Println("got err from Post:", err)
		return
	}
	app.MCApi.ToJSON(body, &resp)
	fmt.Printf("%#v\n", resp)
}

func sendFlowChunk(buf []byte) {

}
<commit_msg>Move getNumThreads into a separate package so it can be used across multiple commands.<commit_after>package upload

import (
	"crypto/tls"
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/materials-commons/gohandy/file"
	"github.com/materials-commons/mcstore/cmd/pkg/opts"
	"github.com/materials-commons/mcstore/cmd/pkg/project"
	"github.com/materials-commons/mcstore/pkg/app"
	"github.com/materials-commons/mcstore/pkg/files"
	"github.com/materials-commons/mcstore/server/mcstored/service/rest/upload"
	"github.com/parnurzeal/gorequest"
)

// Command contains the arguments and functions for the cli upload command.
var Command = cli.Command{
	Name:    "upload",
	Aliases: []string{"up", "u"},
	Usage:   "Upload data to MaterialsCommons",
	Flags: []cli.Flag{
		cli.IntFlag{
			Name:  "parallel, n",
			Value: 3,
			Usage: "Number of simultaneous uploads to perform, defaults to 3",
		},
	},
	Action: uploadCLI,
}

const oneMeg = 1024 * 1024
const twoMeg = oneMeg * 2
const largeFileSize = oneMeg * 25

var proj *project.MCProject

//var pbPool = &pb.Pool{}

// uploadCLI implements the cli command upload.
func uploadCLI(c *cli.Context) {
	fmt.Println("upload: ", c.Args())
	if len(c.Args()) != 1 {
		fmt.Println("You must give a directory to upload.")
		os.Exit(1)
	}
	dir := c.Args()[0]
	numThreads := opts.GetNumThreads(c)

	if !file.IsDir(dir) {
		fmt.Printf("Invalid directory: %s.\n", dir)
		os.Exit(1)
	}

	uploadToServer(dir, numThreads)
}

// uploadToServer
func uploadToServer(dir string, numThreads int) {
	var err error
	proj, err = project.Find(dir)
	if err != nil {
		fmt.Println("Unable to locate project dir is in.")
		os.Exit(1)
	}
	fmt.Printf("project = '%s'\n", proj.ID)
	// _, errc := files.PWalk(dir, numThreads, processFiles)
	// if err := <-errc; err != nil {
	// 	fmt.Println("Got error: ", err)
	// }
}

// processFiles is the callback passed into PWalk. It processes each file, determines
// if it should be uploaded, and if so uploads the file. There can be a maxSimultaneous
// processFiles routines running.
func processFiles(done <-chan struct{}, entries <-chan files.TreeEntry, result chan<- string) {
	fmt.Println("processFiles")
	u := &uploader{
		client: gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true}),
	}
	for entry := range entries {
		select {
		case result <- u.sendFile(entry):
		case <-done:
			// Received done, so stop processing requests.
			return
		}
	}
}

type uploader struct {
	client *gorequest.SuperAgent
}

// sendFile logic:
// if file has changed || file not in local database then
//       compute hash
//       if hash is on server then
//          tell server to create a new entry pointing to
//          the already uploaded file
//       else
//          upload the file
//       end
//  end
//
func (u *uploader) sendFile(fileEntry files.TreeEntry) string {
	u.createUploadRequest()
	//s1 := file.ExInfoFrom(20, time.Now(), time.Now(), time.Now(), file.FID{})
	//fileChanged(s1, s1)
	// buf := make([]byte, twoMeg)
	// f, err := os.Open(fileEntry.Path)
	// if err != nil {
	// 	return ""
	// }
	// fileHash := ""
	// // For small files just transfer the bytes. For
	// // large files compute the file hash.
	// if fileEntry.Finfo.Size() > largeFileSize {
	// 	fileHash, _ = file.HashStr(md5.New(), fileEntry.Path)
	// }
	// for {
	// 	read, err := f.Read(buf)
	// 	sendFlowChunk(buf)
	// }
	return fileEntry.Path
}

func fileChanged(oinfo, ninfo file.ExFileInfo) bool {
	switch {
	case oinfo.Size() != ninfo.Size():
		return true
	case oinfo.CTime().Before(ninfo.CTime()):
		return true
	case oinfo.ModTime().Before(ninfo.ModTime()):
		return true
	default:
		return false
	}
}

func (u *uploader) createUploadRequest() {
	fmt.Println("createUploadRequest")
	req := upload.CreateRequest{
		ProjectID:   "9ead5bbf-f7eb-4010-bc1f-e4a063f56226",
		DirectoryID: "c54a77d6-cd6d-4cd1-8f19-44facc761da6",
		FileName:    "abc.txt",
		FileSize:    10,
		FileMTime:   "Thu, 30 Apr 2015 13:10:04 EST",
	}

	var resp upload.CreateResponse
	fmt.Println("url =", app.MCApi.APIUrl("/upload"))
	r, body, errs := u.client.Post(app.MCApi.APIUrl("/upload")).Send(req).End()
	if err := app.MCApi.APIError(r, errs); err != nil {
		fmt.Println("got err from Post:", err)
		return
	}
	app.MCApi.ToJSON(body, &resp)
	fmt.Printf("%#v\n", resp)
}

func sendFlowChunk(buf []byte) {

}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"github.com/semantic-release/go-semantic-release"
	"github.com/semantic-release/go-semantic-release/condition"
	"github.com/semantic-release/go-semantic-release/update"
	"io/ioutil"
	"log"
	"os"
)

var SRVERSION string

func errorHandler(logger *log.Logger) func(error) {
	return func(err error) {
		if err != nil {
			logger.Println(err)
			os.Exit(1)
		}
	}
}

func main() {
	token := flag.String("token", os.Getenv("GITHUB_TOKEN"), "github token")
	slug := flag.String("slug", os.Getenv("TRAVIS_REPO_SLUG"), "slug of the repository")
	ghr := flag.Bool("ghr", false, "create a .ghr file with the parameters for ghr")
	noci := flag.Bool("noci", false, "run semantic-release locally")
	dry := flag.Bool("dry", false, "do not create release")
	vFile := flag.Bool("vf", false, "create a .version file")
	showVersion := flag.Bool("version", false, "outputs the semantic-release version")
	updateFile := flag.String("update", "", "updates the version of a certain file")
	flag.Parse()

	if *showVersion {
		fmt.Printf("semantic-release v%s", SRVERSION)
		return
	}

	logger := log.New(os.Stderr, "[semantic-release]: ", 0)
	exitIfError := errorHandler(logger)

	if val, ok := os.LookupEnv("GH_TOKEN"); *token == "" && ok {
		*token = val
	}

	if *token == "" {
		exitIfError(errors.New("github token missing"))
	}
	if *slug == "" {
		exitIfError(errors.New("slug missing"))
	}

	repo, err := semrel.NewRepository(context.TODO(), *slug, *token)
	exitIfError(err)

	logger.Println("getting default branch...")
	defaultBranch, isPrivate, err := repo.GetInfo()
	exitIfError(err)
	logger.Println("found default branch: " + defaultBranch)

	if !*noci {
		logger.Println("running CI condition...")
		exitIfError(condition.Travis(*token, defaultBranch, isPrivate))
	}

	logger.Println("getting latest release...")
	release, err := repo.GetLatestRelease("")
	exitIfError(err)
	logger.Println("found version: " + release.Version.String())

	logger.Println("getting commits...")
	commits, err := repo.GetCommits()
	exitIfError(err)

	logger.Println("calculating new version...")
	newVer := semrel.GetNewVersion(commits, release)
	if newVer == nil {
		exitIfError(errors.New("no change"))
	}
	logger.Println("new version: " + newVer.String())

	if *dry {
		exitIfError(errors.New("DRY RUN: no release was created"))
	}

	logger.Println("creating release...")
	exitIfError(repo.CreateRelease(commits, release, newVer))

	if *ghr {
		exitIfError(ioutil.WriteFile(".ghr", []byte(fmt.Sprintf("-u %s -r %s v%s", repo.Owner, repo.Repo, newVer.String())), 0644))
	}

	if *vFile {
		exitIfError(ioutil.WriteFile(".version", []byte(newVer.String()), 0644))
	}

	if *updateFile != "" {
		exitIfError(update.Apply(*updateFile, newVer.String()))
	}

	logger.Println("done.")
}
<commit_msg>feat(cmd): add .semrelrc support<commit_after>package main

import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/semantic-release/go-semantic-release"
	"github.com/semantic-release/go-semantic-release/condition"
	"github.com/semantic-release/go-semantic-release/update"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

var SRVERSION string

func errorHandler(logger *log.Logger) func(error) {
	return func(err error) {
		if err != nil {
			logger.Println(err)
			os.Exit(1)
		}
	}
}

type SemRelConfig struct {
	MaintainedRange string `json:"maintainedRange"`
}

func loadConfig() *SemRelConfig {
	f, err := os.OpenFile(".semrelrc", os.O_RDONLY, 0)
	if err != nil {
		return &SemRelConfig{}
	}
	src := &SemRelConfig{}
	json.NewDecoder(f).Decode(src)
	f.Close()
	return src
}

func main() {
	token := flag.String("token", os.Getenv("GITHUB_TOKEN"), "github token")
	slug := flag.String("slug", os.Getenv("TRAVIS_REPO_SLUG"), "slug of the repository")
	ghr := flag.Bool("ghr", false, "create a .ghr file with the parameters for ghr")
	noci := flag.Bool("noci", false, "run semantic-release locally")
	dry := flag.Bool("dry", false, "do not create release")
	vFile := flag.Bool("vf", false, "create a .version file")
	showVersion := flag.Bool("version", false, "outputs the semantic-release version")
	updateFile := flag.String("update", "", "updates the version of a certain file")
	flag.Parse()

	if *showVersion {
		fmt.Printf("semantic-release v%s", SRVERSION)
		return
	}

	logger := log.New(os.Stderr, "[semantic-release]: ", 0)
	exitIfError := errorHandler(logger)

	if val, ok := os.LookupEnv("GH_TOKEN"); *token == "" && ok {
		*token = val
	}

	if *token == "" {
		exitIfError(errors.New("github token missing"))
	}
	if *slug == "" {
		exitIfError(errors.New("slug missing"))
	}

	repo, err := semrel.NewRepository(context.TODO(), *slug, *token)
	exitIfError(err)

	logger.Println("getting default branch...")
	defaultBranch, isPrivate, err := repo.GetInfo()
	exitIfError(err)
	logger.Println("found default branch: " + defaultBranch)

	currentBranch := condition.GetCurrentBranch()
	if currentBranch == "" {
		exitIfError(fmt.Errorf("current branch not found"))
	}
	logger.Println("found current branch: " + currentBranch)

	config := loadConfig()
	if config.MaintainedRange != "" && currentBranch == defaultBranch {
		exitIfError(fmt.Errorf("maintained range not allowed on default branch"))
	}

	if config.MaintainedRange != "" {
		logger.Println("found maintained range: " + config.MaintainedRange)
		defaultBranch = "*"
	}

	if !*noci {
		logger.Println("running CI condition...")
		exitIfError(condition.Travis(*token, defaultBranch, isPrivate))
	}

	logger.Println("getting latest release...")
	release, err := repo.GetLatestRelease(config.MaintainedRange)
	exitIfError(err)
	logger.Println("found version: " + release.Version.String())

	if strings.Contains(config.MaintainedRange, "-") && release.Version.Prerelease() == "" {
		exitIfError(fmt.Errorf("no prerelease for this version possible"))
	}

	logger.Println("getting commits...")
	commits, err := repo.GetCommits(currentBranch)
	exitIfError(err)

	logger.Println("calculating new version...")
	newVer := semrel.GetNewVersion(commits, release)
	if newVer == nil {
		exitIfError(errors.New("no change"))
	}
	logger.Println("new version: " + newVer.String())

	if *dry {
		exitIfError(errors.New("DRY RUN: no release was created"))
	}

	logger.Println("creating release...")
	exitIfError(repo.CreateRelease(commits, release, newVer, currentBranch))

	if *ghr {
		exitIfError(ioutil.WriteFile(".ghr", []byte(fmt.Sprintf("-u %s -r %s v%s", repo.Owner, repo.Repo, newVer.String())), 0644))
	}

	if *vFile {
		exitIfError(ioutil.WriteFile(".version", []byte(newVer.String()), 0644))
	}

	if *updateFile != "" {
		exitIfError(update.Apply(*updateFile, newVer.String()))
	}

	logger.Println("done.")
}
<|endoftext|>


<commit_before>package main_test

import (
	"fmt"
	"net"
	"net/http"
	"os/exec"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

func startSwitchboard(args ...string) *gexec.Session {
	command := exec.Command(switchboardBinPath, args...)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	Eventually(session).Should(gbytes.Say("started on port"))
	return session
}

func startBackend(args ...string) *gexec.Session {
	command := exec.Command(dummyListenerBinPath, args...)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	Eventually(session).Should(gbytes.Say("Backend listening on"))
	return session
}

func startHealthcheck(args ...string) *gexec.Session {
	command := exec.Command(dummyHealthcheckBinPath, args...)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	Eventually(session).Should(gbytes.Say("Healthcheck listening on"))
	return session
}

func sendData(conn net.Conn, data string) (string, error) {
	conn.Write([]byte(data))
	buffer := make([]byte, 1024)
	_, err := conn.Read(buffer)
	if err != nil {
		return "", err
	} else {
		return string(buffer), nil
	}
}

var _ = Describe("Switchboard", func() {
	var (
		backendSession      *gexec.Session
		backendSession2     *gexec.Session
		healthcheckSession  *gexec.Session
		healthcheckSession2 *gexec.Session
		proxySession        *gexec.Session
		healthcheckTimeout  time.Duration
	)

	BeforeEach(func() {
		healthcheckTimeout = 500 * time.Millisecond

		backendSession = startBackend(
			fmt.Sprintf("-port=%d", backendPort),
		)

		backendSession2 = startBackend(
			fmt.Sprintf("-port=%d", backendPort2),
		)

		healthcheckSession = startHealthcheck(
			fmt.Sprintf("-port=%d", dummyHealthcheckPort),
		)

		healthcheckSession2 = startHealthcheck(
			fmt.Sprintf("-port=%d", dummyHealthcheckPort2),
		)

		proxySession = startSwitchboard(
			"-backendIPs=localhost, localhost",
			fmt.Sprintf("-port=%d", switchboardPort),
			fmt.Sprintf("-backendPorts=%d,%d", backendPort, backendPort2),
			fmt.Sprintf("-healthcheckPorts=%d,%d", dummyHealthcheckPort, dummyHealthcheckPort2),
			fmt.Sprintf("-healthcheckTimeout=%s", healthcheckTimeout),
			fmt.Sprintf("-pidfile=%s", pidfile),
		)
	})

	AfterEach(func() {
		proxySession.Terminate()
		healthcheckSession2.Terminate()
		healthcheckSession.Terminate()
		backendSession2.Terminate()
		backendSession.Terminate()
	})

	Context("when there are multiple concurrent clients", func() {
		var conn1, conn2, conn3 net.Conn
		var data1, data2, data3 string

		It("proxies all the connections to the backend", func() {
			done1 := make(chan interface{})
			go func() {
				defer GinkgoRecover()
				defer close(done1)

				var err error
				Eventually(func() error {
					conn1, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data1, err = sendData(conn1, "test1")
				Expect(err).ToNot(HaveOccurred())
			}()

			done2 := make(chan interface{})
			go func() {
				defer GinkgoRecover()
				defer close(done2)

				var err error
				Eventually(func() error {
					conn2, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data2, err = sendData(conn2, "test2")
				Expect(err).ToNot(HaveOccurred())
			}()

			done3 := make(chan interface{})
			go func() {
				defer GinkgoRecover()
				defer close(done3)

				var err error
				Eventually(func() error {
					conn3, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data3, err = sendData(conn3, "test3")
				Expect(err).ToNot(HaveOccurred())
			}()

			<-done1
			<-done2
			<-done3

			Expect(data1).Should(ContainSubstring(fmt.Sprintf("Echo from port %d: test1", backendPort)))
			Expect(data2).Should(ContainSubstring(fmt.Sprintf("Echo from port %d: test2", backendPort)))
			Expect(data3).Should(ContainSubstring(fmt.Sprintf("Echo from port %d: test3", backendPort)))
		})
	})

	Context("when other clients disconnect", func() {
		var conn net.Conn
		var connToDisconnect net.Conn

		It("maintains a long-lived connection when other clients disconnect", func() {
			Eventually(func() error {
				var err error
				conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
				return err
			}).ShouldNot(HaveOccurred())

			Eventually(func() error {
				var err error
				connToDisconnect, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
				return err
			}).ShouldNot(HaveOccurred())

			dataBeforeDisconnect, err := sendData(conn, "data before disconnect")
			Expect(err).ToNot(HaveOccurred())
			Expect(dataBeforeDisconnect).Should(ContainSubstring("data before disconnect"))

			connToDisconnect.Close()

			dataAfterDisconnect, err := sendData(conn, "data after disconnect")
			Expect(err).ToNot(HaveOccurred())
			Expect(dataAfterDisconnect).Should(ContainSubstring("data after disconnect"))
		})
	})

	Context("when the healthcheck succeeds", func() {
		var client net.Conn

		It("checks health again after the specified interval", func() {
			Eventually(func() error {
				var err error
				client, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
				return err
			}).ShouldNot(HaveOccurred())

			buffer := make([]byte, 1024)

			client.Write([]byte("data around first healthcheck"))
			n, err := client.Read(buffer)
			Expect(err).ToNot(HaveOccurred())
			Expect(string(buffer[:n])).Should(ContainSubstring("data around first healthcheck"))

			Consistently(func() error {
				client.Write([]byte("data around subsequent healthcheck"))
				_, err = client.Read(buffer)
				return err
			}, 3*time.Second).ShouldNot(HaveOccurred())
		})
	})
	Context("when the cluster is down", func() {
		Context("when the healthcheck reports a 503", func() {
			It("disconnects client connections", func() {
				var conn net.Conn
				Eventually(func() error {
					var err error
					conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				dataWhileHealthy, err := sendData(conn, "data while healthy")
				Expect(err).ToNot(HaveOccurred())
				Expect(dataWhileHealthy).Should(ContainSubstring("data while healthy"))

				resp, httpErr := http.Get(fmt.Sprintf("http://localhost:%d/set503", dummyHealthcheckPort))
				Expect(httpErr).NotTo(HaveOccurred())
				Expect(resp.StatusCode).To(Equal(http.StatusOK))

				resp, httpErr = http.Get(fmt.Sprintf("http://localhost:%d/", dummyHealthcheckPort))
				Expect(resp.StatusCode).To(Equal(http.StatusServiceUnavailable))
				Expect(httpErr).NotTo(HaveOccurred())

				Eventually(func() error {
					_, err := sendData(conn, "data when unhealthy")
					return err
				}, 2*time.Second).Should(HaveOccurred())
			})
		})

		Context("when the healthcheck hangs", func() {
			It("disconnects existing client connections", func(done Done) {
				defer close(done)
				defer GinkgoRecover()

				var conn net.Conn
				Eventually(func() (err error) {
					conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data, err := sendData(conn, "data before hang")
				Expect(err).ShouldNot(HaveOccurred())
				Expect(data).Should(ContainSubstring("data before hang"))
				resp, httpErr := http.Get(fmt.Sprintf("http://localhost:%d/setHang", dummyHealthcheckPort))

				Expect(httpErr).NotTo(HaveOccurred())
				Expect(resp.StatusCode).To(Equal(http.StatusOK))

				Eventually(func() error {
					_, err := sendData(conn, "data after hang")
					return err
				}, healthcheckTimeout*4).Should(HaveOccurred())
			}, 5)

			It("rejects any new connections that are attempted", func(done Done) {
				defer close(done)
				defer GinkgoRecover()

				resp, httpErr := http.Get(fmt.Sprintf("http://localhost:%d/setHang", dummyHealthcheckPort))
				Expect(httpErr).NotTo(HaveOccurred())
				Expect(resp.StatusCode).To(Equal(http.StatusOK))

				resp, httpErr = http.Get(fmt.Sprintf("http://localhost:%d/setHang", dummyHealthcheckPort2))
				Expect(httpErr).NotTo(HaveOccurred())
				Expect(resp.StatusCode).To(Equal(http.StatusOK))

				time.Sleep(3 * healthcheckTimeout)

				var conn net.Conn
				Eventually(func() (err error) {
					conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}, 1*time.Second).ShouldNot(HaveOccurred())

				Eventually(func() error {
					_, err := sendData(conn, "write that should fail")
					return err
				}, healthcheckTimeout*4).Should(HaveOccurred())

			}, 20)
		})
	})
})
<commit_msg>Add integration test for failover<commit_after>package main_test

import (
	"fmt"
	"net"
	"net/http"
	"os/exec"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
	"github.com/onsi/gomega/gexec"
)

func startSwitchboard(args ...string) *gexec.Session {
	command := exec.Command(switchboardBinPath, args...)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	Eventually(session).Should(gbytes.Say("started on port"))
	return session
}

func startBackend(args ...string) *gexec.Session {
	command := exec.Command(dummyListenerBinPath, args...)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	Eventually(session).Should(gbytes.Say("Backend listening on"))
	return session
}

func startHealthcheck(args ...string) *gexec.Session {
	command := exec.Command(dummyHealthcheckBinPath, args...)
	session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
	Expect(err).NotTo(HaveOccurred())
	Eventually(session).Should(gbytes.Say("Healthcheck listening on"))
	return session
}

func sendData(conn net.Conn, data string) (string, error) {
	conn.Write([]byte(data))
	buffer := make([]byte, 1024)
	_, err := conn.Read(buffer)
	if err != nil {
		return "", err
	} else {
		return string(buffer), nil
	}
}

var _ = Describe("Switchboard", func() {
	var (
		backendSession      *gexec.Session
		backendSession2     *gexec.Session
		healthcheckSession  *gexec.Session
		healthcheckSession2 *gexec.Session
		proxySession        *gexec.Session
		healthcheckTimeout  time.Duration
	)

	BeforeEach(func() {
		healthcheckTimeout = 500 * time.Millisecond

		backendSession = startBackend(
			fmt.Sprintf("-port=%d", backendPort),
		)

		backendSession2 = startBackend(
			fmt.Sprintf("-port=%d", backendPort2),
		)

		healthcheckSession = startHealthcheck(
			fmt.Sprintf("-port=%d", dummyHealthcheckPort),
		)

		healthcheckSession2 = startHealthcheck(
			fmt.Sprintf("-port=%d", dummyHealthcheckPort2),
		)

		proxySession = startSwitchboard(
			"-backendIPs=localhost, localhost",
			fmt.Sprintf("-port=%d", switchboardPort),
			fmt.Sprintf("-backendPorts=%d,%d", backendPort, backendPort2),
			fmt.Sprintf("-healthcheckPorts=%d,%d", dummyHealthcheckPort, dummyHealthcheckPort2),
			fmt.Sprintf("-healthcheckTimeout=%s", healthcheckTimeout),
			fmt.Sprintf("-pidfile=%s", pidfile),
		)
	})

	AfterEach(func() {
		proxySession.Terminate()
		healthcheckSession2.Terminate()
		healthcheckSession.Terminate()
		backendSession2.Terminate()
		backendSession.Terminate()
	})

	Context("when there are multiple concurrent clients", func() {
		var conn1, conn2, conn3 net.Conn
		var data1, data2, data3 string

		It("proxies all the connections to the backend", func() {
			done1 := make(chan interface{})
			go func() {
				defer GinkgoRecover()
				defer close(done1)

				var err error
				Eventually(func() error {
					conn1, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data1, err = sendData(conn1, "test1")
				Expect(err).ToNot(HaveOccurred())
			}()

			done2 := make(chan interface{})
			go func() {
				defer GinkgoRecover()
				defer close(done2)

				var err error
				Eventually(func() error {
					conn2, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data2, err = sendData(conn2, "test2")
				Expect(err).ToNot(HaveOccurred())
			}()

			done3 := make(chan interface{})
			go func() {
				defer GinkgoRecover()
				defer close(done3)

				var err error
				Eventually(func() error {
					conn3, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data3, err = sendData(conn3, "test3")
				Expect(err).ToNot(HaveOccurred())
			}()

			<-done1
			<-done2
			<-done3

			Expect(data1).Should(ContainSubstring(fmt.Sprintf("Echo from port %d: test1", backendPort)))
			Expect(data2).Should(ContainSubstring(fmt.Sprintf("Echo from port %d: test2", backendPort)))
			Expect(data3).Should(ContainSubstring(fmt.Sprintf("Echo from port %d: test3", backendPort)))
		})
	})

	Context("when other clients disconnect", func() {
		var conn net.Conn
		var connToDisconnect net.Conn

		It("maintains a long-lived connection when other clients disconnect", func() {
			Eventually(func() error {
				var err error
				conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
				return err
			}).ShouldNot(HaveOccurred())

			Eventually(func() error {
				var err error
				connToDisconnect, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
				return err
			}).ShouldNot(HaveOccurred())

			dataBeforeDisconnect, err := sendData(conn, "data before disconnect")
			Expect(err).ToNot(HaveOccurred())
			Expect(dataBeforeDisconnect).Should(ContainSubstring("data before disconnect"))

			connToDisconnect.Close()

			dataAfterDisconnect, err := sendData(conn, "data after disconnect")
			Expect(err).ToNot(HaveOccurred())
			Expect(dataAfterDisconnect).Should(ContainSubstring("data after disconnect"))
		})
	})

	Context("when the healthcheck succeeds", func() {
		var client net.Conn

		It("checks health again after the specified interval", func() {
			Eventually(func() error {
				var err error
				client, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
				return err
			}).ShouldNot(HaveOccurred())

			buffer := make([]byte, 1024)

			client.Write([]byte("data around first healthcheck"))
			n, err := client.Read(buffer)
			Expect(err).ToNot(HaveOccurred())
			Expect(string(buffer[:n])).Should(ContainSubstring("data around first healthcheck"))

			Consistently(func() error {
				client.Write([]byte("data around subsequent healthcheck"))
				_, err = client.Read(buffer)
				return err
			}, 3*time.Second).ShouldNot(HaveOccurred())
		})
	})

	Context("when the cluster is down", func() {
		Context("when the healthcheck reports a 503", func() {
			It("disconnects client connections", func() {
				var conn net.Conn
				Eventually(func() error {
					var err error
					conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				dataWhileHealthy, err := sendData(conn, "data while healthy")
				Expect(err).ToNot(HaveOccurred())
				Expect(dataWhileHealthy).Should(ContainSubstring("data while healthy"))

				resp, httpErr := http.Get(fmt.Sprintf("http://localhost:%d/set503", dummyHealthcheckPort))
				Expect(httpErr).NotTo(HaveOccurred())
				Expect(resp.StatusCode).To(Equal(http.StatusOK))

				resp, httpErr = http.Get(fmt.Sprintf("http://localhost:%d/", dummyHealthcheckPort))
				Expect(resp.StatusCode).To(Equal(http.StatusServiceUnavailable))
				Expect(httpErr).NotTo(HaveOccurred())

				Eventually(func() error {
					_, err := sendData(conn, "data when unhealthy")
					return err
				}, 2*time.Second).Should(HaveOccurred())
			})
		})

		Context("when a backend goes down", func() {
			var conn net.Conn
			var data string

			BeforeEach(func() {
				Eventually(func() (err error) {
					conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data, err := sendData(conn, "data before hang")
				Expect(err).ShouldNot(HaveOccurred())
				Expect(data).Should(ContainSubstring("data before hang"))

				resp, httpErr := http.Get(fmt.Sprintf("http://localhost:%d/setHang", dummyHealthcheckPort))
				Expect(httpErr).NotTo(HaveOccurred())
				Expect(resp.StatusCode).To(Equal(http.StatusOK))
			})

			It("disconnects existing client connections", func(done Done) {
				defer close(done)

				Eventually(func() error {
					_, err := sendData(conn, "data after hang")
					return err
				}, healthcheckTimeout*4).Should(HaveOccurred())
			}, 5)

			It("proxies new connections to another backend", func(done Done) {
				defer close(done)

				time.Sleep(3 * healthcheckTimeout) // wait for failover

				var err error
				Eventually(func() error {
					conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}).ShouldNot(HaveOccurred())

				data, err = sendData(conn, "test")
				Expect(err).ToNot(HaveOccurred())
				Expect(data).Should(ContainSubstring(fmt.Sprintf("Echo from port %d: test", backendPort2)))
			}, 5)
		})

		Context("when all backends are down", func() {
			BeforeEach(func() {
				resp, httpErr := http.Get(fmt.Sprintf("http://localhost:%d/setHang", dummyHealthcheckPort))
				Expect(httpErr).NotTo(HaveOccurred())
				Expect(resp.StatusCode).To(Equal(http.StatusOK))

				resp, httpErr = http.Get(fmt.Sprintf("http://localhost:%d/setHang", dummyHealthcheckPort2))
				Expect(httpErr).NotTo(HaveOccurred())
				Expect(resp.StatusCode).To(Equal(http.StatusOK))
			})

			It("rejects any new connections that are attempted", func(done Done) {
				defer close(done)

				time.Sleep(3 * healthcheckTimeout) // wait for failover

				var conn net.Conn
				Eventually(func() (err error) {
					conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%d", switchboardPort))
					return err
				}, 1*time.Second).ShouldNot(HaveOccurred())

				Eventually(func() error {
					_, err := sendData(conn, "write that should fail")
					return err
				}, healthcheckTimeout*4).Should(HaveOccurred())

			}, 20)
		})
	})
})
<|endoftext|>


<commit_before><commit_msg>Improved perf of bar.Completed method<commit_after><|endoftext|>


<commit_before><commit_msg>change package of doc.go so the docs show up in godoc and godoc.org<commit_after><|endoftext|>


<commit_before><commit_msg>When generating a certificate, just match the SNI.<commit_after><|endoftext|>


<commit_before><commit_msg>Use TLS SNI when fetching certificate to imitate.<commit_after><|endoftext|>


<commit_before>package main

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
)

var dataUrlPattern *regexp.Regexp

func handleGet(res http.ResponseWriter, req *http.Request) {
	url := req.URL.Query().Get("url")
	match := dataUrlPattern.FindStringSubmatch(url)
	if len(match) == 0 {
		log.Println("get.error.url:", url)
		http.Error(res, "Parameter 'url' must be present and in RFC 2397 form", http.StatusBadRequest)
		return
	}
	contentType := match[1]
	isBase64 := match[2] != ""
	data := match[3]

	res.Header().Set("Content-Type", contentType)
	if isBase64 {
		decoded, err := base64.StdEncoding.DecodeString(data)
		if err != nil {
			log.Println("get.error.base64.decode:", err)
			http.Error(res, "Error decoding base64: "+err.Error(), http.StatusBadRequest)
			return
		}
		res.Write(decoded)
	} else {
		fmt.Fprint(res, data)
	}
}

func handlePost(res http.ResponseWriter, req *http.Request) {
	scheme := "http"
	if req.TLS != nil || req.Header.Get("X-Forwarded-Proto") == "https" {
		scheme = "https"
	}

	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Println("post.error.body:", err)
		http.Error(res, "Error reading request body: "+err.Error(), http.StatusBadRequest)
		return
	}

	contentType := req.Header.Get("Content-Type")
	if contentType == "" || contentType == "application/x-www-form-urlencoded" {
		contentType = http.DetectContentType(data)
	}

	base64 := base64.StdEncoding.EncodeToString(data)
	dataUrl := "data:" + contentType + ";base64," + base64
	url := scheme + "://" + req.Host + req.URL.Path + "?url=" + url.QueryEscape(dataUrl)

	fmt.Fprint(res, url)
}

func main() {
	dataUrlPattern, _ = regexp.Compile("^data:(.*?)?(;base64)?,(.+)$")

	http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
		switch req.Method {
		case "GET":
			handleGet(res, req)
		case "POST":
			handlePost(res, req)
		default:
			http.Error(res, "Only GET and POST supported", http.StatusMethodNotAllowed)
		}
	})

	log.Println("listening:true port:", os.Getenv("PORT"))
	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}
<commit_msg>log listening after listening<commit_after>package main

import (
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"os"
	"regexp"
)

var dataUrlPattern *regexp.Regexp

func handleGet(res http.ResponseWriter, req *http.Request) {
	url := req.URL.Query().Get("url")
	match := dataUrlPattern.FindStringSubmatch(url)
	if len(match) == 0 {
		log.Println("get.error.url:", url)
		http.Error(res, "Parameter 'url' must be present and in RFC 2397 form", http.StatusBadRequest)
		return
	}
	contentType := match[1]
	isBase64 := match[2] != ""
	data := match[3]

	res.Header().Set("Content-Type", contentType)
	if isBase64 {
		decoded, err := base64.StdEncoding.DecodeString(data)
		if err != nil {
			log.Println("get.error.base64.decode:", err)
			http.Error(res, "Error decoding base64: "+err.Error(), http.StatusBadRequest)
			return
		}
		res.Write(decoded)
	} else {
		fmt.Fprint(res, data)
	}
}

func handlePost(res http.ResponseWriter, req *http.Request) {
	scheme := "http"
	if req.TLS != nil || req.Header.Get("X-Forwarded-Proto") == "https" {
		scheme = "https"
	}

	data, err := ioutil.ReadAll(req.Body)
	if err != nil {
		log.Println("post.error.body:", err)
		http.Error(res, "Error reading request body: "+err.Error(), http.StatusBadRequest)
		return
	}

	contentType := req.Header.Get("Content-Type")
	if contentType == "" || contentType == "application/x-www-form-urlencoded" {
		contentType = http.DetectContentType(data)
	}

	base64 := base64.StdEncoding.EncodeToString(data)
	dataUrl := "data:" + contentType + ";base64," + base64
	url := scheme + "://" + req.Host + req.URL.Path + "?url=" + url.QueryEscape(dataUrl)

	fmt.Fprint(res, url)
}

func main() {
	dataUrlPattern, _ = regexp.Compile("^data:(.*?)?(;base64)?,(.+)$")

	http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
		switch req.Method {
		case "GET":
			handleGet(res, req)
		case "POST":
			handlePost(res, req)
		default:
			http.Error(res, "Only GET and POST supported", http.StatusMethodNotAllowed)
		}
	})

    port := os.Getenv("PORT")
	err := http.ListenAndServe(":"+port, nil)
	if err != nil {
		panic(err)
	}
	log.Println("listening:true port:", port)
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"regexp"
	"time"
)

var idChars = []rune("0123456789abcdef")
var idLength = 32

func randId() string {
	b := make([]rune, idLength)
	for i := range b {
		b[i] = idChars[rand.Intn(len(idChars))]
	}
	return string(b)
}

type Clients struct {
	clientsById    map[string]Client
	subscriptions  map[string]map[Client]bool
	newClients     chan Client
	defunctClients chan Client
	calls          chan rpcCall
}

type Client struct {
	id      string
	session string
	channel chan string
}

type rpcCall struct {
	client Client
	body   string
}

func (c *Clients) subscribe(id string, client Client) {
	_, set := c.subscriptions[id]
	if !set {
		c.subscriptions[id] = map[Client]bool{client: true}
	} else {
		c.subscriptions[id][client] = true
	}
}

func (c *Clients) unsubscribe(id string, client Client) {
	delete(c.subscriptions[id], client)
	if len(c.subscriptions[id]) == 0 {
		delete(c.subscriptions, id)
	}
}

func (c *Clients) Start(conn net.Conn) {
	for {
		select {
		case client := <-c.newClients:
			c.clientsById[client.id] = client
			c.subscribe(client.id, client)
			c.subscribe(client.session, client)
			c.subscribe("world", client)
			fmt.Fprintf(conn, "connected %s %s\n", client.id, client.session)
			fmt.Printf("-> connected %s %s\n", client.id, client.session)
		case client := <-c.defunctClients:
			c.unsubscribe(client.id, client)
			c.unsubscribe(client.session, client)
			c.unsubscribe("world", client)
			delete(c.clientsById, client.id)
			fmt.Fprintf(conn, "disconnected %s %s\n", client.id, client.session)
			fmt.Printf("-> disconnected %s %s\n", client.id, client.session)
		case call := <-c.calls:
			fmt.Fprintf(conn, "call %s %s\n", call.client.id, call.body)
			fmt.Printf("-> call %s %s\n", call.client.id, call.body)
		}
	}
}

func (c *Clients) processCall(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Error reading body.", http.StatusInternalServerError)
		fmt.Println(err)
		return
	}
	client := c.clientsById[r.URL.Path]
	c.calls <- rpcCall{client, string(body)}
}

func (c *Clients) processStream(w http.ResponseWriter, r *http.Request) {
	cookie, err := r.Cookie("session")
	var sessionId string
	if err == http.ErrNoCookie {
		sessionId = "session" + randId()
		http.SetCookie(w, &http.Cookie{Name: "session",
			Value:    sessionId,
			Path:     "/",
			Expires:  time.Now().AddDate(1, 0, 0),
			MaxAge:   60 * 60 * 24 * 365,
			Secure:   true,
			HttpOnly: true})
	} else {
		sessionId = cookie.Value
	}

	f, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
		return
	}

	id := r.URL.Path
	messageChan := make(chan string)
	client := Client{id, sessionId, messageChan}
	c.newClients <- client

	notify := w.(http.CloseNotifier).CloseNotify()
	go func() {
		<-notify
		c.defunctClients <- client
	}()

	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")

	// Tell nginx to not buffer. Without this it may take up to a minute
	// for events to arrive at the client.
	w.Header().Set("X-Accel-Buffering", "no")

	// Send something to force the headers to flush.
	fmt.Fprintf(w, "\n\n")
	f.Flush()

	for {
		select {
		case msg := <-messageChan:
			fmt.Fprintf(w, "data: %s\n\n", msg)
		case <-time.After(30 * time.Second):
			fmt.Fprintf(w, ":heartbeat\n\n")
		}
		f.Flush()
	}
}

var pattern = regexp.MustCompile(`(\S+) (\S+) (.*)`)

func ReadCommands(conn net.Conn, clients *Clients) {
	reader := bufio.NewReader(conn)
	for {
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			// If the socket is closed we will be having connection errors
			// everywhere when we try to report events. Best to close
			// everything.
			panic("Command center client disconnected.")
		}
		if err != nil {
			panic(err)
		}
		parts := pattern.FindStringSubmatch(line)
		if len(parts) == 0 {
			fmt.Println("Invalid command format. Expected 'command id params'.\n")
			continue
		}
		command := parts[1]
		id := parts[2]
		params := parts[3]
		fmt.Println("<- " + line)
		switch command {
		case "send":
			for client, _ := range clients.subscriptions[id] {
				client.channel <- params
			}
		default:
			fmt.Println("Invalid command " + command + "\n")
		}
	}
}

func waitForClient() net.Conn {
	fmt.Println("Listening for command center client at :8001.")

	ln, err := net.Listen("tcp", ":8001")
	if err != nil {
		panic(err.Error())
	}

	conn, err := ln.Accept()
	if err != nil {
		panic(err.Error())
	}

	fmt.Println("Command center client connected.")

	return conn
}

func main() {
	rand.Seed(time.Now().UTC().UnixNano())

	conn := waitForClient()

	clients := &Clients{
		make(map[string]Client),
		make(map[string]map[Client]bool),
		make(chan Client),
		make(chan Client),
		make(chan rpcCall),
	}

	go clients.Start(conn)

	go ReadCommands(conn, clients)

	http.Handle("/call/", http.StripPrefix("/call/", http.HandlerFunc(clients.processCall)))
	http.Handle("/events/", http.StripPrefix("/events/", http.HandlerFunc(clients.processStream)))

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "index.html")
	})
	http.HandleFunc("/sse.js", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "sse.js")
	})
	http.HandleFunc("/polyfill.js", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "polyfill.js")
	})
	panic(http.ListenAndServe(":8080", nil))
}
<commit_msg>Use handlers package to simplify serving<commit_after>package main

import (
	"bufio"
	"fmt"
	"github.com/boppreh/gohandlers"
	"io"
	"io/ioutil"
	"math/rand"
	"net"
	"net/http"
	"regexp"
	"time"
)

var idChars = []rune("0123456789abcdef")
var idLength = 32

func randId() string {
	b := make([]rune, idLength)
	for i := range b {
		b[i] = idChars[rand.Intn(len(idChars))]
	}
	return string(b)
}

type Clients struct {
	clientsById    map[string]Client
	subscriptions  map[string]map[Client]bool
	newClients     chan Client
	defunctClients chan Client
	calls          chan rpcCall
}

type Client struct {
	id      string
	session string
	channel chan string
}

type rpcCall struct {
	client Client
	body   string
}

func (c *Clients) subscribe(id string, client Client) {
	_, set := c.subscriptions[id]
	if !set {
		c.subscriptions[id] = map[Client]bool{client: true}
	} else {
		c.subscriptions[id][client] = true
	}
}

func (c *Clients) unsubscribe(id string, client Client) {
	delete(c.subscriptions[id], client)
	if len(c.subscriptions[id]) == 0 {
		delete(c.subscriptions, id)
	}
}

func (c *Clients) Start(conn net.Conn) {
	for {
		select {
		case client := <-c.newClients:
			c.clientsById[client.id] = client
			c.subscribe(client.id, client)
			c.subscribe(client.session, client)
			c.subscribe("world", client)
			fmt.Fprintf(conn, "connected %s %s\n", client.id, client.session)
			fmt.Printf("-> connected %s %s\n", client.id, client.session)
		case client := <-c.defunctClients:
			c.unsubscribe(client.id, client)
			c.unsubscribe(client.session, client)
			c.unsubscribe("world", client)
			delete(c.clientsById, client.id)
			fmt.Fprintf(conn, "disconnected %s %s\n", client.id, client.session)
			fmt.Printf("-> disconnected %s %s\n", client.id, client.session)
		case call := <-c.calls:
			fmt.Fprintf(conn, "call %s %s\n", call.client.id, call.body)
			fmt.Printf("-> call %s %s\n", call.client.id, call.body)
		}
	}
}

func (c *Clients) processCall(w http.ResponseWriter, r *http.Request) {
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Error reading body.", http.StatusInternalServerError)
		fmt.Println(err)
		return
	}
	client := c.clientsById[r.URL.Path]
	c.calls <- rpcCall{client, string(body)}
}

func (c *Clients) processStream(w http.ResponseWriter, r *http.Request) {
	cookie, err := r.Cookie("session")
	var sessionId string
	if err == http.ErrNoCookie {
		sessionId = "session" + randId()
		http.SetCookie(w, &http.Cookie{Name: "session",
			Value:    sessionId,
			Path:     "/",
			Expires:  time.Now().AddDate(1, 0, 0),
			MaxAge:   60 * 60 * 24 * 365,
			Secure:   true,
			HttpOnly: true})
	} else {
		sessionId = cookie.Value
	}

	f, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
		return
	}

	id := r.URL.Path
	messageChan := make(chan string)
	client := Client{id, sessionId, messageChan}
	c.newClients <- client

	notify := w.(http.CloseNotifier).CloseNotify()
	go func() {
		<-notify
		c.defunctClients <- client
	}()

	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")

	// Tell nginx to not buffer. Without this it may take up to a minute
	// for events to arrive at the client.
	w.Header().Set("X-Accel-Buffering", "no")

	// Send something to force the headers to flush.
	fmt.Fprintf(w, "\n\n")
	f.Flush()

	for {
		select {
		case msg := <-messageChan:
			fmt.Fprintf(w, "data: %s\n\n", msg)
		case <-time.After(30 * time.Second):
			fmt.Fprintf(w, ":heartbeat\n\n")
		}
		f.Flush()
	}
}

var pattern = regexp.MustCompile(`(\S+) (\S+) (.*)`)

func ReadCommands(conn net.Conn, clients *Clients) {
	reader := bufio.NewReader(conn)
	for {
		line, err := reader.ReadString('\n')
		if err == io.EOF {
			// If the socket is closed we will be having connection errors
			// everywhere when we try to report events. Best to close
			// everything.
			panic("Command center client disconnected.")
		}
		if err != nil {
			panic(err)
		}
		parts := pattern.FindStringSubmatch(line)
		if len(parts) == 0 {
			fmt.Println("Invalid command format. Expected 'command id params'.\n")
			continue
		}
		command := parts[1]
		id := parts[2]
		params := parts[3]
		fmt.Println("<- " + line)
		switch command {
		case "send":
			for client, _ := range clients.subscriptions[id] {
				client.channel <- params
			}
		default:
			fmt.Println("Invalid command " + command + "\n")
		}
	}
}

func waitForClient() net.Conn {
	fmt.Println("Listening for command center client at :8001.")

	ln, err := net.Listen("tcp", ":8001")
	if err != nil {
		panic(err.Error())
	}

	conn, err := ln.Accept()
	if err != nil {
		panic(err.Error())
	}

	fmt.Println("Command center client connected.")

	return conn
}

func main() {
	rand.Seed(time.Now().UTC().UnixNano())

	conn := waitForClient()

	clients := &Clients{
		make(map[string]Client),
		make(map[string]map[Client]bool),
		make(chan Client),
		make(chan Client),
		make(chan rpcCall),
	}

	go clients.Start(conn)

	go ReadCommands(conn, clients)

	handlers.ServeIndex("index.html")
	handlers.ServeFile("sse.js")
	handlers.ServeFile("polyfill.js")
	handlers.HandleFuncStripped("/call", clients.processCall)
	handlers.HandleFuncStripped("/events", clients.processStream)
	handlers.Start("8080")
}
<|endoftext|>


<commit_before><commit_msg>new file<commit_after><|endoftext|>


<commit_before><commit_msg>Added new cases to command line<commit_after><|endoftext|>


<commit_before><commit_msg>Moved help functionality to core<commit_after><|endoftext|>


<commit_before><commit_msg>Find the largest palindrome made from the product of two 3-digit numbers.<commit_after><|endoftext|>


<commit_before><commit_msg>Rough version of something half-working<commit_after><|endoftext|>


<commit_before><commit_msg>more debug<commit_after><|endoftext|>


<commit_before><commit_msg>replace bold with quotes because people will be copying the raid names and slack will copy formatting if they copy the spaces before and or after the bolded text...<commit_after><|endoftext|>


<commit_before><commit_msg>Fixed memory leak with keep-alive connections<commit_after><|endoftext|>


<commit_before><commit_msg>bump up version to 0.3.2<commit_after><|endoftext|>


<commit_before><commit_msg>Add all query string<commit_after><|endoftext|>


<commit_before><commit_msg>updates<commit_after><|endoftext|>


<commit_before><commit_msg>Add creating todirname directory<commit_after><|endoftext|>


<commit_before><commit_msg>Implemented linear scaling on CPU, but performances aren't great<commit_after><|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"

	"github.com/codegangsta/envy/lib"
	"github.com/codegangsta/gin/lib"
	shellwords "github.com/mattn/go-shellwords"
	"gopkg.in/urfave/cli.v1"

	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"
)

var (
	startTime  = time.Now()
	logger     = log.New(os.Stdout, "[gin] ", 0)
	immediate  = false
	buildError error
	colorGreen = string([]byte{27, 91, 57, 55, 59, 51, 50, 59, 49, 109})
	colorRed   = string([]byte{27, 91, 57, 55, 59, 51, 49, 59, 49, 109})
	colorReset = string([]byte{27, 91, 48, 109})
)

func main() {
	app := cli.NewApp()
	app.Name = "gin"
	app.Usage = "A live reload utility for Go web applications."
	app.Action = MainAction
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "laddr,l",
			Value: "",
			Usage: "listening address for the proxy server",
		},
		cli.IntFlag{
			Name:  "port,p",
			Value: 3000,
			Usage: "port for the proxy server",
		},
		cli.IntFlag{
			Name:  "appPort,a",
			Value: 3001,
			Usage: "port for the Go web server",
		},
		cli.StringFlag{
			Name:  "bin,b",
			Value: "gin-bin",
			Usage: "name of generated binary file",
		},
		cli.StringFlag{
			Name:  "path,t",
			Value: ".",
			Usage: "Path to watch files from",
		},
		cli.StringSliceFlag{
			Name:  "excludeDir,x",
			Value: &cli.StringSlice{},
			Usage: "Relative directories to exclude",
		},
		cli.BoolFlag{
			Name:  "immediate,i",
			Usage: "run the server immediately after it's built",
		},
		cli.BoolFlag{
			Name:  "all",
			Usage: "reloads whenever any file changes, as opposed to reloading only on .go file change",
		},
		cli.BoolFlag{
			Name:  "godep,g",
			Usage: "use godep when building",
		},
		cli.StringFlag{
			Name:  "buildArgs",
			Usage: "Additional go build arguments",
		},
		cli.StringFlag{
			Name:  "certFile",
			Usage: "TLS Certificate",
		},
		cli.StringFlag{
			Name:  "keyFile",
			Usage: "TLS Certificate Key",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:      "run",
			ShortName: "r",
			Usage:     "Run the gin proxy in the current working directory",
			Action:    MainAction,
		},
		{
			Name:      "env",
			ShortName: "e",
			Usage:     "Display environment variables set by the .env file",
			Action:    EnvAction,
		},
	}

	app.Run(os.Args)
}

func MainAction(c *cli.Context) {
	laddr := c.GlobalString("laddr")
	port := c.GlobalInt("port")
	all := c.GlobalBool("all")
	appPort := strconv.Itoa(c.GlobalInt("appPort"))
	immediate = c.GlobalBool("immediate")
	keyFile := c.GlobalString("keyFile")
	certFile := c.GlobalString("certFile")

	// Bootstrap the environment
	envy.Bootstrap()

	// Set the PORT env
	os.Setenv("PORT", appPort)

	wd, err := os.Getwd()
	if err != nil {
		logger.Fatal(err)
	}

	buildArgs, err := shellwords.Parse(c.GlobalString("buildArgs"))
	if err != nil {
		logger.Fatal(err)
	}

	builder := gin.NewBuilder(c.GlobalString("path"), c.GlobalString("bin"), c.GlobalBool("godep"), wd, buildArgs)
	runner := gin.NewRunner(filepath.Join(wd, builder.Binary()), c.Args()...)
	runner.SetWriter(os.Stdout)
	proxy := gin.NewProxy(builder, runner)

	config := &gin.Config{
		Laddr:    laddr,
		Port:     port,
		ProxyTo:  "http://localhost:" + appPort,
		KeyFile:  keyFile,
		CertFile: certFile,
	}

	err = proxy.Run(config)
	if err != nil {
		logger.Fatal(err)
	}

	if laddr != "" {
		logger.Printf("listening at %s:%d\n", laddr, port)
	} else {
		logger.Printf("listening on port %d\n", port)
	}

	shutdown(runner)

	// build right now
	build(builder, runner, logger)

	// scan for changes
	scanChanges(c.GlobalString("path"), c.GlobalStringSlice("excludeDir"), all, func(path string) {
		runner.Kill()
		build(builder, runner, logger)
	})
}

func EnvAction(c *cli.Context) {
	// Bootstrap the environment
	env, err := envy.Bootstrap()
	if err != nil {
		logger.Fatalln(err)
	}

	for k, v := range env {
		fmt.Printf("%s: %s\n", k, v)
	}

}

func build(builder gin.Builder, runner gin.Runner, logger *log.Logger) {
	err := builder.Build()
	if err != nil {
		buildError = err
		logger.Printf("%sERROR! Build failed.%s\n", colorRed, colorReset)
		fmt.Println(builder.Errors())
	} else {
		// print success only if there were errors before
		if buildError != nil {
			logger.Printf("%sBuild Successful%s\n", colorGreen, colorReset)
		}
		buildError = nil
		if immediate {
			runner.Run()
		}
	}

	time.Sleep(100 * time.Millisecond)
}

type scanCallback func(path string)

func scanChanges(watchPath string, excludeDirs []string, allFiles bool, cb scanCallback) {
	for {
		filepath.Walk(watchPath, func(path string, info os.FileInfo, err error) error {
			if path == ".git" {
				return filepath.SkipDir
			}
			for _, x := range excludeDirs {
				if x == path {
					return filepath.SkipDir
				}
			}

			// ignore hidden files
			if filepath.Base(path)[0] == '.' {
				return nil
			}

			if (allFiles || filepath.Ext(path) == ".go") && info.ModTime().After(startTime) {
				cb(path)
				startTime = time.Now()
				return errors.New("done")
			}

			return nil
		})
		time.Sleep(500 * time.Millisecond)
	}
}

func shutdown(runner gin.Runner) {
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-c
		log.Println("Got signal: ", s)
		err := runner.Kill()
		if err != nil {
			log.Print("Error killing: ", err)
		}
		os.Exit(1)
	}()
}
<commit_msg>Don't skip directory accidentally if .git is a file instead of a directory (e.g. when it's a submodule).<commit_after>package main

import (
	"errors"
	"fmt"

	"github.com/codegangsta/envy/lib"
	"github.com/codegangsta/gin/lib"
	shellwords "github.com/mattn/go-shellwords"
	"gopkg.in/urfave/cli.v1"

	"log"
	"os"
	"os/signal"
	"path/filepath"
	"strconv"
	"syscall"
	"time"
)

var (
	startTime  = time.Now()
	logger     = log.New(os.Stdout, "[gin] ", 0)
	immediate  = false
	buildError error
	colorGreen = string([]byte{27, 91, 57, 55, 59, 51, 50, 59, 49, 109})
	colorRed   = string([]byte{27, 91, 57, 55, 59, 51, 49, 59, 49, 109})
	colorReset = string([]byte{27, 91, 48, 109})
)

func main() {
	app := cli.NewApp()
	app.Name = "gin"
	app.Usage = "A live reload utility for Go web applications."
	app.Action = MainAction
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "laddr,l",
			Value: "",
			Usage: "listening address for the proxy server",
		},
		cli.IntFlag{
			Name:  "port,p",
			Value: 3000,
			Usage: "port for the proxy server",
		},
		cli.IntFlag{
			Name:  "appPort,a",
			Value: 3001,
			Usage: "port for the Go web server",
		},
		cli.StringFlag{
			Name:  "bin,b",
			Value: "gin-bin",
			Usage: "name of generated binary file",
		},
		cli.StringFlag{
			Name:  "path,t",
			Value: ".",
			Usage: "Path to watch files from",
		},
		cli.StringSliceFlag{
			Name:  "excludeDir,x",
			Value: &cli.StringSlice{},
			Usage: "Relative directories to exclude",
		},
		cli.BoolFlag{
			Name:  "immediate,i",
			Usage: "run the server immediately after it's built",
		},
		cli.BoolFlag{
			Name:  "all",
			Usage: "reloads whenever any file changes, as opposed to reloading only on .go file change",
		},
		cli.BoolFlag{
			Name:  "godep,g",
			Usage: "use godep when building",
		},
		cli.StringFlag{
			Name:  "buildArgs",
			Usage: "Additional go build arguments",
		},
		cli.StringFlag{
			Name:  "certFile",
			Usage: "TLS Certificate",
		},
		cli.StringFlag{
			Name:  "keyFile",
			Usage: "TLS Certificate Key",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:      "run",
			ShortName: "r",
			Usage:     "Run the gin proxy in the current working directory",
			Action:    MainAction,
		},
		{
			Name:      "env",
			ShortName: "e",
			Usage:     "Display environment variables set by the .env file",
			Action:    EnvAction,
		},
	}

	app.Run(os.Args)
}

func MainAction(c *cli.Context) {
	laddr := c.GlobalString("laddr")
	port := c.GlobalInt("port")
	all := c.GlobalBool("all")
	appPort := strconv.Itoa(c.GlobalInt("appPort"))
	immediate = c.GlobalBool("immediate")
	keyFile := c.GlobalString("keyFile")
	certFile := c.GlobalString("certFile")

	// Bootstrap the environment
	envy.Bootstrap()

	// Set the PORT env
	os.Setenv("PORT", appPort)

	wd, err := os.Getwd()
	if err != nil {
		logger.Fatal(err)
	}

	buildArgs, err := shellwords.Parse(c.GlobalString("buildArgs"))
	if err != nil {
		logger.Fatal(err)
	}

	builder := gin.NewBuilder(c.GlobalString("path"), c.GlobalString("bin"), c.GlobalBool("godep"), wd, buildArgs)
	runner := gin.NewRunner(filepath.Join(wd, builder.Binary()), c.Args()...)
	runner.SetWriter(os.Stdout)
	proxy := gin.NewProxy(builder, runner)

	config := &gin.Config{
		Laddr:    laddr,
		Port:     port,
		ProxyTo:  "http://localhost:" + appPort,
		KeyFile:  keyFile,
		CertFile: certFile,
	}

	err = proxy.Run(config)
	if err != nil {
		logger.Fatal(err)
	}

	if laddr != "" {
		logger.Printf("listening at %s:%d\n", laddr, port)
	} else {
		logger.Printf("listening on port %d\n", port)
	}

	shutdown(runner)

	// build right now
	build(builder, runner, logger)

	// scan for changes
	scanChanges(c.GlobalString("path"), c.GlobalStringSlice("excludeDir"), all, func(path string) {
		runner.Kill()
		build(builder, runner, logger)
	})
}

func EnvAction(c *cli.Context) {
	// Bootstrap the environment
	env, err := envy.Bootstrap()
	if err != nil {
		logger.Fatalln(err)
	}

	for k, v := range env {
		fmt.Printf("%s: %s\n", k, v)
	}

}

func build(builder gin.Builder, runner gin.Runner, logger *log.Logger) {
	err := builder.Build()
	if err != nil {
		buildError = err
		logger.Printf("%sERROR! Build failed.%s\n", colorRed, colorReset)
		fmt.Println(builder.Errors())
	} else {
		// print success only if there were errors before
		if buildError != nil {
			logger.Printf("%sBuild Successful%s\n", colorGreen, colorReset)
		}
		buildError = nil
		if immediate {
			runner.Run()
		}
	}

	time.Sleep(100 * time.Millisecond)
}

type scanCallback func(path string)

func scanChanges(watchPath string, excludeDirs []string, allFiles bool, cb scanCallback) {
	for {
		filepath.Walk(watchPath, func(path string, info os.FileInfo, err error) error {
			if path == ".git" && info.IsDir(){
				return filepath.SkipDir
			}
			for _, x := range excludeDirs {
				if x == path {
					return filepath.SkipDir
				}
			}

			// ignore hidden files
			if filepath.Base(path)[0] == '.' {
				return nil
			}

			if (allFiles || filepath.Ext(path) == ".go") && info.ModTime().After(startTime) {
				cb(path)
				startTime = time.Now()
				return errors.New("done")
			}

			return nil
		})
		time.Sleep(500 * time.Millisecond)
	}
}

func shutdown(runner gin.Runner) {
	c := make(chan os.Signal, 2)
	signal.Notify(c, os.Interrupt, syscall.SIGTERM)
	go func() {
		s := <-c
		log.Println("Got signal: ", s)
		err := runner.Kill()
		if err != nil {
			log.Print("Error killing: ", err)
		}
		os.Exit(1)
	}()
}
<|endoftext|>


<commit_before>package main

import (
    "net/http"
    "fmt"
)

func main() {

    //http.HandleFunc("/protobuf", ProtobufHandler)
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello world")
    })

    fmt.Println("Connected to mongodb, wait for connections")
    http.ListenAndServe(":8080", nil)
}
<commit_msg>Just a test<commit_after>package main

import (
    "net/http"
    "fmt"
)

func main() {

    //http.HandleFunc("/protobuf", ProtobufHandler)
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello world")
    })
    http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Only a test")
    })

    fmt.Println("Connected to mongodb, wait for connections")
    http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before><commit_msg>fix wrong location in temporary image handler<commit_after><|endoftext|>


<commit_before><commit_msg>Creating appName flag and short hand version. log.fatal if app name not set.<commit_after><|endoftext|>


<commit_before>// Copyright 2015 Auburn University. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The godoctor command refactors Go code.
package main

import (
	"fmt"
	"os"

	"github.com/godoctor/godoctor/engine/cli"
)

// Name of the refactoring tool (Go Doctor).  This can be overridden using:
// go build -ldflags "-X main.name 'Go Doctor'" github.com/godoctor/godoctor
var name string = "Go Doctor"

// Go Doctor version number.  This can be overriddenusing:
// go build -ldflags "-X main.version 0.2" github.com/godoctor/godoctor
var version string = "0.2 (Beta)"

func main() {
	aboutText := fmt.Sprintf("%s %s", name, version)
	os.Exit(cli.Run(aboutText, os.Stdin, os.Stdout, os.Stderr, os.Args))
}
<commit_msg>Update version to 0.3<commit_after>// Copyright 2016 Auburn University and others. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// The godoctor command refactors Go code.
package main

import (
	"fmt"
	"os"

	"github.com/godoctor/godoctor/engine/cli"
)

// Name of the refactoring tool (Go Doctor).  This can be overridden using:
// go build -ldflags "-X main.name 'Go Doctor'" github.com/godoctor/godoctor
var name string = "Go Doctor"

// Go Doctor version number.  This can be overriddenusing:
// go build -ldflags "-X main.version 0.3" github.com/godoctor/godoctor
var version string = "0.3 (Beta)"

func main() {
	aboutText := fmt.Sprintf("%s %s", name, version)
	os.Exit(cli.Run(aboutText, os.Stdin, os.Stdout, os.Stderr, os.Args))
}
<|endoftext|>


<commit_before>package main

import (
    "os"
    "github.com/codegangsta/cli"
)

func main() {
        app := cli.NewApp()
        app.Name = "authorization"
        app.Usage = "Manager ssh authorizations"
        app.Version = "0.1.0"
        app.Commands = []cli.Command {
                {
                        Name:      "add",
                        ShortName: "a",
                        Usage:     "Add a user",
                        Action: func(c *cli.Context) {
                                Add(c.Args().First())
                        },
                },
                {
                        Name:      "remove",
                        ShortName: "r",
                        Usage:     "Remove a user",
                        Action: func(c *cli.Context) {
                                Remove(c.Args().First())
                        },
                },
        }
        app.Run(os.Args)
}
<commit_msg>Improve usage message<commit_after>package main

import (
    "os"
    "github.com/codegangsta/cli"
)

func main() {
        app := cli.NewApp()
        app.Name = "authorization"
        app.Usage = "Manage ssh authorizations"
        app.Version = "0.1.0"
        app.Commands = []cli.Command {
                {
                        Name:      "add",
                        ShortName: "a",
                        Usage:     "Add a user",
                        Action: func(c *cli.Context) {
                                Add(c.Args().First())
                        },
                },
                {
                        Name:      "remove",
                        ShortName: "r",
                        Usage:     "Remove a user",
                        Action: func(c *cli.Context) {
                                Remove(c.Args().First())
                        },
                },
        }
        app.Run(os.Args)
}
<|endoftext|>