<commit_before>// Copyright 2015 The LUCI 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 lib

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"github.com/maruel/subcommands"

	"go.chromium.org/luci/auth"
	"go.chromium.org/luci/client/archiver"
	"go.chromium.org/luci/client/cas"
	"go.chromium.org/luci/client/isolate"
	"go.chromium.org/luci/common/data/text/units"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/isolated"
	"go.chromium.org/luci/common/isolatedclient"
	"go.chromium.org/luci/common/system/signals"
)

const (
	// infraFailExit is the exit code used when the exparchive fails due to
	// infrastructure errors (for example, failed server requests).
	infraFailExit = 2
)

// CmdArchive returns an object for the `archive` subcommand.
func CmdArchive(defaultAuthOpts auth.Options) *subcommands.Command {
	return &subcommands.Command{
		UsageLine: "archive <options>",
		ShortDesc: "parses a .isolate file to create a .isolated file, and uploads it and all referenced files to an isolate server",
		LongDesc:  "All the files listed in the .isolated file are put in the isolate server cache. Small files are combined together in a tar archive before uploading.",
		CommandRun: func() subcommands.CommandRun {
			c := archiveRun{}
			c.commonServerFlags.Init(defaultAuthOpts)
			c.isolateFlags.Init(&c.Flags)
			c.loggingFlags.Init(&c.Flags)
			c.casFlags.Init(&c.Flags)
			c.Flags.StringVar(&c.Isolated, "isolated", "", ".isolated file to generate")
			c.Flags.StringVar(&c.Isolated, "s", "", "Alias for --isolated")
			c.Flags.IntVar(&c.maxConcurrentChecks, "max-concurrent-checks", 1, "The maximum number of in-flight check requests.")
			c.Flags.IntVar(&c.maxConcurrentUploads, "max-concurrent-uploads", 8, "The maximum number of in-flight uploads.")
			c.Flags.StringVar(&c.dumpJSON, "dump-json", "",
				"Write isolated digests of archived trees to this file as JSON")
			return &c
		},
	}
}

type archiveRun struct {
	commonServerFlags
	isolateFlags
	loggingFlags         loggingFlags
	casFlags             cas.Flags
	maxConcurrentChecks  int
	maxConcurrentUploads int
	dumpJSON             string
}

func (c *archiveRun) Parse(a subcommands.Application, args []string) error {
	if err := c.commonServerFlags.Parse(); err != nil {
		return err
	}
	cwd, err := os.Getwd()
	if err != nil {
		return err
	}
	if err := c.isolateFlags.Parse(cwd, RequireIsolateFile); err != nil {
		return err
	}
	if err := c.casFlags.Parse(); err != nil {
		return err
	}
	if len(args) != 0 {
		return errors.Reason("position arguments not expected").Err()
	}
	return nil
}

func (c *archiveRun) main(a subcommands.Application, args []string) error {
	start := time.Now()
	ctx, cancel := context.WithCancel(c.defaultFlags.MakeLoggingContext(os.Stderr))
	signals.HandleInterrupt(cancel)
	authCl, err := c.createAuthClient(ctx)
	if err != nil {
		return err
	}
	client := c.createIsolatedClient(authCl)

	al := archiveLogger{
		start: start,
		quiet: c.defaultFlags.Quiet,
	}

	return c.archive(ctx, client, al)
}

// archiveLogger reports stats to stderr.
type archiveLogger struct {
	start time.Time
	quiet bool
}

// LogSummary logs (to eventlog and stderr) a high-level summary of archive operations(s).
func (al *archiveLogger) LogSummary(ctx context.Context, hits, misses int64, bytesHit, bytesPushed units.Size, digests []string) {
	end := time.Now()

	if !al.quiet {
		duration := end.Sub(al.start)
		fmt.Fprintf(os.Stderr, "Hits    : %5d (%s)\n", hits, bytesHit)
		fmt.Fprintf(os.Stderr, "Misses  : %5d (%s)\n", misses, bytesPushed)
		fmt.Fprintf(os.Stderr, "Duration: %s\n", units.Round(duration, time.Millisecond))
	}
}

// Print acts like fmt.Printf, but may prepend a prefix to format, depending on the value of al.quiet.
func (al *archiveLogger) Printf(format string, a ...interface{}) (n int, err error) {
	return al.Fprintf(os.Stdout, format, a...)
}

// Print acts like fmt.fprintf, but may prepend a prefix to format, depending on the value of al.quiet.
func (al *archiveLogger) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
	prefix := "\n"
	if al.quiet {
		prefix = ""
	}
	args := []interface{}{prefix}
	args = append(args, a...)
	return fmt.Printf("%s"+format, args...)
}

// archive performs the archive operation for an isolate specified by opts.
// dumpJSON is the path to write a JSON summary of the uploaded isolate, in the same format as batch_archive.
func (c *archiveRun) archive(ctx context.Context, client *isolatedclient.Client, al archiveLogger) error {
	opts := &c.ArchiveOptions
	// Parse the incoming isolate file.
	deps, rootDir, isol, err := isolate.ProcessIsolate(opts)
	if err != nil {
		return errors.Annotate(err, "isolate %s: failed to process", opts.Isolate).Err()
	}
	log.Printf("Isolate %s referenced %d deps", opts.Isolate, len(deps))

	if c.casFlags.Instance != "" {
		if err := uploadToCAS(ctx, &c.casFlags, &c.ArchiveOptions); err != nil {
			return errors.Annotate(err, "failed to upload to CAS").Err()
		}
		return nil
	}

	// Set up a checker and uploader.
	checker := archiver.NewChecker(ctx, client, c.maxConcurrentChecks)
	uploader := archiver.NewUploader(ctx, client, c.maxConcurrentUploads)
	arc := archiver.NewTarringArchiver(checker, uploader)
	isolSummary, err := arc.Archive(&archiver.TarringArgs{
		Deps:          deps,
		RootDir:       rootDir,
		IgnoredPathRe: opts.IgnoredPathFilterRe,
		Isolated:      opts.Isolated,
		Isol:          isol})
	if err != nil {
		return errors.Annotate(err, "isolate %s", opts.Isolate).Err()
	}

	// Make sure that all pending items have been checked.
	if err := checker.Close(); err != nil {
		return err
	}

	// Make sure that all the uploads have completed successfully.
	if err := uploader.Close(); err != nil {
		return err
	}

	printSummary(al, isolSummary)
	if err := dumpSummaryJSON(c.dumpJSON, isolSummary); err != nil {
		return err
	}

	al.LogSummary(ctx, int64(checker.Hit.Count()), int64(checker.Miss.Count()), units.Size(checker.Hit.Bytes()), units.Size(checker.Miss.Bytes()), []string{string(isolSummary.Digest)})
	return nil
}

func (c *archiveRun) Run(a subcommands.Application, args []string, _ subcommands.Env) int {
	if err := c.Parse(a, args); err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}
	cl, err := c.defaultFlags.StartTracing()
	if err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}
	defer cl.Close()
	if err := c.main(a, args); err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}
	return 0
}

func printSummary(al archiveLogger, summary archiver.IsolatedSummary) {
	al.Printf("%s\t%s\n", summary.Digest, summary.Name)
}

func dumpSummaryJSON(filename string, summaries ...archiver.IsolatedSummary) error {
	if len(filename) == 0 {
		return nil
	}
	f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	m := map[string]isolated.HexDigest{}
	for _, summary := range summaries {
		m[summary.Name] = summary.Digest
	}
	return json.NewEncoder(f).Encode(m)
}
<commit_msg>[isolate] Cleanup: Move isolateserver specific code to archiveToIsolate()<commit_after>// Copyright 2015 The LUCI 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 lib

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"time"

	"github.com/maruel/subcommands"

	"go.chromium.org/luci/auth"
	"go.chromium.org/luci/client/archiver"
	"go.chromium.org/luci/client/cas"
	"go.chromium.org/luci/client/isolate"
	"go.chromium.org/luci/common/data/text/units"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/common/isolated"
	"go.chromium.org/luci/common/system/signals"
)

const (
	// infraFailExit is the exit code used when the exparchive fails due to
	// infrastructure errors (for example, failed server requests).
	infraFailExit = 2
)

// CmdArchive returns an object for the `archive` subcommand.
func CmdArchive(defaultAuthOpts auth.Options) *subcommands.Command {
	return &subcommands.Command{
		UsageLine: "archive <options>",
		ShortDesc: "parses a .isolate file to create a .isolated file, and uploads it and all referenced files to an isolate server",
		LongDesc:  "All the files listed in the .isolated file are put in the isolate server cache. Small files are combined together in a tar archive before uploading.",
		CommandRun: func() subcommands.CommandRun {
			c := archiveRun{}
			c.commonServerFlags.Init(defaultAuthOpts)
			c.isolateFlags.Init(&c.Flags)
			c.loggingFlags.Init(&c.Flags)
			c.casFlags.Init(&c.Flags)
			c.Flags.StringVar(&c.Isolated, "isolated", "", ".isolated file to generate")
			c.Flags.StringVar(&c.Isolated, "s", "", "Alias for --isolated")
			c.Flags.IntVar(&c.maxConcurrentChecks, "max-concurrent-checks", 1, "The maximum number of in-flight check requests.")
			c.Flags.IntVar(&c.maxConcurrentUploads, "max-concurrent-uploads", 8, "The maximum number of in-flight uploads.")
			c.Flags.StringVar(&c.dumpJSON, "dump-json", "",
				"Write isolated digests of archived trees to this file as JSON")
			return &c
		},
	}
}

type archiveRun struct {
	commonServerFlags
	isolateFlags
	loggingFlags         loggingFlags
	casFlags             cas.Flags
	maxConcurrentChecks  int
	maxConcurrentUploads int
	dumpJSON             string
}

func (c *archiveRun) Parse(a subcommands.Application, args []string) error {
	if err := c.commonServerFlags.Parse(); err != nil {
		return err
	}
	cwd, err := os.Getwd()
	if err != nil {
		return err
	}
	if err := c.isolateFlags.Parse(cwd, RequireIsolateFile); err != nil {
		return err
	}
	if err := c.casFlags.Parse(); err != nil {
		return err
	}
	if len(args) != 0 {
		return errors.Reason("position arguments not expected").Err()
	}
	return nil
}

func (c *archiveRun) main(a subcommands.Application, args []string) error {
	start := time.Now()
	ctx, cancel := context.WithCancel(c.defaultFlags.MakeLoggingContext(os.Stderr))
	signals.HandleInterrupt(cancel)

	if c.casFlags.Instance != "" {
		return uploadToCAS(ctx, &c.casFlags, &c.ArchiveOptions)
	}

	return c.archiveToIsolate(ctx, start)
}

// archiveLogger reports stats to stderr.
type archiveLogger struct {
	start time.Time
	quiet bool
}

// LogSummary logs (to eventlog and stderr) a high-level summary of archive operations(s).
func (al *archiveLogger) LogSummary(ctx context.Context, hits, misses int64, bytesHit, bytesPushed units.Size, digests []string) {
	end := time.Now()

	if !al.quiet {
		duration := end.Sub(al.start)
		fmt.Fprintf(os.Stderr, "Hits    : %5d (%s)\n", hits, bytesHit)
		fmt.Fprintf(os.Stderr, "Misses  : %5d (%s)\n", misses, bytesPushed)
		fmt.Fprintf(os.Stderr, "Duration: %s\n", units.Round(duration, time.Millisecond))
	}
}

// Print acts like fmt.Printf, but may prepend a prefix to format, depending on the value of al.quiet.
func (al *archiveLogger) Printf(format string, a ...interface{}) (n int, err error) {
	return al.Fprintf(os.Stdout, format, a...)
}

// Print acts like fmt.fprintf, but may prepend a prefix to format, depending on the value of al.quiet.
func (al *archiveLogger) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
	prefix := "\n"
	if al.quiet {
		prefix = ""
	}
	args := []interface{}{prefix}
	args = append(args, a...)
	return fmt.Printf("%s"+format, args...)
}

// archiveToIsolate performs the archiveToIsolate operation for an isolate specified by opts.
// dumpJSON is the path to write a JSON summary of the uploaded isolate, in the same format as batch_archive.
func (c *archiveRun) archiveToIsolate(ctx context.Context, start time.Time) error {
	authCl, err := c.createAuthClient(ctx)
	if err != nil {
		return err
	}
	client := c.createIsolatedClient(authCl)

	al := archiveLogger{
		start: start,
		quiet: c.defaultFlags.Quiet,
	}

	opts := &c.ArchiveOptions
	// Parse the incoming isolate file.
	deps, rootDir, isol, err := isolate.ProcessIsolate(opts)
	if err != nil {
		return errors.Annotate(err, "isolate %s: failed to process", opts.Isolate).Err()
	}
	log.Printf("Isolate %s referenced %d deps", opts.Isolate, len(deps))

	// Set up a checker and uploader.
	checker := archiver.NewChecker(ctx, client, c.maxConcurrentChecks)
	uploader := archiver.NewUploader(ctx, client, c.maxConcurrentUploads)
	arc := archiver.NewTarringArchiver(checker, uploader)
	isolSummary, err := arc.Archive(&archiver.TarringArgs{
		Deps:          deps,
		RootDir:       rootDir,
		IgnoredPathRe: opts.IgnoredPathFilterRe,
		Isolated:      opts.Isolated,
		Isol:          isol})
	if err != nil {
		return errors.Annotate(err, "isolate %s", opts.Isolate).Err()
	}

	// Make sure that all pending items have been checked.
	if err := checker.Close(); err != nil {
		return err
	}

	// Make sure that all the uploads have completed successfully.
	if err := uploader.Close(); err != nil {
		return err
	}

	printSummary(al, isolSummary)
	if err := dumpSummaryJSON(c.dumpJSON, isolSummary); err != nil {
		return err
	}

	al.LogSummary(ctx, int64(checker.Hit.Count()), int64(checker.Miss.Count()), units.Size(checker.Hit.Bytes()), units.Size(checker.Miss.Bytes()), []string{string(isolSummary.Digest)})
	return nil
}

