<commit_before>package haus

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

	"gopkg.in/yaml.v2"
	"github.com/SearchSpring/RepoTsar/gitutils"
)

// Config represents the configurations in haus config file.
type Config struct {
	Name string
	Email string
	Path string
	Pwd string
	Hausrepo string
	Environments map[string]Environment
}

// ReadConfig reads the config file from the supplied full path and
// returns a Config and error.
func ReadConfig(filename string, usrcfgfile string, branch string )(*Config, error) {
	config := &Config{}

	// If the configfile is missing, try to check it out from git repo
	_,err := os.Stat(filename)
	if err != nil {
		// Get the url for the git repo from user config
		err = readCfg(usrcfgfile,config)
		if err != nil {
			return config,err
		}
		// If the url is defined, clone the repo
		if config.Hausrepo != "" {
			cloneinfo := &gitutils.CloneInfo{
				Reponame: "hauscfg",
				Path: ".",
				URL: config.Hausrepo,
				Branch: branch,
			}
			fmt.Printf("Cloning repo hauscfg from %s\n", config.Hausrepo)
			_,err = cloneinfo.CloneRepo()
			if err != nil {
				return config, err
			}
		} else {
			// There's no haus yaml, and hausrepo isn't defined in the user config
			err = fmt.Errorf("No %s file and %s missing 'hausrepo'.", filename,usrcfgfile)
			return config, err
		}
	}

	// Read haus yaml file
	err = readCfg(filename, config)
	if err != nil {
		return config, err
	}

	// Read user config haus yaml
	err = readCfg(usrcfgfile, config)
	if err != nil {
		return config, err
	}

	// Store the current path
	config.Pwd,err = os.Getwd()
	if err != nil {
		return config,err
	}
	return config, nil
}

// readCfg reads a file and parses it for yaml and unmarshals it into config.
func readCfg(cfgfile string, config *Config) (error) {
	// Read config from user home a overrite anything
	_,err := os.Stat(cfgfile)
	if err != nil {
	} else {
		cfg,err := ioutil.ReadFile(cfgfile)
		if err != nil {
			return err
		}
		err = yaml.Unmarshal(cfg, config)
		if err != nil {
			return err
		}
	}
	return nil
}<commit_msg>Fixed expanding ~ to homedir<commit_after>package haus

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

	"gopkg.in/yaml.v2"
	"github.com/SearchSpring/RepoTsar/gitutils"
)

// Config represents the configurations in haus config file.
type Config struct {
	Name string
	Email string
	Path string
	Pwd string
	Hausrepo string
	Environments map[string]Environment
}

// ReadConfig reads the config file from the supplied full path and
// returns a Config and error.
func ReadConfig(filename string, usrcfgfile string, branch string )(*Config, error) {
	config := &Config{}

	// If the configfile is missing, try to check it out from git repo
	_,err := os.Stat(filename)
	if err != nil {
		// Get the url for the git repo from user config
		err = readCfg(usrcfgfile,config)
		if err != nil {
			return config,err
		}
		// If the url is defined, clone the repo
		if config.Hausrepo != "" {
			cloneinfo := &gitutils.CloneInfo{
				Reponame: "hauscfg",
				Path: ".",
				URL: config.Hausrepo,
				Branch: branch,
			}
			fmt.Printf("Cloning repo hauscfg from %s\n", config.Hausrepo)
			_,err = cloneinfo.CloneRepo()
			if err != nil {
				return config, err
			}
		} else {
			// There's no haus yaml, and hausrepo isn't defined in the user config
			err = fmt.Errorf("No %s file and %s missing 'hausrepo'.", filename,usrcfgfile)
			return config, err
		}
	}

	// Read haus yaml file
	err = readCfg(filename, config)
	if err != nil {
		return config, err
	}

	// Read user config haus yaml
	err = readCfg(usrcfgfile, config)
	if err != nil {
		return config, err
	}

	// Store the current path
	config.Pwd,err = os.Getwd()
	if err != nil {
		return config,err
	}
	return config, nil
}

// readCfg reads a file and parses it for yaml and unmarshals it into config.
func readCfg(cfgfile string, config *Config) (error) {
	// Read config from user home a overrite anything

	_,err := os.Stat(expandTilde(cfgfile))
	if err != nil {
		fmt.Printf("Config file %#v missing\n", cfgfile)
	} else {
		cfg,err := ioutil.ReadFile(expandTilde(cfgfile))
		if err != nil {
			return err
		}
		err = yaml.Unmarshal(cfg, config)
		if err != nil {
			return err
		}
	}
	return nil
}

// expandTilde expands ~ to value of ENV HOME
func expandTilde(f string) string {
	if strings.HasPrefix(f, "~"+string(filepath.Separator)) {
		return os.Getenv("HOME") + f[1:]
	}
	return f
}<|endoftext|>


<commit_before>// package kodingkey provides functions for generating koding.key
// and heplers for conversions.
package kodingkey

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"io"
	"io/ioutil"
	"strings"
)

// Length of the koding key bytes.
// Must be multiple of 6 to not create padding in string representation.
const BytesLength = 48

// Number of characters in a koding key when converted to string.
// We are using base64 conversion and it uses 6/8 of the ASCII table,
// that's the reason of this calculation.
const StringLength = BytesLength * 8 / 6

var Encoding *base64.Encoding

func init() {
	Encoding = base64.URLEncoding
}

// KodingKey is a byte representation of a koding.key file
// generated by "kd register" command.
type KodingKey []byte

// NewKodingKey returns a new random generated KodingKey of length "BytesLength".
func NewKodingKey() (KodingKey, error) {
	key := make(KodingKey, BytesLength, BytesLength)

	if _, err := io.ReadFull(rand.Reader, key); err != nil {
		return nil, err
	}

	return key, nil
}

func FromString(s string) (KodingKey, error) {
	s = strings.TrimSpace(s)

	if len(s) == 0 {
		return nil, errors.New("Zero length Koding Key")
	}

	return Encoding.DecodeString(s)
}

func FromFile(path string) (KodingKey, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return FromString(string(data))
}

func (k KodingKey) String() string {
	return Encoding.EncodeToString(k)
}

func (k KodingKey) Bytes32() []byte {
	h := sha256.New()
	h.Write(k)
	return h.Sum(nil)
}
<commit_msg>fix syntax<commit_after>// package kodingkey provides functions for generating koding.key
// and heplers for conversions.
package kodingkey

import (
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"errors"
	"io"
	"io/ioutil"
	"strings"
)

// Length of the koding key bytes.
// Must be multiple of 6 to not create padding in string representation.
const BytesLength = 48

// Number of characters in a koding key when converted to string.
// We are using base64 conversion and it uses 6/8 of the ASCII table,
// that's the reason of this calculation.
const StringLength = BytesLength * 8 / 6

var Encoding *base64.Encoding

func init() {
	Encoding = base64.URLEncoding
}

// KodingKey is a byte representation of a koding.key file
// generated by "kd register" command.
type KodingKey []byte

// NewKodingKey returns a new random generated KodingKey of length "BytesLength".
func NewKodingKey() (KodingKey, error) {
	key := make(KodingKey, BytesLength)

	if _, err := io.ReadFull(rand.Reader, key); err != nil {
		return nil, err
	}

	return key, nil
}

func FromString(s string) (KodingKey, error) {
	s = strings.TrimSpace(s)

	if len(s) == 0 {
		return nil, errors.New("Zero length Koding Key")
	}

	return Encoding.DecodeString(s)
}

func FromFile(path string) (KodingKey, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	return FromString(string(data))
}

func (k KodingKey) String() string {
	return Encoding.EncodeToString(k)
}

func (k KodingKey) Bytes32() []byte {
	h := sha256.New()
	h.Write(k)
	return h.Sum(nil)
}
<|endoftext|>


<commit_before>package ui

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/0xAX/notificator"
	"github.com/davecgh/go-spew/spew"
	"github.com/fatih/color"
	"github.com/jroimartin/gocui"
	"github.com/mephux/komanda-cli/komanda/client"
	"github.com/mephux/komanda-cli/komanda/logger"

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

var (
	LoadingChannel = make(chan string)
	timestampColor = color.New(color.FgMagenta).SprintFunc()
	nickColor      = color.New(color.FgBlue).SprintFunc()
)

