<commit_before>package garvis

import (
	"bytes"
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"golang.org/x/net/context"
	"google.golang.org/appengine/datastore"
	glog "google.golang.org/appengine/log"

	"github.com/go-telegram-bot-api/telegram-bot-api"
)

type TextFilter struct {
	bot  *tgbotapi.BotAPI
	ctx  context.Context
	done chan bool
}

type TextFilterRule struct {
	ChatID    int64
	RxText    string
	TextReply string
	Count     int
	Limit     int
	UserID    int
	Hidden    bool
	CreatorID int
}

type User struct {
	UserID   int
	UserName string
}

func (filter TextFilter) Run(update tgbotapi.Update) error {
	ctx := filter.ctx

	// It is not possible to match usernames to user ids from the API
	// for the case of mentions so we need to store username-ids in the database
	// for lookup
	updateUsers(ctx, update)

	query := datastore.NewQuery("Rule").Filter("ChatID = ", update.Message.Chat.ID)
	queryUserRules := query.Filter("UserID = ", update.Message.From.ID)
	queryStaticRules := query.Filter("UserID = ", 0)

	var userRules []TextFilterRule
	var staticRules []TextFilterRule
	userKeys, err := queryUserRules.GetAll(ctx, &userRules)
	staticKeys, err := queryStaticRules.GetAll(ctx, &staticRules)
	if err != nil {
		glog.Errorf(ctx, "client.GetAll: %v", err)
	}
	rules := append(userRules, staticRules...)
	keys := append(userKeys, staticKeys...)

	for i, rule := range rules {
		k := keys[i]

		rxRule := regexp.MustCompile(rule.RxText)

		if rxRule.MatchString(update.Message.Text) {
			rule.Count = rule.Count + 1
			if rule.Count >= rule.Limit {
				rule.Count = 0
				_, err = datastore.Put(ctx, k, &rule)
				if err != nil {
					glog.Errorf(ctx, "client.Put(reset): %v", err)
				}
				filter.Trigger(rule)
			}
			_, err = datastore.Put(ctx, k, &rule)
			if err != nil {
				glog.Errorf(ctx, "client.Put: %v", err)
			}
		}
	}

	filter.done <- true
	return nil
}

func (filter TextFilter) GetCommands(commands map[string]Filter) {
	commands["addrule"] = filter
	commands["deleterule"] = filter
	commands["listrules"] = filter
	commands["addhiddenrule"] = filter
}

func (filter TextFilter) RunCommand(cmd string, cmdarg CommandArguments) {
	update := cmdarg.update
	var err error
	switch cmd {
	case "addrule":
		err = filter.addRule(update, false)
	case "deleterule":
		err = filter.deleteRule(update)
	case "listrules":
		err = filter.listRules(update)
	case "addhiddenrule":
		err = filter.addRule(update, true)
	}
	if err != nil {
		glog.Errorf(filter.ctx, err.Error())
	}
}

func (filter TextFilter) Trigger(rule TextFilterRule) {
	msg := tgbotapi.NewMessage(rule.ChatID, rule.TextReply)
	filter.bot.Send(msg)
}

func (filter TextFilter) addRule(update tgbotapi.Update, hidden bool) (err error) {
	ctx := filter.ctx

	command := strings.SplitN(update.Message.Text, " ", 2)
	if len(command) < 2 {
		usage := "Usage: /addrule {regex matcher}~{reply}{#count (optional default: 1)}~{user (optional)}"
		msg := tgbotapi.NewMessage(update.Message.Chat.ID, usage)
		filter.bot.Send(msg)
		return nil
	}
	argstr := command[1]
	args := strings.SplitN(argstr, "~", 3)
	var userID int
	switch len(args) {
	case 2:
		userID = 0
	case 3:
		ents := update.Message.Entities
		for _, ent := range *ents {
			switch ent.Type {
			case "text_mention":
				userID = ent.User.ID
			case "mention":
				if userID, err = getUserID(ctx, args[2][1:]); err != nil {
					return err
				}
			}
		}
	default:
		return nil
	}
	arg1 := strings.SplitN(args[0], "#", 2)
	text := fmt.Sprintf("(?i)%v(?-i)", arg1[0])
	_, err = regexp.Compile(text)
	if err != nil {
		usage := "Invalid Regex"
		msg := tgbotapi.NewMessage(update.Message.Chat.ID, usage)
		filter.bot.Send(msg)
		return nil
	}
	var limit int
	if len(arg1) < 2 {
		limit = 1
	} else {
		limit, _ = strconv.Atoi(arg1[1])
	}
	textreply := args[1]

	keyl, _, _ := datastore.AllocateIDs(ctx, "Rule", nil, 1)
	ruleKey := datastore.NewKey(ctx, "Rule", "", keyl, nil)
	rule := TextFilterRule{
		ChatID:    update.Message.Chat.ID,
		RxText:    text,
		TextReply: textreply,
		Count:     0,
		Limit:     int(limit),
		UserID:    userID,
		CreatorID: update.Message.From.ID,
		Hidden:    hidden,
	}

	_, err = datastore.Put(ctx, ruleKey, &rule)

	return err
}

func (filter TextFilter) deleteRule(update tgbotapi.Update) (err error) {
	ctx := filter.ctx

	command := strings.SplitN(update.Message.Text, " ", 2)
	if len(command) < 2 {
		usage := "Usage: /deleterule {ruleID}"
		msg := tgbotapi.NewMessage(update.Message.Chat.ID, usage)
		filter.bot.Send(msg)
		return nil
	}
	key, _ := strconv.ParseInt(command[1], 10, 64)
	ruleKey := datastore.NewKey(ctx, "Rule", "", key, nil)

	userID := update.Message.From.ID

	err = datastore.RunInTransaction(ctx, func(ctx context.Context) error {
		var rule TextFilterRule
		err := datastore.Get(ctx, ruleKey, &rule)
		if err != nil {
			return err
		}

		if rule.ChatID == update.Message.Chat.ID || rule.CreatorID == userID {
			err = datastore.Delete(ctx, ruleKey)
		}

		return err
	}, nil)

	return err
}

func (filter TextFilter) listRules(update tgbotapi.Update) (err error) {
	ctx := filter.ctx

	var buffer bytes.Buffer
	var query *datastore.Query
	var header string

	if update.Message.Chat.Type == "private" {
		userID := update.Message.From.ID
		query = datastore.NewQuery("Rule").Filter("CreatorID = ", userID)
		header = fmt.Sprintf("|%s|%s|%s|%s|%s|%s|\n", "Chat name", "ID", "Regex", "Reply", "Count", "User(0 for all)")
	} else {
		query = datastore.NewQuery("Rule").Filter("ChatID = ", update.Message.Chat.ID)
		header = fmt.Sprintf("|%s|%s|%s|%s|%s|\n", "ID", "Regex", "Reply", "Count", "User(0 for all)")
	}
	buffer.WriteString(header)

	for t := query.Run(ctx); ; {
		var rule TextFilterRule
		var ruleText string

		k, err := t.Next(&rule)
		if err == datastore.Done {
			break
		}

		if update.Message.Chat.Type == "private" {
			chat, _ := filter.bot.GetChat(tgbotapi.ChatConfig{ChatID: rule.ChatID})
			ruleText = fmt.Sprintf("|%v|%v|%v|%v|%v|%v|\n", chat.Title, k.IntID(), rule.RxText, rule.TextReply, rule.Limit, rule.UserID)
		} else if !rule.Hidden {
			ruleText = fmt.Sprintf("|%v|%v|%v|%v|%v|\n", k.IntID(), rule.RxText, rule.TextReply, rule.Limit, rule.UserID)
		}

		buffer.WriteString(ruleText)
	}

	msg := tgbotapi.NewMessage(update.Message.Chat.ID, buffer.String())
	filter.bot.Send(msg)

	return nil
}

func updateUsers(ctx context.Context, update tgbotapi.Update) (err error) {
	userKey := datastore.NewKey(ctx, "User", update.Message.From.UserName, 0, nil)
	user := User{
		UserID:   update.Message.From.ID,
		UserName: update.Message.From.UserName,
	}
	err = datastore.RunInTransaction(ctx, func(ctx context.Context) error {
		var empty User
		if err := datastore.Get(ctx, userKey, &empty); err != datastore.ErrNoSuchEntity {
			return err
		}
		_, err := datastore.Put(ctx, userKey, &user)
		return err
	}, nil)

	return err
}

func getUserID(ctx context.Context, mention string) (int, error) {
	var user User
	key := datastore.NewKey(ctx, "User", mention, 0, nil)
	err := datastore.Get(ctx, key, &user)
	if err != nil {
		glog.Errorf(ctx, "Error fetching user: %v", err)
		return -1, err
	}

	return user.UserID, nil
}
<commit_msg>Make listrules command more clear<commit_after>package garvis

import (
	"bytes"
	"fmt"
	"regexp"
	"strconv"
	"strings"

	"golang.org/x/net/context"
	"google.golang.org/appengine/datastore"
	glog "google.golang.org/appengine/log"

	"github.com/go-telegram-bot-api/telegram-bot-api"
)

type TextFilter struct {
	bot  *tgbotapi.BotAPI
	ctx  context.Context
	done chan bool
}

type TextFilterRule struct {
	ChatID    int64
	RxText    string
	TextReply string
	Count     int
	Limit     int
	UserID    int
	Hidden    bool
	CreatorID int
}

type User struct {
	UserID   int
	UserName string
}

func (filter TextFilter) Run(update tgbotapi.Update) error {
	ctx := filter.ctx

	// It is not possible to match usernames to user ids from the API
	// for the case of mentions so we need to store username-ids in the database
	// for lookup
	updateUsers(ctx, update)

	query := datastore.NewQuery("Rule").Filter("ChatID = ", update.Message.Chat.ID)
	queryUserRules := query.Filter("UserID = ", update.Message.From.ID)
	queryStaticRules := query.Filter("UserID = ", 0)

	var userRules []TextFilterRule
	var staticRules []TextFilterRule
	userKeys, err := queryUserRules.GetAll(ctx, &userRules)
	staticKeys, err := queryStaticRules.GetAll(ctx, &staticRules)
	if err != nil {
		glog.Errorf(ctx, "client.GetAll: %v", err)
	}
	rules := append(userRules, staticRules...)
	keys := append(userKeys, staticKeys...)

	for i, rule := range rules {
		k := keys[i]

		rxRule := regexp.MustCompile(rule.RxText)

		if rxRule.MatchString(update.Message.Text) {
			rule.Count = rule.Count + 1
			if rule.Count >= rule.Limit {
				rule.Count = 0
				_, err = datastore.Put(ctx, k, &rule)
				if err != nil {
					glog.Errorf(ctx, "client.Put(reset): %v", err)
				}
				filter.Trigger(rule)
			}
			_, err = datastore.Put(ctx, k, &rule)
			if err != nil {
				glog.Errorf(ctx, "client.Put: %v", err)
			}
		}
	}

	filter.done <- true
	return nil
}

func (filter TextFilter) GetCommands(commands map[string]Filter) {
	commands["addrule"] = filter
	commands["deleterule"] = filter
	commands["listrules"] = filter
	commands["addhiddenrule"] = filter
}

func (filter TextFilter) RunCommand(cmd string, cmdarg CommandArguments) {
	update := cmdarg.update
	var err error
	switch cmd {
	case "addrule":
		err = filter.addRule(update, false)
	case "deleterule":
		err = filter.deleteRule(update)
	case "listrules":
		err = filter.listRules(update)
	case "addhiddenrule":
		err = filter.addRule(update, true)
	}
	if err != nil {
		glog.Errorf(filter.ctx, err.Error())
	}
}

func (filter TextFilter) Trigger(rule TextFilterRule) {
	msg := tgbotapi.NewMessage(rule.ChatID, rule.TextReply)
	filter.bot.Send(msg)
}