func (c *archiveRun) Run(a subcommands.Application, args []string, _ subcommands.Env) int {
	if err := c.Parse(a, args); err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}
	cl, err := c.defaultFlags.StartTracing()
	if err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}
	defer cl.Close()
	if err := c.main(a, args); err != nil {
		fmt.Fprintf(a.GetErr(), "%s: %s\n", a.GetName(), err)
		return 1
	}
	return 0
}

func printSummary(al archiveLogger, summary archiver.IsolatedSummary) {
	al.Printf("%s\t%s\n", summary.Digest, summary.Name)
}

func dumpSummaryJSON(filename string, summaries ...archiver.IsolatedSummary) error {
	if len(filename) == 0 {
		return nil
	}
	f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}
	defer f.Close()

	m := map[string]isolated.HexDigest{}
	for _, summary := range summaries {
		m[summary.Name] = summary.Digest
	}
	return json.NewEncoder(f).Encode(m)
}
<|endoftext|>


<commit_before>package regolib

const (
	targetLibSrc = `
package hooks["{{.Target}}"]

# Finds all violations for a given target
deny[response] {
	data.hooks["{{.Target}}"].library.matching_constraints[constraint]
	inp := {
		"review": get_default(input, "review", {}),
		"constraint": constraint
	}
	data.templates["{{.Target}}"][constraint.kind].deny[r] with input as inp
	response = {
		"msg": r.msg,
		"metadata": {"details": get_default(r, "details", {})},
		"constraint": constraint
	}
}

# Finds all violations in the cached state of a given target
audit[response] {
	data.hooks["{{.Target}}"].library.matching_reviews_and_constraints[[review, constraint]]
	inp := {
		"review": review,
		"constraint": constraint,
	}
	data.templates["{{.Target}}"][constraint.kind].deny[r] with input as inp
	response = {
		"msg": r.msg,
		"metadata": {"details": get_default(r, "details", {})},
		"constraint": constraint,
		"review": review,
	}
}

# get_default returns the value of an object's field or the provided default value.
# It avoids creating an undefined state when trying to access an object attribute that does
# not exist
get_default(object, field, _default) = object[field]

get_default(object, field, _default) = _default {
  not has_field(object, field)
}

has_field(object, field) {
  _ = object[field]
}
`
)
<commit_msg>Make sure review object is included in response<commit_after>package regolib

const (
	targetLibSrc = `
package hooks["{{.Target}}"]

# Finds all violations for a given target
deny[response] {
	data.hooks["{{.Target}}"].library.matching_constraints[constraint]
	review := get_default(input, "review", {})
	inp := {
		"review": review,
		"constraint": constraint
	}
	data.templates["{{.Target}}"][constraint.kind].deny[r] with input as inp
	response = {
		"msg": r.msg,
		"metadata": {"details": get_default(r, "details", {})},
		"constraint": constraint,
		"review": review,
	}
}

# Finds all violations in the cached state of a given target
audit[response] {
	data.hooks["{{.Target}}"].library.matching_reviews_and_constraints[[review, constraint]]
	inp := {
		"review": review,
		"constraint": constraint,
	}
	data.templates["{{.Target}}"][constraint.kind].deny[r] with input as inp
	response = {
		"msg": r.msg,
		"metadata": {"details": get_default(r, "details", {})},
		"constraint": constraint,
		"review": review,
	}
}

# get_default returns the value of an object's field or the provided default value.
# It avoids creating an undefined state when trying to access an object attribute that does
# not exist
get_default(object, field, _default) = object[field]

get_default(object, field, _default) = _default {
  not has_field(object, field)
}

has_field(object, field) {
  _ = object[field]
}
`
)
<|endoftext|>


<commit_before>package pino

import (
	"fmt"

	irc "github.com/fluffle/goirc/client"
)

// Pino is the central orchestrator
type Pino struct {
	config                   *Config
	ircProxy                 *ircProxy
	slackProxy               *slackProxy
	slackChannelToIRCChannel map[SlackChannel]IRCChannel
	ircChannelToSlackChannel map[IRCChannel]SlackChannel
}

// NewPino creates a new Pino instance
func NewPino(config *Config) (*Pino, error) {
	pino := &Pino{
		config: config,
	}

	ircProxy, err := newIRCProxy(&config.IRC)
	if err != nil {
		return pino, fmt.Errorf("Could not create IRC client: %v", err)
	}
	pino.ircProxy = ircProxy

	slackProxy, err := newSlackProxy(&config.Slack)
	if err != nil {
		return pino, fmt.Errorf("Could not create Slack client: %v", err)
	}
	pino.slackProxy = slackProxy

	pino.slackChannelToIRCChannel = make(map[SlackChannel]IRCChannel)
	pino.ircChannelToSlackChannel = make(map[IRCChannel]SlackChannel)
	// Set up the Slack channel -> IRC channel name mappings, and vice versa
	for slackChannel, ircChannel := range pino.config.ChannelMapping {
		pino.slackChannelToIRCChannel[slackChannel] = ircChannel
		pino.ircChannelToSlackChannel[ircChannel] = slackChannel
	}

	return pino, nil
}

// Run connects to IRC and Slack and runs the main loop
func (pino *Pino) Run() error {
	if err := pino.ircProxy.connect(); err != nil {
		return fmt.Errorf("IRC connection error: %s\n", err.Error())
	}
	if err := pino.slackProxy.connect(); err != nil {
		return fmt.Errorf("Slack connection error: %s\n", err.Error())
	}

	// Channel to signal that the program should stop running
	quit := make(chan bool)

	go pino.handleIRCEvents(quit)

	<-quit

	return nil
}

// Consumes incoming IRC events in a loop
func (pino *Pino) handleIRCEvents(quit chan bool) {
	previousNickMemberships := pino.ircProxy.snapshotOfNicksInChannels()

	for {
		select {
		case line := <-pino.ircProxy.incomingEvents:
			switch line.Cmd {
			case irc.CONNECTED:
				fmt.Printf("Connected to IRC!\n")
				ircChannels := pino.config.getUsedIRCChannels()
				for _, ircChannel := range ircChannels {
					fmt.Printf("Joining IRC channel: %v\n", ircChannel)
					pino.ircProxy.join(ircChannel)
				}

			case irc.DISCONNECTED:
				fmt.Printf("Disconnected from IRC!")

			case irc.ACTION:
				channel := IRCChannel(line.Target())
				action := line.Text()
				username := line.Nick

				fmt.Printf("ACTION: %v %s\n", username, action)
				message := fmt.Sprintf("```%v %v```", username, action)
				pino.slackProxy.sendMessageAsUser(username, message, pino.ircChannelToSlackChannel[channel])

			case irc.JOIN:
				channel := IRCChannel(line.Text())
				username := line.Nick
				usermask := line.Src

				fmt.Printf("JOIN: %v(%v) has joined %v\n", line.Nick, line.Src, channel)
				message := fmt.Sprintf("```%v(%v) joined the channel```", username, usermask)
				pino.slackProxy.sendMessageAsBot(message, pino.ircChannelToSlackChannel[channel])

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.INVITE:
				// Actually doing anything with invites has not been implemented yet.
				channel := line.Args[1]
				fmt.Printf("INVITE: %v(%v) invited you to %v\n", line.Nick, line.Src, channel)

			case irc.KICK:
				kickee := line.Args[1]
				reason := line.Args[2:]
				fmt.Printf("KICK: (%v) %v has kicked %v (%v)\n", line.Target(), line.Nick, kickee, reason)

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.MODE:
				username := line.Nick
				mode := line.Args[1]

				if len(line.Args) == 2 {
					// This was a User mode command
					destination := line.Args[0]
					fmt.Printf("MODE: %v has set mode %v on %v\n", username, mode, destination)
				} else {
					// This was a Channel mode command
					channel := IRCChannel(line.Args[0])
					destination := line.Args[2]
					fmt.Printf("MODE: (%v) %v sets %v %v\n", channel, username, mode, destination)

					message := fmt.Sprintf("```%v sets %v %v```", username, mode, destination)
					pino.slackProxy.sendMessageAsBot(message, pino.ircChannelToSlackChannel[channel])
				}

			case irc.NICK:
				oldNick := line.Nick
				newNick := line.Text()
				fmt.Printf("NICK: %v is now known as %v\n", oldNick, newNick)

				message := fmt.Sprintf("```%v is now known as %v```", oldNick, newNick)
				stateTracker := pino.ircProxy.client.StateTracker()
				for ircChannel, slackChannel := range pino.ircChannelToSlackChannel {
					// The state tracker has already registered the nick change, so check for the new nick
					if _, ok := stateTracker.IsOn(string(ircChannel), newNick); ok != false {
						pino.slackProxy.sendMessageAsBot(message, slackChannel)
					}
				}

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.PART:
				channel := IRCChannel(line.Target())
				reason := line.Text()
				username := line.Nick
				usermask := line.Src
				fmt.Printf("PART: (%v) %v(%v) has left (%s)\n", channel, username, usermask, reason)

				message := fmt.Sprintf("```%v(%v) left the channel```", username, usermask)
				pino.slackProxy.sendMessageAsBot(message, pino.ircChannelToSlackChannel[channel])

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.PRIVMSG:
				fmt.Printf("PRIVMSG: (%v) <%v> %v\n", line.Target(), line.Nick, line.Text())

			case irc.QUIT:
				username := line.Nick
				usermask := line.Src
				reason := line.Args[0]

				fmt.Printf("QUIT: %v(%v) has quit (%v)\n", username, usermask, reason)

				message := fmt.Sprintf("```%v(%v) left IRC (%v)```", username, usermask, reason)
				for ircChannel, nicks := range previousNickMemberships {
					if _, ok := nicks[username]; !ok {
						// The user was not in this channel
						continue
					}

					slackChannel := pino.ircChannelToSlackChannel[ircChannel]
					pino.slackProxy.sendMessageAsBot(message, slackChannel)
				}

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.TOPIC:
				newTopic := line.Text()
				fmt.Printf("TOPIC: (%v) %v has changed the topic to \"%v\"\n", line.Target(), line.Nick, newTopic)

			default:
				fmt.Printf("Received unrecognized line: %#v\n", line)
			}
		default:
			// No message was received
		}

	}
}
<commit_msg>update nick message to check using my own map instead of the IRC lib's state tracker<commit_after>package pino

import (
	"fmt"

	irc "github.com/fluffle/goirc/client"
)

// Pino is the central orchestrator
type Pino struct {
	config                   *Config
	ircProxy                 *ircProxy
	slackProxy               *slackProxy
	slackChannelToIRCChannel map[SlackChannel]IRCChannel
	ircChannelToSlackChannel map[IRCChannel]SlackChannel
}

// NewPino creates a new Pino instance
func NewPino(config *Config) (*Pino, error) {
	pino := &Pino{
		config: config,
	}

	ircProxy, err := newIRCProxy(&config.IRC)
	if err != nil {
		return pino, fmt.Errorf("Could not create IRC client: %v", err)
	}
	pino.ircProxy = ircProxy

	slackProxy, err := newSlackProxy(&config.Slack)
	if err != nil {
		return pino, fmt.Errorf("Could not create Slack client: %v", err)
	}
	pino.slackProxy = slackProxy

	pino.slackChannelToIRCChannel = make(map[SlackChannel]IRCChannel)
	pino.ircChannelToSlackChannel = make(map[IRCChannel]SlackChannel)
	// Set up the Slack channel -> IRC channel name mappings, and vice versa
	for slackChannel, ircChannel := range pino.config.ChannelMapping {
		pino.slackChannelToIRCChannel[slackChannel] = ircChannel
		pino.ircChannelToSlackChannel[ircChannel] = slackChannel
	}

	return pino, nil
}

// Run connects to IRC and Slack and runs the main loop
func (pino *Pino) Run() error {
	if err := pino.ircProxy.connect(); err != nil {
		return fmt.Errorf("IRC connection error: %s\n", err.Error())
	}
	if err := pino.slackProxy.connect(); err != nil {
		return fmt.Errorf("Slack connection error: %s\n", err.Error())
	}

	// Channel to signal that the program should stop running
	quit := make(chan bool)

	go pino.handleIRCEvents(quit)

	<-quit

	return nil
}