func BindHandlers() {

	for _, code := range client.IrcCodes {
		Server.Client.HandleFunc(code, func(conn *irc.Conn, line *irc.Line) {

			Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				// client.StatusMessage(v, fmt.Sprintf("%s (CODE: %s)", line.Text(), line.Cmd))
				client.StatusMessage(v, fmt.Sprintf("%s", line.Text()))
				return nil
			})
		})
	}

	Server.Client.HandleFunc("REGISTER", func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Println("REGISTER -----------------------------", spew.Sdump(line))
	})

	Server.Client.HandleFunc("TOPIC", func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Println("TOPIC  -----------------------------", spew.Sdump(line))

		if c, _, has := Server.HasChannel(line.Args[0]); has {
			Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				c.Topic = line.Args[1]

				fmt.Fprintf(v, "%s %s changed the topic of %s to: %s\n", color.GreenString("**"), line.Nick, line.Nick, c.Topic)

				return nil
			})
		}
	})

	Server.Client.HandleFunc("JOIN", func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Println("JOIN -----------------------------", line.Text())
		// logger.Logger.Println("JOIN -----------------------------", spew.Sdump(line))

		if c, _, has := Server.HasChannel(line.Text()); has {
			Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				c.AddNick(line.Nick)
				fmt.Fprintf(v, "[%s] %s [%s@%s] has joined %s\n", color.GreenString("+JOIN"), line.Nick, line.Ident, line.Host, c.Name)
				return nil
			})
		}
	})

	Server.Client.HandleFunc("PART", func(conn *irc.Conn, line *irc.Line) {
		logger.Logger.Println("PART -----------------------------", line.Text())

		if c, _, has := Server.HasChannel(line.Text()); has {
			Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				c.RemoveNick(line.Nick)
				fmt.Fprintf(v, "[%s] %s [%s@%s] has quit [%s]\n", color.RedString("-PART"), line.Nick, line.Ident, line.Host, line.Text())
				return nil
			})
		}
	})

	// nick in use
	Server.Client.HandleFunc("433", func(conn *irc.Conn, line *irc.Line) {
		Server.Exec(Server.CurrentChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
			fmt.Fprintf(v, "%s %s\n", color.RedString("=="), fmt.Sprintf("Nick %s is already in use.", line.Nick))
			return nil
		})
	})

	// op needed
	Server.Client.HandleFunc("482", func(conn *irc.Conn, line *irc.Line) {
		if c, _, has := Server.HasChannel(line.Args[1]); has {
			Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				fmt.Fprintf(v, "%s %s\n", color.RedString("=="), line.Text())
				return nil
			})
		} else {
			Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				fmt.Fprintf(v, "%s %s\n", color.RedString("=="), line.Text())
				return nil
			})
		}
	})

	Server.Client.HandleFunc("331", func(conn *irc.Conn, line *irc.Line) {
		if c, _, has := Server.HasChannel(line.Args[1]); has {
			c.Topic = "N/A"
		}
	})

	//
	// TOPIC
	// https://www.alien.net.au/irc/irc2numerics.html
	//
	Server.Client.HandleFunc("332", func(conn *irc.Conn, line *irc.Line) {
		logger.Logger.Println("TOPIC........", spew.Sdump(line))

		Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error {

			if c, _, has := Server.HasChannel(line.Args[1]); has {
				c.Topic = line.Args[2]
				fmt.Fprintf(v, "%s Topic of %s: %s\n", color.GreenString("**"), line.Args[1], c.Topic)
			}

			return nil
		})

	})

	// nick list
	Server.Client.HandleFunc("353", func(conn *irc.Conn, line *irc.Line) {
		logger.Logger.Printf("NICK LIST %s\n", spew.Sdump(line))

		Server.Exec(line.Args[2], func(g *gocui.Gui, v *gocui.View, s *client.Server) error {

			if c, _, has := Server.HasChannel(line.Args[2]); has {
				nicks := strings.Split(line.Args[len(line.Args)-1], " ")

				for _, nick := range nicks {
					// UnrealIRCd's coders are lazy and leave a trailing space
					if nick == "" {
						continue
					}

					logger.Logger.Printf("ADD NICK %s\n", spew.Sdump(nick))

					user := &client.User{}

					switch c := nick[0]; c {
					case '~', '&', '@', '%', '+':
						nick = nick[1:]
						fallthrough
					default:
						switch c {
						case '~':
							// conn.st.ChannelModes(ch.Name, "+q", nick)
						case '&':
							// conn.st.ChannelModes(ch.Name, "+a", nick)
						case '@':
							user.Mode = "@"
							// conn.st.ChannelModes(ch.Name, "+o", nick)
							// fmt.Fprintf(v, "@%s ", nick)
						case '%':
							// conn.st.ChannelModes(ch.Name, "+h", nick)
							user.Mode = "%"
						case '+':
							user.Mode = "+"
							// conn.st.ChannelModes(ch.Name, "+v", nick)
							// fmt.Fprintf(v, "+%s ", nick)
						default:
							{

								// fmt.Fprintf(v, "+%s ", nick)
							}
						}

					}

					logger.Logger.Printf("ADD NICK %s\n", spew.Sdump(nick))

					user.Nick = nick
					c.Users = append(c.Users, user)
				}
			}

			return nil
		})
	})

	// Server.Client.HandleFunc("315", func(conn *irc.Conn, line *irc.Line) {
	// Server.Exec(line.Args[1], func(v *gocui.View, s *client.Server) error {
	// return nil
	// })
	// })

	// 328
	// 331 -- no topic

	// 333 -- topic set by
	Server.Client.HandleFunc("333", func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Printf("TOPIC SET BY %s\n", spew.Sdump(line))

		Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error {

			i, err := strconv.ParseInt(line.Args[3], 10, 64)

			if err != nil {
				logger.Logger.Printf(err.Error())
			}

			tm := time.Unix(i, 0)

			if strings.Contains(line.Args[2], "!") {
				ss := strings.Split(line.Args[2], "!")

				fmt.Fprintf(v, "%s Topic set by %s [%s] [%s]\n", color.GreenString("**"),
					ss[0], ss[1], tm.Format(time.RFC822))
			} else {
				fmt.Fprintf(v, "%s Topic set by %s [%s]\n", color.GreenString("**"),
					line.Args[2], tm.Format(time.RFC822))
			}

			return nil
		})
	})

	// names list done
	Server.Client.HandleFunc("366", func(conn *irc.Conn, line *irc.Line) {
		Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error {

			// v.Clear()
			// v.SetCursor(0, 0)

			if c, _, has := s.HasChannel(line.Args[1]); has {

				c.NickListString(v)
				c.NickMetricsString(v)

				// var topic string

				// if len(c.Topic) <= 0 {
				// topic = "N/A"
				// } else {
				// topic = c.Topic
				// }

				// fmt.Fprintf(v, "⣿ CHANNEL: %s\n", c.Name)
				// fmt.Fprintf(v, "⣿   Users: %d\n", len(c.Names))
				// fmt.Fprintf(v, "⣿   TOPIC: %s\n", topic)

				// fmt.Fprint(v, "⣿   NAMES: \n")

				// w := tabwriter.NewWriter(v, 0, 8, 3, ' ', tabwriter.DiscardEmptyColumns)

				// count := 1
				// current := ""
				// for _, u := range c.Names {
				// if count < 7 {
				// current = current + fmt.Sprintf("%s\t", u)
				// count += 1
				// } else {
				// fmt.Fprintln(w, current)
				// current = ""
				// count = 1
				// }
				// }

				// if current != "" {
				// fmt.Fprintln(w, current)
				// }

				// w.Flush()

				// fmt.Fprint(v, "\n")
			}
			return nil
		})
	})

	Server.Client.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) {

		ircChan := line.Args[0]

		logger.Logger.Printf("MSG %s %s %s %s\n", ircChan, line.Nick, line.Host, line.Args)

		if ircChan == Server.Client.Me().Nick {

			if c, _, has := Server.HasChannel(line.Nick); !has {
				Server.NewChannel(line.Nick, true)
			} else {
				if Server.CurrentChannel != line.Nick {
					c.Unread = true

				}
			}

			Server.Exec(line.Nick,
				func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
					timestamp := time.Now().Format("03:04")
					fmt.Fprintf(v, "[%s] <- %s: %s\n", timestampColor(timestamp), nickColor(line.Nick), line.Text())

					notify.Push(fmt.Sprintf("Private message from %s", line.Nick), line.Text(), "", notificator.UR_NORMAL)

					return nil
				})

		} else {

			if c, _, has := Server.HasChannel(ircChan); has {

				if Server.CurrentChannel != c.Name {
					c.Unread = true
				}

				Server.Exec(ircChan,
					func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
						timestamp := time.Now().Format("03:04")
						fmt.Fprintf(v, "[%s] <- %s: %s\n", timestampColor(timestamp), nickColor(line.Nick), line.Text())

						if strings.Contains(line.Text(), Server.Client.Me().Nick) {
							notify.Push(fmt.Sprintf("Highlight from %s", line.Nick), line.Text(), "", notificator.UR_NORMAL)
						}

						return nil
					})
			}

		}
	})

	Server.Client.HandleFunc("464", func(conn *irc.Conn, line *irc.Line) {
		LoadingChannel <- "done"
	})

	Server.Client.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Printf("LINE %s\n", spew.Sdump(line))
		LoadingChannel <- "done"
	})

	Server.Client.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) {
		LoadingChannel <- "done"
	})

}
<commit_msg>nick list fix<commit_after>package ui

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"github.com/0xAX/notificator"
	"github.com/davecgh/go-spew/spew"
	"github.com/fatih/color"
	"github.com/jroimartin/gocui"
	"github.com/mephux/komanda-cli/komanda/client"
	"github.com/mephux/komanda-cli/komanda/logger"

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

var (
	LoadingChannel = make(chan string)
	timestampColor = color.New(color.FgMagenta).SprintFunc()
	nickColor      = color.New(color.FgBlue).SprintFunc()
)

func BindHandlers() {

	for _, code := range client.IrcCodes {
		Server.Client.HandleFunc(code, func(conn *irc.Conn, line *irc.Line) {

			Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				// client.StatusMessage(v, fmt.Sprintf("%s (CODE: %s)", line.Text(), line.Cmd))
				client.StatusMessage(v, fmt.Sprintf("%s", line.Text()))
				return nil
			})
		})
	}

	Server.Client.HandleFunc("REGISTER", func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Println("REGISTER -----------------------------", spew.Sdump(line))
	})

	Server.Client.HandleFunc("TOPIC", func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Println("TOPIC  -----------------------------", spew.Sdump(line))

		if c, _, has := Server.HasChannel(line.Args[0]); has {
			Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				c.Topic = line.Args[1]

				fmt.Fprintf(v, "%s %s changed the topic of %s to: %s\n", color.GreenString("**"), line.Nick, line.Nick, c.Topic)

				return nil
			})
		}
	})

	Server.Client.HandleFunc("JOIN", func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Println("JOIN -----------------------------", line.Text())
		// logger.Logger.Println("JOIN -----------------------------", spew.Sdump(line))

		if c, _, has := Server.HasChannel(line.Text()); has {
			Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				if line.Nick != Server.Client.Me().Nick {
					c.AddNick(line.Nick)
				}
				fmt.Fprintf(v, "[%s] %s [%s@%s] has joined %s\n", color.GreenString("+JOIN"), line.Nick, line.Ident, line.Host, c.Name)
				return nil
			})
		}
	})

	Server.Client.HandleFunc("PART", func(conn *irc.Conn, line *irc.Line) {
		logger.Logger.Println("PART -----------------------------", line.Text())

		if c, _, has := Server.HasChannel(line.Text()); has {
			Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				c.RemoveNick(line.Nick)
				fmt.Fprintf(v, "[%s] %s [%s@%s] has quit [%s]\n", color.RedString("-PART"), line.Nick, line.Ident, line.Host, line.Text())
				return nil
			})
		}
	})

	// nick in use
	Server.Client.HandleFunc("433", func(conn *irc.Conn, line *irc.Line) {
		Server.Exec(Server.CurrentChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
			fmt.Fprintf(v, "%s %s\n", color.RedString("=="), fmt.Sprintf("Nick %s is already in use.", line.Nick))
			return nil
		})
	})

	// op needed
	Server.Client.HandleFunc("482", func(conn *irc.Conn, line *irc.Line) {
		if c, _, has := Server.HasChannel(line.Args[1]); has {
			Server.Exec(c.Name, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				fmt.Fprintf(v, "%s %s\n", color.RedString("=="), line.Text())
				return nil
			})
		} else {
			Server.Exec(client.StatusChannel, func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
				fmt.Fprintf(v, "%s %s\n", color.RedString("=="), line.Text())
				return nil
			})
		}
	})

	Server.Client.HandleFunc("331", func(conn *irc.Conn, line *irc.Line) {
		if c, _, has := Server.HasChannel(line.Args[1]); has {
			c.Topic = "N/A"
		}
	})

	//
	// TOPIC
	// https://www.alien.net.au/irc/irc2numerics.html
	//
	Server.Client.HandleFunc("332", func(conn *irc.Conn, line *irc.Line) {
		logger.Logger.Println("TOPIC........", spew.Sdump(line))

		Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error {

			if c, _, has := Server.HasChannel(line.Args[1]); has {
				c.Topic = line.Args[2]
				fmt.Fprintf(v, "%s Topic of %s: %s\n", color.GreenString("**"), line.Args[1], c.Topic)
			}

			return nil
		})

	})

	// nick list
	Server.Client.HandleFunc("353", func(conn *irc.Conn, line *irc.Line) {
		logger.Logger.Printf("NICK LIST %s\n", spew.Sdump(line))

		Server.Exec(line.Args[2], func(g *gocui.Gui, v *gocui.View, s *client.Server) error {

			if c, _, has := Server.HasChannel(line.Args[2]); has {
				nicks := strings.Split(line.Args[len(line.Args)-1], " ")

				for _, nick := range nicks {
					// UnrealIRCd's coders are lazy and leave a trailing space
					if nick == "" {
						continue
					}

					logger.Logger.Printf("ADD NICK %s\n", spew.Sdump(nick))

					user := &client.User{}

					switch c := nick[0]; c {
					case '~', '&', '@', '%', '+':
						nick = nick[1:]
						fallthrough
					default:
						switch c {
						case '~':
							// conn.st.ChannelModes(ch.Name, "+q", nick)
						case '&':
							// conn.st.ChannelModes(ch.Name, "+a", nick)
						case '@':
							user.Mode = "@"
							// conn.st.ChannelModes(ch.Name, "+o", nick)
							// fmt.Fprintf(v, "@%s ", nick)
						case '%':
							// conn.st.ChannelModes(ch.Name, "+h", nick)
							user.Mode = "%"
						case '+':
							user.Mode = "+"
							// conn.st.ChannelModes(ch.Name, "+v", nick)
							// fmt.Fprintf(v, "+%s ", nick)
						default:
							{

								// fmt.Fprintf(v, "+%s ", nick)
							}
						}

					}

					logger.Logger.Printf("ADD NICK %s\n", spew.Sdump(nick))

					user.Nick = nick
					c.Users = append(c.Users, user)
				}
			}

			return nil
		})
	})

	// Server.Client.HandleFunc("315", func(conn *irc.Conn, line *irc.Line) {
	// Server.Exec(line.Args[1], func(v *gocui.View, s *client.Server) error {
	// return nil
	// })
	// })

	// 328
	// 331 -- no topic

	// 333 -- topic set by
	Server.Client.HandleFunc("333", func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Printf("TOPIC SET BY %s\n", spew.Sdump(line))

		Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error {

			i, err := strconv.ParseInt(line.Args[3], 10, 64)

			if err != nil {
				logger.Logger.Printf(err.Error())
			}

			tm := time.Unix(i, 0)

			if strings.Contains(line.Args[2], "!") {
				ss := strings.Split(line.Args[2], "!")

				fmt.Fprintf(v, "%s Topic set by %s [%s] [%s]\n", color.GreenString("**"),
					ss[0], ss[1], tm.Format(time.RFC822))
			} else {
				fmt.Fprintf(v, "%s Topic set by %s [%s]\n", color.GreenString("**"),
					line.Args[2], tm.Format(time.RFC822))
			}

			return nil
		})
	})

	// names list done
	Server.Client.HandleFunc("366", func(conn *irc.Conn, line *irc.Line) {
		Server.Exec(line.Args[1], func(g *gocui.Gui, v *gocui.View, s *client.Server) error {

			// v.Clear()
			// v.SetCursor(0, 0)

			if c, _, has := s.HasChannel(line.Args[1]); has {

				c.NickListString(v)
				c.NickMetricsString(v)

				// var topic string

				// if len(c.Topic) <= 0 {
				// topic = "N/A"
				// } else {
				// topic = c.Topic
				// }

				// fmt.Fprintf(v, "⣿ CHANNEL: %s\n", c.Name)
				// fmt.Fprintf(v, "⣿   Users: %d\n", len(c.Names))
				// fmt.Fprintf(v, "⣿   TOPIC: %s\n", topic)

				// fmt.Fprint(v, "⣿   NAMES: \n")

				// w := tabwriter.NewWriter(v, 0, 8, 3, ' ', tabwriter.DiscardEmptyColumns)

				// count := 1
				// current := ""
				// for _, u := range c.Names {
				// if count < 7 {
				// current = current + fmt.Sprintf("%s\t", u)
				// count += 1
				// } else {
				// fmt.Fprintln(w, current)
				// current = ""
				// count = 1
				// }
				// }

				// if current != "" {
				// fmt.Fprintln(w, current)
				// }

				// w.Flush()

				// fmt.Fprint(v, "\n")
			}
			return nil
		})
	})

	Server.Client.HandleFunc(irc.PRIVMSG, func(conn *irc.Conn, line *irc.Line) {

		ircChan := line.Args[0]

		logger.Logger.Printf("MSG %s %s %s %s\n", ircChan, line.Nick, line.Host, line.Args)

		if ircChan == Server.Client.Me().Nick {

			if c, _, has := Server.HasChannel(line.Nick); !has {
				Server.NewChannel(line.Nick, true)
			} else {
				if Server.CurrentChannel != line.Nick {
					c.Unread = true

				}
			}

			Server.Exec(line.Nick,
				func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
					timestamp := time.Now().Format("03:04")
					fmt.Fprintf(v, "[%s] <- %s: %s\n", timestampColor(timestamp), nickColor(line.Nick), line.Text())

					notify.Push(fmt.Sprintf("Private message from %s", line.Nick), line.Text(), "", notificator.UR_NORMAL)

					return nil
				})

		} else {

			if c, _, has := Server.HasChannel(ircChan); has {

				if Server.CurrentChannel != c.Name {
					c.Unread = true
				}

				Server.Exec(ircChan,
					func(g *gocui.Gui, v *gocui.View, s *client.Server) error {
						timestamp := time.Now().Format("03:04")
						fmt.Fprintf(v, "[%s] <- %s: %s\n", timestampColor(timestamp), nickColor(line.Nick), line.Text())

						if strings.Contains(line.Text(), Server.Client.Me().Nick) {
							notify.Push(fmt.Sprintf("Highlight from %s", line.Nick), line.Text(), "", notificator.UR_NORMAL)
						}

						return nil
					})
			}

		}
	})

	Server.Client.HandleFunc("464", func(conn *irc.Conn, line *irc.Line) {
		LoadingChannel <- "done"
	})

	Server.Client.HandleFunc(irc.CONNECTED, func(conn *irc.Conn, line *irc.Line) {
		// logger.Logger.Printf("LINE %s\n", spew.Sdump(line))
		LoadingChannel <- "done"
	})

	Server.Client.HandleFunc(irc.DISCONNECTED, func(conn *irc.Conn, line *irc.Line) {
		LoadingChannel <- "done"
	})

}
<|endoftext|>