func (filter TextFilter) addRule(update tgbotapi.Update, hidden bool) (err error) {
	ctx := filter.ctx

	command := strings.SplitN(update.Message.Text, " ", 2)
	if len(command) < 2 {
		usage := "Usage: /addrule [regex matcher case insensitive by default]~[reply][#count (optional default: 1)]~[user (optional)]"
		msg := tgbotapi.NewMessage(update.Message.Chat.ID, usage)
		filter.bot.Send(msg)
		return nil
	}
	argstr := command[1]
	args := strings.SplitN(argstr, "~", 3)
	var userID int
	switch len(args) {
	case 2:
		userID = 0
	case 3:
		ents := update.Message.Entities
		for _, ent := range *ents {
			switch ent.Type {
			case "text_mention":
				userID = ent.User.ID
			case "mention":
				if userID, err = getUserID(ctx, args[2][1:]); err != nil {
					return err
				}
			}
		}
	default:
		return nil
	}
	arg1 := strings.SplitN(args[0], "#", 2)
	text := fmt.Sprintf("(?i)%v", arg1[0])
	_, err = regexp.Compile(text)
	if err != nil {
		usage := "Invalid Regex"
		msg := tgbotapi.NewMessage(update.Message.Chat.ID, usage)
		filter.bot.Send(msg)
		return nil
	}
	var limit int
	if len(arg1) < 2 {
		limit = 1
	} else {
		limit, _ = strconv.Atoi(arg1[1])
	}
	textreply := args[1]

	keyl, _, _ := datastore.AllocateIDs(ctx, "Rule", nil, 1)
	ruleKey := datastore.NewKey(ctx, "Rule", "", keyl, nil)
	rule := TextFilterRule{
		ChatID:    update.Message.Chat.ID,
		RxText:    text,
		TextReply: textreply,
		Count:     0,
		Limit:     int(limit),
		UserID:    userID,
		CreatorID: update.Message.From.ID,
		Hidden:    hidden,
	}

	_, err = datastore.Put(ctx, ruleKey, &rule)

	return err
}

func (filter TextFilter) deleteRule(update tgbotapi.Update) (err error) {
	ctx := filter.ctx

	command := strings.SplitN(update.Message.Text, " ", 2)
	if len(command) < 2 {
		usage := "Usage: /deleterule [ruleID]"
		msg := tgbotapi.NewMessage(update.Message.Chat.ID, usage)
		filter.bot.Send(msg)
		return nil
	}
	key, _ := strconv.ParseInt(command[1], 10, 64)
	ruleKey := datastore.NewKey(ctx, "Rule", "", key, nil)

	userID := update.Message.From.ID

	err = datastore.RunInTransaction(ctx, func(ctx context.Context) error {
		var rule TextFilterRule
		err := datastore.Get(ctx, ruleKey, &rule)
		if err != nil {
			return err
		}

		if rule.ChatID == update.Message.Chat.ID || rule.CreatorID == userID {
			err = datastore.Delete(ctx, ruleKey)
		}

		return err
	}, nil)

	return err
}

func (filter TextFilter) listRules(update tgbotapi.Update) (err error) {
	ctx := filter.ctx

	var buffer bytes.Buffer
	var query *datastore.Query
	var header string

	if update.Message.Chat.Type == "private" {
		userID := update.Message.From.ID
		query = datastore.NewQuery("Rule").Filter("CreatorID = ", userID)
		header = fmt.Sprintf("|%s|%s%s%s%s|%s|\n", "ID", "Regex", "~Reply", "(#Count)", "(~For User)", "Chat name")
	} else {
		query = datastore.NewQuery("Rule").Filter("ChatID = ", update.Message.Chat.ID)
		header = fmt.Sprintf("|%s|%s%s%s%s|\n", "ID", "Regex", "~Reply", "(#Count)", "(~For User)")
	}
	buffer.WriteString("All the Regexes are prepended with (?i) to be case insensitive\n")
	buffer.WriteString(header)
	buffer.String()

	for t := query.Run(ctx); ; {
		var rule TextFilterRule
		var userName string
		var userID int

		k, err := t.Next(&rule)
		if err == datastore.Done {
			break
		}

		if rule.UserID != 0 {
			userName, userID, _ = getUserName(ctx, rule.UserID)
		}

		if update.Message.Chat.Type == "private" || !rule.Hidden {
			// strip (?i) rule that makes the regexes case-sensitive by default before showing
			buffer.WriteString(fmt.Sprintf("|%v|%v~%v", k.IntID(), rule.RxText[4:], rule.TextReply))
			if rule.Limit != 1 {
				buffer.WriteString(fmt.Sprintf("#%v", rule.Limit))
			}
			if rule.UserID != 0 {
				if userName != "" {
					buffer.WriteString(fmt.Sprintf("~@%v", userName))
				} else {
					buffer.WriteString(fmt.Sprintf("~{%v}", userID))
				}
			}

			if update.Message.Chat.Type == "private" {
				chat, _ := filter.bot.GetChat(tgbotapi.ChatConfig{ChatID: rule.ChatID})
				buffer.WriteString(fmt.Sprintf("|%v", chat.Title))
			}

			buffer.WriteString(fmt.Sprintf("|\n"))
		}
	}

	msg := tgbotapi.NewMessage(update.Message.Chat.ID, buffer.String())
	filter.bot.Send(msg)

	return nil
}

func updateUsers(ctx context.Context, update tgbotapi.Update) (err error) {
	userKey := datastore.NewKey(ctx, "User", update.Message.From.UserName, 0, nil)
	user := User{
		UserID:   update.Message.From.ID,
		UserName: update.Message.From.UserName,
	}
	err = datastore.RunInTransaction(ctx, func(ctx context.Context) error {
		var empty User
		if err := datastore.Get(ctx, userKey, &empty); err != datastore.ErrNoSuchEntity {
			return err
		}
		_, err := datastore.Put(ctx, userKey, &user)
		return err
	}, nil)

	return err
}

func getUserID(ctx context.Context, mention string) (int, error) {
	var user User
	key := datastore.NewKey(ctx, "User", mention, 0, nil)
	err := datastore.Get(ctx, key, &user)
	if err != nil {
		glog.Errorf(ctx, "Error fetching user: %v", err)
		return -1, err
	}

	return user.UserID, nil
}

/* Return User's ID if user doesn't have a username and therefore doesn't exist in the database */
func getUserName(ctx context.Context, userID int) (string, int, error) {
	var users []User
	query := datastore.NewQuery("User").Filter("UserID = ", userID)

	query.GetAll(ctx, &users)

	if len(users) == 0 {
		return "", userID, nil
	}

	return users[0].UserName, 0, nil
}
<|endoftext|>


<commit_before>package flags

import (
	"flag"
	"log"
	"strings"
	"time"
)

var (
	stringPtrs   = map[string]*string{}
	boolPtrs     = map[string]*bool{}
	durationPtrs = map[string]*time.Duration{}
	float64Ptrs  = map[string]*float64{}
	intPtrs      = map[string]*int{}
	slicePtrs    = map[string]*[]string{}
)

func ValidateNonZero(names ...string) {
	for _, name := range names {
		// NOTE: Bool flags not supported.
		if stringPtrs[name] == nil && durationPtrs[name] == nil && float64Ptrs[name] == nil && intPtrs[name] == nil && slicePtrs[name] == nil {
			log.Fatalf("%s is not defined", name)
		}
		if stringPtrs[name] != nil && *stringPtrs[name] == "" {
			log.Fatalf("Missing --%s", name)
		}
		if durationPtrs[name] != nil && int64(*durationPtrs[name]) == 0 {
			log.Fatalf("Missing --%s", name)
		}
		if float64Ptrs[name] != nil && *float64Ptrs[name] == 0 {
			log.Fatalf("Missing --%s", name)
		}
		if intPtrs[name] != nil && *intPtrs[name] == 0 {
			log.Fatalf("Missing --%s", name)
		}
		if slicePtrs[name] != nil && len(*slicePtrs[name]) == 0 {
			log.Fatalf("Missing --%s", name)
		}
	}
}

type sliceContainer struct {
	S *[]string
}

func (s *sliceContainer) String() string {
	if s == nil || s.S == nil {
		return ""
	}
	return strings.Join(*s.S, ",")
}

func (s *sliceContainer) Set(value string) error {
	*s.S = strings.Split(value, ",")
	return nil
}

func String(name string, value string, usage string) *string {
	if _, exists := stringPtrs[name]; !exists {
		stringPtrs[name] = flag.String(name, value, usage)
	}

	return stringPtrs[name]
}

func Int(name string, value int, usage string) *int {
	if _, exists := intPtrs[name]; !exists {
		intPtrs[name] = flag.Int(name, value, usage)
	}

	return intPtrs[name]
}

func Bool(name string, value bool, usage string) *bool {
	if _, exists := boolPtrs[name]; !exists {
		boolPtrs[name] = flag.Bool(name, value, usage)
	}

	return boolPtrs[name]
}

func Float64(name string, value float64, usage string) *float64 {
	if _, exists := float64Ptrs[name]; !exists {
		float64Ptrs[name] = flag.Float64(name, value, usage)
	}

	return float64Ptrs[name]
}

func Slice(name string, value []string, usage string) *[]string {
	if _, exists := slicePtrs[name]; !exists {
		var s []string
		if value == nil {
			s = []string{}
		} else {
			s = value
		}
		slicePtrs[name] = &s

		container := sliceContainer{S: &s}
		flag.Var(&container, name, usage)
	}
	return slicePtrs[name]
}

func Duration(name string, value time.Duration, usage string) *time.Duration {
	if _, exists := float64Ptrs[name]; !exists {
		durationPtrs[name] = flag.Duration(name, value, usage)
	}

	return durationPtrs[name]
}
<commit_msg>[Flags] Fix Slice not proper setting values when set empty.<commit_after>package flags

import (
	"flag"
	"log"
	"strings"
	"time"
)

var (
	stringPtrs   = map[string]*string{}
	boolPtrs     = map[string]*bool{}
	durationPtrs = map[string]*time.Duration{}
	float64Ptrs  = map[string]*float64{}
	intPtrs      = map[string]*int{}
	slicePtrs    = map[string]*[]string{}
)

func ValidateNonZero(names ...string) {
	for _, name := range names {
		// NOTE: Bool flags not supported.
		if stringPtrs[name] == nil && durationPtrs[name] == nil && float64Ptrs[name] == nil && intPtrs[name] == nil && slicePtrs[name] == nil {
			log.Fatalf("%s is not defined", name)
		}
		if stringPtrs[name] != nil && *stringPtrs[name] == "" {
			log.Fatalf("Missing --%s", name)
		}
		if durationPtrs[name] != nil && int64(*durationPtrs[name]) == 0 {
			log.Fatalf("Missing --%s", name)
		}
		if float64Ptrs[name] != nil && *float64Ptrs[name] == 0 {
			log.Fatalf("Missing --%s", name)
		}
		if intPtrs[name] != nil && *intPtrs[name] == 0 {
			log.Fatalf("Missing --%s", name)
		}
		if slicePtrs[name] != nil && len(*slicePtrs[name]) == 0 {
			log.Fatalf("Missing --%s", name)
		}
	}
}

type sliceContainer struct {
	S *[]string
}

func (s *sliceContainer) String() string {
	if s == nil || s.S == nil {
		return ""
	}
	return strings.Join(*s.S, ",")
}

func (s *sliceContainer) Set(value string) error {
	if value == "" {
		*s.S = nil
	} else {
		*s.S = strings.Split(value, ",")
	}
	return nil
}

func String(name string, value string, usage string) *string {
	if _, exists := stringPtrs[name]; !exists {
		stringPtrs[name] = flag.String(name, value, usage)
	}

	return stringPtrs[name]
}

func Int(name string, value int, usage string) *int {
	if _, exists := intPtrs[name]; !exists {
		intPtrs[name] = flag.Int(name, value, usage)
	}

	return intPtrs[name]
}

func Bool(name string, value bool, usage string) *bool {
	if _, exists := boolPtrs[name]; !exists {
		boolPtrs[name] = flag.Bool(name, value, usage)
	}

	return boolPtrs[name]
}

func Float64(name string, value float64, usage string) *float64 {
	if _, exists := float64Ptrs[name]; !exists {
		float64Ptrs[name] = flag.Float64(name, value, usage)
	}

	return float64Ptrs[name]
}

func Slice(name string, value []string, usage string) *[]string {
	if _, exists := slicePtrs[name]; !exists {
		var s []string
		if value == nil {
			s = []string{}
		} else {
			s = value
		}
		slicePtrs[name] = &s

		container := sliceContainer{S: &s}
		flag.Var(&container, name, usage)
	}
	return slicePtrs[name]
}