// Consumes incoming IRC events in a loop
func (pino *Pino) handleIRCEvents(quit chan bool) {
	previousNickMemberships := pino.ircProxy.snapshotOfNicksInChannels()

	for {
		select {
		case line := <-pino.ircProxy.incomingEvents:
			switch line.Cmd {
			case irc.CONNECTED:
				fmt.Printf("Connected to IRC!\n")
				ircChannels := pino.config.getUsedIRCChannels()
				for _, ircChannel := range ircChannels {
					fmt.Printf("Joining IRC channel: %v\n", ircChannel)
					pino.ircProxy.join(ircChannel)
				}

			case irc.DISCONNECTED:
				fmt.Printf("Disconnected from IRC!")

			case irc.ACTION:
				channel := IRCChannel(line.Target())
				action := line.Text()
				username := line.Nick

				fmt.Printf("ACTION: %v %s\n", username, action)
				message := fmt.Sprintf("```%v %v```", username, action)
				pino.slackProxy.sendMessageAsUser(username, message, pino.ircChannelToSlackChannel[channel])

			case irc.JOIN:
				channel := IRCChannel(line.Text())
				username := line.Nick
				usermask := line.Src

				fmt.Printf("JOIN: %v(%v) has joined %v\n", line.Nick, line.Src, channel)
				message := fmt.Sprintf("```%v(%v) joined the channel```", username, usermask)
				pino.slackProxy.sendMessageAsBot(message, pino.ircChannelToSlackChannel[channel])

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.INVITE:
				// Actually doing anything with invites has not been implemented yet.
				channel := line.Args[1]
				fmt.Printf("INVITE: %v(%v) invited you to %v\n", line.Nick, line.Src, channel)

			case irc.KICK:
				kickee := line.Args[1]
				reason := line.Args[2:]
				fmt.Printf("KICK: (%v) %v has kicked %v (%v)\n", line.Target(), line.Nick, kickee, reason)

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.MODE:
				username := line.Nick
				mode := line.Args[1]

				if len(line.Args) == 2 {
					// This was a User mode command
					destination := line.Args[0]
					fmt.Printf("MODE: %v has set mode %v on %v\n", username, mode, destination)
				} else {
					// This was a Channel mode command
					channel := IRCChannel(line.Args[0])
					destination := line.Args[2]
					fmt.Printf("MODE: (%v) %v sets %v %v\n", channel, username, mode, destination)

					message := fmt.Sprintf("```%v sets %v %v```", username, mode, destination)
					pino.slackProxy.sendMessageAsBot(message, pino.ircChannelToSlackChannel[channel])
				}

			case irc.NICK:
				oldNick := line.Nick
				newNick := line.Text()
				fmt.Printf("NICK: %v is now known as %v\n", oldNick, newNick)

				message := fmt.Sprintf("```%v is now known as %v```", oldNick, newNick)
				for ircChannel, nicks := range previousNickMemberships {
					if _, ok := nicks[oldNick]; !ok {
						// The user was not in this channel
						continue
					}

					slackChannel := pino.ircChannelToSlackChannel[ircChannel]
					pino.slackProxy.sendMessageAsBot(message, slackChannel)
				}

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.PART:
				channel := IRCChannel(line.Target())
				reason := line.Text()
				username := line.Nick
				usermask := line.Src
				fmt.Printf("PART: (%v) %v(%v) has left (%s)\n", channel, username, usermask, reason)

				message := fmt.Sprintf("```%v(%v) left the channel```", username, usermask)
				pino.slackProxy.sendMessageAsBot(message, pino.ircChannelToSlackChannel[channel])

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.PRIVMSG:
				fmt.Printf("PRIVMSG: (%v) <%v> %v\n", line.Target(), line.Nick, line.Text())

			case irc.QUIT:
				username := line.Nick
				usermask := line.Src
				reason := line.Args[0]

				fmt.Printf("QUIT: %v(%v) has quit (%v)\n", username, usermask, reason)

				message := fmt.Sprintf("```%v(%v) left IRC (%v)```", username, usermask, reason)
				for ircChannel, nicks := range previousNickMemberships {
					if _, ok := nicks[username]; !ok {
						// The user was not in this channel
						continue
					}

					slackChannel := pino.ircChannelToSlackChannel[ircChannel]
					pino.slackProxy.sendMessageAsBot(message, slackChannel)
				}

				previousNickMemberships = pino.ircProxy.snapshotOfNicksInChannels()
			case irc.TOPIC:
				newTopic := line.Text()
				fmt.Printf("TOPIC: (%v) %v has changed the topic to \"%v\"\n", line.Target(), line.Nick, newTopic)

			default:
				fmt.Printf("Received unrecognized line: %#v\n", line)
			}
		default:
			// No message was received
		}

	}
}
<|endoftext|>


<commit_before>package piper

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"syscall"
	"time"
	"unsafe"

	"github.com/gorilla/websocket"
	"github.com/kr/pty"
)

type Pipe struct {
	conn *websocket.Conn
	send chan []byte
	opts Opts
}

type Opts struct {
	Tty    bool `json:"tty"`
	Width  int  `json:"width,omitempty"`
	Height int  `json:"height,omitempty"`
}

type pipedCmd struct {
	pipe   *Pipe
	cmd    *exec.Cmd
	stdin  io.WriteCloser
	stdout io.ReadCloser
	stderr io.ReadCloser
}

type Winsize struct {
	Height uint16
	Width  uint16
	x      uint16
	y      uint16
}

func NewClientPipe(host string, opts Opts) (*Pipe, error) {
	encoded, err := json.Marshal(opts)
	if err != nil {
		return nil, err
	}
	h := http.Header{}
	h.Add("X-Pipe-Opts", string(encoded))
	url := fmt.Sprintf("ws://%s", host)
	conn, _, err := websocket.DefaultDialer.Dial(url, h)
	if err != nil {
		return nil, err
	}
	pipe := &Pipe{
		conn: conn,
		send: make(chan []byte),
		opts: opts,
	}
	go pipe.writer()
	return pipe, nil
}

func NewServerPipe(req *http.Request, conn *websocket.Conn) (*Pipe, error) {
	xPipeOpts := req.Header.Get("X-Pipe-Opts")
	if xPipeOpts == "" {
		return nil, fmt.Errorf("missing X-Pipe-Opts")
	}
	var opts Opts
	if err := json.Unmarshal([]byte(xPipeOpts), &opts); err != nil {
		return nil, err
	}
	pipe := &Pipe{
		conn: conn,
		send: make(chan []byte),
		opts: opts,
	}
	go pipe.writer()
	return pipe, nil
}

func (pipe *Pipe) writer() {
	ticker := time.NewTicker(((60 * time.Second) * 9) / 10)
	defer func() {
		ticker.Stop()
		pipe.conn.Close()
	}()
	write := func(mt int, payload []byte) error {
		pipe.conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
		return pipe.conn.WriteMessage(mt, payload)
	}
	for {
		select {
		case msg, ok := <-pipe.send:
			if !ok {
				write(websocket.CloseMessage, []byte{})
				return
			}
			if err := write(websocket.BinaryMessage, msg); err != nil {
				return
			}
		case <-ticker.C:
			if err := write(websocket.PingMessage, []byte{}); err != nil {
				return
			}
		}
	}
}

func (pipe *Pipe) sendExit(code uint32) {
	msg := Message{
		Kind:     EXIT,
		ExitCode: code,
	}
	payload, _ := msg.Prepare()
	pipe.send <- payload
}

func (pipe *Pipe) sendEOF() {
	msg := Message{Kind: EOF}
	payload, _ := msg.Prepare()
	pipe.send <- payload
}

func (pipe *Pipe) RunCmd(cmd *exec.Cmd) error {
	if pipe.opts.Tty {
		return pipe.runPtyCmd(cmd)
	}
	return pipe.runStdCmd(cmd)
}

func (pipe *Pipe) runStdCmd(cmd *exec.Cmd) error {
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}
	fmt.Println("aaba")
	pCmd := pipedCmd{
		pipe:   pipe,
		cmd:    cmd,
		stdin:  stdin,
		stdout: stdout,
		stderr: stderr,
	}
	return pCmd.run()
}

func (pipe *Pipe) runPtyCmd(cmd *exec.Cmd) error {
	py, tty, err := pty.Open()
	if err != nil {
		return err
	}
	defer tty.Close()
	env := os.Environ()
	env = append(env, "TERM=xterm")
	cmd.Env = env
	cmd.Stdout = tty
	cmd.Stdin = tty
	cmd.Stderr = tty
	cmd.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true}
	ws := &Winsize{
		Width:  uint16(pipe.opts.Width),
		Height: uint16(pipe.opts.Height),
	}
	_, _, syserr := syscall.Syscall(syscall.SYS_IOCTL, py.Fd(), uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
	if syserr != 0 {
		return syserr
	}
	pCmd := pipedCmd{
		pipe:   pipe,
		cmd:    cmd,
		stdin:  py,
		stdout: py,
		stderr: nil,
	}
	return pCmd.run()
}

func (pCmd *pipedCmd) run() error {
	defer close(pCmd.pipe.send)
	go pCmd.pipe.copyFrom(pCmd.stdin, STDIN)
	go pCmd.pipe.copyTo(pCmd.stdout, STDOUT)
	if pCmd.stderr != nil {
		go pCmd.pipe.copyTo(pCmd.stderr, STDERR)
	}
	if err := pCmd.cmd.Start(); err != nil {
		pCmd.pipe.sendExit(uint32(1))
		return err
	}
	waitErrCh := make(chan error)
	go func() {
		waitErrCh <- pCmd.cmd.Wait()
	}()
	select {
	case err := <-waitErrCh:
		status, err := pCmd.exitStatus(err)
		if err != nil {
			pCmd.pipe.sendExit(uint32(1))
			return err
		}
		pCmd.pipe.sendExit(status)
	}
	return nil
}

func (pCmd *pipedCmd) exitStatus(err error) (uint32, error) {
	if err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				return uint32(status.ExitStatus()), nil
			}
		}
		return 0, err
	}
	return 0, nil
}

func (pipe *Pipe) copyFrom(w io.WriteCloser, kind int) error {
	defer w.Close()
	_, err := io.Copy(w, pipeIO{pipe: pipe, kind: kind})
	if err != nil {
		return err
	}
	return nil
}

func (pipe *Pipe) copyTo(r io.Reader, kind int) error {
	_, err := io.Copy(pipeIO{pipe: pipe, kind: kind}, r)
	if err != nil {
		return err
	}
	return nil
}

func (pipe *Pipe) Interact() (int, error) {
	go func() {
		stdinPipe := pipeIO{pipe: pipe, kind: STDIN}
		_, err := io.Copy(stdinPipe, os.Stdin)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		pipe.sendEOF()
	}()
	var exitCode int
loop:
	for {
		_, r, err := pipe.conn.NextReader()
		if err != nil {
			return 1, fmt.Errorf("reading message: %s", err)
		}
		m, err := DecodeMessage(r)
		if err != nil {
			return 1, fmt.Errorf("decoding message: %s", err)
		}
		switch m.Kind {
		case STDOUT:
			os.Stdout.Write(m.Payload)
			break
		case STDERR:
			os.Stderr.Write(m.Payload)
			break
		case EXIT:
			exitCode = int(m.ExitCode)
			break loop
		}
	}
	pipe.Close("")
	return exitCode, nil
}

func (pipe *Pipe) Close(msg string) {
	pipe.conn.WriteMessage(
		websocket.CloseMessage,
		websocket.FormatCloseMessage(websocket.CloseNormalClosure, msg),
	)
	pipe.conn.Close()
}
<commit_msg>removed debug<commit_after>package piper

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"syscall"
	"time"
	"unsafe"

	"github.com/gorilla/websocket"
	"github.com/kr/pty"
)

type Pipe struct {
	conn *websocket.Conn
	send chan []byte
	opts Opts
}

type Opts struct {
	Tty    bool `json:"tty"`
	Width  int  `json:"width,omitempty"`
	Height int  `json:"height,omitempty"`
}

type pipedCmd struct {
	pipe   *Pipe
	cmd    *exec.Cmd
	stdin  io.WriteCloser
	stdout io.ReadCloser
	stderr io.ReadCloser
}

type Winsize struct {
	Height uint16
	Width  uint16
	x      uint16
	y      uint16
}

func NewClientPipe(host string, opts Opts) (*Pipe, error) {
	encoded, err := json.Marshal(opts)
	if err != nil {
		return nil, err
	}
	h := http.Header{}
	h.Add("X-Pipe-Opts", string(encoded))
	url := fmt.Sprintf("ws://%s", host)
	conn, _, err := websocket.DefaultDialer.Dial(url, h)
	if err != nil {
		return nil, err
	}
	pipe := &Pipe{
		conn: conn,
		send: make(chan []byte),
		opts: opts,
	}
	go pipe.writer()
	return pipe, nil
}

func NewServerPipe(req *http.Request, conn *websocket.Conn) (*Pipe, error) {
	xPipeOpts := req.Header.Get("X-Pipe-Opts")
	if xPipeOpts == "" {
		return nil, fmt.Errorf("missing X-Pipe-Opts")
	}
	var opts Opts
	if err := json.Unmarshal([]byte(xPipeOpts), &opts); err != nil {
		return nil, err
	}
	pipe := &Pipe{
		conn: conn,
		send: make(chan []byte),
		opts: opts,
	}
	go pipe.writer()
	return pipe, nil
}