<commit_before>package kuzzle

import (
  "encoding/json"
  "github.com/kuzzleio/sdk-go/types"
  "errors"
  "github.com/kuzzleio/sdk-go/internal"
)

func (k *Kuzzle) CreateIndex(index string, options *types.Options) (*types.AckResponse, error) {
  if index == "" {
    return nil, errors.New("Kuzzle.createIndex: index required")
  }

  result := make(chan types.KuzzleResponse)

  go k.Query(internal.BuildQuery("index", "create", index, "", nil), options, result)

  res := <-result

  if res.Error.Message != "" {
    return nil, errors.New(res.Error.Message)
  }

  ack := &types.AckResponse{}
  json.Unmarshal(res.Result, &ack)

  return ack, nil
}<commit_msg>remove unused pointer<commit_after>package kuzzle

import (
  "encoding/json"
  "github.com/kuzzleio/sdk-go/types"
  "errors"
  "github.com/kuzzleio/sdk-go/internal"
)

func (k Kuzzle) CreateIndex(index string, options *types.Options) (*types.AckResponse, error) {
  if index == "" {
    return nil, errors.New("Kuzzle.createIndex: index required")
  }

  result := make(chan types.KuzzleResponse)

  go k.Query(internal.BuildQuery("index", "create", index, "", nil), options, result)

  res := <-result

  if res.Error.Message != "" {
    return nil, errors.New(res.Error.Message)
  }

  ack := &types.AckResponse{}
  json.Unmarshal(res.Result, &ack)

  return ack, nil
}<|endoftext|>


<commit_before>package plugins

import (
	"errors"
	"strings"

	"time"

	"sync"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/Seklfreak/Robyul2/models"
	"github.com/bwmarrin/discordgo"
	"github.com/globalsign/mgo/bson"
	"github.com/sirupsen/logrus"
)

type namesAction func(args []string, in *discordgo.Message, out **discordgo.MessageSend) (next namesAction)

type Names struct{}

var (
	previousNicknames      map[string]map[string]string
	previousNicknamesMutex sync.RWMutex
	previousUsernames      map[string]string
	previousUsernamesMutex sync.RWMutex
)

func (n *Names) Commands() []string {
	return []string{
		"names",
		"nicknames",
	}
}

// TODO: switch to robyul state

func (n *Names) Init(session *discordgo.Session) {
	previousNicknamesMutex.Lock()
	previousNicknames = make(map[string]map[string]string, 0)
	previousNicknamesMutex.Unlock()
	previousUsernamesMutex.Lock()
	previousUsernames = make(map[string]string, 0)
	previousUsernamesMutex.Unlock()
	session.AddHandler(n.OnGuildMemberListChunk)
	session.AddHandler(n.OnPresenceUpdate)
	session.AddHandler(n.OnGuildMemberUpdate)
}

func (n *Names) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
	if !helpers.ModuleIsAllowed(msg.ChannelID, msg.ID, msg.Author.ID, helpers.ModulePermNames) {
		return
	}

	session.ChannelTyping(msg.ChannelID)

	var result *discordgo.MessageSend
	args := strings.Fields(content)

	action := n.actionStart
	for action != nil {
		action = action(args, msg, &result)
	}
}

func (n *Names) actionStart(args []string, in *discordgo.Message, out **discordgo.MessageSend) namesAction {
	cache.GetSession().ChannelTyping(in.ChannelID)

	if len(args) < 1 {
		*out = n.newMsg(helpers.GetText("bot.arguments.too-few"))
		return n.actionFinish
	}

	return n.actionNames
}

func (n *Names) actionNames(args []string, in *discordgo.Message, out **discordgo.MessageSend) namesAction {
	user, err := helpers.GetUserFromMention(args[0])
	if err != nil || user == nil || user.ID == "" {
		*out = n.newMsg(helpers.GetText("bot.arguments.invalid"))
		return n.actionFinish
	}
	channel, err := helpers.GetChannel(in.ChannelID)
	helpers.Relax(err)
	member, _ := helpers.GetGuildMember(channel.GuildID, user.ID)

	var pastUsernamesText, pastNicknamesText string

	pastUsernames, err := n.GetUsernames(user.ID)
	if err != nil && strings.Contains(err.Error(), "no username entries") {
		helpers.Relax(err)
	}

	if len(pastUsernames) <= 0 || pastUsernames[len(pastUsernames)-1] != user.Username+"#"+user.Discriminator {
		pastUsernames = append(pastUsernames, user.Username+"#"+user.Discriminator)
	}

	for i, pastUsername := range pastUsernames {
		pastUsernamesText += "`" + pastUsername + "`"
		if i < len(pastUsernames)-1 {
			pastUsernamesText += ", "
		}
		if i == len(pastUsernames) {
			pastUsernamesText += " and "
		}
	}

	if pastUsernamesText == "" {
		pastUsernamesText = "None"
	}

	pastNicknames, err := n.GetNicknames(channel.GuildID, user.ID)
	if err != nil && !strings.Contains(err.Error(), "no nickname entries") {
		helpers.Relax(err)
	}

	if member != nil && member.User != nil && member.User.ID != "" {
		if member.Nick != "" {
			if len(pastNicknames) <= 0 || pastNicknames[len(pastNicknames)-1] != member.Nick {
				pastNicknames = append(pastNicknames, member.Nick)
			}
		}
	}

	for i, pastNickname := range pastNicknames {
		pastNicknamesText += "`" + pastNickname + "`"
		if i < len(pastNicknames)-1 {
			pastNicknamesText += ", "
		}
		if i == len(pastNicknames) {
			pastNicknamesText += " and "
		}
	}

	if pastNicknamesText == "" {
		pastNicknamesText = "None"
	}

	resultText := helpers.GetTextF("plugins.names.list-result",
		user.Username, user.Discriminator, user.ID, pastUsernamesText, pastNicknamesText)
	for _, page := range helpers.Pagify(resultText, ",") {
		_, err := helpers.SendMessage(in.ChannelID, page)
		helpers.RelaxMessage(err, in.ChannelID, in.ID)
	}

	return nil
}

func (n *Names) OnPresenceUpdate(session *discordgo.Session, presence *discordgo.PresenceUpdate) {
	if presence.GuildID == "" || presence.User == nil || presence.User.ID == "" {
		return
	}

	go func() {
		defer helpers.Recover()
		if presence.Presence.User.Username != "" {
			err := n.UpdateUsername(presence.Presence.User.ID, presence.Presence.User.Username+"#"+presence.Presence.User.Discriminator)
			helpers.Relax(err)
		}
	}()
}

func (n *Names) OnGuildMemberUpdate(session *discordgo.Session, member *discordgo.GuildMemberUpdate) {
	if member.Member == nil {
		return
	}

	go func() {
		defer helpers.Recover()

		if member.Member.Nick != "" {
			err := n.UpdateNickname(member.Member.GuildID, member.Member.User.ID, member.Member.Nick)
			helpers.Relax(err)
		}
	}()
}

func (n *Names) UpdateNickname(guildID string, userID string, newNick string) (err error) {
	previousNicknamesMutex.Lock()
	defer previousNicknamesMutex.Unlock()
	var oldNick string
	if previousNicknames[guildID] == nil {
		previousNicknames[guildID] = make(map[string]string, 0)
	}
	oldNick, _ = previousNicknames[guildID][userID]

	lastSavedNickname, err := n.GetLastNickname(guildID, userID)
	if err != nil && !strings.Contains(err.Error(), "no nickname entry") {
		helpers.RelaxLog(err)
	}

	if oldNick != "" && lastSavedNickname != oldNick {
		err = n.SaveNickname(guildID, userID, oldNick)
		helpers.RelaxLog(err)
		lastSavedNickname = oldNick
	}

	if lastSavedNickname != newNick {
		err = n.SaveNickname(guildID, userID, newNick)
		previousNicknames[guildID][userID] = newNick
		return err
	}
	return nil
}

func (n *Names) UpdateUsername(userID string, newUsername string) (err error) {
	previousUsernamesMutex.Lock()
	defer previousUsernamesMutex.Unlock()
	var oldUsername string
	oldUsername, _ = previousUsernames[userID]

	lastSavedUsername, err := n.GetLastUsername(userID)
	if err != nil && !strings.Contains(err.Error(), "no username entry") {
		helpers.RelaxLog(err)
	}

	if oldUsername != "" && lastSavedUsername != oldUsername {
		err = n.SaveUsername(userID, oldUsername)
		helpers.RelaxLog(err)
		lastSavedUsername = oldUsername
	}

	if lastSavedUsername != newUsername {
		err = n.SaveUsername(userID, newUsername)
		previousUsernames[userID] = newUsername
		return err
	}
	return nil
}

func (n *Names) GetLastNickname(guildID string, userID string) (nickname string, err error) {
	var entryBucket models.NamesEntry
	err = helpers.MdbOne(
		helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": userID, "guildid": guildID}).Sort("-changedat"),
		&entryBucket,
	)

	if err != nil {
		if strings.Contains(err.Error(), "not found") {
			return "", errors.New("no nickname entry")
		}
		return "", err
	}

	return entryBucket.Nickname, nil
}