func Duration(name string, value time.Duration, usage string) *time.Duration {
	if _, exists := float64Ptrs[name]; !exists {
		durationPtrs[name] = flag.Duration(name, value, usage)
	}

	return durationPtrs[name]
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/acm"
	"github.com/hashicorp/errwrap"
	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsAcmCertificate() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsAcmCertificateRead,
		Schema: map[string]*schema.Schema{
			"domain": {
				Type:     schema.TypeString,
				Required: true,
			},
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"statuses": {
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"types": {
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"most_recent": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
		},
	}
}

type arnData struct {
	arn       string
	notBefore *time.Time
}

func describeCertificate(arn *arnData, conn *acm.ACM) (*acm.DescribeCertificateOutput, error) {
	params := &acm.DescribeCertificateInput{}
	params.CertificateArn = &arn.arn

	description, err := conn.DescribeCertificate(params)
	if err != nil {
		return nil, err
	}

	return description, nil
}

func dataSourceAwsAcmCertificateRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).acmconn

	params := &acm.ListCertificatesInput{}
	target := d.Get("domain")
	statuses, ok := d.GetOk("statuses")
	if ok {
		statusStrings := statuses.([]interface{})
		params.CertificateStatuses = expandStringList(statusStrings)
	} else {
		params.CertificateStatuses = []*string{aws.String("ISSUED")}
	}

	var arns []*arnData
	log.Printf("[DEBUG] Reading ACM Certificate: %s", params)
	err := conn.ListCertificatesPages(params, func(page *acm.ListCertificatesOutput, lastPage bool) bool {
		for _, cert := range page.CertificateSummaryList {
			if *cert.DomainName == target {
				arns = append(arns, &arnData{*cert.CertificateArn, nil})
			}
		}

		return true
	})
	if err != nil {
		return errwrap.Wrapf("Error listing certificates: {{err}}", err)
	}

	// filter based on certificate type (imported or aws-issued)
	types, ok := d.GetOk("types")
	if ok {
		typesStrings := expandStringList(types.([]interface{}))
		var matchedArns []*arnData
		for _, arn := range arns {
			description, err := describeCertificate(arn, conn)
			if err != nil {
				return errwrap.Wrapf("Error describing certificates: {{err}}", err)
			}

			for _, certType := range typesStrings {
				if *description.Certificate.Type == *certType {
					matchedArns = append(
						matchedArns,
						&arnData{arn.arn, description.Certificate.NotBefore},
					)
					break
				}
			}
		}

		arns = matchedArns
	}

	if len(arns) == 0 {
		return fmt.Errorf("No certificate for domain %q found in this region.", target)
	}

	if len(arns) > 1 {
		// Get most recent sorting by notBefore date. Notice that createdAt field is only valid
		// for ACM issued certificates but not for imported ones so in a mixed scenario only
		// fields extracted from the certificate are valid.
		_, ok = d.GetOk("most_recent")
		if ok {
			mr := arns[0]
			if mr.notBefore == nil {
				description, err := describeCertificate(mr, conn)
				if err != nil {
					return errwrap.Wrapf("Error describing certificates: {{err}}", err)
				}

				mr.notBefore = description.Certificate.NotBefore
			}
			for _, arn := range arns[1:] {
				if arn.notBefore == nil {
					description, err := describeCertificate(arn, conn)
					if err != nil {
						return errwrap.Wrapf("Error describing certificates: {{err}}", err)
					}

					arn.notBefore = description.Certificate.NotBefore
				}

				if arn.notBefore.After(*mr.notBefore) {
					mr = arn
				}
			}

			arns = []*arnData{mr}
		} else {
			return fmt.Errorf("Multiple certificates for domain %q found in this region.", target)
		}
	}

	d.SetId(time.Now().UTC().String())
	d.Set("arn", arns[0].arn)

	return nil
}
<commit_msg>Apply feedback<commit_after>package aws

import (
	"fmt"
	"log"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/acm"
	"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsAcmCertificate() *schema.Resource {
	return &schema.Resource{
		Read: dataSourceAwsAcmCertificateRead,
		Schema: map[string]*schema.Schema{
			"domain": {
				Type:     schema.TypeString,
				Required: true,
			},
			"arn": {
				Type:     schema.TypeString,
				Computed: true,
			},
			"statuses": {
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"types": {
				Type:     schema.TypeList,
				Optional: true,
				Elem:     &schema.Schema{Type: schema.TypeString},
			},
			"most_recent": {
				Type:     schema.TypeBool,
				Optional: true,
				Default:  false,
			},
		},
	}
}

func describeCertificateByArn(arn *string, conn *acm.ACM) (*acm.CertificateDetail, error) {
	input := &acm.DescribeCertificateInput{
		CertificateArn: aws.String(*arn),
	}
	log.Printf("[DEBUG] Describing ACM Certificate: %s", input)
	output, err := conn.DescribeCertificate(input)
	return output.Certificate, err
}

func dataSourceAwsAcmCertificateRead(d *schema.ResourceData, meta interface{}) error {
	conn := meta.(*AWSClient).acmconn

	params := &acm.ListCertificatesInput{}
	target := d.Get("domain")
	statuses, ok := d.GetOk("statuses")
	if ok {
		statusStrings := statuses.([]interface{})
		params.CertificateStatuses = expandStringList(statusStrings)
	} else {
		params.CertificateStatuses = []*string{aws.String("ISSUED")}
	}

	var arns []*string
	log.Printf("[DEBUG] Reading ACM Certificate: %s", params)
	err := conn.ListCertificatesPages(params, func(page *acm.ListCertificatesOutput, lastPage bool) bool {
		for _, cert := range page.CertificateSummaryList {
			if *cert.DomainName == target {
				arns = append(arns, cert.CertificateArn)
			}
		}

		return true
	})
	if err != nil {
		return fmt.Errorf("Error listing certificates: %q", err)
	}

	if len(arns) == 0 {
		return fmt.Errorf("No certificate for domain %q found in this region", target)
	}

	filterMostRecent := d.Get("most_recent").(bool)
	filterTypes, filterTypesOk := d.GetOk("types")

	var matchedCertificate *acm.CertificateDetail

	if !filterMostRecent && !filterTypesOk {
		if len(arns) > 1 {
			// Multiple certificates have been found and no flags set. Error
			return fmt.Errorf("Multiple certificates for domain %q found in this region", target)
		}
		// Only 1 certificate has been found and no flags set. Get details and return it.
		matchedCertificate, err = describeCertificateByArn(arns[0], conn)
		if err != nil {
			return fmt.Errorf("Error describing ACM certificate: %q", err)
		}
	} else {
		typesStrings := expandStringList(filterTypes.([]interface{}))

		for _, arn := range arns {
			certificate, err := describeCertificateByArn(arn, conn)
			if err != nil {
				return fmt.Errorf("Error describing ACM certificate: %q", err)
			}
			if filterTypesOk {
				for _, certType := range typesStrings {
					if *certificate.Type == *certType {
						// We do not have a candidate certificate
						if matchedCertificate == nil {
							matchedCertificate = certificate
							continue
						}
						// At this point, we already have a candidate certificate
						// Check if we are filtering by most recent and update if necessary
						if filterMostRecent && (*certificate.NotBefore).After(*matchedCertificate.NotBefore) {
							matchedCertificate = certificate
							break
						}
						// Now we have multiple candidate certificates and we only allow one certificate
						return fmt.Errorf("Multiple certificates for domain %q found in this region", target)
					}
				}
				continue
			}
			// At this point, we already have a candidate certificate
			// Check if we are filtering by most recent and update if necessary
			if filterMostRecent {
				// We do not have a candidate certificate
				if matchedCertificate == nil {
					matchedCertificate = certificate
					continue
				}
				if (*certificate.NotBefore).After(*matchedCertificate.NotBefore) {
					matchedCertificate = certificate
				}
				continue
			}
			// Now we have multiple candidate certificates and we only allow one certificate
			return fmt.Errorf("Multiple certificates for domain %q found in this region", target)
		}
	}

	if matchedCertificate == nil {
		return fmt.Errorf("No certificate for domain %q found in this region", target)
	}

	d.SetId(time.Now().UTC().String())
	d.Set("arn", matchedCertificate.CertificateArn)

	return nil
}
<|endoftext|>


<commit_before>package logger

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/Sirupsen/logrus"
	"net/http"
	"os"
	"strings"
)

type SumoLogicHook struct {
	Url             string
	HttpClient      *http.Client
	PendingMessages [][]byte
	AppName         string
}

func NewSumo(config Config) Client {
	var client Client
	host, _ := os.Hostname()
	client.Logger = logrus.New()
	client.Logger.Formatter = &logrus.TextFormatter{
		ForceColors: false,
	}
	hook, _ := NewSumoHook(config.Host, host)
	client.Logger.Hooks.Add(hook)

	return client
}

func NewSumoHook(url string, appname string) (*SumoLogicHook, error) {
	client := &http.Client{}
	return &SumoLogicHook{url, client, make([][]byte, 0), appname}, nil
}

func (hook *SumoLogicHook) Fire(entry *logrus.Entry) error {
	data := make(logrus.Fields, len(entry.Data))
	for k, v := range entry.Data {
		switch v := v.(type) {
		case error:
			data[k] = v.Error()
		default:
			data[k] = v
		}
	}
	data["tstamp"] = entry.Time.Format(logrus.DefaultTimestampFormat)
	data["message"] = strings.Replace(entry.Message, "\"", "'", -1)
	data["level"] = entry.Level.String()

	s, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("Failed to build json: %v", err)
	}
	// attempt to process pending messages first
	if len(hook.PendingMessages) != 0 {
		for i, m := range hook.PendingMessages {
			err := hook.httpPost(m)
			if err == nil {
				hook.PendingMessages, hook.PendingMessages[len(hook.PendingMessages)-1] = append(hook.PendingMessages[:i], hook.PendingMessages[i+1:]...), nil
			}
		}
	}
	err = hook.httpPost(s)
	if err != nil {
		// stash messages for next run
		hook.PendingMessages = append(hook.PendingMessages, s)
		return err
	}
	return nil
}

func (hook *SumoLogicHook) httpPost(s []byte) error {
	if hook.Url == "" {
		return fmt.Errorf("Unable to push logs to Sumo Logic. SUMO_ENDPOINT not provided")
	}
	body := bytes.NewBuffer(s)
	req, err := http.NewRequest("POST", hook.Url, body)
	client := http.Client{}
	if req == nil {
		return fmt.Errorf("Something went wrong")
	}
	req.Header.Add("X-Sumo-Name", hook.AppName)
	resp, err := client.Do(req)
	defer resp.Body.Close()
	if err != nil || resp == nil {
		return fmt.Errorf("Failed to post data: %s", err.Error())
	} else if resp.StatusCode != 200 {
		return fmt.Errorf("Failed to post data: %s", resp.Status)
	} else {
		return nil
	}

}

func (s *SumoLogicHook) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.PanicLevel,
		logrus.FatalLevel,
		logrus.ErrorLevel,
		logrus.WarnLevel,
		logrus.InfoLevel,
		logrus.DebugLevel,
	}
}
<commit_msg>don't bug people<commit_after>package logger

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/Sirupsen/logrus"
	"net/http"
	"os"
	"strings"
)

type SumoLogicHook struct {
	Url             string
	HttpClient      *http.Client
	PendingMessages [][]byte
	AppName         string
}

func NewSumo(config Config) Client {
	var client Client
	host, _ := os.Hostname()
	client.Logger = logrus.New()
	client.Logger.Formatter = &logrus.TextFormatter{
		ForceColors: false,
	}
	hook, err := NewSumoHook(config.Host, host)
	if err != nil {
		fmt.Println(err.Error())
		return client
	}
	client.Logger.Hooks.Add(hook)
	return client
}

func NewSumoHook(url string, appname string) (*SumoLogicHook, error) {
	if url == "" {
		return nil, fmt.Errorf("Unable to send logs to Sumo Logic. SUMO_ENDPOINT not provided")
	}
	client := &http.Client{}
	return &SumoLogicHook{url, client, make([][]byte, 0), appname}, nil
}

func (hook *SumoLogicHook) Fire(entry *logrus.Entry) error {
	data := make(logrus.Fields, len(entry.Data))
	for k, v := range entry.Data {
		switch v := v.(type) {
		case error:
			data[k] = v.Error()
		default:
			data[k] = v
		}
	}
	data["tstamp"] = entry.Time.Format(logrus.DefaultTimestampFormat)
	data["message"] = strings.Replace(entry.Message, "\"", "'", -1)
	data["level"] = entry.Level.String()

	s, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("Failed to build json: %v", err)
	}
	// attempt to process pending messages first
	if len(hook.PendingMessages) != 0 {
		for i, m := range hook.PendingMessages {
			err := hook.httpPost(m)
			if err == nil {
				hook.PendingMessages, hook.PendingMessages[len(hook.PendingMessages)-1] = append(hook.PendingMessages[:i], hook.PendingMessages[i+1:]...), nil
			}
		}
	}
	err = hook.httpPost(s)
	if err != nil {
		// stash messages for next run
		hook.PendingMessages = append(hook.PendingMessages, s)
		return err
	}
	return nil
}