func (pipe *Pipe) writer() {
	ticker := time.NewTicker(((60 * time.Second) * 9) / 10)
	defer func() {
		ticker.Stop()
		pipe.conn.Close()
	}()
	write := func(mt int, payload []byte) error {
		pipe.conn.SetWriteDeadline(time.Now().Add(10 * time.Second))
		return pipe.conn.WriteMessage(mt, payload)
	}
	for {
		select {
		case msg, ok := <-pipe.send:
			if !ok {
				write(websocket.CloseMessage, []byte{})
				return
			}
			if err := write(websocket.BinaryMessage, msg); err != nil {
				return
			}
		case <-ticker.C:
			if err := write(websocket.PingMessage, []byte{}); err != nil {
				return
			}
		}
	}
}

func (pipe *Pipe) sendExit(code uint32) {
	msg := Message{
		Kind:     EXIT,
		ExitCode: code,
	}
	payload, _ := msg.Prepare()
	pipe.send <- payload
}

func (pipe *Pipe) sendEOF() {
	msg := Message{Kind: EOF}
	payload, _ := msg.Prepare()
	pipe.send <- payload
}

func (pipe *Pipe) RunCmd(cmd *exec.Cmd) error {
	if pipe.opts.Tty {
		return pipe.runPtyCmd(cmd)
	}
	return pipe.runStdCmd(cmd)
}

func (pipe *Pipe) runStdCmd(cmd *exec.Cmd) error {
	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return err
	}
	stderr, err := cmd.StderrPipe()
	if err != nil {
		return err
	}
	pCmd := pipedCmd{
		pipe:   pipe,
		cmd:    cmd,
		stdin:  stdin,
		stdout: stdout,
		stderr: stderr,
	}
	return pCmd.run()
}

func (pipe *Pipe) runPtyCmd(cmd *exec.Cmd) error {
	py, tty, err := pty.Open()
	if err != nil {
		return err
	}
	defer tty.Close()
	env := os.Environ()
	env = append(env, "TERM=xterm")
	cmd.Env = env
	cmd.Stdout = tty
	cmd.Stdin = tty
	cmd.Stderr = tty
	cmd.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true}
	ws := &Winsize{
		Width:  uint16(pipe.opts.Width),
		Height: uint16(pipe.opts.Height),
	}
	_, _, syserr := syscall.Syscall(syscall.SYS_IOCTL, py.Fd(), uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
	if syserr != 0 {
		return syserr
	}
	pCmd := pipedCmd{
		pipe:   pipe,
		cmd:    cmd,
		stdin:  py,
		stdout: py,
		stderr: nil,
	}
	return pCmd.run()
}

func (pCmd *pipedCmd) run() error {
	defer close(pCmd.pipe.send)
	go pCmd.pipe.copyFrom(pCmd.stdin, STDIN)
	go pCmd.pipe.copyTo(pCmd.stdout, STDOUT)
	if pCmd.stderr != nil {
		go pCmd.pipe.copyTo(pCmd.stderr, STDERR)
	}
	if err := pCmd.cmd.Start(); err != nil {
		pCmd.pipe.sendExit(uint32(1))
		return err
	}
	waitErrCh := make(chan error)
	go func() {
		waitErrCh <- pCmd.cmd.Wait()
	}()
	select {
	case err := <-waitErrCh:
		status, err := pCmd.exitStatus(err)
		if err != nil {
			pCmd.pipe.sendExit(uint32(1))
			return err
		}
		pCmd.pipe.sendExit(status)
	}
	return nil
}

func (pCmd *pipedCmd) exitStatus(err error) (uint32, error) {
	if err != nil {
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				return uint32(status.ExitStatus()), nil
			}
		}
		return 0, err
	}
	return 0, nil
}

func (pipe *Pipe) copyFrom(w io.WriteCloser, kind int) error {
	defer w.Close()
	_, err := io.Copy(w, pipeIO{pipe: pipe, kind: kind})
	if err != nil {
		return err
	}
	return nil
}

func (pipe *Pipe) copyTo(r io.Reader, kind int) error {
	_, err := io.Copy(pipeIO{pipe: pipe, kind: kind}, r)
	if err != nil {
		return err
	}
	return nil
}

func (pipe *Pipe) Interact() (int, error) {
	go func() {
		stdinPipe := pipeIO{pipe: pipe, kind: STDIN}
		_, err := io.Copy(stdinPipe, os.Stdin)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
		pipe.sendEOF()
	}()
	var exitCode int
loop:
	for {
		_, r, err := pipe.conn.NextReader()
		if err != nil {
			return 1, fmt.Errorf("reading message: %s", err)
		}
		m, err := DecodeMessage(r)
		if err != nil {
			return 1, fmt.Errorf("decoding message: %s", err)
		}
		switch m.Kind {
		case STDOUT:
			os.Stdout.Write(m.Payload)
			break
		case STDERR:
			os.Stderr.Write(m.Payload)
			break
		case EXIT:
			exitCode = int(m.ExitCode)
			break loop
		}
	}
	pipe.Close("")
	return exitCode, nil
}

func (pipe *Pipe) Close(msg string) {
	pipe.conn.WriteMessage(
		websocket.CloseMessage,
		websocket.FormatCloseMessage(websocket.CloseNormalClosure, msg),
	)
	pipe.conn.Close()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"log"
	"os"

	"golang.org/x/net/context"

	"github.com/docker/docker/api/client/bundlefile"
	"github.com/docker/docker/api/client/stack"
	"github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/filters"
	"github.com/docker/engine-api/types/swarm"
	"github.com/fatih/color"
	"github.com/urfave/cli"
)

var Replica1 uint64 = 1

type Services map[string]swarm.Service

func plan(c *cli.Context) error {
	stacks, err := getStacks(c)
	if err != nil {
		return err
	}

	detail := c.Bool("detail")
	target := c.StringSlice("target")
	targetMap := map[string]bool{}

	for _, name := range target {
		targetMap[name] = true
	}

	swarm, swarmErr := client.NewEnvClient()
	if swarmErr != nil {
		return cli.NewExitError(swarmErr.Error(), 3)
	}

	for _, stack := range stacks {
		filter := filters.NewArgs()
		filter.Add("label", "com.docker.stack.namespace="+stack.Name)
		services, servicesErr := swarm.ServiceList(context.Background(), types.ServiceListOptions{Filter: filter})
		if servicesErr != nil {
			return cli.NewExitError(servicesErr.Error(), 3)
		}

		expected := getBundleServicesSpec(stack.Bundle, stack.Name)
		translateNetworkToIds(&expected, swarm, stack.Name)

		current := getSwarmServicesSpecForStack(services)

		w := bufio.NewWriter(os.Stdout)
		sp := NewServicePrinter(w, detail)

		for n, es := range expected {
			// Only process found target services
			if _, found := targetMap[es.Spec.Name]; len(targetMap) == 0 || found {
				if cs, found := current[n]; !found {
					// New service to create
					color.Green("+ %s", n)
					sp.PrintServiceSpec(es.Spec)
					w.Flush()
					fmt.Println()
				} else {
					different := sp.PrintServiceSpecDiff(cs.Spec, es.Spec)
					if different {
						color.Yellow("~ %s\n", es.Spec.Name)
					} else if detail {
						color.Cyan("%s\n", es.Spec.Name)
					}

					return swarm.ServiceMode{
						Replicated: &swarm.ReplicatedService{
							Replicas: &Replica1,
						},
					}
					// flush if results
					if different || detail {
						w.Flush()
						fmt.Println()
					}
				}
			}
		}

		// Checks services to remove
		for n, cs := range current {
			// Only process found target services
			if _, found := targetMap[cs.Spec.Name]; len(targetMap) == 0 || found {
				if _, found := expected[n]; !found {
					color.Red("- %s", n)
					sp.PrintServiceSpec(cs.Spec)
					w.Flush()
					fmt.Println()
				}
			}

		}
	}

	return nil
}

func safeDereference(p *string) string {
	if p == nil {
		return ""
	}
	return *p
}

func translateNetworkToIds(services *Services, cli *client.Client, stackName string) {
	existingNetworks, err := stack.GetNetworks(context.Background(), cli, stackName)
	if err != nil {
		log.Fatal("Error retrieving networks")
	}

	for _, service := range *services {
		for i, network := range service.Spec.Networks {
			for _, enet := range existingNetworks {
				if enet.Name == network.Target {
					service.Spec.Networks[i].Target = enet.ID
					network.Target = enet.ID
				}
			}
		}
	}
}

func getBundleServicesSpec(bundle *bundlefile.Bundlefile, stackName string) Services {
	specs := Services{}

	for name, service := range bundle.Services {
		spec := swarm.ServiceSpec{
			TaskTemplate: swarm.TaskSpec{
				ContainerSpec: swarm.ContainerSpec{
					Image:   service.Image,
					Labels:  service.Labels,
					Command: service.Command,
					Args:    service.Args,
					Env:     service.Env,
					Dir:     safeDereference(service.WorkingDir),
					User:    safeDereference(service.User),
				},
				Placement: &swarm.Placement{Constraints: service.Constraints},
			},
			Networks: convertNetworks(service.Networks, stackName, name),
		}

		spec.Mode = getServiceMode(service.Mode)

		if service.Replicas != nil {
			spec.Mode.Replicated.Replicas = service.Replicas
		}

		spec.Labels = map[string]string{"com.docker.stack.namespace": stackName}
		spec.Name = fmt.Sprintf("%s_%s", stackName, name)

		// Populate ports
		ports := []swarm.PortConfig{}
		for _, port := range service.Ports {
			p := swarm.PortConfig{
				TargetPort:    port.Port,
				Protocol:      swarm.PortConfigProtocol(port.Protocol),
				PublishedPort: port.PublishedPort,
			}

			ports = append(ports, p)
		}
		// Hardcode resolution mode to VIP as it's the default with dab
		mode := "vip"
		if service.EndpointMode != nil {
			if *service.EndpointMode != "dnsrr" && *service.EndpointMode != "vip" {
				log.Fatalf("Invalid mode \"%s\" for service %s, only \"dnsrr\" or \"vip\" is allowed", *service.EndpointMode, spec.Name)
			}
			mode = *service.EndpointMode
		}
		spec.EndpointSpec = &swarm.EndpointSpec{Ports: ports, Mode: swarm.ResolutionMode(mode)}

		service := swarm.Service{}
		service.ID = spec.Name
		service.Spec = spec

		specs[spec.Name] = service
	}
	return specs
}

func getServiceMode(mode *string) swarm.ServiceMode {
	if mode != nil && *mode == "global" {
		return swarm.ServiceMode{
			Global: &swarm.GlobalService{},
		}
	} else {
		return swarm.ServiceMode{
			Replicated: &swarm.ReplicatedService{
				Replicas: &Replica1,
			},
		}
	}
}

func convertNetworks(networks []string, namespace string, name string) []swarm.NetworkAttachmentConfig {
	nets := []swarm.NetworkAttachmentConfig{}
	for _, network := range networks {
		nets = append(nets, swarm.NetworkAttachmentConfig{
			Target:  namespace + "_" + network,
			Aliases: []string{name},
		})
	}
	return nets
}

func getSwarmServicesSpecForStack(services []swarm.Service) Services {
	specs := Services{}

	for _, service := range services {
		specs[service.Spec.Name] = service
	}

	return specs
}
<commit_msg>Remove copy/pasted line<commit_after>package main

import (
	"bufio"
	"fmt"
	"log"
	"os"

	"golang.org/x/net/context"

	"github.com/docker/docker/api/client/bundlefile"
	"github.com/docker/docker/api/client/stack"
	"github.com/docker/engine-api/client"
	"github.com/docker/engine-api/types"
	"github.com/docker/engine-api/types/filters"
	"github.com/docker/engine-api/types/swarm"
	"github.com/fatih/color"
	"github.com/urfave/cli"
)

var Replica1 uint64 = 1

type Services map[string]swarm.Service

func plan(c *cli.Context) error {
	stacks, err := getStacks(c)
	if err != nil {
		return err
	}

	detail := c.Bool("detail")
	target := c.StringSlice("target")
	targetMap := map[string]bool{}

	for _, name := range target {
		targetMap[name] = true
	}

	swarm, swarmErr := client.NewEnvClient()
	if swarmErr != nil {
		return cli.NewExitError(swarmErr.Error(), 3)
	}

	for _, stack := range stacks {
		filter := filters.NewArgs()
		filter.Add("label", "com.docker.stack.namespace="+stack.Name)
		services, servicesErr := swarm.ServiceList(context.Background(), types.ServiceListOptions{Filter: filter})
		if servicesErr != nil {
			return cli.NewExitError(servicesErr.Error(), 3)
		}

		expected := getBundleServicesSpec(stack.Bundle, stack.Name)
		translateNetworkToIds(&expected, swarm, stack.Name)

		current := getSwarmServicesSpecForStack(services)

		w := bufio.NewWriter(os.Stdout)
		sp := NewServicePrinter(w, detail)

		for n, es := range expected {
			// Only process found target services
			if _, found := targetMap[es.Spec.Name]; len(targetMap) == 0 || found {
				if cs, found := current[n]; !found {
					// New service to create
					color.Green("+ %s", n)
					sp.PrintServiceSpec(es.Spec)
					w.Flush()
					fmt.Println()
				} else {
					different := sp.PrintServiceSpecDiff(cs.Spec, es.Spec)
					if different {
						color.Yellow("~ %s\n", es.Spec.Name)
					} else if detail {
						color.Cyan("%s\n", es.Spec.Name)
					}

					// flush if results
					if different || detail {
						w.Flush()
						fmt.Println()
					}
				}
			}
		}

		// Checks services to remove
		for n, cs := range current {
			// Only process found target services
			if _, found := targetMap[cs.Spec.Name]; len(targetMap) == 0 || found {
				if _, found := expected[n]; !found {
					color.Red("- %s", n)
					sp.PrintServiceSpec(cs.Spec)
					w.Flush()
					fmt.Println()
				}
			}

		}
	}

	return nil
}