func (n *Names) SaveNickname(guildID string, userID string, nickname string) (err error) {
	// don't store duplicates
	lastNickname, err := n.GetLastNickname(guildID, userID)
	if err == nil {
		if nickname == lastNickname {
			return nil
		}
	}
	// insert nickname
	_, err = helpers.MDbInsert(
		models.NamesTable,
		models.NamesEntry{
			ChangedAt: time.Now(),
			GuildID:   guildID,
			UserID:    userID,
			Nickname:  nickname,
			Username:  "",
		},
	)
	return err
}

func (n *Names) GetLastUsername(userID string) (username string, err error) {
	var entryBucket models.NamesEntry
	err = helpers.MdbOne(
		helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": userID, "guildid": "global"}).Sort("-changedat"),
		&entryBucket,
	)

	if err != nil {
		if strings.Contains(err.Error(), "not found") {
			return "", errors.New("no username entry")
		}
		return "", err
	}

	return entryBucket.Username, nil
}

func (n *Names) SaveUsername(userID string, username string) (err error) {
	// don't store duplicates
	lastUsername, err := n.GetLastUsername(userID)
	if err == nil {
		if username == lastUsername {
			return nil
		}
	}
	// insert username
	_, err = helpers.MDbInsert(
		models.NamesTable,
		models.NamesEntry{
			ChangedAt: time.Now(),
			GuildID:   "global",
			UserID:    userID,
			Nickname:  "",
			Username:  username,
		},
	)
	return err
}