func (hook *SumoLogicHook) httpPost(s []byte) error {
	// already printed error about sumo_endpoint so be silent
	if hook.Url == "" {
		// avoid panic and return if no url
		return nil
	}
	body := bytes.NewBuffer(s)
	req, err := http.NewRequest("POST", hook.Url, body)
	client := http.Client{}
	if req == nil {
		return fmt.Errorf("Something went wrong")
	}
	req.Header.Add("X-Sumo-Name", hook.AppName)
	resp, err := client.Do(req)
	defer resp.Body.Close()
	if err != nil || resp == nil {
		return fmt.Errorf("Failed to post data: %s", err.Error())
	} else if resp.StatusCode != 200 {
		return fmt.Errorf("Failed to post data: %s", resp.Status)
	} else {
		return nil
	}

}

func (s *SumoLogicHook) Levels() []logrus.Level {
	return []logrus.Level{
		logrus.PanicLevel,
		logrus.FatalLevel,
		logrus.ErrorLevel,
		logrus.WarnLevel,
		logrus.InfoLevel,
		logrus.DebugLevel,
	}
}
<|endoftext|>


<commit_before>package daemon

import (
	"bufio"
	"context"
	"encoding/json"
	"net"
	"os"
	"path/filepath"
	"time"

	"crawshaw.io/sqlite"
	"github.com/itchio/butler/butlerd"
	"github.com/itchio/butler/database"
	"github.com/sourcegraph/jsonrpc2"

	"github.com/itchio/butler/comm"
	"github.com/itchio/butler/mansion"
	"github.com/pkg/errors"
)

func Register(ctx *mansion.Context) {
	cmd := ctx.App.Command("daemon", "Start a butlerd instance").Hidden()
	ctx.Register(cmd, do)
}

const minSecretLength = 256

func do(ctx *mansion.Context) {
	if !comm.JsonEnabled() {
		comm.Notice("Hello from butler daemon", []string{"We can't do anything interesting without --json, bailing out", "", "Learn more: https://docs.itch.ovh/butlerd/master/"})
		os.Exit(1)
	}

	if ctx.DBPath == "" {
		comm.Dief("butlerd: dbPath must be set")
	}

	comm.Object("butlerd/secret-request", map[string]interface{}{
		"minLength": minSecretLength,
	})

	secretChan := make(chan string)
	go func() {
		secret := ""
		scanner := bufio.NewScanner(os.Stdin)
		for scanner.Scan() {
			line := scanner.Bytes()
			m := make(map[string]interface{})
			err := json.Unmarshal(line, &m)
			if err != nil {
				comm.Warnf("could not unmarshal JSON input, ignoring: %s", err.Error())
				continue
			}

			if typ, ok := m["type"].(string); ok {
				switch typ {
				case "butlerd/secret-result":
					if s, ok := m["secret"].(string); ok {
						secret = s
						secretChan <- secret
						comm.Logf("Received secret")
						return
					}
				default:
					comm.Warnf("unrecognized json message type %s, ignoring", typ)
				}
			} else {
				comm.Warnf("json message missing 'type' field, ignoring")
			}
		}
	}()

	var secret string
	select {
	case secret = <-secretChan:
		// woo
	case <-time.After(15 * time.Second):
		comm.Dief("butlerd: Timed out while waiting for secret")
	}

	if len(secret) < minSecretLength {
		comm.Dief("butlerd: Secret too short (must be %d chars, received %d chars) or more", minSecretLength, len(secret))
	}

	err := os.MkdirAll(filepath.Dir(ctx.DBPath), 0755)
	if err != nil {
		ctx.Must(errors.WithMessage(err, "creating DB directory if necessary"))
	}

	dbPool, err := sqlite.Open(ctx.DBPath, 0, 2)
	if err != nil {
		ctx.Must(errors.WithMessage(err, "opening DB for the first time"))
	}
	defer dbPool.Close()

	func() {
		conn := dbPool.Get(context.Background().Done())
		defer dbPool.Put(conn)
		err = database.Prepare(conn)
	}()
	if err != nil {
		ctx.Must(errors.WithMessage(err, "preparing DB"))
	}

	ctx.Must(Do(ctx, context.Background(), dbPool, secret, func(addr string) {
		comm.Object("butlerd/listen-notification", map[string]interface{}{
			"address": addr,
		})
	}))
}

type handler struct {
	ctx    *mansion.Context
	router *butlerd.Router
}

func (h *handler) Handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) {
	if req.Notif {
		return
	}

	h.router.Dispatch(ctx, conn, req)
}

type OnListenFunc func(addr string)

func Do(mansionContext *mansion.Context, ctx context.Context, dbPool *sqlite.Pool, secret string, onListen OnListenFunc) error {
	listenSpec := "127.0.0.1:"

	lis, err := net.Listen("tcp", listenSpec)
	if err != nil {
		return errors.WithStack(err)
	}

	onListen(lis.Addr().String())
	s := butlerd.NewServer(secret)

	h := &handler{
		ctx:    mansionContext,
		router: getRouter(dbPool, mansionContext),
	}
	err = s.Serve(ctx, lis, h, comm.NewStateConsumer())
	if err != nil {
		return errors.WithStack(err)
	}

	return nil
}
<commit_msg>Bump sqlite connection pool to 100<commit_after>package daemon

import (
	"bufio"
	"context"
	"encoding/json"
	"net"
	"os"
	"path/filepath"
	"time"

	"crawshaw.io/sqlite"
	"github.com/itchio/butler/butlerd"
	"github.com/itchio/butler/database"
	"github.com/sourcegraph/jsonrpc2"

	"github.com/itchio/butler/comm"
	"github.com/itchio/butler/mansion"
	"github.com/pkg/errors"
)

func Register(ctx *mansion.Context) {
	cmd := ctx.App.Command("daemon", "Start a butlerd instance").Hidden()
	ctx.Register(cmd, do)
}

const minSecretLength = 256

func do(ctx *mansion.Context) {
	if !comm.JsonEnabled() {
		comm.Notice("Hello from butler daemon", []string{"We can't do anything interesting without --json, bailing out", "", "Learn more: https://docs.itch.ovh/butlerd/master/"})
		os.Exit(1)
	}

	if ctx.DBPath == "" {
		comm.Dief("butlerd: dbPath must be set")
	}

	comm.Object("butlerd/secret-request", map[string]interface{}{
		"minLength": minSecretLength,
	})

	secretChan := make(chan string)
	go func() {
		secret := ""
		scanner := bufio.NewScanner(os.Stdin)
		for scanner.Scan() {
			line := scanner.Bytes()
			m := make(map[string]interface{})
			err := json.Unmarshal(line, &m)
			if err != nil {
				comm.Warnf("could not unmarshal JSON input, ignoring: %s", err.Error())
				continue
			}

			if typ, ok := m["type"].(string); ok {
				switch typ {
				case "butlerd/secret-result":
					if s, ok := m["secret"].(string); ok {
						secret = s
						secretChan <- secret
						comm.Logf("Received secret")
						return
					}
				default:
					comm.Warnf("unrecognized json message type %s, ignoring", typ)
				}
			} else {
				comm.Warnf("json message missing 'type' field, ignoring")
			}
		}
	}()

	var secret string
	select {
	case secret = <-secretChan:
		// woo
	case <-time.After(15 * time.Second):
		comm.Dief("butlerd: Timed out while waiting for secret")
	}

	if len(secret) < minSecretLength {
		comm.Dief("butlerd: Secret too short (must be %d chars, received %d chars) or more", minSecretLength, len(secret))
	}

	err := os.MkdirAll(filepath.Dir(ctx.DBPath), 0755)
	if err != nil {
		ctx.Must(errors.WithMessage(err, "creating DB directory if necessary"))
	}

	dbPool, err := sqlite.Open(ctx.DBPath, 0, 100)
	if err != nil {
		ctx.Must(errors.WithMessage(err, "opening DB for the first time"))
	}
	defer dbPool.Close()

	func() {
		conn := dbPool.Get(context.Background().Done())
		defer dbPool.Put(conn)
		err = database.Prepare(conn)
	}()
	if err != nil {
		ctx.Must(errors.WithMessage(err, "preparing DB"))
	}

	ctx.Must(Do(ctx, context.Background(), dbPool, secret, func(addr string) {
		comm.Object("butlerd/listen-notification", map[string]interface{}{
			"address": addr,
		})
	}))
}

type handler struct {
	ctx    *mansion.Context
	router *butlerd.Router
}

func (h *handler) Handle(ctx context.Context, conn *jsonrpc2.Conn, req *jsonrpc2.Request) {
	if req.Notif {
		return
	}

	h.router.Dispatch(ctx, conn, req)
}

type OnListenFunc func(addr string)