func safeDereference(p *string) string {
	if p == nil {
		return ""
	}
	return *p
}

func translateNetworkToIds(services *Services, cli *client.Client, stackName string) {
	existingNetworks, err := stack.GetNetworks(context.Background(), cli, stackName)
	if err != nil {
		log.Fatal("Error retrieving networks")
	}

	for _, service := range *services {
		for i, network := range service.Spec.Networks {
			for _, enet := range existingNetworks {
				if enet.Name == network.Target {
					service.Spec.Networks[i].Target = enet.ID
					network.Target = enet.ID
				}
			}
		}
	}
}

func getBundleServicesSpec(bundle *bundlefile.Bundlefile, stackName string) Services {
	specs := Services{}

	for name, service := range bundle.Services {
		spec := swarm.ServiceSpec{
			TaskTemplate: swarm.TaskSpec{
				ContainerSpec: swarm.ContainerSpec{
					Image:   service.Image,
					Labels:  service.Labels,
					Command: service.Command,
					Args:    service.Args,
					Env:     service.Env,
					Dir:     safeDereference(service.WorkingDir),
					User:    safeDereference(service.User),
				},
				Placement: &swarm.Placement{Constraints: service.Constraints},
			},
			Networks: convertNetworks(service.Networks, stackName, name),
		}

		spec.Mode = getServiceMode(service.Mode)

		if service.Replicas != nil {
			spec.Mode.Replicated.Replicas = service.Replicas
		}

		spec.Labels = map[string]string{"com.docker.stack.namespace": stackName}
		spec.Name = fmt.Sprintf("%s_%s", stackName, name)

		// Populate ports
		ports := []swarm.PortConfig{}
		for _, port := range service.Ports {
			p := swarm.PortConfig{
				TargetPort:    port.Port,
				Protocol:      swarm.PortConfigProtocol(port.Protocol),
				PublishedPort: port.PublishedPort,
			}

			ports = append(ports, p)
		}
		// Hardcode resolution mode to VIP as it's the default with dab
		mode := "vip"
		if service.EndpointMode != nil {
			if *service.EndpointMode != "dnsrr" && *service.EndpointMode != "vip" {
				log.Fatalf("Invalid mode \"%s\" for service %s, only \"dnsrr\" or \"vip\" is allowed", *service.EndpointMode, spec.Name)
			}
			mode = *service.EndpointMode
		}
		spec.EndpointSpec = &swarm.EndpointSpec{Ports: ports, Mode: swarm.ResolutionMode(mode)}

		service := swarm.Service{}
		service.ID = spec.Name
		service.Spec = spec

		specs[spec.Name] = service
	}
	return specs
}

func getServiceMode(mode *string) swarm.ServiceMode {
	if mode != nil && *mode == "global" {
		return swarm.ServiceMode{
			Global: &swarm.GlobalService{},
		}
	} else {
		return swarm.ServiceMode{
			Replicated: &swarm.ReplicatedService{
				Replicas: &Replica1,
			},
		}
	}
}

func convertNetworks(networks []string, namespace string, name string) []swarm.NetworkAttachmentConfig {
	nets := []swarm.NetworkAttachmentConfig{}
	for _, network := range networks {
		nets = append(nets, swarm.NetworkAttachmentConfig{
			Target:  namespace + "_" + network,
			Aliases: []string{name},
		})
	}
	return nets
}

func getSwarmServicesSpecForStack(services []swarm.Service) Services {
	specs := Services{}

	for _, service := range services {
		specs[service.Spec.Name] = service
	}

	return specs
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
	"time"
)

type Line struct {
	Moves []Move
}

const INFINITY int = int(math.MaxInt32) // I win!
const MATE int = INFINITY - 10          // Value of a checkmate in 1

var nodecount uint64

func Evaluate(board *Board) int {
	return MaterialCount(board)
}

func MaterialCount(b *Board) int {
	var retval int
	for _, i := range b.PieceList {
		if OnBoard(i) && GetPiece(b.Data[i]) != EMPTY {
			if GetSide(b.Data[i]) == b.ToMove {
				retval += Value[GetPiece(b.Data[i])] + Pst(GetPiece(b.Data[i]), b.ToMove, i)
			} else {
				retval -= (Value[GetPiece(b.Data[i])] + Pst(GetPiece(b.Data[i]), b.ToMove, i))
			}
		}
	}
	return retval
}

func Pst(piece, side, index byte) int {
	switch piece {
	case PAWN:
		return GetPst(index, side, pstPawnMg)
	case KNIGHT:
		return GetPst(index, side, pstKnightMg)
	case BISHOP:
		return GetPst(index, side, pstBishopMg)
	case ROOK:
		return GetPst(index, side, pstKnightMg)
	case QUEEN:
		return GetPst(index, side, pstQueenMg)
	case KING:
		return GetPst(index, side, pstKingMg)
	default:
		return 0
	}
}

func GetPst(index, side byte, table [64]int) int {
	file, rank := IndexToCartesian(index)
	var tableindex byte
	if side == BLACK {
		tableindex = (8 * (7 - rank)) + file
	} else {
		tableindex = (8 * rank) + file
	}
	return table[tableindex]
}

func Quies(board *Board, alpha, beta int) int {
	nodecount++
	eval := Evaluate(board)
	if eval >= beta {
		return beta
	}
	if eval > alpha {
		alpha = eval
	}
	moves := FilterCaptures(MoveGen(board))
	for _, move := range moves {
		undo := MakeMove(board, &move)
		if Illegal(board) {
			UnmakeMove(board, &move, undo)
			continue
		}
		val := -Quies(board, -beta, -alpha)
		UnmakeMove(board, &move, undo)
		if val >= beta {
			return beta
		}
		if val > alpha {
			alpha = val
		}
	}
	return alpha
}

func AlphaBeta(board *Board, depth, alpha, beta, mate int, pline *Line) int {
	nodecount++
	legal := 0
	if depth <= 0 {
		return Quies(board, alpha, beta)
	}
	line := new(Line)
	moves := MoveGen(board)
	for _, move := range moves {
		undo := MakeMove(board, &move)
		if Illegal(board) {
			UnmakeMove(board, &move, undo)
			continue
		}
		val := -AlphaBeta(board, depth-1, -beta, -alpha, mate-1, line)
		UnmakeMove(board, &move, undo)
		if val >= beta {
			return beta
		}
		if val > alpha {
			alpha = val
			pline.Moves = append([]Move{move}, pline.Moves...)
			line.Moves = append(pline.Moves, move)
		}
		legal++
	}
	if legal == 0 {
		if !InCheck(board) {
			return 0
		}
		return -mate
	}
	return alpha
}

func AllotTime(board *Board) time.Duration {
	repeat := TimeRepeat
	if repeat <= 0 {
		repeat = 40
	}
	moves := repeat - board.Moves
	for moves <= 0 {
		moves += repeat
	}
	return (Clock/time.Duration(moves+1))/10 - 20*time.Millisecond
}

func ThinkingOutput(depth, score int, start time.Time, pv *Line) {
	fmt.Println(depth, score, int64(time.Since(start)/time.Millisecond)/10, nodecount, pv)
}

func FindMove(board *Board) *Move {
	start := time.Now()
	timetomove := AllotTime(board)
	bedoneby := start.Add(timetomove)
	nodecount = 0
	for depth := 1; ; depth++ {
		line := new(Line)
		score := AlphaBeta(board, depth, -INFINITY, INFINITY, MATE, line)
		ThinkingOutput(depth, score, start, line)
		retval := &line.Moves[0]
		if time.Now().After(bedoneby) {
			retval.Score = score
			Clock -= time.Since(start)
			return retval
		}
	}
}
<commit_msg>make rook use correct pst<commit_after>package main

import (
	"fmt"
	"math"
	"time"
)

type Line struct {
	Moves []Move
}

const INFINITY int = int(math.MaxInt32) // I win!
const MATE int = INFINITY - 10          // Value of a checkmate in 1

var nodecount uint64

func Evaluate(board *Board) int {
	return MaterialCount(board)
}

func MaterialCount(b *Board) int {
	var retval int
	for _, i := range b.PieceList {
		if OnBoard(i) && GetPiece(b.Data[i]) != EMPTY {
			if GetSide(b.Data[i]) == b.ToMove {
				retval += Value[GetPiece(b.Data[i])] + Pst(GetPiece(b.Data[i]), b.ToMove, i)
			} else {
				retval -= (Value[GetPiece(b.Data[i])] + Pst(GetPiece(b.Data[i]), b.ToMove, i))
			}
		}
	}
	return retval
}

func Pst(piece, side, index byte) int {
	switch piece {
	case PAWN:
		return GetPst(index, side, pstPawnMg)
	case KNIGHT:
		return GetPst(index, side, pstKnightMg)
	case BISHOP:
		return GetPst(index, side, pstBishopMg)
	case ROOK:
		return GetPst(index, side, pstRookMg)
	case QUEEN:
		return GetPst(index, side, pstQueenMg)
	case KING:
		return GetPst(index, side, pstKingMg)
	default:
		return 0
	}
}

func GetPst(index, side byte, table [64]int) int {
	file, rank := IndexToCartesian(index)
	var tableindex byte
	if side == BLACK {
		tableindex = (8 * (7 - rank)) + file
	} else {
		tableindex = (8 * rank) + file
	}
	return table[tableindex]
}

func Quies(board *Board, alpha, beta int) int {
	nodecount++
	eval := Evaluate(board)
	if eval >= beta {
		return beta
	}
	if eval > alpha {
		alpha = eval
	}
	moves := FilterCaptures(MoveGen(board))
	for _, move := range moves {
		undo := MakeMove(board, &move)
		if Illegal(board) {
			UnmakeMove(board, &move, undo)
			continue
		}
		val := -Quies(board, -beta, -alpha)
		UnmakeMove(board, &move, undo)
		if val >= beta {
			return beta
		}
		if val > alpha {
			alpha = val
		}
	}
	return alpha
}

func AlphaBeta(board *Board, depth, alpha, beta, mate int, pline *Line) int {
	nodecount++
	legal := 0
	if depth <= 0 {
		return Quies(board, alpha, beta)
	}
	line := new(Line)
	moves := MoveGen(board)
	for _, move := range moves {
		undo := MakeMove(board, &move)
		if Illegal(board) {
			UnmakeMove(board, &move, undo)
			continue
		}
		val := -AlphaBeta(board, depth-1, -beta, -alpha, mate-1, line)
		UnmakeMove(board, &move, undo)
		if val >= beta {
			return beta
		}
		if val > alpha {
			alpha = val
			pline.Moves = append([]Move{move}, pline.Moves...)
			line.Moves = append(pline.Moves, move)
		}
		legal++
	}
	if legal == 0 {
		if !InCheck(board) {
			return 0
		}
		return -mate
	}
	return alpha
}

func AllotTime(board *Board) time.Duration {
	repeat := TimeRepeat
	if repeat <= 0 {
		repeat = 40
	}
	moves := repeat - board.Moves
	for moves <= 0 {
		moves += repeat
	}
	return (Clock/time.Duration(moves+1))/10 - 20*time.Millisecond
}

func ThinkingOutput(depth, score int, start time.Time, pv *Line) {
	fmt.Println(depth, score, int64(time.Since(start)/time.Millisecond)/10, nodecount, pv)
}

func FindMove(board *Board) *Move {
	start := time.Now()
	timetomove := AllotTime(board)
	bedoneby := start.Add(timetomove)
	nodecount = 0
	for depth := 1; ; depth++ {
		line := new(Line)
		score := AlphaBeta(board, depth, -INFINITY, INFINITY, MATE, line)
		ThinkingOutput(depth, score, start, line)
		retval := &line.Moves[0]
		if time.Now().After(bedoneby) {
			retval.Score = score
			Clock -= time.Since(start)
			return retval
		}
	}
}
<|endoftext|>


<commit_before>// Package service combines the other various packages in http-handlers to
// provide an operations-friendly http.Handler for your application. Including
// this package will also allow you to dump a full stack trace to stderr by
// sending your application the SIGUSR1 signal.
package service

import (
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	"github.com/codahale/http-handlers/debug"
	"github.com/codahale/http-handlers/logging"
	"github.com/codahale/http-handlers/metrics"
	"github.com/codahale/http-handlers/recovery"
)

// Wrap returns a new service-ready handler given an application handler.
//
// This stack application-level metrics, debug endpoints, panic recovery, and
// request logging, in that order.
func Wrap(h http.Handler) http.Handler {
	return logging.Wrap(
		recovery.Wrap(
			debug.Wrap(
				metrics.Wrap(
					h,
				),
			),
		),
		os.Stdout,
	)
}

func init() {
	dump := make(chan os.Signal)
	go func() {
		stack := make([]byte, 16*1024)
		for _ = range dump {
			n := runtime.Stack(stack, true)
			fmt.Fprintf(os.Stderr, "==== %s\n%s\n====\n", time.Now(), stack[0:n])
		}
	}()
	signal.Notify(dump, syscall.SIGUSR1)
}
<commit_msg>Fix service package.<commit_after>// Package service combines the other various packages in http-handlers to
// provide an operations-friendly http.Handler for your application. Including
// this package will also allow you to dump a full stack trace to stderr by
// sending your application the SIGUSR1 signal.
package service