func (n *Names) GetNicknames(guildID string, userID string) (nicknames []string, err error) {
	var entryBucket []models.NamesEntry
	err = helpers.MDbIter(helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": userID, "guildid": guildID}).Sort("changedat")).All(&entryBucket)

	if err != nil {
		return nicknames, err
	}

	if entryBucket == nil || len(entryBucket) <= 0 {
		return nicknames, errors.New("no nickname entries")
	}

	for _, entry := range entryBucket {
		if len(nicknames) <= 0 || nicknames[len(nicknames)-1] != entry.Nickname {
			nicknames = append(nicknames, entry.Nickname)
		}
	}
	return nicknames, nil
}

func (n *Names) GetUsernames(userID string) (usernames []string, err error) {
	var entryBucket []models.NamesEntry
	err = helpers.MDbIter(helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": userID, "guildid": "global"}).Sort("changedat")).All(&entryBucket)

	if err != nil {
		return usernames, err
	}

	if entryBucket == nil || len(entryBucket) <= 0 {
		return usernames, errors.New("no username entries")
	}

	for _, entry := range entryBucket {
		if len(usernames) <= 0 || usernames[len(usernames)-1] != entry.Username {
			usernames = append(usernames, entry.Username)
		}
	}
	return usernames, nil
}

func (n *Names) OnGuildMemberListChunk(session *discordgo.Session, members *discordgo.GuildMembersChunk) {
	previousUsernamesMutex.Lock()
	previousNicknamesMutex.Lock()
	defer previousUsernamesMutex.Unlock()
	defer previousNicknamesMutex.Unlock()
	for _, member := range members.Members {
		previousUsernames[member.User.ID] = member.User.Username + "#" + member.User.Discriminator
		if member.Nick != "" {
			if previousNicknames[members.GuildID] == nil {
				previousNicknames[members.GuildID] = make(map[string]string, 0)
			}
			previousNicknames[members.GuildID][member.User.ID] = member.Nick
		}
	}
}

func (n *Names) actionFinish(args []string, in *discordgo.Message, out **discordgo.MessageSend) namesAction {
	_, err := helpers.SendComplex(in.ChannelID, *out)
	helpers.Relax(err)

	return nil
}

func (n *Names) newMsg(content string) *discordgo.MessageSend {
	return &discordgo.MessageSend{Content: helpers.GetText(content)}
}

func (n *Names) Relax(err error) {
	if err != nil {
		panic(err)
	}
}

func (n *Names) logger() *logrus.Entry {
	return cache.GetLogger().WithField("module", "names")
}
<commit_msg>[names] don't log last username/nickname queries 👀<commit_after>package plugins

import (
	"errors"
	"strings"

	"time"

	"sync"

	"github.com/Seklfreak/Robyul2/cache"
	"github.com/Seklfreak/Robyul2/helpers"
	"github.com/Seklfreak/Robyul2/models"
	"github.com/bwmarrin/discordgo"
	"github.com/globalsign/mgo/bson"
	"github.com/sirupsen/logrus"
)

type namesAction func(args []string, in *discordgo.Message, out **discordgo.MessageSend) (next namesAction)

type Names struct{}

var (
	previousNicknames      map[string]map[string]string
	previousNicknamesMutex sync.RWMutex
	previousUsernames      map[string]string
	previousUsernamesMutex sync.RWMutex
)

func (n *Names) Commands() []string {
	return []string{
		"names",
		"nicknames",
	}
}

// TODO: switch to robyul state

func (n *Names) Init(session *discordgo.Session) {
	previousNicknamesMutex.Lock()
	previousNicknames = make(map[string]map[string]string, 0)
	previousNicknamesMutex.Unlock()
	previousUsernamesMutex.Lock()
	previousUsernames = make(map[string]string, 0)
	previousUsernamesMutex.Unlock()
	session.AddHandler(n.OnGuildMemberListChunk)
	session.AddHandler(n.OnPresenceUpdate)
	session.AddHandler(n.OnGuildMemberUpdate)
}

func (n *Names) Action(command string, content string, msg *discordgo.Message, session *discordgo.Session) {
	if !helpers.ModuleIsAllowed(msg.ChannelID, msg.ID, msg.Author.ID, helpers.ModulePermNames) {
		return
	}

	session.ChannelTyping(msg.ChannelID)

	var result *discordgo.MessageSend
	args := strings.Fields(content)

	action := n.actionStart
	for action != nil {
		action = action(args, msg, &result)
	}
}

func (n *Names) actionStart(args []string, in *discordgo.Message, out **discordgo.MessageSend) namesAction {
	cache.GetSession().ChannelTyping(in.ChannelID)

	if len(args) < 1 {
		*out = n.newMsg(helpers.GetText("bot.arguments.too-few"))
		return n.actionFinish
	}

	return n.actionNames
}

func (n *Names) actionNames(args []string, in *discordgo.Message, out **discordgo.MessageSend) namesAction {
	user, err := helpers.GetUserFromMention(args[0])
	if err != nil || user == nil || user.ID == "" {
		*out = n.newMsg(helpers.GetText("bot.arguments.invalid"))
		return n.actionFinish
	}
	channel, err := helpers.GetChannel(in.ChannelID)
	helpers.Relax(err)
	member, _ := helpers.GetGuildMember(channel.GuildID, user.ID)

	var pastUsernamesText, pastNicknamesText string

	pastUsernames, err := n.GetUsernames(user.ID)
	if err != nil && strings.Contains(err.Error(), "no username entries") {
		helpers.Relax(err)
	}

	if len(pastUsernames) <= 0 || pastUsernames[len(pastUsernames)-1] != user.Username+"#"+user.Discriminator {
		pastUsernames = append(pastUsernames, user.Username+"#"+user.Discriminator)
	}

	for i, pastUsername := range pastUsernames {
		pastUsernamesText += "`" + pastUsername + "`"
		if i < len(pastUsernames)-1 {
			pastUsernamesText += ", "
		}
		if i == len(pastUsernames) {
			pastUsernamesText += " and "
		}
	}

	if pastUsernamesText == "" {
		pastUsernamesText = "None"
	}

	pastNicknames, err := n.GetNicknames(channel.GuildID, user.ID)
	if err != nil && !strings.Contains(err.Error(), "no nickname entries") {
		helpers.Relax(err)
	}

	if member != nil && member.User != nil && member.User.ID != "" {
		if member.Nick != "" {
			if len(pastNicknames) <= 0 || pastNicknames[len(pastNicknames)-1] != member.Nick {
				pastNicknames = append(pastNicknames, member.Nick)
			}
		}
	}

	for i, pastNickname := range pastNicknames {
		pastNicknamesText += "`" + pastNickname + "`"
		if i < len(pastNicknames)-1 {
			pastNicknamesText += ", "
		}
		if i == len(pastNicknames) {
			pastNicknamesText += " and "
		}
	}

	if pastNicknamesText == "" {
		pastNicknamesText = "None"
	}

	resultText := helpers.GetTextF("plugins.names.list-result",
		user.Username, user.Discriminator, user.ID, pastUsernamesText, pastNicknamesText)
	for _, page := range helpers.Pagify(resultText, ",") {
		_, err := helpers.SendMessage(in.ChannelID, page)
		helpers.RelaxMessage(err, in.ChannelID, in.ID)
	}

	return nil
}

func (n *Names) OnPresenceUpdate(session *discordgo.Session, presence *discordgo.PresenceUpdate) {
	if presence.GuildID == "" || presence.User == nil || presence.User.ID == "" {
		return
	}

	go func() {
		defer helpers.Recover()
		if presence.Presence.User.Username != "" {
			err := n.UpdateUsername(presence.Presence.User.ID, presence.Presence.User.Username+"#"+presence.Presence.User.Discriminator)
			helpers.Relax(err)
		}
	}()
}

func (n *Names) OnGuildMemberUpdate(session *discordgo.Session, member *discordgo.GuildMemberUpdate) {
	if member.Member == nil {
		return
	}

	go func() {
		defer helpers.Recover()

		if member.Member.Nick != "" {
			err := n.UpdateNickname(member.Member.GuildID, member.Member.User.ID, member.Member.Nick)
			helpers.Relax(err)
		}
	}()
}

func (n *Names) UpdateNickname(guildID string, userID string, newNick string) (err error) {
	previousNicknamesMutex.Lock()
	defer previousNicknamesMutex.Unlock()
	var oldNick string
	if previousNicknames[guildID] == nil {
		previousNicknames[guildID] = make(map[string]string, 0)
	}
	oldNick, _ = previousNicknames[guildID][userID]

	lastSavedNickname, err := n.GetLastNickname(guildID, userID)
	if err != nil && !strings.Contains(err.Error(), "no nickname entry") {
		helpers.RelaxLog(err)
	}

	if oldNick != "" && lastSavedNickname != oldNick {
		err = n.SaveNickname(guildID, userID, oldNick)
		helpers.RelaxLog(err)
		lastSavedNickname = oldNick
	}

	if lastSavedNickname != newNick {
		err = n.SaveNickname(guildID, userID, newNick)
		previousNicknames[guildID][userID] = newNick
		return err
	}
	return nil
}

func (n *Names) UpdateUsername(userID string, newUsername string) (err error) {
	previousUsernamesMutex.Lock()
	defer previousUsernamesMutex.Unlock()
	var oldUsername string
	oldUsername, _ = previousUsernames[userID]

	lastSavedUsername, err := n.GetLastUsername(userID)
	if err != nil && !strings.Contains(err.Error(), "no username entry") {
		helpers.RelaxLog(err)
	}

	if oldUsername != "" && lastSavedUsername != oldUsername {
		err = n.SaveUsername(userID, oldUsername)
		helpers.RelaxLog(err)
		lastSavedUsername = oldUsername
	}

	if lastSavedUsername != newUsername {
		err = n.SaveUsername(userID, newUsername)
		previousUsernames[userID] = newUsername
		return err
	}
	return nil
}

func (n *Names) GetLastNickname(guildID string, userID string) (nickname string, err error) {
	var entryBucket models.NamesEntry
	err = helpers.MdbOneWithoutLogging(
		helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": userID, "guildid": guildID}).Sort("-changedat"),
		&entryBucket,
	)

	if err != nil {
		if strings.Contains(err.Error(), "not found") {
			return "", errors.New("no nickname entry")
		}
		return "", err
	}

	return entryBucket.Nickname, nil
}

func (n *Names) SaveNickname(guildID string, userID string, nickname string) (err error) {
	// don't store duplicates
	lastNickname, err := n.GetLastNickname(guildID, userID)
	if err == nil {
		if nickname == lastNickname {
			return nil
		}
	}
	// insert nickname
	_, err = helpers.MDbInsert(
		models.NamesTable,
		models.NamesEntry{
			ChangedAt: time.Now(),
			GuildID:   guildID,
			UserID:    userID,
			Nickname:  nickname,
			Username:  "",
		},
	)
	return err
}

func (n *Names) GetLastUsername(userID string) (username string, err error) {
	var entryBucket models.NamesEntry
	err = helpers.MdbOneWithoutLogging(
		helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": userID, "guildid": "global"}).Sort("-changedat"),
		&entryBucket,
	)

	if err != nil {
		if strings.Contains(err.Error(), "not found") {
			return "", errors.New("no username entry")
		}
		return "", err
	}

	return entryBucket.Username, nil
}

func (n *Names) SaveUsername(userID string, username string) (err error) {
	// don't store duplicates
	lastUsername, err := n.GetLastUsername(userID)
	if err == nil {
		if username == lastUsername {
			return nil
		}
	}
	// insert username
	_, err = helpers.MDbInsert(
		models.NamesTable,
		models.NamesEntry{
			ChangedAt: time.Now(),
			GuildID:   "global",
			UserID:    userID,
			Nickname:  "",
			Username:  username,
		},
	)
	return err
}

func (n *Names) GetNicknames(guildID string, userID string) (nicknames []string, err error) {
	var entryBucket []models.NamesEntry
	err = helpers.MDbIter(helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": userID, "guildid": guildID}).Sort("changedat")).All(&entryBucket)

	if err != nil {
		return nicknames, err
	}

	if entryBucket == nil || len(entryBucket) <= 0 {
		return nicknames, errors.New("no nickname entries")
	}

	for _, entry := range entryBucket {
		if len(nicknames) <= 0 || nicknames[len(nicknames)-1] != entry.Nickname {
			nicknames = append(nicknames, entry.Nickname)
		}
	}
	return nicknames, nil
}

func (n *Names) GetUsernames(userID string) (usernames []string, err error) {
	var entryBucket []models.NamesEntry
	err = helpers.MDbIter(helpers.MdbCollection(models.NamesTable).Find(bson.M{"userid": userID, "guildid": "global"}).Sort("changedat")).All(&entryBucket)

	if err != nil {
		return usernames, err
	}

	if entryBucket == nil || len(entryBucket) <= 0 {
		return usernames, errors.New("no username entries")
	}

	for _, entry := range entryBucket {
		if len(usernames) <= 0 || usernames[len(usernames)-1] != entry.Username {
			usernames = append(usernames, entry.Username)
		}
	}
	return usernames, nil
}

func (n *Names) OnGuildMemberListChunk(session *discordgo.Session, members *discordgo.GuildMembersChunk) {
	previousUsernamesMutex.Lock()
	previousNicknamesMutex.Lock()
	defer previousUsernamesMutex.Unlock()
	defer previousNicknamesMutex.Unlock()
	for _, member := range members.Members {
		previousUsernames[member.User.ID] = member.User.Username + "#" + member.User.Discriminator
		if member.Nick != "" {
			if previousNicknames[members.GuildID] == nil {
				previousNicknames[members.GuildID] = make(map[string]string, 0)
			}
			previousNicknames[members.GuildID][member.User.ID] = member.Nick
		}
	}
}

func (n *Names) actionFinish(args []string, in *discordgo.Message, out **discordgo.MessageSend) namesAction {
	_, err := helpers.SendComplex(in.ChannelID, *out)
	helpers.Relax(err)

	return nil
}

func (n *Names) newMsg(content string) *discordgo.MessageSend {
	return &discordgo.MessageSend{Content: helpers.GetText(content)}
}

func (n *Names) Relax(err error) {
	if err != nil {
		panic(err)
	}
}

func (n *Names) logger() *logrus.Entry {
	return cache.GetLogger().WithField("module", "names")
}
<|endoftext|>


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

package syntax

import "fmt"

type token uint

const (
	_ token = iota
	_EOF

	// names and literals
	_Name
	_Literal

	// operators and operations
	_Operator // excluding '*' (_Star)
	_AssignOp
	_IncOp
	_Assign
	_Define
	_Arrow
	_Star

	// delimitors
	_Lparen
	_Lbrack
	_Lbrace
	_Rparen
	_Rbrack
	_Rbrace
	_Comma
	_Semi
	_Colon
	_Dot
	_DotDotDot

	// keywords
	_Break
	_Case
	_Chan
	_Const
	_Continue
	_Default
	_Defer
	_Else
	_Fallthrough
	_For
	_Func
	_Go
	_Goto
	_If
	_Import
	_Interface
	_Map
	_Package
	_Range
	_Return
	_Select
	_Struct
	_Switch
	_Type
	_Var

	tokenCount
)

const (
	// for BranchStmt
	Break       = _Break
	Continue    = _Continue
	Fallthrough = _Fallthrough
	Goto        = _Goto

	// for CallStmt
	Go    = _Go
	Defer = _Defer
)

var tokstrings = [...]string{
	// source control
	_EOF: "EOF",

	// names and literals
	_Name:    "name",
	_Literal: "literal",

	// operators and operations
	_Operator: "op",
	_AssignOp: "op=",
	_IncOp:    "opop",
	_Assign:   "=",
	_Define:   ":=",
	_Arrow:    "<-",
	_Star:     "*",

	// delimitors
	_Lparen:    "(",
	_Lbrack:    "[",
	_Lbrace:    "{",
	_Rparen:    ")",
	_Rbrack:    "]",
	_Rbrace:    "}",
	_Comma:     ",",
	_Semi:      ";",
	_Colon:     ":",
	_Dot:       ".",
	_DotDotDot: "...",

	// keywords
	_Break:       "break",
	_Case:        "case",
	_Chan:        "chan",
	_Const:       "const",
	_Continue:    "continue",
	_Default:     "default",
	_Defer:       "defer",
	_Else:        "else",
	_Fallthrough: "fallthrough",
	_For:         "for",
	_Func:        "func",
	_Go:          "go",
	_Goto:        "goto",
	_If:          "if",
	_Import:      "import",
	_Interface:   "interface",
	_Map:         "map",
	_Package:     "package",
	_Range:       "range",
	_Return:      "return",
	_Select:      "select",
	_Struct:      "struct",
	_Switch:      "switch",
	_Type:        "type",
	_Var:         "var",
}

func (tok token) String() string {
	var s string
	if 0 <= tok && int(tok) < len(tokstrings) {
		s = tokstrings[tok]
	}
	if s == "" {
		s = fmt.Sprintf("<tok-%d>", tok)
	}
	return s
}

// Make sure we have at most 64 tokens so we can use them in a set.
const _ uint64 = 1 << (tokenCount - 1)

// contains reports whether tok is in tokset.
func contains(tokset uint64, tok token) bool {
	return tokset&(1<<tok) != 0
}

type LitKind uint

const (
	IntLit LitKind = iota
	FloatLit
	ImagLit
	RuneLit
	StringLit
)

type Operator uint

const (
	_    Operator = iota
	Def           // :=
	Not           // !
	Recv          // <-

	// precOrOr
	OrOr // ||

	// precAndAnd
	AndAnd // &&

	// precCmp
	Eql // ==
	Neq // !=
	Lss // <
	Leq // <=
	Gtr // >
	Geq // >=

	// precAdd
	Add // +
	Sub // -
	Or  // |
	Xor // ^

	// precMul
	Mul    // *
	Div    // /
	Rem    // %
	And    // &
	AndNot // &^
	Shl    // <<
	Shr    // >>
)

var opstrings = [...]string{
	// prec == 0
	Def:  ":", // : in :=
	Not:  "!",
	Recv: "<-",

	// precOrOr
	OrOr: "||",

	// precAndAnd
	AndAnd: "&&",

	// precCmp
	Eql: "==",
	Neq: "!=",
	Lss: "<",
	Leq: "<=",
	Gtr: ">",
	Geq: ">=",

	// precAdd
	Add: "+",
	Sub: "-",
	Or:  "|",
	Xor: "^",

	// precMul
	Mul:    "*",
	Div:    "/",
	Rem:    "%",
	And:    "&",
	AndNot: "&^",
	Shl:    "<<",
	Shr:    ">>",
}

func (op Operator) String() string {
	var s string
	if 0 <= op && int(op) < len(opstrings) {
		s = opstrings[op]
	}
	if s == "" {
		s = fmt.Sprintf("<op-%d>", op)
	}
	return s
}

// Operator precedences
const (
	_ = iota
	precOrOr
	precAndAnd
	precCmp
	precAdd
	precMul
)
<commit_msg>cmd/compile/internal/syntax: fix 'delimiters' spelling<commit_after>// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package syntax

import "fmt"

type token uint

const (
	_ token = iota
	_EOF

	// names and literals
	_Name
	_Literal

	// operators and operations
	_Operator // excluding '*' (_Star)
	_AssignOp
	_IncOp
	_Assign
	_Define
	_Arrow
	_Star

	// delimiters
	_Lparen
	_Lbrack
	_Lbrace
	_Rparen
	_Rbrack
	_Rbrace
	_Comma
	_Semi
	_Colon
	_Dot
	_DotDotDot

	// keywords
	_Break
	_Case
	_Chan
	_Const
	_Continue
	_Default
	_Defer
	_Else
	_Fallthrough
	_For
	_Func
	_Go
	_Goto
	_If
	_Import
	_Interface
	_Map
	_Package
	_Range
	_Return
	_Select
	_Struct
	_Switch
	_Type
	_Var

	tokenCount
)

const (
	// for BranchStmt
	Break       = _Break
	Continue    = _Continue
	Fallthrough = _Fallthrough
	Goto        = _Goto

	// for CallStmt
	Go    = _Go
	Defer = _Defer
)

var tokstrings = [...]string{
	// source control
	_EOF: "EOF",

	// names and literals
	_Name:    "name",
	_Literal: "literal",

	// operators and operations
	_Operator: "op",
	_AssignOp: "op=",
	_IncOp:    "opop",
	_Assign:   "=",
	_Define:   ":=",
	_Arrow:    "<-",
	_Star:     "*",

	// delimiters
	_Lparen:    "(",
	_Lbrack:    "[",
	_Lbrace:    "{",
	_Rparen:    ")",
	_Rbrack:    "]",
	_Rbrace:    "}",
	_Comma:     ",",
	_Semi:      ";",
	_Colon:     ":",
	_Dot:       ".",
	_DotDotDot: "...",

	// keywords
	_Break:       "break",
	_Case:        "case",
	_Chan:        "chan",
	_Const:       "const",
	_Continue:    "continue",
	_Default:     "default",
	_Defer:       "defer",
	_Else:        "else",
	_Fallthrough: "fallthrough",
	_For:         "for",
	_Func:        "func",
	_Go:          "go",
	_Goto:        "goto",
	_If:          "if",
	_Import:      "import",
	_Interface:   "interface",
	_Map:         "map",
	_Package:     "package",
	_Range:       "range",
	_Return:      "return",
	_Select:      "select",
	_Struct:      "struct",
	_Switch:      "switch",
	_Type:        "type",
	_Var:         "var",
}

func (tok token) String() string {
	var s string
	if 0 <= tok && int(tok) < len(tokstrings) {
		s = tokstrings[tok]
	}
	if s == "" {
		s = fmt.Sprintf("<tok-%d>", tok)
	}
	return s
}

// Make sure we have at most 64 tokens so we can use them in a set.
const _ uint64 = 1 << (tokenCount - 1)

// contains reports whether tok is in tokset.
func contains(tokset uint64, tok token) bool {
	return tokset&(1<<tok) != 0
}

type LitKind uint

const (
	IntLit LitKind = iota
	FloatLit
	ImagLit
	RuneLit
	StringLit
)

type Operator uint

const (
	_    Operator = iota
	Def           // :=
	Not           // !
	Recv          // <-

	// precOrOr
	OrOr // ||

	// precAndAnd
	AndAnd // &&

	// precCmp
	Eql // ==
	Neq // !=
	Lss // <
	Leq // <=
	Gtr // >
	Geq // >=

	// precAdd
	Add // +
	Sub // -
	Or  // |
	Xor // ^

	// precMul
	Mul    // *
	Div    // /
	Rem    // %
	And    // &
	AndNot // &^
	Shl    // <<
	Shr    // >>
)

var opstrings = [...]string{
	// prec == 0
	Def:  ":", // : in :=
	Not:  "!",
	Recv: "<-",

	// precOrOr
	OrOr: "||",

	// precAndAnd
	AndAnd: "&&",

	// precCmp
	Eql: "==",
	Neq: "!=",
	Lss: "<",
	Leq: "<=",
	Gtr: ">",
	Geq: ">=",

	// precAdd
	Add: "+",
	Sub: "-",
	Or:  "|",
	Xor: "^",

	// precMul
	Mul:    "*",
	Div:    "/",
	Rem:    "%",
	And:    "&",
	AndNot: "&^",
	Shl:    "<<",
	Shr:    ">>",
}

func (op Operator) String() string {
	var s string
	if 0 <= op && int(op) < len(opstrings) {
		s = opstrings[op]
	}
	if s == "" {
		s = fmt.Sprintf("<op-%d>", op)
	}
	return s
}

// Operator precedences
const (
	_ = iota
	precOrOr
	precAndAnd
	precCmp
	precAdd
	precMul
)
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 bannedapi

import (
	"path/filepath"
	"strings"
	"testing"

	"golang.org/x/tools/go/analysis/analysistest"
)

func TestBannedAPIAnalyzer(t *testing.T) {
	for _, test := range []struct {
		desc  string
		files map[string]string
	}{
		{
			desc: "No banned APIs",
			files: map[string]string{
				"config.json": `
				{}
				`,
				"main/test.go": `
				package main;
				func main() {}
				`,
			},
		},
		{
			desc: "Banned APIs exist",
			files: map[string]string{
				"config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A"
						}
					],
					"imports": [
						{
							"name": "fmt",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import "fmt" // want "Banned API found \"fmt\". Additional info: Banned by team A"

				func main() {
					fmt.Printf("Hello") // want "Banned API found \"fmt.Printf\". Additional info: Banned by team A"
				}
				`,
			},
		},
		{
			desc: "Banned APIs in exempted package",
			files: map[string]string{
				"config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A",
							"exemptions": [
								{
									"justification": "#yolo",
									"allowedPkg": "main"
								}
							]
						}
					],
					"imports": [
						{
							"name": "fmt",
							"msg": "Banned by team A",
							"exemptions": [
								{
									"justification": "#yolo",
									"allowedPkg": "main"
								}
							]
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import "fmt"

				func main() {
					fmt.Printf("Hello")
				}
				`,
			},
		},
		{
			desc: "Banned renamed import",
			files: map[string]string{
				"config.json": `
				{
					"imports": [
						{
							"name": "fmt",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import renamed "fmt" // want "Banned API found \"fmt\". Additional info: Banned by team A"

				func main() {
					renamed.Printf("Hello")
				}
				`,
			},
		},
		{
			desc: "Banned function from renamed import",
			files: map[string]string{
				"config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import renamed "fmt"

				func main() {
					renamed.Printf("Hello") // want "Banned API found \"fmt.Printf\". Additional info: Banned by team A"
				}
				`,
			},
		},
		{
			desc: "Package and function name collission",
			files: map[string]string{
				"config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				type Foo struct{}

				func (f *Foo) Printf(txt string) {}

				func main() {
					var fmt = &Foo{}
					fmt.Printf("Hello")
				}
				`,
			},
		},
		{
			desc: "Banned API from multiple config files",
			files: map[string]string{
				"team_a_config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"team_b_config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team B"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import "fmt"

				func main() {
					fmt.Printf("Hello") // want "Banned API found \"fmt.Printf\". Additional info: Banned by team A" "Banned API found \"fmt.Printf\". Additional info: Banned by team B"
				}
				`,
			},
		},
		{
			desc: "Banned API in one of many config files",
			files: map[string]string{
				"team_a_config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A",
							"exemptions": [
								{
									"justification": "#yolo",
									"allowedPkg": "main"
								}
							]
						}
					]
				}
				`,
				"team_b_config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team B for realz"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import "fmt"

				func main() {
					fmt.Printf("Hello") // want "Banned API found \"fmt.Printf\". Additional info: Banned by team B for realz"
				}
				`,
			},
		},
	} {
		t.Run(test.desc, func(t *testing.T) {
			dir, cleanup, err := analysistest.WriteFiles(test.files)
			if err != nil {
				t.Fatalf("WriteFiles() returned err: %v", err)
			}
			defer cleanup()

			var configFiles []string
			for name := range test.files {
				if strings.HasSuffix(name, "config.json") {
					configFiles = append(configFiles, filepath.Join(dir, "src", name))
				}
			}

			a := NewAnalyzer()
			a.Flags.Set("configs", strings.Join(configFiles, ","))
			analysistest.Run(t, dir, a, "main")
		})
	}
}
<commit_msg>Speed up bancheck tests.<commit_after>// Copyright 2020 Google LLC
//
// 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
//
// 	https://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 bannedapi

import (
	"path/filepath"
	"strings"
	"testing"

	"golang.org/x/tools/go/analysis/analysistest"
)

func TestBannedAPIAnalyzer(t *testing.T) {
	t.Parallel()
	tests := []struct {
		desc  string
		files map[string]string
	}{
		{
			desc: "No banned APIs",
			files: map[string]string{
				"config.json": `
				{}
				`,
				"main/test.go": `
				package main;
				func main() {}
				`,
			},
		},
		{
			desc: "Banned APIs exist",
			files: map[string]string{
				"config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A"
						}
					],
					"imports": [
						{
							"name": "fmt",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import "fmt" // want "Banned API found \"fmt\". Additional info: Banned by team A"

				func main() {
					fmt.Printf("Hello") // want "Banned API found \"fmt.Printf\". Additional info: Banned by team A"
				}
				`,
			},
		},
		{
			desc: "Banned APIs in exempted package",
			files: map[string]string{
				"config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A",
							"exemptions": [
								{
									"justification": "#yolo",
									"allowedPkg": "main"
								}
							]
						}
					],
					"imports": [
						{
							"name": "fmt",
							"msg": "Banned by team A",
							"exemptions": [
								{
									"justification": "#yolo",
									"allowedPkg": "main"
								}
							]
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import "fmt"

				func main() {
					fmt.Printf("Hello")
				}
				`,
			},
		},
		{
			desc: "Banned renamed import",
			files: map[string]string{
				"config.json": `
				{
					"imports": [
						{
							"name": "fmt",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import renamed "fmt" // want "Banned API found \"fmt\". Additional info: Banned by team A"

				func main() {
					renamed.Printf("Hello")
				}
				`,
			},
		},
		{
			desc: "Banned function from renamed import",
			files: map[string]string{
				"config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import renamed "fmt"

				func main() {
					renamed.Printf("Hello") // want "Banned API found \"fmt.Printf\". Additional info: Banned by team A"
				}
				`,
			},
		},
		{
			desc: "Package and function name collission",
			files: map[string]string{
				"config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				type Foo struct{}

				func (f *Foo) Printf(txt string) {}

				func main() {
					var fmt = &Foo{}
					fmt.Printf("Hello")
				}
				`,
			},
		},
		{
			desc: "Banned API from multiple config files",
			files: map[string]string{
				"team_a_config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A"
						}
					]
				}
				`,
				"team_b_config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team B"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import "fmt"

				func main() {
					fmt.Printf("Hello") // want "Banned API found \"fmt.Printf\". Additional info: Banned by team A" "Banned API found \"fmt.Printf\". Additional info: Banned by team B"
				}
				`,
			},
		},
		{
			desc: "Banned API in one of many config files",
			files: map[string]string{
				"team_a_config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team A",
							"exemptions": [
								{
									"justification": "#yolo",
									"allowedPkg": "main"
								}
							]
						}
					]
				}
				`,
				"team_b_config.json": `
				{
					"functions": [
						{
							"name": "fmt.Printf",
							"msg": "Banned by team B for realz"
						}
					]
				}
				`,
				"main/test.go": `
				package main

				import "fmt"

				func main() {
					fmt.Printf("Hello") // want "Banned API found \"fmt.Printf\". Additional info: Banned by team B for realz"
				}
				`,
			},
		},
	}

	for _, test := range tests {
		test := test
		t.Run(test.desc, func(t *testing.T) {
			t.Parallel()
			dir, cleanup, err := analysistest.WriteFiles(test.files)
			if err != nil {
				t.Fatalf("WriteFiles() returned err: %v", err)
			}
			defer cleanup()

			var configFiles []string
			for name := range test.files {
				if strings.HasSuffix(name, "config.json") {
					configFiles = append(configFiles, filepath.Join(dir, "src", name))
				}
			}

			a := NewAnalyzer()
			a.Flags.Set("configs", strings.Join(configFiles, ","))
			analysistest.Run(t, dir, a, "main")
		})
	}
}
<|endoftext|>


<commit_before>package hmm

import (
	"math"
	"testing"

	"github.com/akualab/gjoa/model"
	"github.com/akualab/narray"
)

// Test embedded hmm.

var (
	hmms2 *chain
	ms2   modelSet
)

func TestDebug(t *testing.T) {

	initChainFB2()
	t.Log("compute fb using package")
	hmms2.update()
	nq := hmms2.nq
	alpha2 := hmms2.alpha.At(nq-1, hmms2.ns[nq-1]-1, nobs-1)
	beta2 := hmms2.beta.At(0, 0, 0)

	t.Logf("alpha2:%f", alpha2)
	t.Logf("beta2:%f", beta2)

	// check log prob per obs calculated with alpha and beta
	delta := math.Abs(alpha2-beta2) / float64(nobs)
	if delta > 0.00001 {
		t.Fatalf("alphaLogProb:%f does not match betaLogProb:%f", alpha2, beta2)
	}

	ms2.reestimate()

}

func initChainFB2() {

	hmm0 := newHMM("model 0", 0, narray.New(nstates[0], nstates[0]),
		[]model.Scorer{nil, newScorer(0, 1), newScorer(0, 2), newScorer(0, 3), nil})

	hmm1 := newHMM("model 1", 1, narray.New(nstates[1], nstates[1]),
		[]model.Scorer{nil, newScorer(1, 1), newScorer(1, 2), nil})

	testScorer := func() scorer {
		return scorer{[]float64{math.Log(0.4), math.Log(0.2), math.Log(0.4)}}
	}
	hmm2 := newHMM("model 2", 2, narray.New(3, 3),
		[]model.Scorer{nil, testScorer(), nil})

	hmm3 := newHMM("model 3", 3, narray.New(4, 4),
		[]model.Scorer{nil, testScorer(), testScorer(), nil})

	hmm0.a.Set(.9, 0, 1)
	//	hmm0.a.Set(1, 0, 1)
	hmm0.a.Set(.1, 0, 4)
	hmm0.a.Set(.5, 1, 1)
	hmm0.a.Set(.5, 1, 2)
	hmm0.a.Set(.3, 2, 2)
	hmm0.a.Set(.6, 2, 3)
	hmm0.a.Set(.1, 2, 4)
	hmm0.a.Set(.7, 3, 3)
	hmm0.a.Set(.3, 3, 4)

	hmm1.a.Set(1, 0, 1)
	hmm1.a.Set(.3, 1, 1)
	hmm1.a.Set(.2, 1, 2)
	hmm1.a.Set(.5, 1, 3)
	hmm1.a.Set(.6, 2, 2)
	hmm1.a.Set(.4, 2, 3)

	hmm2.a.Set(1, 0, 1)
	hmm2.a.Set(0.5, 1, 1)
	hmm2.a.Set(0.5, 1, 2)

	hmm3.a.Set(1, 0, 1)
	hmm3.a.Set(0.5, 1, 1)
	hmm3.a.Set(0.5, 1, 2)
	hmm3.a.Set(0.5, 2, 2)
	hmm3.a.Set(0.5, 2, 3)

	hmm0.a = narray.Log(nil, hmm0.a.Copy())
	hmm1.a = narray.Log(nil, hmm1.a.Copy())
	hmm2.a = narray.Log(nil, hmm2.a.Copy())
	hmm3.a = narray.Log(nil, hmm3.a.Copy())

	xobs := make([]model.Obs, nobs, nobs)
	for k, v := range obs {
		xobs[k] = model.NewIntObs(v, model.NoLabel())
	}

	ms2 = make(modelSet)
	//	hmms2 = newChain(ms2, xobs, hmm1, hmm1,hmm2)
	hmms2 = newChain(ms2, xobs, hmm3, hmm0, hmm3, hmm0, hmm0, hmm0, hmm0, hmm3)
}
<commit_msg>Remove debug test.<commit_after><|endoftext|>


<commit_before>// Copyright 2014 The Prometheus 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 model

import (
	"runtime"
	"sync"
	"testing"
)

func TestLabelsToSignature(t *testing.T) {
	var scenarios = []struct {
		in  map[string]string
		out uint64
	}{
		{
			in:  map[string]string{},
			out: 14695981039346656037,
		},
		{
			in:  map[string]string{"name": "garland, briggs", "fear": "love is not enough"},
			out: 5799056148416392346,
		},
	}

	for i, scenario := range scenarios {
		actual := LabelsToSignature(scenario.in)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func TestMetricToFingerprint(t *testing.T) {
	var scenarios = []struct {
		in  LabelSet
		out Fingerprint
	}{
		{
			in:  LabelSet{},
			out: 14695981039346656037,
		},
		{
			in:  LabelSet{"name": "garland, briggs", "fear": "love is not enough"},
			out: 5799056148416392346,
		},
	}

	for i, scenario := range scenarios {
		actual := labelSetToFingerprint(scenario.in)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func TestMetricToFastFingerprint(t *testing.T) {
	var scenarios = []struct {
		in  LabelSet
		out Fingerprint
	}{
		{
			in:  LabelSet{},
			out: 14695981039346656037,
		},
		{
			in:  LabelSet{"name": "garland, briggs", "fear": "love is not enough"},
			out: 12952432476264840823,
		},
	}

	for i, scenario := range scenarios {
		actual := labelSetToFastFingerprint(scenario.in)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func TestSignatureForLabels(t *testing.T) {
	var scenarios = []struct {
		in     Metric
		labels LabelNames
		out    uint64
	}{
		{
			in:     Metric{},
			labels: nil,
			out:    14695981039346656037,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: LabelNames{"fear", "name"},
			out:    5799056148416392346,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"},
			labels: LabelNames{"fear", "name"},
			out:    5799056148416392346,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: LabelNames{},
			out:    14695981039346656037,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: nil,
			out:    14695981039346656037,
		},
	}

	for i, scenario := range scenarios {
		actual := SignatureForLabels(scenario.in, scenario.labels...)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func TestSignatureWithoutLabels(t *testing.T) {
	var scenarios = []struct {
		in     Metric
		labels map[LabelName]struct{}
		out    uint64
	}{
		{
			in:     Metric{},
			labels: nil,
			out:    14695981039346656037,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: map[LabelName]struct{}{"fear": struct{}{}, "name": struct{}{}},
			out:    14695981039346656037,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"},
			labels: map[LabelName]struct{}{"foo": struct{}{}},
			out:    5799056148416392346,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: map[LabelName]struct{}{},
			out:    5799056148416392346,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: nil,
			out:    5799056148416392346,
		},
	}

	for i, scenario := range scenarios {
		actual := SignatureWithoutLabels(scenario.in, scenario.labels)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func benchmarkLabelToSignature(b *testing.B, l map[string]string, e uint64) {
	for i := 0; i < b.N; i++ {
		if a := LabelsToSignature(l); a != e {
			b.Fatalf("expected signature of %d for %s, got %d", e, l, a)
		}
	}
}

func BenchmarkLabelToSignatureScalar(b *testing.B) {
	benchmarkLabelToSignature(b, nil, 14695981039346656037)
}

func BenchmarkLabelToSignatureSingle(b *testing.B) {
	benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value"}, 5146282821936882169)
}

func BenchmarkLabelToSignatureDouble(b *testing.B) {
	benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717)
}

func BenchmarkLabelToSignatureTriple(b *testing.B) {
	benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121)
}

func benchmarkMetricToFingerprint(b *testing.B, ls LabelSet, e Fingerprint) {
	for i := 0; i < b.N; i++ {
		if a := labelSetToFingerprint(ls); a != e {
			b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
		}
	}
}

func BenchmarkMetricToFingerprintScalar(b *testing.B) {
	benchmarkMetricToFingerprint(b, nil, 14695981039346656037)
}

func BenchmarkMetricToFingerprintSingle(b *testing.B) {
	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5146282821936882169)
}

func BenchmarkMetricToFingerprintDouble(b *testing.B) {
	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717)
}

func BenchmarkMetricToFingerprintTriple(b *testing.B) {
	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121)
}

func benchmarkMetricToFastFingerprint(b *testing.B, ls LabelSet, e Fingerprint) {
	for i := 0; i < b.N; i++ {
		if a := labelSetToFastFingerprint(ls); a != e {
			b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
		}
	}
}

func BenchmarkMetricToFastFingerprintScalar(b *testing.B) {
	benchmarkMetricToFastFingerprint(b, nil, 14695981039346656037)
}

func BenchmarkMetricToFastFingerprintSingle(b *testing.B) {
	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5147259542624943964)
}

func BenchmarkMetricToFastFingerprintDouble(b *testing.B) {
	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 18269973311206963528)
}

func BenchmarkMetricToFastFingerprintTriple(b *testing.B) {
	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676)
}

func TestEmptyLabelSignature(t *testing.T) {
	input := []map[string]string{nil, {}}

	var ms runtime.MemStats
	runtime.ReadMemStats(&ms)

	alloc := ms.Alloc

	for _, labels := range input {
		LabelsToSignature(labels)
	}

	runtime.ReadMemStats(&ms)

	if got := ms.Alloc; alloc != got {
		t.Fatal("expected LabelsToSignature with empty labels not to perform allocations")
	}
}

func benchmarkMetricToFastFingerprintConc(b *testing.B, ls LabelSet, e Fingerprint, concLevel int) {
	var start, end sync.WaitGroup
	start.Add(1)
	end.Add(concLevel)

	for i := 0; i < concLevel; i++ {
		go func() {
			start.Wait()
			for j := b.N / concLevel; j >= 0; j-- {
				if a := labelSetToFastFingerprint(ls); a != e {
					b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
				}
			}
			end.Done()
		}()
	}
	b.ResetTimer()
	start.Done()
	end.Wait()
}

func BenchmarkMetricToFastFingerprintTripleConc1(b *testing.B) {
	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 1)
}

func BenchmarkMetricToFastFingerprintTripleConc2(b *testing.B) {
	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 2)
}

func BenchmarkMetricToFastFingerprintTripleConc4(b *testing.B) {
	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 4)
}

func BenchmarkMetricToFastFingerprintTripleConc8(b *testing.B) {
	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 8)
}
<commit_msg>Turn allocation test into benchmark<commit_after>// Copyright 2014 The Prometheus 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 model

import (
	"runtime"
	"sync"
	"testing"
)

func TestLabelsToSignature(t *testing.T) {
	var scenarios = []struct {
		in  map[string]string
		out uint64
	}{
		{
			in:  map[string]string{},
			out: 14695981039346656037,
		},
		{
			in:  map[string]string{"name": "garland, briggs", "fear": "love is not enough"},
			out: 5799056148416392346,
		},
	}

	for i, scenario := range scenarios {
		actual := LabelsToSignature(scenario.in)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func TestMetricToFingerprint(t *testing.T) {
	var scenarios = []struct {
		in  LabelSet
		out Fingerprint
	}{
		{
			in:  LabelSet{},
			out: 14695981039346656037,
		},
		{
			in:  LabelSet{"name": "garland, briggs", "fear": "love is not enough"},
			out: 5799056148416392346,
		},
	}

	for i, scenario := range scenarios {
		actual := labelSetToFingerprint(scenario.in)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func TestMetricToFastFingerprint(t *testing.T) {
	var scenarios = []struct {
		in  LabelSet
		out Fingerprint
	}{
		{
			in:  LabelSet{},
			out: 14695981039346656037,
		},
		{
			in:  LabelSet{"name": "garland, briggs", "fear": "love is not enough"},
			out: 12952432476264840823,
		},
	}

	for i, scenario := range scenarios {
		actual := labelSetToFastFingerprint(scenario.in)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func TestSignatureForLabels(t *testing.T) {
	var scenarios = []struct {
		in     Metric
		labels LabelNames
		out    uint64
	}{
		{
			in:     Metric{},
			labels: nil,
			out:    14695981039346656037,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: LabelNames{"fear", "name"},
			out:    5799056148416392346,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"},
			labels: LabelNames{"fear", "name"},
			out:    5799056148416392346,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: LabelNames{},
			out:    14695981039346656037,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: nil,
			out:    14695981039346656037,
		},
	}

	for i, scenario := range scenarios {
		actual := SignatureForLabels(scenario.in, scenario.labels...)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func TestSignatureWithoutLabels(t *testing.T) {
	var scenarios = []struct {
		in     Metric
		labels map[LabelName]struct{}
		out    uint64
	}{
		{
			in:     Metric{},
			labels: nil,
			out:    14695981039346656037,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: map[LabelName]struct{}{"fear": struct{}{}, "name": struct{}{}},
			out:    14695981039346656037,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough", "foo": "bar"},
			labels: map[LabelName]struct{}{"foo": struct{}{}},
			out:    5799056148416392346,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: map[LabelName]struct{}{},
			out:    5799056148416392346,
		},
		{
			in:     Metric{"name": "garland, briggs", "fear": "love is not enough"},
			labels: nil,
			out:    5799056148416392346,
		},
	}

	for i, scenario := range scenarios {
		actual := SignatureWithoutLabels(scenario.in, scenario.labels)

		if actual != scenario.out {
			t.Errorf("%d. expected %d, got %d", i, scenario.out, actual)
		}
	}
}

func benchmarkLabelToSignature(b *testing.B, l map[string]string, e uint64) {
	for i := 0; i < b.N; i++ {
		if a := LabelsToSignature(l); a != e {
			b.Fatalf("expected signature of %d for %s, got %d", e, l, a)
		}
	}
}

func BenchmarkLabelToSignatureScalar(b *testing.B) {
	benchmarkLabelToSignature(b, nil, 14695981039346656037)
}

func BenchmarkLabelToSignatureSingle(b *testing.B) {
	benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value"}, 5146282821936882169)
}

func BenchmarkLabelToSignatureDouble(b *testing.B) {
	benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717)
}

func BenchmarkLabelToSignatureTriple(b *testing.B) {
	benchmarkLabelToSignature(b, map[string]string{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121)
}

func benchmarkMetricToFingerprint(b *testing.B, ls LabelSet, e Fingerprint) {
	for i := 0; i < b.N; i++ {
		if a := labelSetToFingerprint(ls); a != e {
			b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
		}
	}
}

func BenchmarkMetricToFingerprintScalar(b *testing.B) {
	benchmarkMetricToFingerprint(b, nil, 14695981039346656037)
}

func BenchmarkMetricToFingerprintSingle(b *testing.B) {
	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5146282821936882169)
}

func BenchmarkMetricToFingerprintDouble(b *testing.B) {
	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 3195800080984914717)
}

func BenchmarkMetricToFingerprintTriple(b *testing.B) {
	benchmarkMetricToFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 13843036195897128121)
}

func benchmarkMetricToFastFingerprint(b *testing.B, ls LabelSet, e Fingerprint) {
	for i := 0; i < b.N; i++ {
		if a := labelSetToFastFingerprint(ls); a != e {
			b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
		}
	}
}

func BenchmarkMetricToFastFingerprintScalar(b *testing.B) {
	benchmarkMetricToFastFingerprint(b, nil, 14695981039346656037)
}

func BenchmarkMetricToFastFingerprintSingle(b *testing.B) {
	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value"}, 5147259542624943964)
}

func BenchmarkMetricToFastFingerprintDouble(b *testing.B) {
	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value"}, 18269973311206963528)
}

func BenchmarkMetricToFastFingerprintTriple(b *testing.B) {
	benchmarkMetricToFastFingerprint(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676)
}

func BenchmarkEmptyLabelSignature(b *testing.B) {
	input := []map[string]string{nil, {}}

	var ms runtime.MemStats
	runtime.ReadMemStats(&ms)

	alloc := ms.Alloc

	for _, labels := range input {
		LabelsToSignature(labels)
	}

	runtime.ReadMemStats(&ms)

	if got := ms.Alloc; alloc != got {
		b.Fatal("expected LabelsToSignature with empty labels not to perform allocations")
	}
}

func benchmarkMetricToFastFingerprintConc(b *testing.B, ls LabelSet, e Fingerprint, concLevel int) {
	var start, end sync.WaitGroup
	start.Add(1)
	end.Add(concLevel)

	for i := 0; i < concLevel; i++ {
		go func() {
			start.Wait()
			for j := b.N / concLevel; j >= 0; j-- {
				if a := labelSetToFastFingerprint(ls); a != e {
					b.Fatalf("expected signature of %d for %s, got %d", e, ls, a)
				}
			}
			end.Done()
		}()
	}
	b.ResetTimer()
	start.Done()
	end.Wait()
}

func BenchmarkMetricToFastFingerprintTripleConc1(b *testing.B) {
	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 1)
}

func BenchmarkMetricToFastFingerprintTripleConc2(b *testing.B) {
	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 2)
}

func BenchmarkMetricToFastFingerprintTripleConc4(b *testing.B) {
	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 4)
}

func BenchmarkMetricToFastFingerprintTripleConc8(b *testing.B) {
	benchmarkMetricToFastFingerprintConc(b, LabelSet{"first-label": "first-label-value", "second-label": "second-label-value", "third-label": "third-label-value"}, 15738406913934009676, 8)
}
<|endoftext|>


<commit_before>package survey

import (
	"database/sql"
	"errors"
	"github.com/curt-labs/GoSurvey/helpers/database"
	_ "github.com/go-sql-driver/mysql"
	"time"
)

var (
	getAllSurveys = `select id, name, description,
										date_added, date_modifed, userID, deleted
										from Survey
										where deleted = 0
										order by date_modifed desc`
	getSurvey = `select id, name, description,
										date_added, date_modifed, userID, deleted
										from Survey
										where id = ? && deleted = 0 limit 1`
	getSurveyRevisions = `select
												sv.ID as revisionID, sv.new_name, sv.old_name,
												sv.date, sv.changeType,
												u.id as userID, u.fname, u.lname, u.username
												from Survey_Revisions as sv
												join admin.user as u on sv.userID = u.id
												where surveyID = ?
												order by date desc`
	insertSurvey = `insert into Survey(name, description, date_added, userID)
									values(?,?,NOW(), ?)`
	updateSurvey = `update Survey set name = ?, description = ?, userID = ?
									where surveyID = ?`
	deleteSurvey = `update Survey set deleted = 1, userID = ? where surveyID = ?`
)

type Survey struct {
	ID           int              `json:"id"`
	Name         string           `json:"name"`
	Description  string           `json:"description"`
	DateAdded    time.Time        `json:"date_added"`
	DateModified time.Time        `json:"date_modified"`
	UserID       int              `json:"-"`
	Deleted      bool             `json:"-"`
	Revisions    []SurveyRevision `json:"revisions"`
	Questions    []Question       `json:"questions"`
	Completion   SurveyStatus     `json:"-"`
}

type SurveyStatus struct {
	Completed     bool `json:"completed"`
	QuestionCount int  `json:"question_count"`
}

type SurveyRevision struct {
	ID         int          `json:"id"`
	NewName    *string      `json:"new_name"`
	OldName    *string      `json:"old_name"`
	Date       time.Time    `json:"date"`
	ChangeType string       `json:"change_type"`
	User       RevisionUser `json:"user"`
}

type RevisionUser struct {
	ID        int    `json:"id"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Username  string `json:"username"`
}

// GetSurveys will return a list of surveys in
// the database or an error if empty.
func GetSurveys() ([]Survey, error) {

	svs := make([]Survey, 0)
	var err error

	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return svs, err
	}

	defer db.Close()

	stmt, err := db.Prepare(getAllSurveys)
	if err != nil {
		return svs, err
	}

	defer stmt.Close()

	res, err := stmt.Query()
	if err != nil {
		return svs, err
	}

	for res.Next() {
		var sv Survey
		err = res.Scan(&sv.ID, &sv.Name, &sv.Description, &sv.DateAdded, &sv.DateModified, &sv.UserID, &sv.Deleted)
		if err == nil {
			if err = sv.revisions(); err != nil {
				panic(err)
			}
			svs = append(svs, sv)
		}
	}

	return svs, err
}

// Get will update the values on the bound
// Survey or return an error.
func (s *Survey) Get() error {
	var err error

	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}

	defer db.Close()

	stmt, err := db.Prepare(getSurvey)
	if err != nil {
		return err
	}

	defer stmt.Close()

	id := s.ID
	s.ID = 0
	stmt.QueryRow(id).Scan(&s.ID, &s.Name, &s.Description, &s.DateAdded, &s.DateModified, &s.UserID, &s.Deleted)
	if s.ID == 0 {
		return errors.New("no survey found")
	}

	return s.revisions()
}

// revisions will assign revision
// history to the bound Survey.
func (s *Survey) revisions() error {
	var err error

	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}

	defer db.Close()

	stmt, err := db.Prepare(getSurveyRevisions)
	if err != nil {
		return err
	}

	defer stmt.Close()

	res, err := stmt.Query(s.ID)
	if err != nil {
		return err
	}

	for res.Next() {
		var r SurveyRevision
		err = res.Scan(&r.ID, &r.NewName, &r.OldName, &r.Date, &r.ChangeType,
			&r.User.ID, &r.User.FirstName, &r.User.LastName,
			&r.User.Username)
		if err == nil {
			s.Revisions = append(s.Revisions, r)
		}
	}

	return nil
}

// Add will commit the current Survey
// to the database.
func (s *Survey) Save() error {

	if s.Name == "" {
		return errors.New("survey name cannot be blank")
	}

	if s.UserID == 0 {
		return errors.New("invalid user reference")
	}

	if s.ID == 0 {
		return s.insert()
	}
	return s.update()
}

// insert will insert a new survey record.
func (s *Survey) insert() error {
	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}
	defer db.Close()

	stmt, err := db.Prepare(insertSurvey)
	if err != nil {
		return err
	}
	defer stmt.Close()

	res, err := stmt.Exec(s.Name, s.Description, s.UserID)
	if err != nil {
		return err
	}

	id, err := res.LastInsertId()
	if err != nil {
		return err
	}

	s.ID = int(id)

	return nil
}

// update will update an existing survey
// record.
func (s *Survey) update() error {
	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}
	defer db.Close()

	stmt, err := db.Prepare(updateSurvey)
	if err != nil {
		return err
	}
	defer stmt.Close()

	_, err = stmt.Exec(s.Name, s.Description, s.UserID, s.ID)

	return err
}

// Delete will remove (mark as deleted) a Survey
// from the list of returned results
func (s *Survey) Delete() error {
	if s.ID == 0 {
		return errors.New("invalid survey record")
	}

	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}
	defer db.Close()

	stmt, err := db.Prepare(deleteSurvey)
	if err != nil {
		return err
	}
	defer stmt.Close()

	_, err = stmt.Exec(s.UserID, s.ID)

	return err
}
<commit_msg>fixed bad where clause<commit_after>package survey

import (
	"database/sql"
	"errors"
	"github.com/curt-labs/GoSurvey/helpers/database"
	_ "github.com/go-sql-driver/mysql"
	"time"
)

var (
	getAllSurveys = `select id, name, description,
										date_added, date_modifed, userID, deleted
										from Survey
										where deleted = 0
										order by date_modifed desc`
	getSurvey = `select id, name, description,
										date_added, date_modifed, userID, deleted
										from Survey
										where id = ? && deleted = 0 limit 1`
	getSurveyRevisions = `select
												sv.ID as revisionID, sv.new_name, sv.old_name,
												sv.date, sv.changeType,
												u.id as userID, u.fname, u.lname, u.username
												from Survey_Revisions as sv
												join admin.user as u on sv.userID = u.id
												where sv.surveyID = ?
												order by date desc`
	insertSurvey = `insert into Survey(name, description, date_added, userID)
									values(?,?,NOW(), ?)`
	updateSurvey = `update Survey set name = ?, description = ?, userID = ?
									where id = ?`
	deleteSurvey = `update Survey set deleted = 1, userID = ? where id = ?`
)

type Survey struct {
	ID           int              `json:"id"`
	Name         string           `json:"name"`
	Description  string           `json:"description"`
	DateAdded    time.Time        `json:"date_added"`
	DateModified time.Time        `json:"date_modified"`
	UserID       int              `json:"-"`
	Deleted      bool             `json:"-"`
	Revisions    []SurveyRevision `json:"revisions"`
	Questions    []Question       `json:"questions"`
	Completion   SurveyStatus     `json:"-"`
}

type SurveyStatus struct {
	Completed     bool `json:"completed"`
	QuestionCount int  `json:"question_count"`
}

type SurveyRevision struct {
	ID         int          `json:"id"`
	NewName    *string      `json:"new_name"`
	OldName    *string      `json:"old_name"`
	Date       time.Time    `json:"date"`
	ChangeType string       `json:"change_type"`
	User       RevisionUser `json:"user"`
}

type RevisionUser struct {
	ID        int    `json:"id"`
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Username  string `json:"username"`
}

// GetSurveys will return a list of surveys in
// the database or an error if empty.
func GetSurveys() ([]Survey, error) {

	svs := make([]Survey, 0)
	var err error

	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return svs, err
	}

	defer db.Close()

	stmt, err := db.Prepare(getAllSurveys)
	if err != nil {
		return svs, err
	}

	defer stmt.Close()

	res, err := stmt.Query()
	if err != nil {
		return svs, err
	}

	for res.Next() {
		var sv Survey
		err = res.Scan(&sv.ID, &sv.Name, &sv.Description, &sv.DateAdded, &sv.DateModified, &sv.UserID, &sv.Deleted)
		if err == nil {
			if err = sv.revisions(); err != nil {
				panic(err)
			}
			svs = append(svs, sv)
		}
	}

	return svs, err
}

// Get will update the values on the bound
// Survey or return an error.
func (s *Survey) Get() error {
	var err error

	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}

	defer db.Close()

	stmt, err := db.Prepare(getSurvey)
	if err != nil {
		return err
	}

	defer stmt.Close()

	id := s.ID
	s.ID = 0
	stmt.QueryRow(id).Scan(&s.ID, &s.Name, &s.Description, &s.DateAdded, &s.DateModified, &s.UserID, &s.Deleted)
	if s.ID == 0 {
		return errors.New("no survey found")
	}

	return s.revisions()
}

// revisions will assign revision
// history to the bound Survey.
func (s *Survey) revisions() error {
	var err error

	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}

	defer db.Close()

	stmt, err := db.Prepare(getSurveyRevisions)
	if err != nil {
		return err
	}

	defer stmt.Close()

	res, err := stmt.Query(s.ID)
	if err != nil {
		return err
	}

	for res.Next() {
		var r SurveyRevision
		err = res.Scan(&r.ID, &r.NewName, &r.OldName, &r.Date, &r.ChangeType,
			&r.User.ID, &r.User.FirstName, &r.User.LastName,
			&r.User.Username)
		if err == nil {
			s.Revisions = append(s.Revisions, r)
		}
	}

	return nil
}

// Add will commit the current Survey
// to the database.
func (s *Survey) Save() error {

	if s.Name == "" {
		return errors.New("survey name cannot be blank")
	}

	if s.UserID == 0 {
		return errors.New("invalid user reference")
	}

	if s.ID == 0 {
		return s.insert()
	}
	return s.update()
}

// insert will insert a new survey record.
func (s *Survey) insert() error {
	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}
	defer db.Close()

	stmt, err := db.Prepare(insertSurvey)
	if err != nil {
		return err
	}
	defer stmt.Close()

	res, err := stmt.Exec(s.Name, s.Description, s.UserID)
	if err != nil {
		return err
	}

	id, err := res.LastInsertId()
	if err != nil {
		return err
	}

	s.ID = int(id)

	return nil
}

// update will update an existing survey
// record.
func (s *Survey) update() error {
	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}
	defer db.Close()

	stmt, err := db.Prepare(updateSurvey)
	if err != nil {
		return err
	}
	defer stmt.Close()

	_, err = stmt.Exec(s.Name, s.Description, s.UserID, s.ID)

	return err
}

// Delete will remove (mark as deleted) a Survey
// from the list of returned results
func (s *Survey) Delete() error {
	if s.ID == 0 {
		return errors.New("invalid survey record")
	}

	db, err := sql.Open("mysql", database.ConnectionString())
	if err != nil {
		return err
	}
	defer db.Close()

	stmt, err := db.Prepare(deleteSurvey)
	if err != nil {
		return err
	}
	defer stmt.Close()

	_, err = stmt.Exec(s.UserID, s.ID)

	return err
}
<|endoftext|>