func Do(mansionContext *mansion.Context, ctx context.Context, dbPool *sqlite.Pool, secret string, onListen OnListenFunc) error {
	listenSpec := "127.0.0.1:"

	lis, err := net.Listen("tcp", listenSpec)
	if err != nil {
		return errors.WithStack(err)
	}

	onListen(lis.Addr().String())
	s := butlerd.NewServer(secret)

	h := &handler{
		ctx:    mansionContext,
		router: getRouter(dbPool, mansionContext),
	}
	err = s.Serve(ctx, lis, h, comm.NewStateConsumer())
	if err != nil {
		return errors.WithStack(err)
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"expvar"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"
	"runtime/pprof"
	"syscall"
	"time"

	"github.com/ekanite/ekanite"
	"github.com/ekanite/ekanite/input"
	"github.com/ekanite/ekanite/status"
)

var (
	stats = expvar.NewMap("ekanite")
)

// Program parameters
var datadir string
var tcpIface string
var udpIface string
var caPemPath string
var caKeyPath string
var queryIface string
var batchSize int
var batchTimeout int
var indexMaxPending int
var gomaxprocs int
var numShards int
var retentionPeriod string
var cpuProfile string
var memProfile string
var inputFormat string

// Flag set
var fs *flag.FlagSet

// Types
const (
	DefaultDataDir         = "/var/opt/ekanite"
	DefaultBatchSize       = 300
	DefaultBatchTimeout    = 1000
	DefaultIndexMaxPending = 1000
	DefaultNumShards       = 4
	DefaultRetentionPeriod = "168h"
	DefaultQueryAddr       = "localhost:9950"
	DefaultHTTPQueryAddr   = "localhost:8080"
	DefaultDiagsIface      = "localhost:9951"
	DefaultTCPServer       = "localhost:5514"
	DefaultInputFormat     = "syslog"
)

func main() {
	fs = flag.NewFlagSet("", flag.ExitOnError)
	var (
		datadir         = fs.String("datadir", DefaultDataDir, "Set data directory")
		batchSize       = fs.Int("batchsize", DefaultBatchSize, "Indexing batch size")
		batchTimeout    = fs.Int("batchtime", DefaultBatchTimeout, "Indexing batch timeout, in milliseconds")
		indexMaxPending = fs.Int("maxpending", DefaultIndexMaxPending, "Maximum pending index events")
		tcpIface        = fs.String("tcp", DefaultTCPServer, "Syslog server TCP bind address in the form host:port. To disable set to empty string")
		udpIface        = fs.String("udp", "", "Syslog server UDP bind address in the form host:port. If not set, not started")
		diagIface       = fs.String("diag", DefaultDiagsIface, "expvar and pprof bind address in the form host:port. If not set, not started")
		caPemPath       = fs.String("tlspem", "", "path to CA PEM file for TLS-enabled TCP server. If not set, TLS not activated")
		caKeyPath       = fs.String("tlskey", "", "path to CA key file for TLS-enabled TCP server. If not set, TLS not activated")
		queryIface      = fs.String("query", DefaultQueryAddr, "TCP Bind address for query server in the form host:port. To disable set to empty string")
		queryIfaceHttp  = fs.String("queryhttp", DefaultHTTPQueryAddr, "TCP Bind address for http query server in the form host:port. To disable set to empty string")
		numShards       = fs.Int("numshards", DefaultNumShards, "Set number of shards per index")
		retentionPeriod = fs.String("retention", DefaultRetentionPeriod, "Data retention period. Minimum is 24 hours")
		cpuProfile      = fs.String("cpuprof", "", "Where to write CPU profiling data. Not written if not set")
		memProfile      = fs.String("memprof", "", "Where to write memory profiling data. Not written if not set")
		inputFormat     = fs.String("input", DefaultInputFormat, "Message format of input (only syslog supported)")
	)
	fs.Usage = printHelp
	fs.Parse(os.Args[1:])

	absDataDir, err := filepath.Abs(*datadir)
	if err != nil {
		log.Fatalf("failed to get absolute data path for '%s': %s", *datadir, err.Error())
	}

	// Get the retention period.
	retention, err := time.ParseDuration(*retentionPeriod)
	if err != nil {
		log.Fatalf("failed to parse retention period '%s'", *retentionPeriod)
	}

	log.SetFlags(log.LstdFlags)
	log.SetPrefix("[ekanite] ")
	log.Printf("ekanite started using %s for index storage", absDataDir)

	runtime.GOMAXPROCS(runtime.NumCPU())
	log.Println("GOMAXPROCS set to", runtime.GOMAXPROCS(0))

	// Start the expvar handler if requested.
	if *diagIface != "" {
		startDiagServer(*diagIface)
	}

	// Create and open the Engine.
	engine := ekanite.NewEngine(absDataDir)
	engine.NumShards = *numShards
	engine.RetentionPeriod = retention

	if err := engine.Open(); err != nil {
		log.Fatalf("failed to open engine: %s", err.Error())
	}
	log.Printf("engine opened with shard number of %d, retention period of %s",
		engine.NumShards, engine.RetentionPeriod)

	// Start the simple query server if requested.
	if *queryIface != "" {
		startQueryServer(*queryIface, engine)
	}

	// Start the http query server if requested.
	if *queryIfaceHttp != "" {
		startHTTPQueryServer(*queryIfaceHttp, engine)
	}

	// Create and start the batcher.
	batcherTimeout := time.Duration(*batchTimeout) * time.Millisecond
	batcher := ekanite.NewBatcher(engine, *batchSize, batcherTimeout, *indexMaxPending)

	errChan := make(chan error)
	if err := batcher.Start(errChan); err != nil {
		log.Fatalf("failed to start indexing batcher: %s", err.Error())
	}
	log.Printf("batching configured with size %d, timeout %s, max pending %d",
		*batchSize, batcherTimeout, *indexMaxPending)

	// Start draining batcher errors.
	go drainLog("error indexing batch", errChan)

	// Start TCP collector if requested.
	if *tcpIface != "" {
		var tlsConfig *tls.Config
		if *caPemPath != "" && *caKeyPath != "" {
			tlsConfig, err = newTLSConfig(*caPemPath, *caKeyPath)
			if err != nil {
				log.Fatalf("failed to configure TLS: %s", err.Error())
			}
			log.Printf("TLS successfully configured")
		}

		if err := startTCPCollector(*tcpIface, *inputFormat, tlsConfig, batcher); err != nil {
			log.Fatalf("failed to start TCP collector: %s", err.Error())
		}
		log.Printf("TCP collector listening to %s", *tcpIface)
	}

	// Start UDP collector if requested.
	if *udpIface != "" {
		if err := startUDPCollector(*udpIface, *inputFormat, batcher); err != nil {
			log.Fatalf("failed to start UDP collector: %s", err.Error())
		}
		log.Printf("UDP collector listening to %s", *udpIface)
	}

	// Start profiling.
	startProfile(*cpuProfile, *memProfile)

	stats.Set("launch", time.Now().UTC())

	// Set up signal handling.
	signalCh := make(chan os.Signal, 1)
	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)

	// Block until one of the signals above is received
	select {
	case <-signalCh:
		log.Println("signal received, shutting down...")
	}

	stopProfile()
}

func startTCPCollector(iface, format string, tls *tls.Config, batcher *ekanite.Batcher) error {
	collector, err := input.NewCollector("tcp", iface, format, tls)
	if err != nil {
		return fmt.Errorf(("failed to create TCP collector: %s"), err.Error())
	}
	if err := collector.Start(batcher.C()); err != nil {
		return fmt.Errorf("failed to start TCP collector: %s", err.Error())
	}

	return nil
}

func startUDPCollector(iface, format string, batcher *ekanite.Batcher) error {
	collector, err := input.NewCollector("udp", iface, format, nil)
	if err != nil {
		return fmt.Errorf("failed to create UDP collector: %s", err.Error())
	}
	if err := collector.Start(batcher.C()); err != nil {
		return fmt.Errorf("failed to start UDP collector: %s", err.Error())
	}

	return nil
}

func startQueryServer(iface string, engine *ekanite.Engine) {
	server := ekanite.NewServer(iface, engine)
	if server == nil {
		log.Fatal("failed to create query server")
	}
	if err := server.Start(); err != nil {
		log.Fatalf("failed to start query server: %s", err.Error())
	}
	log.Printf("query server listening on %s", iface)
}

func startHTTPQueryServer(iface string, engine *ekanite.Engine) {
	server := ekanite.NewHTTPServer(iface, engine)
	if server == nil {
		log.Fatal("failed to create HTTP query server")
	}
	if err := server.Start(); err != nil {
		log.Fatalf("failed to start HTTP query server: %s", err.Error())
	}
	log.Printf("HTTP query server listening on %s", iface)
}

func startDiagServer(iface string) {
	diagServer := status.NewService(iface)
	if err := diagServer.Start(); err != nil {
		log.Fatalf("failed to start status server on %s: %s", iface, err.Error())
	}
	log.Printf("diagnostic server listening on %s", iface)
}

func newTLSConfig(caPemPath, caKeyPath string) (*tls.Config, error) {
	var config *tls.Config

	caPem, err := ioutil.ReadFile(caPemPath)
	if err != nil {
		return nil, err
	}
	ca, err := x509.ParseCertificate(caPem)
	if err != nil {
		return nil, err
	}

	caKey, err := ioutil.ReadFile(caKeyPath)
	if err != nil {
		return nil, err
	}
	key, err := x509.ParsePKCS1PrivateKey(caKey)
	if err != nil {
		return nil, err
	}
	pool := x509.NewCertPool()
	pool.AddCert(ca)

	cert := tls.Certificate{
		Certificate: [][]byte{caPem},
		PrivateKey:  key,
	}

	config = &tls.Config{
		ClientAuth:   tls.RequireAndVerifyClientCert,
		Certificates: []tls.Certificate{cert},
		ClientCAs:    pool,
	}

	config.Rand = rand.Reader

	return config, nil
}

// drainLog drains errors from the channel and simply logs them
func drainLog(msg string, errChan <-chan error) {
	for {
		select {
		case err := <-errChan:
			if err != nil {
				log.Printf("%s: %s", msg, err.Error())
			}
		}
	}
}

// prof stores the file locations of active profiles.
var prof struct {
	cpu *os.File
	mem *os.File
}

// StartProfile initializes the cpu and memory profile, if specified.
func startProfile(cpuprofile, memprofile string) {
	if cpuprofile != "" {
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Fatalf("cpuprofile: %v", err)
		}
		log.Printf("writing CPU profile to: %s\n", cpuprofile)
		prof.cpu = f
		pprof.StartCPUProfile(prof.cpu)
	}

	if memprofile != "" {
		f, err := os.Create(memprofile)
		if err != nil {
			log.Fatalf("memprofile: %v", err)
		}
		log.Printf("writing memory profile to: %s\n", memprofile)
		prof.mem = f
		runtime.MemProfileRate = 4096
	}

}

// StopProfile closes the cpu and memory profiles if they are running.
func stopProfile() {
	if prof.cpu != nil {
		pprof.StopCPUProfile()
		prof.cpu.Close()
		log.Println("CPU profile stopped")
	}
	if prof.mem != nil {
		pprof.Lookup("heap").WriteTo(prof.mem, 0)
		prof.mem.Close()
		log.Println("memory profile stopped")
	}
}

func printHelp() {
	fmt.Println("ekanited [options]")
	fs.PrintDefaults()
}
<commit_msg>Move signal handling to distinct function<commit_after>package main

import (
	"crypto/rand"
	"crypto/tls"
	"crypto/x509"
	"expvar"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	_ "net/http/pprof"
	"os"
	"os/signal"
	"path/filepath"
	"runtime"
	"runtime/pprof"
	"syscall"
	"time"

	"github.com/ekanite/ekanite"
	"github.com/ekanite/ekanite/input"
	"github.com/ekanite/ekanite/status"
)

var (
	stats = expvar.NewMap("ekanite")
)

// Program parameters
var datadir string
var tcpIface string
var udpIface string
var caPemPath string
var caKeyPath string
var queryIface string
var batchSize int
var batchTimeout int
var indexMaxPending int
var gomaxprocs int
var numShards int
var retentionPeriod string
var cpuProfile string
var memProfile string
var inputFormat string

// Flag set
var fs *flag.FlagSet

// Types
const (
	DefaultDataDir         = "/var/opt/ekanite"
	DefaultBatchSize       = 300
	DefaultBatchTimeout    = 1000
	DefaultIndexMaxPending = 1000
	DefaultNumShards       = 4
	DefaultRetentionPeriod = "168h"
	DefaultQueryAddr       = "localhost:9950"
	DefaultHTTPQueryAddr   = "localhost:8080"
	DefaultDiagsIface      = "localhost:9951"
	DefaultTCPServer       = "localhost:5514"
	DefaultInputFormat     = "syslog"
)

func main() {
	fs = flag.NewFlagSet("", flag.ExitOnError)
	var (
		datadir         = fs.String("datadir", DefaultDataDir, "Set data directory")
		batchSize       = fs.Int("batchsize", DefaultBatchSize, "Indexing batch size")
		batchTimeout    = fs.Int("batchtime", DefaultBatchTimeout, "Indexing batch timeout, in milliseconds")
		indexMaxPending = fs.Int("maxpending", DefaultIndexMaxPending, "Maximum pending index events")
		tcpIface        = fs.String("tcp", DefaultTCPServer, "Syslog server TCP bind address in the form host:port. To disable set to empty string")
		udpIface        = fs.String("udp", "", "Syslog server UDP bind address in the form host:port. If not set, not started")
		diagIface       = fs.String("diag", DefaultDiagsIface, "expvar and pprof bind address in the form host:port. If not set, not started")
		caPemPath       = fs.String("tlspem", "", "path to CA PEM file for TLS-enabled TCP server. If not set, TLS not activated")
		caKeyPath       = fs.String("tlskey", "", "path to CA key file for TLS-enabled TCP server. If not set, TLS not activated")
		queryIface      = fs.String("query", DefaultQueryAddr, "TCP Bind address for query server in the form host:port. To disable set to empty string")
		queryIfaceHttp  = fs.String("queryhttp", DefaultHTTPQueryAddr, "TCP Bind address for http query server in the form host:port. To disable set to empty string")
		numShards       = fs.Int("numshards", DefaultNumShards, "Set number of shards per index")
		retentionPeriod = fs.String("retention", DefaultRetentionPeriod, "Data retention period. Minimum is 24 hours")
		cpuProfile      = fs.String("cpuprof", "", "Where to write CPU profiling data. Not written if not set")
		memProfile      = fs.String("memprof", "", "Where to write memory profiling data. Not written if not set")
		inputFormat     = fs.String("input", DefaultInputFormat, "Message format of input (only syslog supported)")
	)
	fs.Usage = printHelp
	fs.Parse(os.Args[1:])

	absDataDir, err := filepath.Abs(*datadir)
	if err != nil {
		log.Fatalf("failed to get absolute data path for '%s': %s", *datadir, err.Error())
	}

	// Get the retention period.
	retention, err := time.ParseDuration(*retentionPeriod)
	if err != nil {
		log.Fatalf("failed to parse retention period '%s'", *retentionPeriod)
	}

	log.SetFlags(log.LstdFlags)
	log.SetPrefix("[ekanite] ")
	log.Printf("ekanite started using %s for index storage", absDataDir)

	runtime.GOMAXPROCS(runtime.NumCPU())
	log.Println("GOMAXPROCS set to", runtime.GOMAXPROCS(0))

	// Start the expvar handler if requested.
	if *diagIface != "" {
		startDiagServer(*diagIface)
	}

	// Create and open the Engine.
	engine := ekanite.NewEngine(absDataDir)
	engine.NumShards = *numShards
	engine.RetentionPeriod = retention

	if err := engine.Open(); err != nil {
		log.Fatalf("failed to open engine: %s", err.Error())
	}
	log.Printf("engine opened with shard number of %d, retention period of %s",
		engine.NumShards, engine.RetentionPeriod)

	// Start the simple query server if requested.
	if *queryIface != "" {
		startQueryServer(*queryIface, engine)
	}

	// Start the http query server if requested.
	if *queryIfaceHttp != "" {
		startHTTPQueryServer(*queryIfaceHttp, engine)
	}

	// Create and start the batcher.
	batcherTimeout := time.Duration(*batchTimeout) * time.Millisecond
	batcher := ekanite.NewBatcher(engine, *batchSize, batcherTimeout, *indexMaxPending)

	errChan := make(chan error)
	if err := batcher.Start(errChan); err != nil {
		log.Fatalf("failed to start indexing batcher: %s", err.Error())
	}
	log.Printf("batching configured with size %d, timeout %s, max pending %d",
		*batchSize, batcherTimeout, *indexMaxPending)

	// Start draining batcher errors.
	go drainLog("error indexing batch", errChan)

	// Start TCP collector if requested.
	if *tcpIface != "" {
		var tlsConfig *tls.Config
		if *caPemPath != "" && *caKeyPath != "" {
			tlsConfig, err = newTLSConfig(*caPemPath, *caKeyPath)
			if err != nil {
				log.Fatalf("failed to configure TLS: %s", err.Error())
			}
			log.Printf("TLS successfully configured")
		}

		if err := startTCPCollector(*tcpIface, *inputFormat, tlsConfig, batcher); err != nil {
			log.Fatalf("failed to start TCP collector: %s", err.Error())
		}
		log.Printf("TCP collector listening to %s", *tcpIface)
	}

	// Start UDP collector if requested.
	if *udpIface != "" {
		if err := startUDPCollector(*udpIface, *inputFormat, batcher); err != nil {
			log.Fatalf("failed to start UDP collector: %s", err.Error())
		}
		log.Printf("UDP collector listening to %s", *udpIface)
	}

	// Start profiling.
	startProfile(*cpuProfile, *memProfile)

	stats.Set("launch", time.Now().UTC())

	// Wait forever for signals.
	waitForSignals()

	stopProfile()
}