import (
	"fmt"
	"net/http"
	"os"
	"os/signal"
	"runtime"
	"syscall"
	"time"

	"github.com/codahale/http-handlers/debug"
	"github.com/codahale/http-handlers/logging"
	"github.com/codahale/http-handlers/metrics"
	"github.com/codahale/http-handlers/recovery"
)

// Service is an HTTP service.
type Service struct {
	h *logging.LoggingHandler
}

func (s Service) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	s.h.ServeHTTP(w, r)
}

// Close stops the service.
func (s Service) Close() error {
	s.h.Stop()
	return nil
}

// New returns a new service-ready handler given an application handler.
//
// This stack application-level metrics, debug endpoints, panic recovery, and
// request logging, in that order.
func New(h http.Handler) Service {
	l := logging.Wrap(
		recovery.Wrap(
			debug.Wrap(
				metrics.Wrap(
					h,
				),
			),
		),
		os.Stdout,
	)
	l.Start()
	return Service{h: l}
}

func init() {
	dump := make(chan os.Signal)
	go func() {
		stack := make([]byte, 16*1024)
		for _ = range dump {
			n := runtime.Stack(stack, true)
			fmt.Fprintf(os.Stderr, "==== %s\n%s\n====\n", time.Now(), stack[0:n])
		}
	}()
	signal.Notify(dump, syscall.SIGUSR1)
}
<|endoftext|>


<commit_before>package service

import (
	"errors"
	"fmt"
	"github.com/SudoQ/crisp/external"
	"github.com/SudoQ/crisp/item"
	"github.com/SudoQ/crisp/resources"
	"github.com/SudoQ/crisp/storage"
	//"github.com/gorilla/mux"
	"io/ioutil"
	"log"
	//"net/http"
	"net/url"
	"os"
	"time"
)

type Service struct {
	URL             string
	Port            string
	Period          time.Duration
	Limit           uint
	Cache           *storage.Store
	logger          *log.Logger
	ext             *external.Ext
	resourceManager *resources.Manager
}

func New(target, port string, limit uint) *Service {
	period, err := LimitToPeriod(limit)
	if err != nil {
		limit = 1
		period, _ = LimitToPeriod(limit)
	}
	srv := &Service{
		URL:             target,
		Port:            port,
		Period:          period,
		Limit:           limit,
		Cache:           storage.New(),
		logger:          nil,
		ext:             external.New(target, period),
		resourceManager: nil,
	}
	srv.initLogger()
	srv.initResouceManager()
	return srv
}

func (this *Service) initResouceManager() {
	this.resourceManager = resources.New(this.Cache)
}

func (this *Service) initLogger() {
	u, err := url.Parse(this.URL)
	label := u.Host
	if err != nil {
		label = "?"
	}
	this.logger = log.New(os.Stdin, fmt.Sprintf("crisp[%s]: ", label), log.Lshortfile)
}

func LimitToPeriod(limit uint) (time.Duration, error) {
	if limit == 0 {
		return 0, errors.New("Division with zero")
	}

	period := (60.0 / float64(limit)) * 60
	return (time.Duration(period) * time.Second), nil
}

func (this *Service) LoadCache(filename string) error {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	newItem, err := item.NewFromJSON(content)
	if err != nil {
		return err
	}
	this.Cache.Add(newItem)
	return nil
}

func (this *Service) Info() string {
	return fmt.Sprintf("Crisp API caching service v0.1")
}

func (this *Service) Run() {
	err := this.LoadCache("cache.json")
	if err != nil {
		this.logger.Fatal(err)
	}
	dataCh := this.ext.DataChannel()
	defer this.ext.Close()
	go this.ext.Collect()
	go func() {
		for payload := range dataCh {
			newItem := item.New(time.Now(), payload)
			this.Cache.Add(newItem)
			cacheFilename := "cache.json"
			latestItem, err := this.Cache.Get()
			if err != nil {
				this.logger.Fatal(err)
			}
			err = latestItem.WriteFile(cacheFilename)
			if err != nil {
				this.logger.Fatal(err)
			}
			this.logger.Printf("Saved cache to %s\n", cacheFilename)
		}
	}()

	this.resourceManager.Run(this.Port)
}
<commit_msg>Removed readin cache.json as default<commit_after>package service

import (
	"errors"
	"fmt"
	"github.com/SudoQ/crisp/external"
	"github.com/SudoQ/crisp/item"
	"github.com/SudoQ/crisp/resources"
	"github.com/SudoQ/crisp/storage"
	//"github.com/gorilla/mux"
	"io/ioutil"
	"log"
	//"net/http"
	"net/url"
	"os"
	"time"
)

type Service struct {
	URL             string
	Port            string
	Period          time.Duration
	Limit           uint
	Cache           *storage.Store
	logger          *log.Logger
	ext             *external.Ext
	resourceManager *resources.Manager
}

func New(target, port string, limit uint) *Service {
	period, err := LimitToPeriod(limit)
	if err != nil {
		limit = 1
		period, _ = LimitToPeriod(limit)
	}
	srv := &Service{
		URL:             target,
		Port:            port,
		Period:          period,
		Limit:           limit,
		Cache:           storage.New(),
		logger:          nil,
		ext:             external.New(target, period),
		resourceManager: nil,
	}
	srv.initLogger()
	srv.initResouceManager()
	return srv
}

func (this *Service) initResouceManager() {
	this.resourceManager = resources.New(this.Cache)
}

func (this *Service) initLogger() {
	u, err := url.Parse(this.URL)
	label := u.Host
	if err != nil {
		label = "?"
	}
	this.logger = log.New(os.Stdin, fmt.Sprintf("crisp[%s]: ", label), log.Lshortfile)
}

func LimitToPeriod(limit uint) (time.Duration, error) {
	if limit == 0 {
		return 0, errors.New("Division with zero")
	}

	period := (60.0 / float64(limit)) * 60
	return (time.Duration(period) * time.Second), nil
}

func (this *Service) LoadCache(filename string) error {
	content, err := ioutil.ReadFile(filename)
	if err != nil {
		return err
	}
	newItem, err := item.NewFromJSON(content)
	if err != nil {
		return err
	}
	this.Cache.Add(newItem)
	return nil
}

func (this *Service) Info() string {
	return fmt.Sprintf("Crisp API caching service v0.1")
}

func (this *Service) Run() {
	dataCh := this.ext.DataChannel()
	defer this.ext.Close()
	go this.ext.Collect()
	go func() {
		for payload := range dataCh {
			newItem := item.New(time.Now(), payload)
			this.Cache.Add(newItem)
			cacheFilename := "cache.json"
			latestItem, err := this.Cache.Get()
			if err != nil {
				this.logger.Fatal(err)
			}
			err = latestItem.WriteFile(cacheFilename)
			if err != nil {
				this.logger.Fatal(err)
			}
			this.logger.Printf("Saved cache to %s\n", cacheFilename)
		}
	}()

	this.resourceManager.Run(this.Port)
}
<|endoftext|>


<commit_before>package gokeepasslib

import (
	"bytes"
	"compress/gzip"
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha256"
	"encoding/binary"
	"encoding/xml"
	"io"
)

//Size in bytes of the data in each block
const blockSplitRate = 16384

//Header to be put before xml content in kdbx file
var xmlHeader = []byte(`<?xml version="1.0" encoding="utf-8" standalone="yes"?>`)

//Encoder is used to automaticaly encrypt and write a database to a file, network, etc
type Encoder struct {
	w io.Writer
}

//Writes db to e's internal writer
func (e *Encoder) Encode(db *Database) error {
	return e.writeData(db)
}

//Creates a new encoder with writer w, identical to gokeepasslib.Encoder{w}
func NewEncoder(w io.Writer) *Encoder {
	return &Encoder{w: w}
}

//Internal function to write database to encoder's writer, called by Encode
func (e *Encoder) writeData(db *Database) error {
	db.LockProtectedEntries()

	//Creates XML data with from database content, and appends header to top
	xmlData, err := xml.MarshalIndent(db.Content, "", "\t")
	if err != nil {
		return err
	}
	xmlData = append(xmlHeader, xmlData...)

	var hashData []byte
	if db.Headers.CompressionFlags == 1 { //If database header says to compress with gzip, compress xml data and put into block form
		b := new(bytes.Buffer)
		w := gzip.NewWriter(b)
		defer w.Close()

		if _, err = w.Write(xmlData); err != nil {
			return err
		}

		if err = w.Flush(); err != nil {
			return err
		}

		hashData, err = hashBlocks(b.Bytes())
		if err != nil {
			return err
		}
	} else { //Otherwise put un-compressed xml content into block form
		hashData,err = hashBlocks(xmlData)
		if err != nil {
			return err
		}
	}

	//Appends the stream startmStartBytes from db header to the blocked data, used to verify that the key is correct when decrypting
	hashData = append(db.Headers.StreamStartBytes, hashData...)

	//Adds padding to data as required to encrypt properly
	if len(hashData)%16 != 0 {
		padding := make([]byte, 16-(len(hashData)%16))
		for i := 0; i < len(padding); i++ {
			padding[i] = byte(len(padding))
		}
		hashData = append(hashData, padding...)
	}

	//Uses database credentials info to build encryption key
	masterKey, err := db.Credentials.buildMasterKey(db)
	if err != nil {
		return err
	}

	//Creates an AES cipher block from the masterkey
	block, err := aes.NewCipher(masterKey)
	if err != nil {
		return err
	}

	//Encrypts block data using AES block with initialization vector from header
	mode := cipher.NewCBCEncrypter(block, db.Headers.EncryptionIV)
	encrypted := make([]byte, len(hashData))
	mode.CryptBlocks(encrypted, hashData)

	//Writes file signature (tells program it's a kdbx file of x version)
	err = db.Signature.WriteSignature(e.w)
	if err != nil {
		return err
	}

	//Writes headers of database
	err = db.Headers.WriteHeaders(e.w)
	if err != nil {
		return err
	}

	//Writes the encrypted database content
	_,err = e.w.Write(encrypted)
	if err != nil {
		return err
	}

	return nil
}

/* Converts raw xml data to keepass's block format, which includes a hash of each block to check for data corruption,
 * Every block contains the following elements:
 * (4 bytes) ID : an unique interger id for this block
 * (32 bytes) sha-256 hash of block data
 * (4 bytes) size on bytes of the block data
 * (Data Size Bytes) the actual xml data of the block, will be blockSplitRate bytes at most
 */
func hashBlocks(data []byte) ([]byte, error) {
	b := new(bytes.Buffer)

	i := 0
	for len(data) > 0 { //For each block
		var block []byte
		if len(data) >= blockSplitRate { //If there is enough data for another block, use blockSplitRate bytes of data for block
			block = append(block, data[:blockSplitRate]...)
			data = data[blockSplitRate:]
		} else { //Otherwise just use what is remaining and clear data to break from the loop
			block = append(block, data[:len(data)]...)
			data = make([]byte, 0)
		}

		//Writes the block id to output, discussed above
		if err := binary.Write(b, binary.LittleEndian, uint32(i)); err != nil {
			return nil, err
		}

		//Hashes block data and appends to output
		hash := sha256.Sum256(block)
		if _, err := b.Write(hash[:]); err != nil {
			return nil, err
		}

		//Writes length of block data to output
		if err := binary.Write(b, binary.LittleEndian, uint32(len(block))); err != nil {
			return nil, err
		}

		//Writes block data
		if _, err := b.Write(block); err != nil {
			return nil, err
		}

		i++
	}

	//Adds empty block to output, so keepass knows data stream is over
	if err := binary.Write(b, binary.LittleEndian, uint32(i)); err != nil {
		return nil, err
	}
	endBlock := make([]byte, 36)
	if _, err := b.Write(endBlock); err != nil {
		return nil, err
	}

	return b.Bytes(), nil
}
<commit_msg>fixed typo<commit_after>package gokeepasslib

import (
	"bytes"
	"compress/gzip"
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha256"
	"encoding/binary"
	"encoding/xml"
	"io"
)

//Size in bytes of the data in each block
const blockSplitRate = 16384

//Header to be put before xml content in kdbx file
var xmlHeader = []byte(`<?xml version="1.0" encoding="utf-8" standalone="yes"?>`)

//Encoder is used to automaticaly encrypt and write a database to a file, network, etc
type Encoder struct {
	w io.Writer
}

//Writes db to e's internal writer
func (e *Encoder) Encode(db *Database) error {
	return e.writeData(db)
}

//Creates a new encoder with writer w, identical to gokeepasslib.Encoder{w}
func NewEncoder(w io.Writer) *Encoder {
	return &Encoder{w: w}
}