func startTCPCollector(iface, format string, tls *tls.Config, batcher *ekanite.Batcher) error {
	collector, err := input.NewCollector("tcp", iface, format, tls)
	if err != nil {
		return fmt.Errorf(("failed to create TCP collector: %s"), err.Error())
	}
	if err := collector.Start(batcher.C()); err != nil {
		return fmt.Errorf("failed to start TCP collector: %s", err.Error())
	}

	return nil
}

func startUDPCollector(iface, format string, batcher *ekanite.Batcher) error {
	collector, err := input.NewCollector("udp", iface, format, nil)
	if err != nil {
		return fmt.Errorf("failed to create UDP collector: %s", err.Error())
	}
	if err := collector.Start(batcher.C()); err != nil {
		return fmt.Errorf("failed to start UDP collector: %s", err.Error())
	}

	return nil
}

func startQueryServer(iface string, engine *ekanite.Engine) {
	server := ekanite.NewServer(iface, engine)
	if server == nil {
		log.Fatal("failed to create query server")
	}
	if err := server.Start(); err != nil {
		log.Fatalf("failed to start query server: %s", err.Error())
	}
	log.Printf("query server listening on %s", iface)
}

func startHTTPQueryServer(iface string, engine *ekanite.Engine) {
	server := ekanite.NewHTTPServer(iface, engine)
	if server == nil {
		log.Fatal("failed to create HTTP query server")
	}
	if err := server.Start(); err != nil {
		log.Fatalf("failed to start HTTP query server: %s", err.Error())
	}
	log.Printf("HTTP query server listening on %s", iface)
}

func startDiagServer(iface string) {
	diagServer := status.NewService(iface)
	if err := diagServer.Start(); err != nil {
		log.Fatalf("failed to start status server on %s: %s", iface, err.Error())
	}
	log.Printf("diagnostic server listening on %s", iface)
}

func newTLSConfig(caPemPath, caKeyPath string) (*tls.Config, error) {
	var config *tls.Config

	caPem, err := ioutil.ReadFile(caPemPath)
	if err != nil {
		return nil, err
	}
	ca, err := x509.ParseCertificate(caPem)
	if err != nil {
		return nil, err
	}

	caKey, err := ioutil.ReadFile(caKeyPath)
	if err != nil {
		return nil, err
	}
	key, err := x509.ParsePKCS1PrivateKey(caKey)
	if err != nil {
		return nil, err
	}
	pool := x509.NewCertPool()
	pool.AddCert(ca)

	cert := tls.Certificate{
		Certificate: [][]byte{caPem},
		PrivateKey:  key,
	}

	config = &tls.Config{
		ClientAuth:   tls.RequireAndVerifyClientCert,
		Certificates: []tls.Certificate{cert},
		ClientCAs:    pool,
	}

	config.Rand = rand.Reader

	return config, nil
}

// drainLog drains errors from the channel and simply logs them
func drainLog(msg string, errChan <-chan error) {
	for {
		select {
		case err := <-errChan:
			if err != nil {
				log.Printf("%s: %s", msg, err.Error())
			}
		}
	}
}

// waitForSignals blocks until a signal is received.
func waitForSignals() {
	// Set up signal handling.
	signalCh := make(chan os.Signal, 1)
	signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)

	// Block until one of the signals above is received
	select {
	case <-signalCh:
		log.Println("signal received, shutting down...")
	}
}

// prof stores the file locations of active profiles.
var prof struct {
	cpu *os.File
	mem *os.File
}

// StartProfile initializes the cpu and memory profile, if specified.
func startProfile(cpuprofile, memprofile string) {
	if cpuprofile != "" {
		f, err := os.Create(cpuprofile)
		if err != nil {
			log.Fatalf("cpuprofile: %v", err)
		}
		log.Printf("writing CPU profile to: %s\n", cpuprofile)
		prof.cpu = f
		pprof.StartCPUProfile(prof.cpu)
	}

	if memprofile != "" {
		f, err := os.Create(memprofile)
		if err != nil {
			log.Fatalf("memprofile: %v", err)
		}
		log.Printf("writing memory profile to: %s\n", memprofile)
		prof.mem = f
		runtime.MemProfileRate = 4096
	}

}

// StopProfile closes the cpu and memory profiles if they are running.
func stopProfile() {
	if prof.cpu != nil {
		pprof.StopCPUProfile()
		prof.cpu.Close()
		log.Println("CPU profile stopped")
	}
	if prof.mem != nil {
		pprof.Lookup("heap").WriteTo(prof.mem, 0)
		prof.mem.Close()
		log.Println("memory profile stopped")
	}
}

func printHelp() {
	fmt.Println("ekanited [options]")
	fs.PrintDefaults()
}
<|endoftext|>


<commit_before>package main

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

	"github.com/n1tr0g/godoauth"
)

var (
	name    string = "godoauth - Go Docker Token Authenticator"
	version string = "v0.0.1"
	commit  string
)

var (
	confFile    string
	showVersion bool
)

func init() {
	flag.StringVar(&confFile, "config", "config.yaml", "Go Docker Token Auth Config file")
	flag.BoolVar(&showVersion, "version", false, "show the version and exit")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of Go Docker Token Auth (version %v):\n", version)
		flag.PrintDefaults()
	}
}

func main() {
	flag.Parse()

	if showVersion {
		fmt.Fprintln(os.Stderr, os.Args[0], version)
		return
	}

	var config godoauth.Config
	if err := config.LoadFromFile(confFile); err != nil {
		fmt.Fprintln(os.Stderr, "error parsing config file: ", err)
		os.Exit(1)
	}

	if err := config.LoadCerts(); err != nil {
		fmt.Fprintln(os.Stderr, "error while loading/veryfing certs: ", err)
	}

	fmt.Printf("Starting %s version: %s\n", name, version)

	timeout, err := time.ParseDuration(config.HTTP.Timeout)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error parsing HTTP read timeout")
		return
	}

	authHandler := &godoauth.TokenAuthHandler{
		Config: &config,
	}

	server := &http.Server{
		Addr:        config.HTTP.Addr,
		Handler:     godoauth.NewHandler(authHandler),
		ReadTimeout: timeout,
	}

	if config.HTTP.TLS.Certificate != "" && config.HTTP.TLS.Key != "" {
		server.ListenAndServeTLS(config.HTTP.TLS.Certificate, config.HTTP.TLS.Key)
		return
	}
	server.ListenAndServe()
}
<commit_msg>Implemented graceful HTTP shutdown<commit_after>package main

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

	"gopkg.in/tylerb/graceful.v1"

	"github.com/n1tr0g/godoauth"
)

var (
	name    string = "godoauth - Go Docker Token Authenticator"
	version string = "v0.0.1"
	commit  string
)

var (
	confFile    string
	showVersion bool
)

const shutdownTimeout = 10 * time.Second

func init() {
	flag.StringVar(&confFile, "config", "config.yaml", "Go Docker Token Auth Config file")
	flag.BoolVar(&showVersion, "version", false, "show the version and exit")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of Go Docker Token Auth (version %v):\n", version)
		flag.PrintDefaults()
	}
}

func main() {
	flag.Parse()

	if showVersion {
		fmt.Fprintln(os.Stderr, os.Args[0], version)
		return
	}

	var config godoauth.Config
	if err := config.LoadFromFile(confFile); err != nil {
		fmt.Fprintln(os.Stderr, "error parsing config file: ", err)
		os.Exit(1)
	}

	if err := config.LoadCerts(); err != nil {
		fmt.Fprintln(os.Stderr, "error while loading/veryfing certs: ", err)
	}

	fmt.Printf("Starting %s version: %s\n", name, version)

	timeout, err := time.ParseDuration(config.HTTP.Timeout)
	if err != nil {
		fmt.Fprintln(os.Stderr, "error parsing HTTP read timeout")
		return
	}

	authHandler := &godoauth.TokenAuthHandler{
		Config: &config,
	}

	server := &graceful.Server{
		Timeout: shutdownTimeout,
		Server: &http.Server{
			Addr:        config.HTTP.Addr,
			Handler:     godoauth.NewHandler(authHandler),
			ReadTimeout: timeout,
		},
	}

	if config.HTTP.TLS.Certificate != "" && config.HTTP.TLS.Key != "" {
		server.ListenAndServeTLS(config.HTTP.TLS.Certificate, config.HTTP.TLS.Key)
		return
	}
	server.ListenAndServe()
}
<|endoftext|>


<commit_before>// groot-ls recursively dumps the hierarchy tree of a ROOT file
package main

import (
	"flag"
	"fmt"
	"os"

	"bitbucket.org/binet/go-root/pkg/groot"
)

var fname = flag.String("f", "small.ntuple.0.root", "ROOT file to inspect")

func main() {
	fmt.Printf(":: groot-ls ::\n")
	flag.Parse()

	f, err := groot.NewFileReader(*fname)
	if err != nil {
		fmt.Printf("**error**: %v\n", err)
		os.Exit(1)
	}

	if f == nil {
		fmt.Printf("**error**: invalid file pointer\n")
		os.Exit(1)
	}

	fmt.Printf("file: '%s' (version=%v)\n", f.Name(), f.Version())

	var inspect func(*groot.Directory, string, string)
	inspect = func(dir *groot.Directory, name, indent string) {
		if dir == nil {
			fmt.Printf("err: invalid directory [%s]\n", name)
			return
		}
		keys := dir.Keys()
		fmt.Printf("%s%s -> #%d key(s)\n", indent, name, len(keys))
		for _, k := range keys {
			fmt.Printf("%skey: name='%s' title='%s' type=%s\n",
				indent, k.Name(), k.Title(), k.Class())
			if v, ok := k.Value().(*groot.Directory); ok {
				name := name
				if name == "/" {
					name = "/"+k.Name()
				} else {
					name = name+"/"+k.Name()
				}
				inspect(v, name, indent+"  ")
			}
		}
	}

	dir := f.Dir()
	inspect(dir, "/", "")

	fmt.Printf("::bye.\n")
}

// EOF
<commit_msg>test some of the Factory API<commit_after>// groot-ls recursively dumps the hierarchy tree of a ROOT file
package main

import (
	"flag"
	"fmt"
	"os"

	"bitbucket.org/binet/go-root/pkg/groot"
)

var fname = flag.String("f", "ntuple.root", "ROOT file to inspect")

func main() {
	fmt.Printf(":: groot-ls ::\n")
	flag.Parse()

	nfactories := groot.Factory.NumKey()
	fmt.Printf(":: groot has registered %d factory-type(s)\n", nfactories)

	f, err := groot.NewFileReader(*fname)
	if err != nil {
		fmt.Printf("**error**: %v\n", err)
		os.Exit(1)
	}

	if f == nil {
		fmt.Printf("**error**: invalid file pointer\n")
		os.Exit(1)
	}

	fmt.Printf("file: '%s' (version=%v)\n", f.Name(), f.Version())

	var inspect func(*groot.Directory, string, string)
	inspect = func(dir *groot.Directory, name, indent string) {
		if dir == nil {
			fmt.Printf("err: invalid directory [%s]\n", name)
			return
		}
		keys := dir.Keys()
		fmt.Printf("%s%s -> #%d key(s)\n", indent, name, len(keys))
		for _, k := range keys {
			fmt.Printf("%skey: name='%s' title='%s' type=%s\n",
				indent, k.Name(), k.Title(), k.Class())
			if v, ok := k.Value().(*groot.Directory); ok {
				name := name
				if name == "/" {
					name = "/"+k.Name()
				} else {
					name = name+"/"+k.Name()
				}
				inspect(v, name, indent+"  ")
			}
		}
	}

	dir := f.Dir()
	inspect(dir, "/", "")

	fmt.Printf("::bye.\n")
}

// EOF
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"github.com/summerwind/h2spec"
	"os"
	"strings"
	"time"
)

const VERSION = "v1.3.1"

type sections []string

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

func (s *sections) Set(v string) error {
	*s = append(*s, v)
	return nil
}

func main() {
	port := flag.Int("p", 0, "Target port.")
	host := flag.String("h", "127.0.0.1", "Target host.")
	useTls := flag.Bool("t", false, "Connect over TLS.")
	insecureSkipVerify := flag.Bool("k", false, "Don't verify server's certificate.")
	timeout := flag.Int("o", 2, "Maximum time allowed for test.")
	strict := flag.Bool("S", false, "Strict mode.")
	version := flag.Bool("version", false, "Display version information and exit.")

	var sectionFlag sections
	flag.Var(&sectionFlag, "s", "Section number on which to run the test")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS]\n\n", os.Args[0])
		fmt.Println("Options:")
		fmt.Println("  -p:        Target port. (Default: 80 or 443)")
		fmt.Println("  -h:        Target host. (Default: 127.0.0.1)")
		fmt.Println("  -t:        Connect over TLS. (Default: false)")
		fmt.Println("  -k:        Don't verify server's certificate. (Default: false)")
		fmt.Println("  -o:        Maximum time allowed for test. (Default: 2)")
		fmt.Println("  -s:        Section number on which to run the test. (Example: -s 6.1 -s 6.2)")
		fmt.Println("  -S:        Run the test cases marked as \"strict\".")
		fmt.Println("  --version: Display version information and exit.")
		fmt.Println("  --help:    Display this help and exit.")
		os.Exit(1)
	}

	flag.Parse()

	if *version {
		fmt.Fprintf(os.Stderr, "h2spec %s\n", VERSION)
		os.Exit(0)
	}

	if *port == 0 {
		if *useTls {
			*port = 443
		} else {
			*port = 80
		}
	}

	var ctx h2spec.Context
	ctx.Port = *port
	ctx.Host = *host
	ctx.Timeout = time.Duration(*timeout) * time.Second
	ctx.Strict = *strict
	ctx.Tls = *useTls
	ctx.TlsConfig = &tls.Config{
		InsecureSkipVerify: *insecureSkipVerify,
	}

	if len(sectionFlag) > 0 {
		ctx.Sections = map[string]bool{}
		for _, sec := range sectionFlag {
			splitedSec := strings.Split(sec, ".")
			lastIndex := len(splitedSec) - 1

			num := []string{}
			for i, sec := range splitedSec {
				num = append(num, sec)
				if i != 0 {
					key := strings.Join(num, ".")

					runAll := false
					if i == lastIndex || ctx.Sections[key] {
						runAll = true
					}

					ctx.Sections[key] = runAll
				}
			}
		}
	}

	if !h2spec.Run(&ctx) {
		os.Exit(1)
	}
}
<commit_msg>Bump version<commit_after>package main

import (
	"crypto/tls"
	"flag"
	"fmt"
	"github.com/summerwind/h2spec"
	"os"
	"strings"
	"time"
)

const VERSION = "v1.4.0"

type sections []string

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

func (s *sections) Set(v string) error {
	*s = append(*s, v)
	return nil
}