//Internal function to write database to encoder's writer, called by Encode
func (e *Encoder) writeData(db *Database) error {
	db.LockProtectedEntries()

	//Creates XML data with from database content, and appends header to top
	xmlData, err := xml.MarshalIndent(db.Content, "", "\t")
	if err != nil {
		return err
	}
	xmlData = append(xmlHeader, xmlData...)

	var hashData []byte
	if db.Headers.CompressionFlags == 1 { //If database header says to compress with gzip, compress xml data and put into block form
		b := new(bytes.Buffer)
		w := gzip.NewWriter(b)
		defer w.Close()

		if _, err = w.Write(xmlData); err != nil {
			return err
		}

		if err = w.Flush(); err != nil {
			return err
		}

		hashData, err = hashBlocks(b.Bytes())
		if err != nil {
			return err
		}
	} else { //Otherwise put un-compressed xml content into block form
		hashData,err = hashBlocks(xmlData)
		if err != nil {
			return err
		}
	}

	//Appends the startmStreamBytes from db header to the blocked data, used to verify that the key is correct when decrypting
	hashData = append(db.Headers.StreamStartBytes, hashData...)

	//Adds padding to data as required to encrypt properly
	if len(hashData)%16 != 0 {
		padding := make([]byte, 16-(len(hashData)%16))
		for i := 0; i < len(padding); i++ {
			padding[i] = byte(len(padding))
		}
		hashData = append(hashData, padding...)
	}

	//Uses database credentials info to build encryption key
	masterKey, err := db.Credentials.buildMasterKey(db)
	if err != nil {
		return err
	}

	//Creates an AES cipher block from the masterkey
	block, err := aes.NewCipher(masterKey)
	if err != nil {
		return err
	}

	//Encrypts block data using AES block with initialization vector from header
	mode := cipher.NewCBCEncrypter(block, db.Headers.EncryptionIV)
	encrypted := make([]byte, len(hashData))
	mode.CryptBlocks(encrypted, hashData)

	//Writes file signature (tells program it's a kdbx file of x version)
	err = db.Signature.WriteSignature(e.w)
	if err != nil {
		return err
	}

	//Writes headers of database
	err = db.Headers.WriteHeaders(e.w)
	if err != nil {
		return err
	}

	//Writes the encrypted database content
	_,err = e.w.Write(encrypted)
	if err != nil {
		return err
	}

	return nil
}

/* Converts raw xml data to keepass's block format, which includes a hash of each block to check for data corruption,
 * Every block contains the following elements:
 * (4 bytes) ID : an unique interger id for this block
 * (32 bytes) sha-256 hash of block data
 * (4 bytes) size on bytes of the block data
 * (Data Size Bytes) the actual xml data of the block, will be blockSplitRate bytes at most
 */
func hashBlocks(data []byte) ([]byte, error) {
	b := new(bytes.Buffer)

	i := 0
	for len(data) > 0 { //For each block
		var block []byte
		if len(data) >= blockSplitRate { //If there is enough data for another block, use blockSplitRate bytes of data for block
			block = append(block, data[:blockSplitRate]...)
			data = data[blockSplitRate:]
		} else { //Otherwise just use what is remaining and clear data to break from the loop
			block = append(block, data[:len(data)]...)
			data = make([]byte, 0)
		}

		//Writes the block id to output, discussed above
		if err := binary.Write(b, binary.LittleEndian, uint32(i)); err != nil {
			return nil, err
		}

		//Hashes block data and appends to output
		hash := sha256.Sum256(block)
		if _, err := b.Write(hash[:]); err != nil {
			return nil, err
		}

		//Writes length of block data to output
		if err := binary.Write(b, binary.LittleEndian, uint32(len(block))); err != nil {
			return nil, err
		}

		//Writes block data
		if _, err := b.Write(block); err != nil {
			return nil, err
		}

		i++
	}

	//Adds empty block to output, so keepass knows data stream is over
	if err := binary.Write(b, binary.LittleEndian, uint32(i)); err != nil {
		return nil, err
	}
	endBlock := make([]byte, 36)
	if _, err := b.Write(endBlock); err != nil {
		return nil, err
	}

	return b.Bytes(), nil
}
<|endoftext|>


<commit_before>package service

import (
	"database/sql"
	"log"
	"net"
	"os"
	"time"

	pb "github.com/otoolep/go-grpc-pg/proto"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

// Service represents a gRPC service that communicates with a database backend.
type Service struct {
	grpc *grpc.Server
	db   *sql.DB

	ln   net.Listener
	addr string

	logger *log.Logger
}

// New returns an instantiated service.
func New(addr string, db *sql.DB) *Service {
	s := Service{
		grpc:   grpc.NewServer(),
		db:     db,
		addr:   addr,
		logger: log.New(os.Stderr, "[service] ", log.LstdFlags),
	}

	pb.RegisterDBProviderServer(s.grpc, (*gprcService)(&s))
	return &s
}

// Addr returns the address on which the service is listening.
func (s *Service) Addr() string {
	return s.ln.Addr().String()
}

// Open opens the service, starting it listening on the configured address.
func (s *Service) Open() error {
	ln, err := net.Listen("tcp", s.addr)
	if err != nil {
		return err
	}
	s.ln = ln
	s.logger.Println("listening on", s.ln.Addr().String())

	go func() {
		err := s.grpc.Serve(s.ln)
		if err != nil {
			s.logger.Println("gRPC Serve() returned:", err.Error())
		}
	}()

	return nil
}

// Close closes the service.
func (s *Service) Close() error {
	s.grpc.GracefulStop()
	s.ln = nil
	s.logger.Println("gRPC server stopped")
	return nil
}

// gprcService is an unexported type, that is the same type as Service.
//
// Having the methods that the gRPC service requires on this type means that even though
// the methods are exported, since the type is not, these methods are not visible outside
// this package.
type gprcService Service

// Query implements the Query interface of the gRPC service.
func (g *gprcService) Query(c context.Context, q *pb.QueryRequest) (*pb.QueryResponse, error) {
	start := time.Now()
	rows, err := g.db.Query(q.Stmt)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	// Get the column names.
	cols, err := rows.Columns()
	if err != nil {
		return nil, err
	}

	response := pb.QueryResponse{
		Columns: cols,
	}

	// Iterate through each row returned by the query.
	for rows.Next() {
		row := make([]string, len(cols))
		// Get a set of pointers to the strings allocated above.
		rowI := make([]interface{}, len(cols))
		for i := range row {
			rowI[i] = &row[i]
		}

		if err := rows.Scan(rowI...); err != nil {
			return nil, err
		}

		// Add the latest rows to existing rows.
		response.Rows = append(response.Rows, &pb.Row{Values: row})
	}

	g.logger.Printf(`query '%s' completed in %s, %d %s returned`,
		q.Stmt, time.Since(start), len(response.Rows), prettyRows(int64(len(response.Rows))))
	return &response, nil
}

// Exec implements the Exec interface of the gRPC service.
func (g *gprcService) Exec(c context.Context, e *pb.ExecRequest) (*pb.ExecResponse, error) {
	start := time.Now()
	r, err := g.db.Exec(e.Stmt)
	if err != nil {
		return nil, err
	}

	lid, err := r.LastInsertId()
	if err != nil {
		// Not all databases support LastInsertId()
		lid = -1
	}
	ra, err := r.RowsAffected()
	if err != nil {
		return nil, err
	}

	g.logger.Printf(`exec '%s' completed in %s, %d %s affected`,
		e.Stmt, time.Since(start), ra, prettyRows(ra))
	return &pb.ExecResponse{
		LastInsertId: lid,
		RowsAffected: ra,
	}, nil
}

// prettyRows returns a singular or plural form of "row", depending on n.
func prettyRows(n int64) string {
	if n == 1 {
		return "row"
	}
	return "rows"
}
<commit_msg>Listener closed by gRPC framework<commit_after>package service

import (
	"database/sql"
	"log"
	"net"
	"os"
	"time"

	pb "github.com/otoolep/go-grpc-pg/proto"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

// Service represents a gRPC service that communicates with a database backend.
type Service struct {
	grpc *grpc.Server
	db   *sql.DB

	ln   net.Listener
	addr string

	logger *log.Logger
}

// New returns an instantiated service.
func New(addr string, db *sql.DB) *Service {
	s := Service{
		grpc:   grpc.NewServer(),
		db:     db,
		addr:   addr,
		logger: log.New(os.Stderr, "[service] ", log.LstdFlags),
	}

	pb.RegisterDBProviderServer(s.grpc, (*gprcService)(&s))
	return &s
}

// Addr returns the address on which the service is listening.
func (s *Service) Addr() string {
	return s.ln.Addr().String()
}

// Open opens the service, starting it listening on the configured address.
func (s *Service) Open() error {
	ln, err := net.Listen("tcp", s.addr)
	if err != nil {
		return err
	}
	s.ln = ln
	s.logger.Println("listening on", s.ln.Addr().String())

	go func() {
		err := s.grpc.Serve(s.ln)
		if err != nil {
			s.logger.Println("gRPC Serve() returned:", err.Error())
		}
	}()

	return nil
}

// Close closes the service.
func (s *Service) Close() error {
	s.grpc.GracefulStop()
	s.logger.Println("gRPC server stopped")
	return nil
}

// gprcService is an unexported type, that is the same type as Service.
//
// Having the methods that the gRPC service requires on this type means that even though
// the methods are exported, since the type is not, these methods are not visible outside
// this package.
type gprcService Service

// Query implements the Query interface of the gRPC service.
func (g *gprcService) Query(c context.Context, q *pb.QueryRequest) (*pb.QueryResponse, error) {
	start := time.Now()
	rows, err := g.db.Query(q.Stmt)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	// Get the column names.
	cols, err := rows.Columns()
	if err != nil {
		return nil, err
	}

	response := pb.QueryResponse{
		Columns: cols,
	}

	// Iterate through each row returned by the query.
	for rows.Next() {
		row := make([]string, len(cols))
		// Get a set of pointers to the strings allocated above.
		rowI := make([]interface{}, len(cols))
		for i := range row {
			rowI[i] = &row[i]
		}

		if err := rows.Scan(rowI...); err != nil {
			return nil, err
		}

		// Add the latest rows to existing rows.
		response.Rows = append(response.Rows, &pb.Row{Values: row})
	}

	g.logger.Printf(`query '%s' completed in %s, %d %s returned`,
		q.Stmt, time.Since(start), len(response.Rows), prettyRows(int64(len(response.Rows))))
	return &response, nil
}

// Exec implements the Exec interface of the gRPC service.
func (g *gprcService) Exec(c context.Context, e *pb.ExecRequest) (*pb.ExecResponse, error) {
	start := time.Now()
	r, err := g.db.Exec(e.Stmt)
	if err != nil {
		return nil, err
	}

	lid, err := r.LastInsertId()
	if err != nil {
		// Not all databases support LastInsertId()
		lid = -1
	}
	ra, err := r.RowsAffected()
	if err != nil {
		return nil, err
	}

	g.logger.Printf(`exec '%s' completed in %s, %d %s affected`,
		e.Stmt, time.Since(start), ra, prettyRows(ra))
	return &pb.ExecResponse{
		LastInsertId: lid,
		RowsAffected: ra,
	}, nil
}

// prettyRows returns a singular or plural form of "row", depending on n.
func prettyRows(n int64) string {
	if n == 1 {
		return "row"
	}
	return "rows"
}
<|endoftext|>


<commit_before>package encoder

// Original code borrowed from https://github.com/PuerkitoBio/martini-api-example
// TextEncoder and XmlEncoder has been removed. If someone really needs it, let me know.

// Supported tags:
// 	 - "out" if it sets to "false", value won't be set to field
import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"reflect"
	"time"
)

// An Encoder implements an encoding format of values to be sent as response to
// requests on the API endpoints.
type Encoder interface {
	Encode(v ...interface{}) ([]byte, error)
}

// Because `panic`s are caught by martini's Recovery handler, it can be used
// to return server-side errors (500). Some helpful text message should probably
// be sent, although not the technical error (which is printed in the log).
func Must(data []byte, err error) []byte {
	if err != nil {
		panic(err)
	}
	return data
}

type JsonEncoder struct {
	PrettyPrint bool
}

// @todo test for slice of structure support
func (self JsonEncoder) Encode(v ...interface{}) ([]byte, error) {
	var data interface{} = v
	var result interface{}

	if v == nil {
		// So that empty results produces `[]` and not `null`
		data = []interface{}{}
	} else if len(v) == 1 {
		data = v[0]
	}

	t := reflect.TypeOf(data)
	for t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	switch t.Kind() {
	case reflect.Slice:
		result = iterateSlice(reflect.ValueOf(data)).Interface()

	case reflect.Struct:
		result = copyStruct(reflect.ValueOf(data)).Interface()

	default:
		result = data
	}

	if self.PrettyPrint {
		return json.MarshalIndent(result, "", "	")
	} else {
		return json.Marshal(result)
	}
}

type XmlEncoder struct{}

// Since we don't use xml as a binding source, we don't need to use
// copyStruct here. Just Marshal.
func (_ XmlEncoder) Encode(v ...interface{}) ([]byte, error) {
	var data interface{} = v
	var buffer bytes.Buffer

	if v == nil {
		data = []interface{}{}
	} else if len(v) == 1 {
		data = v[0]
	}

	if _, err := buffer.Write([]byte(xml.Header)); err != nil {
		return []byte{}, err
	}

	b, err := xml.Marshal(data)
	if err != nil {
		return []byte{}, err
	}

	buffer.Write(b)

	return buffer.Bytes(), nil
}

func copyStruct(v reflect.Value) reflect.Value {
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	result := reflect.New(v.Type()).Elem()

	t := v.Type()

	for i := 0; i < v.NumField(); i++ {
		vfield := v.Field(i)

		if tag := t.Field(i).Tag.Get("out"); tag == "false" {
			continue
		}

		if vfield.Type() == reflect.TypeOf(time.Time{}) {
			result.Field(i).Set(vfield)
			continue
		}

		if vfield.Kind() == reflect.Interface && vfield.Interface() != nil {
			vfield = vfield.Elem()

			for vfield.Kind() == reflect.Ptr {
				vfield = vfield.Elem()
			}

			result.Field(i).Set(copyStruct(vfield))
			continue
		}

		if vfield.Kind() == reflect.Struct || vfield.Kind() == reflect.Ptr {
			r := copyStruct(vfield)

			if result.Field(i).Kind() == reflect.Ptr {
				result.Field(i).Set(r.Addr())
			} else {
				result.Field(i).Set(r)
			}

			continue
		}

		if vfield.Kind() == reflect.Array || vfield.Kind() == reflect.Slice {
			result.Field(i).Set(iterateSlice(vfield))
			continue
		}

		if result.Field(i).CanSet() {
			result.Field(i).Set(vfield)
		}
	}

	return result
}

func iterateSlice(v reflect.Value) reflect.Value {
	result := reflect.MakeSlice(v.Type(), 0, v.Len())

	for i := 0; i < v.Len(); i++ {
		value := v.Index(i)

		if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
			result = reflect.Append(result, iterateSlice(value))
			continue
		}

		vi := value
		if value.Kind() == reflect.Struct {
			vi = copyStruct(value)
		}

		if value.Kind() == reflect.Ptr {
			result = reflect.Append(result, vi.Addr())
		} else {
			result = reflect.Append(result, vi)
		}
	}

	return result
}
<commit_msg>Fixes to addressing panics<commit_after>package encoder