func main() {
	port := flag.Int("p", 0, "Target port.")
	host := flag.String("h", "127.0.0.1", "Target host.")
	useTls := flag.Bool("t", false, "Connect over TLS.")
	insecureSkipVerify := flag.Bool("k", false, "Don't verify server's certificate.")
	timeout := flag.Int("o", 2, "Maximum time allowed for test.")
	strict := flag.Bool("S", false, "Strict mode.")
	version := flag.Bool("version", false, "Display version information and exit.")

	var sectionFlag sections
	flag.Var(&sectionFlag, "s", "Section number on which to run the test")

	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS]\n\n", os.Args[0])
		fmt.Println("Options:")
		fmt.Println("  -p:        Target port. (Default: 80 or 443)")
		fmt.Println("  -h:        Target host. (Default: 127.0.0.1)")
		fmt.Println("  -t:        Connect over TLS. (Default: false)")
		fmt.Println("  -k:        Don't verify server's certificate. (Default: false)")
		fmt.Println("  -o:        Maximum time allowed for test. (Default: 2)")
		fmt.Println("  -s:        Section number on which to run the test. (Example: -s 6.1 -s 6.2)")
		fmt.Println("  -S:        Run the test cases marked as \"strict\".")
		fmt.Println("  --version: Display version information and exit.")
		fmt.Println("  --help:    Display this help and exit.")
		os.Exit(1)
	}

	flag.Parse()

	if *version {
		fmt.Fprintf(os.Stderr, "h2spec %s\n", VERSION)
		os.Exit(0)
	}

	if *port == 0 {
		if *useTls {
			*port = 443
		} else {
			*port = 80
		}
	}

	var ctx h2spec.Context
	ctx.Port = *port
	ctx.Host = *host
	ctx.Timeout = time.Duration(*timeout) * time.Second
	ctx.Strict = *strict
	ctx.Tls = *useTls
	ctx.TlsConfig = &tls.Config{
		InsecureSkipVerify: *insecureSkipVerify,
	}

	if len(sectionFlag) > 0 {
		ctx.Sections = map[string]bool{}
		for _, sec := range sectionFlag {
			splitedSec := strings.Split(sec, ".")
			lastIndex := len(splitedSec) - 1

			num := []string{}
			for i, sec := range splitedSec {
				num = append(num, sec)
				if i != 0 {
					key := strings.Join(num, ".")

					runAll := false
					if i == lastIndex || ctx.Sections[key] {
						runAll = true
					}

					ctx.Sections[key] = runAll
				}
			}
		}
	}

	if !h2spec.Run(&ctx) {
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>/*
i-sudoku is an interactive command-line sudoku tool. Although its main
puropse is debugging the sudoku package, it's a reasonably full-featured
command-line sudoku game in its own right.
*/

package main

import (
	"fmt"
	"github.com/jkomoros/sudoku"
	"github.com/nsf/termbox-go"
	"log"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

//A debug override; if true will print a color palette to the screen, wait for
//a keypress, and then quit. Useful for seeing what different colors are
//available to use.
const DRAW_PALETTE = false

var tickCount int

func main() {

	//TODO: should be possible to run it and pass in a puzzle to use.

	if err := termbox.Init(); err != nil {
		log.Fatal("Termbox initialization failed:", err)
	}
	defer termbox.Close()

	termbox.SetOutputMode(termbox.Output256)

	model := newModel()

	width, _ := termbox.Size()
	model.outputWidth = width

	if DRAW_PALETTE {
		drawColorPalette()
		//Wait until something happens, generally a key is pressed.
		termbox.PollEvent()
		return
	}

	draw(model)

	eventChan := make(chan termbox.Event, 1)
	go func() {
		for {
			eventChan <- termbox.PollEvent()
		}
	}()

	timeTick := time.Tick(time.Second * 1)

mainloop:
	for {
		select {
		case evt := <-eventChan:
			switch evt.Type {
			case termbox.EventKey:
				model.state.handleInput(model, evt)
			}
		case <-timeTick:
			tickCount++
		}

		draw(model)
		if model.exitNow {
			break mainloop
		}
		model.EndOfEventLoop()
	}
}

func clearScreen() {
	width, height := termbox.Size()
	for x := 0; x < width; x++ {
		for y := 0; y < height; y++ {
			termbox.SetCell(x, y, ' ', termbox.ColorDefault, termbox.ColorDefault)
		}
	}
}

func drawColorPalette() {
	clearScreen()
	x := 0
	y := 0

	for i := 0x00; i <= 0xFF; i++ {
		numToPrint := "  " + fmt.Sprintf("%02X", i) + "  "
		for _, ch := range numToPrint {
			termbox.SetCell(x, y, ch, termbox.ColorBlack, termbox.Attribute(i))
			x++
		}
		//Fit 8 print outs on a line before creating a new one
		if i%8 == 0 {
			x = 0
			y++
		}
	}

	termbox.Flush()
}

func drawGrid(y int, model *mainModel) (endY int) {
	var x int
	grid := model.grid

	fg := termbox.ColorBlack
	bg := termbox.ColorGreen

	//Iterate through toggles backwards, since earlier ones have higher preference
	for i := len(model.toggles) - 1; i >= 0; i-- {
		toggle := model.toggles[i]
		if toggle.Value() {
			bg = toggle.GridColor
		}
	}

	if model.grid.Invalid() {
		bg = termbox.ColorRed
	} else if model.grid.Solved() {
		bg = termbox.ColorYellow
	}

	//The column where the grid starts
	gridLeft := 1
	gridTop := 1

	termbox.SetCell(0, y, ' ', fg, bg)
	x++

	for i := 0; i < sudoku.DIM; i++ {

		cellLeft, _, _, _ := grid.Cell(0, i).DiagramExtents()
		cellLeft += gridLeft
		//Pad until we get to the start of this cell area
		for x < cellLeft {
			termbox.SetCell(x, y, '|', fg, bg)
			x++
		}
		for _, ch := range " " + strconv.Itoa(i) + " " {
			termbox.SetCell(x, y, ch, fg, bg)
			x++
		}
	}

	y++

	//Draw diagram down left rail
	x = 0
	tempY := y
	for i := 0; i < sudoku.DIM; i++ {

		_, cellTop, _, _ := grid.Cell(i, 0).DiagramExtents()
		cellTop += gridTop
		//Pad until we get to the start of this cell area
		for tempY < cellTop {
			termbox.SetCell(x, tempY, '-', fg, bg)
			tempY++
		}
		for _, ch := range " " + strconv.Itoa(i) + " " {
			termbox.SetCell(x, tempY, ch, fg, bg)
			tempY++
		}
	}

	fg, bg = bg, fg

	//TODO: I'm pretty sure top/left are reversed
	selectedTop, selectedLeft, selectedHeight, selectedWidth := model.Selected().DiagramExtents()
	//Correct the selected coordinate for the offset of the grid from the top.
	selectedLeft += gridTop
	selectedTop += gridLeft
	for _, line := range strings.Split(grid.Diagram(true), "\n") {
		//Grid starts at 1 cell over from left edge
		x = gridLeft
		//The first number in range will be byte offset, but for some items like the bullet, it's two bytes.
		//But what we care about is that each item is a character.
		for _, ch := range line {

			defaultColor := fg

			numberRune, _ := utf8.DecodeRuneInString(sudoku.DIAGRAM_NUMBER)
			lockedRune, _ := utf8.DecodeRuneInString(sudoku.DIAGRAM_LOCKED)

			if ch == numberRune {
				defaultColor = 0x12
			} else if ch == lockedRune {
				defaultColor = 0x35
			} else if runeIsNum(ch) {
				defaultColor = termbox.ColorWhite | termbox.AttrBold
			}

			backgroundColor := bg
			if x >= selectedTop && x < (selectedTop+selectedHeight) && y >= selectedLeft && y < (selectedLeft+selectedWidth) {
				//We're on the selected cell
				backgroundColor = 0xf0
			}

			termbox.SetCell(x, y, ch, defaultColor, backgroundColor)
			x++
		}
		y++
	}
	//The last loop added one extra to y.
	y--
	return y
}

func drawToggleLine(y int, model *mainModel) (newY int) {
	x := 0

	for _, toggle := range model.toggles {
		msg := toggle.OffText
		fg := toggle.GridColor
		bg := termbox.ColorBlack
		if toggle.Value() {
			msg = toggle.OnText
			fg, bg = bg, fg
		}
		for _, ch := range msg {
			termbox.SetCell(x, y, ch, fg, bg)
			x++
		}
	}
	return y
}

func drawStatusLine(y int, model *mainModel) (newY int) {
	x := 0
	var fg termbox.Attribute
	underlined := false
	for _, ch := range ">>> " + model.StatusLine() {
		//The ( and ) are non-printing control characters
		if ch == '{' {
			underlined = true
			continue
		} else if ch == '}' {
			underlined = false
			continue
		}
		fg = termbox.ColorBlack
		if underlined {
			fg = fg | termbox.AttrUnderline | termbox.AttrBold
		}

		termbox.SetCell(x, y, ch, fg, termbox.ColorWhite)
		x++
	}

	width, _ := termbox.Size()

	for x < width {
		termbox.SetCell(x, y, ' ', fg, termbox.ColorWhite)
		x++
	}
	return y
}

func drawConsole(y int, model *mainModel) (newY int) {

	x := 0

	underlined := false

	splitMessage := strings.Split(model.consoleMessage, "\n")

	for _, line := range splitMessage {

		x = 0
		for _, ch := range line {
			if ch == '{' {
				underlined = true
				continue
			} else if ch == '}' {
				underlined = false
				continue
			}
			fg := termbox.Attribute(0xf6)
			if underlined {
				fg = termbox.Attribute(0xFC) | termbox.AttrBold
			}
			termbox.SetCell(x, y, ch, fg, termbox.ColorBlack)
			x++
		}
		y++
	}
	//y is one too many
	y--
	return y
}

func draw(model *mainModel) {

	clearScreen()

	y := 0

	y = drawGrid(y, model)
	y++
	y = drawToggleLine(y, model)
	y++
	y = drawStatusLine(y, model)
	y++
	y = drawConsole(y, model)

	termbox.Flush()
}
<commit_msg>Whoops, removed code that should have been out after 62888.<commit_after>/*
i-sudoku is an interactive command-line sudoku tool. Although its main
puropse is debugging the sudoku package, it's a reasonably full-featured
command-line sudoku game in its own right.
*/

package main

import (
	"fmt"
	"github.com/jkomoros/sudoku"
	"github.com/nsf/termbox-go"
	"log"
	"strconv"
	"strings"
	"time"
	"unicode/utf8"
)

//A debug override; if true will print a color palette to the screen, wait for
//a keypress, and then quit. Useful for seeing what different colors are
//available to use.
const DRAW_PALETTE = false

var tickCount int

func main() {

	//TODO: should be possible to run it and pass in a puzzle to use.

	if err := termbox.Init(); err != nil {
		log.Fatal("Termbox initialization failed:", err)
	}
	defer termbox.Close()

	termbox.SetOutputMode(termbox.Output256)

	model := newModel()

	width, _ := termbox.Size()
	model.outputWidth = width

	if DRAW_PALETTE {
		drawColorPalette()
		//Wait until something happens, generally a key is pressed.
		termbox.PollEvent()
		return
	}

	draw(model)

	eventChan := make(chan termbox.Event, 1)
	go func() {
		for {
			eventChan <- termbox.PollEvent()
		}
	}()

	timeTick := time.Tick(time.Second * 1)

mainloop:
	for {
		select {
		case evt := <-eventChan:
			switch evt.Type {
			case termbox.EventKey:
				model.state.handleInput(model, evt)
			}
		case <-timeTick:
			tickCount++
		}

		draw(model)
		if model.exitNow {
			break mainloop
		}
		model.EndOfEventLoop()
	}
}

func clearScreen() {
	width, height := termbox.Size()
	for x := 0; x < width; x++ {
		for y := 0; y < height; y++ {
			termbox.SetCell(x, y, ' ', termbox.ColorDefault, termbox.ColorDefault)
		}
	}
}

func drawColorPalette() {
	clearScreen()
	x := 0
	y := 0

	for i := 0x00; i <= 0xFF; i++ {
		numToPrint := "  " + fmt.Sprintf("%02X", i) + "  "
		for _, ch := range numToPrint {
			termbox.SetCell(x, y, ch, termbox.ColorBlack, termbox.Attribute(i))
			x++
		}
		//Fit 8 print outs on a line before creating a new one
		if i%8 == 0 {
			x = 0
			y++
		}
	}

	termbox.Flush()
}

func drawGrid(y int, model *mainModel) (endY int) {
	var x int
	grid := model.grid

	fg := termbox.ColorBlack
	bg := termbox.ColorGreen

	//Iterate through toggles backwards, since earlier ones have higher preference
	for i := len(model.toggles) - 1; i >= 0; i-- {
		toggle := model.toggles[i]
		if toggle.Value() {
			bg = toggle.GridColor
		}
	}

	//The column where the grid starts
	gridLeft := 1
	gridTop := 1

	termbox.SetCell(0, y, ' ', fg, bg)
	x++

	for i := 0; i < sudoku.DIM; i++ {

		cellLeft, _, _, _ := grid.Cell(0, i).DiagramExtents()
		cellLeft += gridLeft
		//Pad until we get to the start of this cell area
		for x < cellLeft {
			termbox.SetCell(x, y, '|', fg, bg)
			x++
		}
		for _, ch := range " " + strconv.Itoa(i) + " " {
			termbox.SetCell(x, y, ch, fg, bg)
			x++
		}
	}

	y++

	//Draw diagram down left rail
	x = 0
	tempY := y
	for i := 0; i < sudoku.DIM; i++ {

		_, cellTop, _, _ := grid.Cell(i, 0).DiagramExtents()
		cellTop += gridTop
		//Pad until we get to the start of this cell area
		for tempY < cellTop {
			termbox.SetCell(x, tempY, '-', fg, bg)
			tempY++
		}
		for _, ch := range " " + strconv.Itoa(i) + " " {
			termbox.SetCell(x, tempY, ch, fg, bg)
			tempY++
		}
	}

	fg, bg = bg, fg

	//TODO: I'm pretty sure top/left are reversed
	selectedTop, selectedLeft, selectedHeight, selectedWidth := model.Selected().DiagramExtents()
	//Correct the selected coordinate for the offset of the grid from the top.
	selectedLeft += gridTop
	selectedTop += gridLeft
	for _, line := range strings.Split(grid.Diagram(true), "\n") {
		//Grid starts at 1 cell over from left edge
		x = gridLeft
		//The first number in range will be byte offset, but for some items like the bullet, it's two bytes.
		//But what we care about is that each item is a character.
		for _, ch := range line {

			defaultColor := fg

			numberRune, _ := utf8.DecodeRuneInString(sudoku.DIAGRAM_NUMBER)
			lockedRune, _ := utf8.DecodeRuneInString(sudoku.DIAGRAM_LOCKED)

			if ch == numberRune {
				defaultColor = 0x12
			} else if ch == lockedRune {
				defaultColor = 0x35
			} else if runeIsNum(ch) {
				defaultColor = termbox.ColorWhite | termbox.AttrBold
			}

			backgroundColor := bg
			if x >= selectedTop && x < (selectedTop+selectedHeight) && y >= selectedLeft && y < (selectedLeft+selectedWidth) {
				//We're on the selected cell
				backgroundColor = 0xf0
			}

			termbox.SetCell(x, y, ch, defaultColor, backgroundColor)
			x++
		}
		y++
	}
	//The last loop added one extra to y.
	y--
	return y
}

func drawToggleLine(y int, model *mainModel) (newY int) {
	x := 0

	for _, toggle := range model.toggles {
		msg := toggle.OffText
		fg := toggle.GridColor
		bg := termbox.ColorBlack
		if toggle.Value() {
			msg = toggle.OnText
			fg, bg = bg, fg
		}
		for _, ch := range msg {
			termbox.SetCell(x, y, ch, fg, bg)
			x++
		}
	}
	return y
}

func drawStatusLine(y int, model *mainModel) (newY int) {
	x := 0
	var fg termbox.Attribute
	underlined := false
	for _, ch := range ">>> " + model.StatusLine() {
		//The ( and ) are non-printing control characters
		if ch == '{' {
			underlined = true
			continue
		} else if ch == '}' {
			underlined = false
			continue
		}
		fg = termbox.ColorBlack
		if underlined {
			fg = fg | termbox.AttrUnderline | termbox.AttrBold
		}

		termbox.SetCell(x, y, ch, fg, termbox.ColorWhite)
		x++
	}

	width, _ := termbox.Size()

	for x < width {
		termbox.SetCell(x, y, ' ', fg, termbox.ColorWhite)
		x++
	}
	return y
}

func drawConsole(y int, model *mainModel) (newY int) {

	x := 0

	underlined := false

	splitMessage := strings.Split(model.consoleMessage, "\n")

	for _, line := range splitMessage {

		x = 0
		for _, ch := range line {
			if ch == '{' {
				underlined = true
				continue
			} else if ch == '}' {
				underlined = false
				continue
			}
			fg := termbox.Attribute(0xf6)
			if underlined {
				fg = termbox.Attribute(0xFC) | termbox.AttrBold
			}
			termbox.SetCell(x, y, ch, fg, termbox.ColorBlack)
			x++
		}
		y++
	}
	//y is one too many
	y--
	return y
}

func draw(model *mainModel) {

	clearScreen()

	y := 0

	y = drawGrid(y, model)
	y++
	y = drawToggleLine(y, model)
	y++
	y = drawStatusLine(y, model)
	y++
	y = drawConsole(y, model)

	termbox.Flush()
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"io/ioutil"
	"math/rand"
	"os"
	"time"

	"golang.org/x/tools/imports"
	"kego.io/kerr"
	"kego.io/kerr/kerrsource"
)

func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	flag.Parse()
	if err := processFile(flag.Arg(0)); err != nil {
		panic(err.Error())
	}
}

func processFile(filename string) error {

	if filename == "" {
		return kerr.New("CKBKFTNVXI", "File not found")
	}

	options := &imports.Options{
		TabWidth:  4,
		TabIndent: true,
		Comments:  true,
		Fragment:  true,
	}

	f, err := os.Open(filename)
	if err != nil {
		return kerr.Wrap("WCQEVUWMAI", err)
	}
	defer f.Close()

	src, err := ioutil.ReadAll(f)
	if err != nil {
		return kerr.Wrap("DWTHNAVSVY", err)
	}

	var res []byte

	res, err = kerrsource.Process(filename, res)
	if err != nil {
		return kerr.Wrap("UFVVOEXSYE", err)
	}

	res, err = imports.Process(filename, src, options)
	if err != nil {
		return kerr.Wrap("XFILQRWHSI", err)
	}

	if !bytes.Equal(src, res) {
		// formatting has changed
		err = ioutil.WriteFile(filename, res, 0)
		if err != nil {
			return kerr.Wrap("NFFAOHJQLG", err)
		}
	}

	return nil

}
<commit_msg>Use default options for imports<commit_after>package main

import (
	"bytes"
	"flag"
	"io/ioutil"
	"math/rand"
	"os"
	"time"

	"golang.org/x/tools/imports"
	"kego.io/kerr"
	"kego.io/kerr/kerrsource"
)

func main() {
	rand.Seed(time.Now().UTC().UnixNano())
	flag.Parse()
	if err := processFile(flag.Arg(0)); err != nil {
		panic(err.Error())
	}
}

func processFile(filename string) error {

	if filename == "" {
		return kerr.New("CKBKFTNVXI", "File not found")
	}

	f, err := os.Open(filename)
	if err != nil {
		return kerr.Wrap("WCQEVUWMAI", err)
	}
	defer f.Close()

	src, err := ioutil.ReadAll(f)
	if err != nil {
		return kerr.Wrap("DWTHNAVSVY", err)
	}

	var res []byte

	res, err = kerrsource.Process(filename, res)
	if err != nil {
		return kerr.Wrap("UFVVOEXSYE", err)
	}

	res, err = imports.Process(filename, src, nil)
	if err != nil {
		return kerr.Wrap("XFILQRWHSI", err)
	}

	if !bytes.Equal(src, res) {
		// formatting has changed
		err = ioutil.WriteFile(filename, res, 0)
		if err != nil {
			return kerr.Wrap("NFFAOHJQLG", err)
		}
	}

	return nil

}
<|endoftext|>