// Original code borrowed from https://github.com/PuerkitoBio/martini-api-example
// TextEncoder and XmlEncoder has been removed. If someone really needs it, let me know.

// Supported tags:
// 	 - "out" if it sets to "false", value won't be set to field
import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"reflect"
	"time"
)

// An Encoder implements an encoding format of values to be sent as response to
// requests on the API endpoints.
type Encoder interface {
	Encode(v ...interface{}) ([]byte, error)
}

// Because `panic`s are caught by martini's Recovery handler, it can be used
// to return server-side errors (500). Some helpful text message should probably
// be sent, although not the technical error (which is printed in the log).
func Must(data []byte, err error) []byte {
	if err != nil {
		panic(err)
	}
	return data
}

type JsonEncoder struct {
	PrettyPrint bool
}

// @todo test for slice of structure support
func (self JsonEncoder) Encode(v ...interface{}) ([]byte, error) {
	var data interface{} = v
	var result interface{}

	if v == nil {
		// So that empty results produces `[]` and not `null`
		data = []interface{}{}
	} else if len(v) == 1 {
		data = v[0]
	}

	t := reflect.TypeOf(data)
	for t.Kind() == reflect.Ptr {
		t = t.Elem()
	}

	switch t.Kind() {
	case reflect.Slice:
		result = iterateSlice(reflect.ValueOf(data)).Interface()

	case reflect.Struct:
		result = copyStruct(reflect.ValueOf(data)).Interface()

	default:
		result = data
	}

	if self.PrettyPrint {
		return json.MarshalIndent(result, "", "	")
	} else {
		return json.Marshal(result)
	}
}

type XmlEncoder struct{}

// Since we don't use xml as a binding source, we don't need to use
// copyStruct here. Just Marshal.
func (_ XmlEncoder) Encode(v ...interface{}) ([]byte, error) {
	var data interface{} = v
	var buffer bytes.Buffer

	if v == nil {
		data = []interface{}{}
	} else if len(v) == 1 {
		data = v[0]
	}

	if _, err := buffer.Write([]byte(xml.Header)); err != nil {
		return []byte{}, err
	}

	b, err := xml.Marshal(data)
	if err != nil {
		return []byte{}, err
	}

	buffer.Write(b)

	return buffer.Bytes(), nil
}

func copyStruct(v reflect.Value) reflect.Value {
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}
	if !v.IsValid() {
		return reflect.Value{}
	}

	result := reflect.New(v.Type()).Elem()

	t := v.Type()

	for i := 0; i < v.NumField(); i++ {
		vfield := v.Field(i)

		if tag := t.Field(i).Tag.Get("out"); tag == "false" {
			continue
		}

		if vfield.Type() == reflect.TypeOf(time.Time{}) {
			result.Field(i).Set(vfield)
			continue
		}

		if vfield.Kind() == reflect.Interface && vfield.Interface() != nil {
			vfield = vfield.Elem()

			for vfield.Kind() == reflect.Ptr {
				vfield = vfield.Elem()
			}

			result.Field(i).Set(copyStruct(vfield))
			continue
		}

		if vfield.Kind() == reflect.Struct || vfield.Kind() == reflect.Ptr {
			r := copyStruct(vfield)

			if result.Field(i).Kind() == reflect.Ptr {
				if r.CanAddr() {
					result.Field(i).Set(r.Addr())
				}
			} else {
				result.Field(i).Set(r)
			}

			continue
		}

		if vfield.Kind() == reflect.Array || vfield.Kind() == reflect.Slice {
			result.Field(i).Set(iterateSlice(vfield))
			continue
		}

		if result.Field(i).CanSet() {
			result.Field(i).Set(vfield)
		}
	}

	return result
}

func iterateSlice(v reflect.Value) reflect.Value {
	result := reflect.MakeSlice(v.Type(), 0, v.Len())

	for i := 0; i < v.Len(); i++ {
		value := v.Index(i)

		if value.Kind() == reflect.Slice || value.Kind() == reflect.Array {
			result = reflect.Append(result, iterateSlice(value))
			continue
		}

		vi := value
		if value.Kind() == reflect.Struct {
			vi = copyStruct(value)
		}

		if value.Kind() == reflect.Ptr && reflect.SliceOf(vi.Type()) != v.Type() {
			result = reflect.Append(result, vi.Addr())
		} else {
			result = reflect.Append(result, vi)
		}
	}

	return result
}
<|endoftext|>


<commit_before>package bittrex_test

import (
	"fmt"
	"testing"
	"time"

	"github.com/thebotguys/golang-bittrex-api/bittrex"
)

var latestTestedVersion = "2.11"

func TestGetServerAPIVersion(t *testing.T) {
	if testIsAPIAlive(t) {
		version, err := bittrex.GetServerAPIVersion()
		if err != nil {
			t.Fatal(err)
		}
		if version != latestTestedVersion {
			t.Errorf(`Please check version you are testing, on server it is %s,
while on this client it is %s.`,
				latestTestedVersion, version)
		}
	}
}

func TestGetBTCPrice(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetBTCPrice()
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestGetTicks(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetTicks("BTC-ETH", "thirtyMin")
		if err != nil {
			t.Fatal(err)
		}
		val, err := bittrex.GetTicks("INVALID-MARKET-HAHA", "thirtyMin")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetTicks(\"INVALID-MARKET-HAHA\", " +
				"\"thirtyMin\"))\n Value Returned : " +
				fmt.Sprint(val))
		}
		val, err = bittrex.GetTicks("", "thirtyMin")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetTicks(\"\", \"thirtyMin\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
		val, err = bittrex.GetTicks("BTC-LTC", "INVALID-INTERVAL-HAHA")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetTicks(\"BTC-LTC\", \"INVALID-INTERVAL-HAHA\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
		val, err = bittrex.GetTicks("BTC-LTC", "")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetTicks(\"BTC-LTC\", \"\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
	}
}

func TestGetLatestTick(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetLatestTick("BTC-ETH", "thirtyMin")
		if err != nil {
			t.Fatal(err)
		}
		val, err := bittrex.GetLatestTick("INVALID-MARKET-HAHA", "thirtyMin")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetLatestTick(\"INVALID-MARKET-HAHA\", " +
				"\"thirtyMin\"))\n Value Returned : " +
				fmt.Sprint(val))
		}
		val, err = bittrex.GetLatestTick("", "thirtyMin")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetLatestTick(\"\", \"thirtyMin\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
		val, err = bittrex.GetLatestTick("BTC-LTC", "INVALID-INTERVAL-HAHA")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetLatestTick(\"BTC-LTC\", \"INVALID-INTERVAL-HAHA\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
		val, err = bittrex.GetLatestTick("BTC-LTC", "")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetLatestTick(\"BTC-LTC\", \"\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
	}
}

func TestGetMarketSummaries(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetMarketSummaries()
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestGetMarketSummary(t *testing.T) {
	if testIsAPIAlive(t) {
		var err error
		_, err = bittrex.GetMarketSummary("BTC-ETH") // no error expected
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Second)
		val, err := bittrex.GetMarketSummary("INVALID-MARKET-HAHA") // error expected
		if err == nil {
			t.Fatal("Error expected, but function did not fail (GetMarketSummary(\"INVALID-MARKET-HAHA\"))\n Value Returned : " + fmt.Sprint(val))
		}
		time.Sleep(time.Second)
		val, err = bittrex.GetMarketSummary("") // error expected
		if err == nil {
			t.Fatal("Error expected, but function did not fail (GetMarketSummary(\"\"))\n Value Returned : " + fmt.Sprint(val))
		}
	}
}

func TestGetMarkets(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetMarkets() // no error expected
		if err != nil {
			t.Fatal(err)
		}
	}
}
<commit_msg>fixing broken tests<commit_after>package bittrex_test

import (
	"fmt"
	"testing"
	"time"

	"github.com/thebotguys/golang-bittrex-api/bittrex"
)

var latestTestedVersion = "2.11"

func TestGetServerAPIVersion(t *testing.T) {
	if testIsAPIAlive(t) {
		version, err := bittrex.GetServerAPIVersion()
		if err != nil {
			t.Fatal(err)
		}
		if version != latestTestedVersion {
			t.Errorf(`Please check version you are testing, on server it is %s,
while on this client it is %s.`,
				latestTestedVersion, version)
		}
	}
}

func TestGetBTCPrice(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetBTCPrice()
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestGetTicks(t *testing.T) {
	if testIsAPIAlive(t) {
		time.Sleep(time.Second * 2)
		_, err := bittrex.GetTicks("BTC-ETH", "thirtyMin")
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Second * 2)
		val, err := bittrex.GetTicks("INVALID-MARKET-HAHA", "thirtyMin")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetTicks(\"INVALID-MARKET-HAHA\", " +
				"\"thirtyMin\"))\n Value Returned : " +
				fmt.Sprint(val))
		}
		time.Sleep(time.Second * 2)
		val, err = bittrex.GetTicks("", "thirtyMin")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetTicks(\"\", \"thirtyMin\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
		time.Sleep(time.Second * 2)
		val, err = bittrex.GetTicks("BTC-LTC", "INVALID-INTERVAL-HAHA")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetTicks(\"BTC-LTC\", \"INVALID-INTERVAL-HAHA\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
		time.Sleep(time.Second * 2)
		val, err = bittrex.GetTicks("BTC-LTC", "")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetTicks(\"BTC-LTC\", \"\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
	}
}

func TestGetLatestTick(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetLatestTick("BTC-ETH", "thirtyMin")
		if err != nil {
			t.Fatal(err)
		}
		val, err := bittrex.GetLatestTick("INVALID-MARKET-HAHA", "thirtyMin")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetLatestTick(\"INVALID-MARKET-HAHA\", " +
				"\"thirtyMin\"))\n Value Returned : " +
				fmt.Sprint(val))
		}
		val, err = bittrex.GetLatestTick("", "thirtyMin")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetLatestTick(\"\", \"thirtyMin\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
		val, err = bittrex.GetLatestTick("BTC-LTC", "INVALID-INTERVAL-HAHA")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetLatestTick(\"BTC-LTC\", \"INVALID-INTERVAL-HAHA\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
		val, err = bittrex.GetLatestTick("BTC-LTC", "")
		if err == nil {
			t.Fatal("Error expected, but function did " +
				"not fail (GetLatestTick(\"BTC-LTC\", \"\"))\n" +
				"Value Returned : " + fmt.Sprint(val))
		}
	}
}

func TestGetMarketSummaries(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetMarketSummaries()
		if err != nil {
			t.Fatal(err)
		}
	}
}

func TestGetMarketSummary(t *testing.T) {
	if testIsAPIAlive(t) {
		var err error
		_, err = bittrex.GetMarketSummary("BTC-ETH") // no error expected
		if err != nil {
			t.Fatal(err)
		}
		time.Sleep(time.Second)
		val, err := bittrex.GetMarketSummary("INVALID-MARKET-HAHA") // error expected
		if err == nil {
			t.Fatal("Error expected, but function did not fail (GetMarketSummary(\"INVALID-MARKET-HAHA\"))\n Value Returned : " + fmt.Sprint(val))
		}
		time.Sleep(time.Second)
		val, err = bittrex.GetMarketSummary("") // error expected
		if err == nil {
			t.Fatal("Error expected, but function did not fail (GetMarketSummary(\"\"))\n Value Returned : " + fmt.Sprint(val))
		}
	}
}

func TestGetMarkets(t *testing.T) {
	if testIsAPIAlive(t) {
		_, err := bittrex.GetMarkets() // no error expected
		if err != nil {
			t.Fatal(err)
		}
	}
}
<|endoftext|>