<commit_before>package lfs

import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/vendor/_nuts/github.com/ThomsonReutersEikon/go-ntlm/ntlm"
	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

var (
	Config        = NewConfig()
	defaultRemote = "origin"
)

// FetchPruneConfig collects together the config options that control fetching and pruning
type FetchPruneConfig struct {
	// The number of days prior to current date for which (local) refs other than HEAD
	// will be fetched with --recent (default 7, 0 = only fetch HEAD)
	FetchRecentRefsDays int
	// Makes the FetchRecentRefsDays option apply to remote refs from fetch source as well (default true)
	FetchRecentRefsIncludeRemotes bool
	// number of days prior to latest commit on a ref that we'll fetch previous
	// LFS changes too (default 0 = only fetch at ref)
	FetchRecentCommitsDays int
	// Whether to always fetch recent even without --recent
	FetchRecentAlways bool
	// Number of days added to FetchRecent*; data outside combined window will be
	// deleted when prune is run. (default 3)
	PruneOffsetDays int
	// Always verify with remote before pruning
	PruneVerifyRemoteAlways bool
	// Name of remote to check for unpushed and verify checks
	PruneRemoteName string
}

type Configuration struct {
	CurrentRemote         string
	httpClient            *HttpClient
	redirectingHttpClient *http.Client
	ntlmSession           ntlm.ClientSession
	envVars               map[string]string
	isTracingHttp         bool
	isLoggingStats        bool

	loading           sync.Mutex // guards initialization of gitConfig and remotes
	gitConfig         map[string]string
	origConfig        map[string]string
	remotes           []string
	extensions        map[string]Extension
	fetchIncludePaths []string
	fetchExcludePaths []string
	fetchPruneConfig  *FetchPruneConfig
}

func NewConfig() *Configuration {
	c := &Configuration{
		CurrentRemote: defaultRemote,
		envVars:       make(map[string]string),
	}
	c.isTracingHttp = c.GetenvBool("GIT_CURL_VERBOSE", false)
	c.isLoggingStats = c.GetenvBool("GIT_LOG_STATS", false)
	return c
}

func (c *Configuration) Getenv(key string) string {
	if i, ok := c.envVars[key]; ok {
		return i
	}

	v := os.Getenv(key)
	c.envVars[key] = v
	return v
}

func (c *Configuration) Setenv(key, value string) error {
	// Check see if we have this in our cache, if so update it
	if _, ok := c.envVars[key]; ok {
		c.envVars[key] = value
	}

	// Now set in process
	return os.Setenv(key, value)
}

// GetenvBool parses a boolean environment variable and returns the result as a bool.
// If the environment variable is unset, empty, or if the parsing fails,
// the value of def (default) is returned instead.
func (c *Configuration) GetenvBool(key string, def bool) bool {
	s := c.Getenv(key)
	if len(s) == 0 {
		return def
	}

	b, err := parseConfigBool(s)
	if err != nil {
		return def
	}
	return b
}

func (c *Configuration) Endpoint() Endpoint {
	if url, ok := c.GitConfig("lfs.url"); ok {
		return NewEndpoint(url)
	}

	if len(c.CurrentRemote) > 0 && c.CurrentRemote != defaultRemote {
		if endpoint := c.RemoteEndpoint(c.CurrentRemote); len(endpoint.Url) > 0 {
			return endpoint
		}
	}

	return c.RemoteEndpoint(defaultRemote)
}

func (c *Configuration) ConcurrentTransfers() int {
	if c.NtlmAccess() {
		return 1
	}

	uploads := 3

	if v, ok := c.GitConfig("lfs.concurrenttransfers"); ok {
		n, err := strconv.Atoi(v)
		if err == nil && n > 0 {
			uploads = n
		}
	}

	return uploads
}

func (c *Configuration) BatchTransfer() bool {
	value, ok := c.GitConfig("lfs.batch")
	if !ok || len(value) == 0 {
		return true
	}

	useBatch, err := parseConfigBool(value)
	if err != nil {
		return false
	}

	return useBatch
}

func (c *Configuration) NtlmAccess() bool {
	return c.Access() == "ntlm"
}

// PrivateAccess will retrieve the access value and return true if
// the value is set to private. When a repo is marked as having private
// access, the http requests for the batch api will fetch the credentials
// before running, otherwise the request will run without credentials.
func (c *Configuration) PrivateAccess() bool {
	return c.Access() != "none"
}

// Access returns the access auth type.
func (c *Configuration) Access() string {
	return c.EndpointAccess(c.Endpoint())
}

// SetAccess will set the private access flag in .git/config.
func (c *Configuration) SetAccess(authType string) {
	c.SetEndpointAccess(c.Endpoint(), authType)
}

func (c *Configuration) EndpointAccess(e Endpoint) string {
	key := fmt.Sprintf("lfs.%s.access", e.Url)
	if v, ok := c.GitConfig(key); ok && len(v) > 0 {
		lower := strings.ToLower(v)
		if lower == "private" {
			return "basic"
		}
		return lower
	}
	return "none"
}

func (c *Configuration) SetEndpointAccess(e Endpoint, authType string) {
	tracerx.Printf("setting repository access to %s", authType)
	key := fmt.Sprintf("lfs.%s.access", e.Url)

	// Modify the config cache because it's checked again in this process
	// without being reloaded.
	switch authType {
	case "", "none":
		git.Config.UnsetLocalKey("", key)

		c.loading.Lock()
		delete(c.gitConfig, strings.ToLower(key))
		c.loading.Unlock()
	default:
		git.Config.SetLocal("", key, authType)

		c.loading.Lock()
		c.gitConfig[strings.ToLower(key)] = authType
		c.loading.Unlock()
	}
}

func (c *Configuration) FetchIncludePaths() []string {
	c.loadGitConfig()
	return c.fetchIncludePaths
}
func (c *Configuration) FetchExcludePaths() []string {
	c.loadGitConfig()
	return c.fetchExcludePaths
}

func (c *Configuration) RemoteEndpoint(remote string) Endpoint {
	if len(remote) == 0 {
		remote = defaultRemote
	}
	if url, ok := c.GitConfig("remote." + remote + ".lfsurl"); ok {
		return NewEndpoint(url)
	}

	if url, ok := c.GitConfig("remote." + remote + ".url"); ok {
		return NewEndpointFromCloneURL(url)
	}

	return Endpoint{}
}

func (c *Configuration) Remotes() []string {
	c.loadGitConfig()
	return c.remotes
}

func (c *Configuration) Extensions() map[string]Extension {
	c.loadGitConfig()
	return c.extensions
}

func (c *Configuration) GitConfig(key string) (string, bool) {
	c.loadGitConfig()
	value, ok := c.gitConfig[strings.ToLower(key)]
	return value, ok
}

func (c *Configuration) AllGitConfig() map[string]string {
	c.loadGitConfig()
	return c.gitConfig
}

func (c *Configuration) ObjectUrl(oid string) (*url.URL, error) {
	return ObjectUrl(c.Endpoint(), oid)
}

func (c *Configuration) FetchPruneConfig() *FetchPruneConfig {
	if c.fetchPruneConfig == nil {
		c.fetchPruneConfig = &FetchPruneConfig{
			FetchRecentRefsDays:           7,
			FetchRecentRefsIncludeRemotes: true,
			FetchRecentCommitsDays:        0,
			PruneOffsetDays:               3,
			PruneVerifyRemoteAlways:       false,
			PruneRemoteName:               "origin",
		}
		if v, ok := c.GitConfig("lfs.fetchrecentrefsdays"); ok {
			n, err := strconv.Atoi(v)
			if err == nil && n >= 0 {
				c.fetchPruneConfig.FetchRecentRefsDays = n
			}
		}
		if v, ok := c.GitConfig("lfs.fetchrecentremoterefs"); ok {
			if b, err := parseConfigBool(v); err == nil {
				c.fetchPruneConfig.FetchRecentRefsIncludeRemotes = b
			}
		}
		if v, ok := c.GitConfig("lfs.fetchrecentcommitsdays"); ok {
			n, err := strconv.Atoi(v)
			if err == nil && n >= 0 {
				c.fetchPruneConfig.FetchRecentCommitsDays = n
			}
		}
		if v, ok := c.GitConfig("lfs.fetchrecentalways"); ok {
			if b, err := parseConfigBool(v); err == nil {
				c.fetchPruneConfig.FetchRecentAlways = b
			}
		}
		if v, ok := c.GitConfig("lfs.pruneoffsetdays"); ok {
			n, err := strconv.Atoi(v)
			if err == nil && n >= 0 {
				c.fetchPruneConfig.PruneOffsetDays = n
			}
		}
		if v, ok := c.GitConfig("lfs.pruneverifyremotealways"); ok {
			if b, err := parseConfigBool(v); err == nil {
				c.fetchPruneConfig.PruneVerifyRemoteAlways = b
			}
		}
		if v, ok := c.GitConfig("lfs.pruneremotetocheck"); ok {
			c.fetchPruneConfig.PruneRemoteName = v
		}

	}
	return c.fetchPruneConfig
}

func parseConfigBool(str string) (bool, error) {
	switch strings.ToLower(str) {
	case "true", "1", "on", "yes", "t":
		return true, nil
	case "false", "0", "off", "no", "f":
		return false, nil
	}
	return false, fmt.Errorf("Unable to parse %q as a boolean", str)
}

func (c *Configuration) loadGitConfig() bool {
	c.loading.Lock()
	defer c.loading.Unlock()

	if c.gitConfig != nil {
		return false
	}

	c.gitConfig = make(map[string]string)
	c.extensions = make(map[string]Extension)
	uniqRemotes := make(map[string]bool)

	configFiles := []string{
		filepath.Join(LocalWorkingDir, ".lfsconfig"),
		filepath.Join(LocalWorkingDir, ".gitconfig"),
	}
	c.readGitConfigFromFiles(configFiles, 0, uniqRemotes)

	listOutput, err := git.Config.List()
	if err != nil {
		panic(fmt.Errorf("Error listing git config: %s", err))
	}

	c.readGitConfig(listOutput, uniqRemotes, false)

	c.remotes = make([]string, 0, len(uniqRemotes))
	for remote, isOrigin := range uniqRemotes {
		if isOrigin {
			continue
		}
		c.remotes = append(c.remotes, remote)
	}

	return true
}

func (c *Configuration) readGitConfigFromFiles(filenames []string, filenameIndex int, uniqRemotes map[string]bool) {
	filename := filenames[filenameIndex]
	_, err := os.Stat(filename)
	if err == nil {
		fileOutput, err := git.Config.ListFromFile(filename)
		if err != nil {
			panic(fmt.Errorf("Error listing git config from %s: %s", filename, err))
		}
		c.readGitConfig(fileOutput, uniqRemotes, true)
		return
	}

	if os.IsNotExist(err) {
		newIndex := filenameIndex + 1
		if len(filenames) > newIndex {
			c.readGitConfigFromFiles(filenames, newIndex, uniqRemotes)
		}
		return
	}

	panic(fmt.Errorf("Error listing git config from %s: %s", filename, err))
}

func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool, onlySafe bool) {
	lines := strings.Split(output, "\n")
	for _, line := range lines {
		pieces := strings.SplitN(line, "=", 2)
		if len(pieces) < 2 {
			continue
		}

		allowed := !onlySafe
		key := strings.ToLower(pieces[0])
		value := pieces[1]

		keyParts := strings.Split(key, ".")
		if len(keyParts) == 4 && keyParts[0] == "lfs" && keyParts[1] == "extension" {
			name := keyParts[2]
			ext := c.extensions[name]
			switch keyParts[3] {
			case "clean":
				if onlySafe {
					continue
				}
				ext.Clean = value
			case "smudge":
				if onlySafe {
					continue
				}
				ext.Smudge = value
			case "priority":
				allowed = true
				p, err := strconv.Atoi(value)
				if err == nil && p >= 0 {
					ext.Priority = p
				}
			}

			ext.Name = name
			c.extensions[name] = ext
		} else if len(keyParts) > 1 && keyParts[0] == "remote" {
			if onlySafe && (len(keyParts) == 3 && keyParts[2] != "lfsurl") {
				continue
			}

			allowed = true
			remote := keyParts[1]
			uniqRemotes[remote] = remote == "origin"
		}

		if !allowed && keyIsUnsafe(key) {
			continue
		}

		c.gitConfig[key] = value

		if len(keyParts) == 2 && keyParts[0] == "lfs" && keyParts[1] == "fetchinclude" {
			for _, inc := range strings.Split(value, ",") {
				inc = strings.TrimSpace(inc)
				c.fetchIncludePaths = append(c.fetchIncludePaths, inc)
			}
		} else if len(keyParts) == 2 && keyParts[0] == "lfs" && keyParts[1] == "fetchexclude" {
			for _, ex := range strings.Split(value, ",") {
				ex = strings.TrimSpace(ex)
				c.fetchExcludePaths = append(c.fetchExcludePaths, ex)
			}
		}
	}
}

func keyIsUnsafe(key string) bool {
	for _, safe := range safeKeys {
		if safe == key {
			return false
		}
	}
	return true
}

var safeKeys = []string{
	"lfs.url",
	"lfs.fetchinclude",
	"lfs.fetchexclude",
}
<commit_msg>add a warning message for .gitconfig users<commit_after>package lfs

import (
	"fmt"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"

	"github.com/github/git-lfs/git"
	"github.com/github/git-lfs/vendor/_nuts/github.com/ThomsonReutersEikon/go-ntlm/ntlm"
	"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
)

var (
	Config        = NewConfig()
	defaultRemote = "origin"
)

// FetchPruneConfig collects together the config options that control fetching and pruning
type FetchPruneConfig struct {
	// The number of days prior to current date for which (local) refs other than HEAD
	// will be fetched with --recent (default 7, 0 = only fetch HEAD)
	FetchRecentRefsDays int
	// Makes the FetchRecentRefsDays option apply to remote refs from fetch source as well (default true)
	FetchRecentRefsIncludeRemotes bool
	// number of days prior to latest commit on a ref that we'll fetch previous
	// LFS changes too (default 0 = only fetch at ref)
	FetchRecentCommitsDays int
	// Whether to always fetch recent even without --recent
	FetchRecentAlways bool
	// Number of days added to FetchRecent*; data outside combined window will be
	// deleted when prune is run. (default 3)
	PruneOffsetDays int
	// Always verify with remote before pruning
	PruneVerifyRemoteAlways bool
	// Name of remote to check for unpushed and verify checks
	PruneRemoteName string
}

type Configuration struct {
	CurrentRemote         string
	httpClient            *HttpClient
	redirectingHttpClient *http.Client
	ntlmSession           ntlm.ClientSession
	envVars               map[string]string
	isTracingHttp         bool
	isLoggingStats        bool

	loading           sync.Mutex // guards initialization of gitConfig and remotes
	gitConfig         map[string]string
	origConfig        map[string]string
	remotes           []string
	extensions        map[string]Extension
	fetchIncludePaths []string
	fetchExcludePaths []string
	fetchPruneConfig  *FetchPruneConfig
}

func NewConfig() *Configuration {
	c := &Configuration{
		CurrentRemote: defaultRemote,
		envVars:       make(map[string]string),
	}
	c.isTracingHttp = c.GetenvBool("GIT_CURL_VERBOSE", false)
	c.isLoggingStats = c.GetenvBool("GIT_LOG_STATS", false)
	return c
}

func (c *Configuration) Getenv(key string) string {
	if i, ok := c.envVars[key]; ok {
		return i
	}

	v := os.Getenv(key)
	c.envVars[key] = v
	return v
}

func (c *Configuration) Setenv(key, value string) error {
	// Check see if we have this in our cache, if so update it
	if _, ok := c.envVars[key]; ok {
		c.envVars[key] = value
	}

	// Now set in process
	return os.Setenv(key, value)
}

// GetenvBool parses a boolean environment variable and returns the result as a bool.
// If the environment variable is unset, empty, or if the parsing fails,
// the value of def (default) is returned instead.
func (c *Configuration) GetenvBool(key string, def bool) bool {
	s := c.Getenv(key)
	if len(s) == 0 {
		return def
	}

	b, err := parseConfigBool(s)
	if err != nil {
		return def
	}
	return b
}

func (c *Configuration) Endpoint() Endpoint {
	if url, ok := c.GitConfig("lfs.url"); ok {
		return NewEndpoint(url)
	}

	if len(c.CurrentRemote) > 0 && c.CurrentRemote != defaultRemote {
		if endpoint := c.RemoteEndpoint(c.CurrentRemote); len(endpoint.Url) > 0 {
			return endpoint
		}
	}

	return c.RemoteEndpoint(defaultRemote)
}

func (c *Configuration) ConcurrentTransfers() int {
	if c.NtlmAccess() {
		return 1
	}

	uploads := 3

	if v, ok := c.GitConfig("lfs.concurrenttransfers"); ok {
		n, err := strconv.Atoi(v)
		if err == nil && n > 0 {
			uploads = n
		}
	}

	return uploads
}

func (c *Configuration) BatchTransfer() bool {
	value, ok := c.GitConfig("lfs.batch")
	if !ok || len(value) == 0 {
		return true
	}

	useBatch, err := parseConfigBool(value)
	if err != nil {
		return false
	}

	return useBatch
}

func (c *Configuration) NtlmAccess() bool {
	return c.Access() == "ntlm"
}

// PrivateAccess will retrieve the access value and return true if
// the value is set to private. When a repo is marked as having private
// access, the http requests for the batch api will fetch the credentials
// before running, otherwise the request will run without credentials.
func (c *Configuration) PrivateAccess() bool {
	return c.Access() != "none"
}

// Access returns the access auth type.
func (c *Configuration) Access() string {
	return c.EndpointAccess(c.Endpoint())
}

// SetAccess will set the private access flag in .git/config.
func (c *Configuration) SetAccess(authType string) {
	c.SetEndpointAccess(c.Endpoint(), authType)
}

func (c *Configuration) EndpointAccess(e Endpoint) string {
	key := fmt.Sprintf("lfs.%s.access", e.Url)
	if v, ok := c.GitConfig(key); ok && len(v) > 0 {
		lower := strings.ToLower(v)
		if lower == "private" {
			return "basic"
		}
		return lower
	}
	return "none"
}

func (c *Configuration) SetEndpointAccess(e Endpoint, authType string) {
	tracerx.Printf("setting repository access to %s", authType)
	key := fmt.Sprintf("lfs.%s.access", e.Url)

	// Modify the config cache because it's checked again in this process
	// without being reloaded.
	switch authType {
	case "", "none":
		git.Config.UnsetLocalKey("", key)

		c.loading.Lock()
		delete(c.gitConfig, strings.ToLower(key))
		c.loading.Unlock()
	default:
		git.Config.SetLocal("", key, authType)

		c.loading.Lock()
		c.gitConfig[strings.ToLower(key)] = authType
		c.loading.Unlock()
	}
}

func (c *Configuration) FetchIncludePaths() []string {
	c.loadGitConfig()
	return c.fetchIncludePaths
}
func (c *Configuration) FetchExcludePaths() []string {
	c.loadGitConfig()
	return c.fetchExcludePaths
}

func (c *Configuration) RemoteEndpoint(remote string) Endpoint {
	if len(remote) == 0 {
		remote = defaultRemote
	}
	if url, ok := c.GitConfig("remote." + remote + ".lfsurl"); ok {
		return NewEndpoint(url)
	}

	if url, ok := c.GitConfig("remote." + remote + ".url"); ok {
		return NewEndpointFromCloneURL(url)
	}

	return Endpoint{}
}

func (c *Configuration) Remotes() []string {
	c.loadGitConfig()
	return c.remotes
}

func (c *Configuration) Extensions() map[string]Extension {
	c.loadGitConfig()
	return c.extensions
}

func (c *Configuration) GitConfig(key string) (string, bool) {
	c.loadGitConfig()
	value, ok := c.gitConfig[strings.ToLower(key)]
	return value, ok
}

func (c *Configuration) AllGitConfig() map[string]string {
	c.loadGitConfig()
	return c.gitConfig
}

func (c *Configuration) ObjectUrl(oid string) (*url.URL, error) {
	return ObjectUrl(c.Endpoint(), oid)
}

func (c *Configuration) FetchPruneConfig() *FetchPruneConfig {
	if c.fetchPruneConfig == nil {
		c.fetchPruneConfig = &FetchPruneConfig{
			FetchRecentRefsDays:           7,
			FetchRecentRefsIncludeRemotes: true,
			FetchRecentCommitsDays:        0,
			PruneOffsetDays:               3,
			PruneVerifyRemoteAlways:       false,
			PruneRemoteName:               "origin",
		}
		if v, ok := c.GitConfig("lfs.fetchrecentrefsdays"); ok {
			n, err := strconv.Atoi(v)
			if err == nil && n >= 0 {
				c.fetchPruneConfig.FetchRecentRefsDays = n
			}
		}
		if v, ok := c.GitConfig("lfs.fetchrecentremoterefs"); ok {
			if b, err := parseConfigBool(v); err == nil {
				c.fetchPruneConfig.FetchRecentRefsIncludeRemotes = b
			}
		}
		if v, ok := c.GitConfig("lfs.fetchrecentcommitsdays"); ok {
			n, err := strconv.Atoi(v)
			if err == nil && n >= 0 {
				c.fetchPruneConfig.FetchRecentCommitsDays = n
			}
		}
		if v, ok := c.GitConfig("lfs.fetchrecentalways"); ok {
			if b, err := parseConfigBool(v); err == nil {
				c.fetchPruneConfig.FetchRecentAlways = b
			}
		}
		if v, ok := c.GitConfig("lfs.pruneoffsetdays"); ok {
			n, err := strconv.Atoi(v)
			if err == nil && n >= 0 {
				c.fetchPruneConfig.PruneOffsetDays = n
			}
		}
		if v, ok := c.GitConfig("lfs.pruneverifyremotealways"); ok {
			if b, err := parseConfigBool(v); err == nil {
				c.fetchPruneConfig.PruneVerifyRemoteAlways = b
			}
		}
		if v, ok := c.GitConfig("lfs.pruneremotetocheck"); ok {
			c.fetchPruneConfig.PruneRemoteName = v
		}

	}
	return c.fetchPruneConfig
}

func parseConfigBool(str string) (bool, error) {
	switch strings.ToLower(str) {
	case "true", "1", "on", "yes", "t":
		return true, nil
	case "false", "0", "off", "no", "f":
		return false, nil
	}
	return false, fmt.Errorf("Unable to parse %q as a boolean", str)
}

func (c *Configuration) loadGitConfig() bool {
	c.loading.Lock()
	defer c.loading.Unlock()

	if c.gitConfig != nil {
		return false
	}

	c.gitConfig = make(map[string]string)
	c.extensions = make(map[string]Extension)
	uniqRemotes := make(map[string]bool)

	configFiles := []string{
		filepath.Join(LocalWorkingDir, ".lfsconfig"),

		// TODO: remove .gitconfig support for Git LFS v2.0
		filepath.Join(LocalWorkingDir, ".gitconfig"),
	}
	c.readGitConfigFromFiles(configFiles, 0, uniqRemotes)

	listOutput, err := git.Config.List()
	if err != nil {
		panic(fmt.Errorf("Error listing git config: %s", err))
	}

	c.readGitConfig(listOutput, uniqRemotes, false)

	c.remotes = make([]string, 0, len(uniqRemotes))
	for remote, isOrigin := range uniqRemotes {
		if isOrigin {
			continue
		}
		c.remotes = append(c.remotes, remote)
	}

	return true
}

func (c *Configuration) readGitConfigFromFiles(filenames []string, filenameIndex int, uniqRemotes map[string]bool) {
	filename := filenames[filenameIndex]
	_, err := os.Stat(filename)
	if err == nil {
		fileOutput, err := git.Config.ListFromFile(filename)
		if err != nil {
			panic(fmt.Errorf("Error listing git config from %s: %s", filename, err))
		}
		c.readGitConfig(fileOutput, uniqRemotes, true)
		return
	}

	if os.IsNotExist(err) {
		newIndex := filenameIndex + 1
		if len(filenames) > newIndex {
			expected := ".lfsconfig"
			fmt.Fprintf(os.Stderr, "WARNING: Reading LFS config from %q, not %q. Rename to %q before Git LFS v2.0 to remove this warning.\n",
				filepath.Base(filenames[newIndex]), expected, expected)
			c.readGitConfigFromFiles(filenames, newIndex, uniqRemotes)
		}
		return
	}

	panic(fmt.Errorf("Error listing git config from %s: %s", filename, err))
}

func (c *Configuration) readGitConfig(output string, uniqRemotes map[string]bool, onlySafe bool) {
	lines := strings.Split(output, "\n")
	for _, line := range lines {
		pieces := strings.SplitN(line, "=", 2)
		if len(pieces) < 2 {
			continue
		}

		allowed := !onlySafe
		key := strings.ToLower(pieces[0])
		value := pieces[1]

		keyParts := strings.Split(key, ".")
		if len(keyParts) == 4 && keyParts[0] == "lfs" && keyParts[1] == "extension" {
			name := keyParts[2]
			ext := c.extensions[name]
			switch keyParts[3] {
			case "clean":
				if onlySafe {
					continue
				}
				ext.Clean = value
			case "smudge":
				if onlySafe {
					continue
				}
				ext.Smudge = value
			case "priority":
				allowed = true
				p, err := strconv.Atoi(value)
				if err == nil && p >= 0 {
					ext.Priority = p
				}
			}

			ext.Name = name
			c.extensions[name] = ext
		} else if len(keyParts) > 1 && keyParts[0] == "remote" {
			if onlySafe && (len(keyParts) == 3 && keyParts[2] != "lfsurl") {
				continue
			}

			allowed = true
			remote := keyParts[1]
			uniqRemotes[remote] = remote == "origin"
		}

		if !allowed && keyIsUnsafe(key) {
			continue
		}

		c.gitConfig[key] = value

		if len(keyParts) == 2 && keyParts[0] == "lfs" && keyParts[1] == "fetchinclude" {
			for _, inc := range strings.Split(value, ",") {
				inc = strings.TrimSpace(inc)
				c.fetchIncludePaths = append(c.fetchIncludePaths, inc)
			}
		} else if len(keyParts) == 2 && keyParts[0] == "lfs" && keyParts[1] == "fetchexclude" {
			for _, ex := range strings.Split(value, ",") {
				ex = strings.TrimSpace(ex)
				c.fetchExcludePaths = append(c.fetchExcludePaths, ex)
			}
		}
	}
}

func keyIsUnsafe(key string) bool {
	for _, safe := range safeKeys {
		if safe == key {
			return false
		}
	}
	return true
}

var safeKeys = []string{
	"lfs.url",
	"lfs.fetchinclude",
	"lfs.fetchexclude",
}
<|endoftext|>


<commit_before>package timeutil

import (
	"fmt"
	"strconv"
	"time"
)

func IsGreaterThan(timeLeft time.Time, timeRight time.Time) bool {
	durDelta := timeLeft.Sub(timeRight)
	if durZero, _ := time.ParseDuration("0ns"); durDelta > durZero {
		return true
	}
	return false
}

func IsLessThan(timeLeft time.Time, timeRight time.Time) bool {
	durDelta := timeLeft.Sub(timeRight)
	if durZero, _ := time.ParseDuration("0ns"); durDelta < durZero {
		return true
	}
	return false
}

func Dt8Now() int32 {
	return Dt8ForTime(time.Now())
}

func Dt8ForString(layout, value string) (int32, error) {
	dt8 := int32(0)
	t, err := time.Parse(layout, value)
	if err == nil {
		dt8 = Dt8ForTime(t)
	}
	return dt8, err
}

func Dt8ForInts(yyyy int, mm int, dd int) int32 {
	sDt8 := fmt.Sprintf("%04d%02d%02d", yyyy, mm, dd)
	iDt8, _ := strconv.ParseInt(sDt8, 10, 32)
	return int32(iDt8)
}

func Dt8ForTime(t time.Time) int32 {
	u := t.UTC()
	s := u.Format("20060102")
	iDt8, _ := strconv.ParseInt(s, 10, 32)
	return int32(iDt8)
	//return Dt8ForInts(u.Year(), int(u.Month()), u.Day())
}

func DurationForNowSubDt8(dt8 int32) (time.Duration, error) {
	t, err := TimeForDt8(dt8)
	if err != nil {
		var d time.Duration
		return d, err
	}
	now := time.Now()
	return now.Sub(t), nil
}

func TimeForDt8(dt8 int32) (time.Time, error) {
	return time.Parse("20060102", strconv.FormatInt(int64(dt8), 10))
}

func Dt14Now() int64 {
	return Dt14ForTime(time.Now())
}

func Dt14ForString(layout, value string) (int64, error) {
	dt14 := int64(0)
	t, err := time.Parse(layout, value)
	if err == nil {
		dt14 = Dt14ForTime(t)
	}
	return dt14, err
}

func Dt14ForInts(yyyy int, mm int, dd int, hr int, mn int, dy int) int64 {
	sDt14 := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", yyyy, mm, dd, hr, mn, dy)
	iDt14, _ := strconv.ParseInt(sDt14, 10, 64)
	return int64(iDt14)
}

func Dt14ForTime(t time.Time) int64 {
	u := t.UTC()
	s := u.Format("20060102150405")
	iDt14, _ := strconv.ParseInt(s, 10, 64)
	return int64(iDt14)
	//return Dt14ForInts(u.Year(), int(u.Month()), u.Day(), u.Hour(), u.Minute(), u.Second())
}

func TimeForDt14(dt14 int64) (time.Time, error) {
	return time.Parse("20060102150405", strconv.FormatInt(dt14, 10))
}
<commit_msg>increase timeutil performance<commit_after>package timeutil

import (
	"fmt"
	"strconv"
	"time"
)

func IsGreaterThan(timeLeft time.Time, timeRight time.Time) bool {
	durDelta := timeLeft.Sub(timeRight)
	if durZero, _ := time.ParseDuration("0ns"); durDelta > durZero {
		return true
	}
	return false
}

func IsLessThan(timeLeft time.Time, timeRight time.Time) bool {
	durDelta := timeLeft.Sub(timeRight)
	if durZero, _ := time.ParseDuration("0ns"); durDelta < durZero {
		return true
	}
	return false
}

func Dt8Now() int32 {
	return Dt8ForTime(time.Now())
}

func Dt8ForString(layout, value string) (int32, error) {
	dt8 := int32(0)
	t, err := time.Parse(layout, value)
	if err == nil {
		dt8 = Dt8ForTime(t)
	}
	return dt8, err
}

func Dt8ForInts(yyyy int, mm int, dd int) int32 {
	sDt8 := fmt.Sprintf("%04d%02d%02d", yyyy, mm, dd)
	iDt8, _ := strconv.ParseInt(sDt8, 10, 32)
	return int32(iDt8)
}

func Dt8ForTime(t time.Time) int32 {
	u := t.UTC()
	s := u.Format("20060102")
	iDt8, _ := strconv.ParseInt(s, 10, 32)
	return int32(iDt8)
}

func TimeForDt8(dt8 int32) (time.Time, error) {
	return time.Parse("20060102", strconv.FormatInt(int64(dt8), 10))
}

func DurationForNowSubDt8(dt8 int32) (time.Duration, error) {
	t, err := TimeForDt8(dt8)
	if err != nil {
		var d time.Duration
		return d, err
	}
	now := time.Now()
	return now.Sub(t), nil
}

func Dt14Now() int64 {
	return Dt14ForTime(time.Now())
}

func Dt14ForString(layout, value string) (int64, error) {
	dt14 := int64(0)
	t, err := time.Parse(layout, value)
	if err == nil {
		dt14 = Dt14ForTime(t)
	}
	return dt14, err
}

func Dt14ForInts(yyyy int, mm int, dd int, hr int, mn int, dy int) int64 {
	sDt14 := fmt.Sprintf("%04d%02d%02d%02d%02d%02d", yyyy, mm, dd, hr, mn, dy)
	iDt14, _ := strconv.ParseInt(sDt14, 10, 64)
	return int64(iDt14)
}

func Dt14ForTime(t time.Time) int64 {
	u := t.UTC()
	s := u.Format("20060102150405")
	iDt14, _ := strconv.ParseInt(s, 10, 64)
	return int64(iDt14)
}

func TimeForDt14(dt14 int64) (time.Time, error) {
	return time.Parse("20060102150405", strconv.FormatInt(dt14, 10))
}
<|endoftext|>


<commit_before>package pki

import (
	"encoding/base64"
	"fmt"

	"github.com/hashicorp/vault/helper/certutil"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

func pathGenerateIntermediate(b *backend) *framework.Path {
	ret := &framework.Path{
		Pattern: "intermediate/generate/" + framework.GenericNameRegex("exported"),

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathGenerateIntermediate,
		},

		HelpSynopsis:    pathGenerateIntermediateHelpSyn,
		HelpDescription: pathGenerateIntermediateHelpDesc,
	}

	ret.Fields = addCACommonFields(map[string]*framework.FieldSchema{})
	ret.Fields = addCAKeyGenerationFields(ret.Fields)

	return ret
}

func pathSetSignedIntermediate(b *backend) *framework.Path {
	ret := &framework.Path{
		Pattern: "intermediate/set-signed",

		Fields: map[string]*framework.FieldSchema{
			"certificate": &framework.FieldSchema{
				Type: framework.TypeString,
				Description: `PEM-format certificate. This must be a CA
certificate with a public key matching the
previously-generated key from the generation
endpoint.`,
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathSetSignedIntermediate,
		},

		HelpSynopsis:    pathSetSignedIntermediateHelpSyn,
		HelpDescription: pathSetSignedIntermediateHelpDesc,
	}

	return ret
}

func (b *backend) pathGenerateIntermediate(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	var err error

	exported, format, role, errorResp := b.getGenerationParams(data)
	if errorResp != nil {
		return errorResp, nil
	}

	var resp *logical.Response
	parsedBundle, err := generateIntermediateCSR(b, role, nil, req, data)
	if err != nil {
		switch err.(type) {
		case certutil.UserError:
			return logical.ErrorResponse(err.Error()), nil
		case certutil.InternalError:
			return nil, err
		}
	}

	csrb, err := parsedBundle.ToCSRBundle()
	if err != nil {
		return nil, fmt.Errorf("Error converting raw CSR bundle to CSR bundle: %s", err)
	}

	resp = &logical.Response{
		Data: map[string]interface{}{},
	}

	switch format {
	case "pem":
		resp.Data["csr"] = csrb.CSR
		if exported {
			resp.Data["private_key"] = csrb.PrivateKey
			resp.Data["private_key_type"] = csrb.PrivateKeyType
		}

	case "pem_bundle":
		resp.Data["csr"] = csrb.CSR
		if exported {
			resp.Data["csr"] = fmt.Sprintf("%s\n%s", csrb.PrivateKey, csrb.CSR)
			resp.Data["private_key"] = csrb.PrivateKey
			resp.Data["private_key_type"] = csrb.PrivateKeyType
		}

	case "der":
		resp.Data["csr"] = base64.StdEncoding.EncodeToString(parsedBundle.CSRBytes)
		if exported {
			resp.Data["private_key"] = base64.StdEncoding.EncodeToString(parsedBundle.PrivateKeyBytes)
			resp.Data["private_key_type"] = csrb.PrivateKeyType
		}
	}

	cb := &certutil.CertBundle{}
	cb.PrivateKey = csrb.PrivateKey
	cb.PrivateKeyType = csrb.PrivateKeyType

	entry, err := logical.StorageEntryJSON("config/ca_bundle", cb)
	if err != nil {
		return nil, err
	}
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func (b *backend) pathSetSignedIntermediate(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	cert := data.Get("certificate").(string)

	if cert == "" {
		return logical.ErrorResponse("no certificate provided in the \"certficate\" parameter"), nil
	}

	inputBundle, err := certutil.ParsePEMBundle(cert)
	if err != nil {
		switch err.(type) {
		case certutil.InternalError:
			return nil, err
		default:
			return logical.ErrorResponse(err.Error()), nil
		}
	}

	// If only one certificate is provided and it's a CA
	// the parsing will assign it to the IssuingCA, so move it over
	if inputBundle.Certificate == nil && inputBundle.IssuingCA != nil {
		inputBundle.Certificate = inputBundle.IssuingCA
		inputBundle.IssuingCA = nil
		inputBundle.CertificateBytes = inputBundle.IssuingCABytes
		inputBundle.IssuingCABytes = nil
	}

	if inputBundle.Certificate == nil {
		return logical.ErrorResponse("supplied certificate could not be successfully parsed"), nil
	}

	cb := &certutil.CertBundle{}
	entry, err := req.Storage.Get("config/ca_bundle")
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return logical.ErrorResponse("could not find any existing entry with a private key"), nil
	}

	err = entry.DecodeJSON(cb)
	if err != nil {
		return nil, err
	}

	if len(cb.PrivateKey) == 0 || cb.PrivateKeyType == "" {
		return logical.ErrorResponse("could not find an existing privat key"), nil
	}

	parsedCB, err := cb.ToParsedCertBundle()
	if err != nil {
		return nil, err
	}
	if parsedCB.PrivateKey == nil {
		return nil, fmt.Errorf("saved key could not be parsed successfully")
	}

	equal, err := certutil.ComparePublicKeys(parsedCB.PrivateKey.Public(), inputBundle.Certificate.PublicKey)
	if err != nil {
		return logical.ErrorResponse(fmt.Sprintf(
			"error matching public keys: %v", err)), nil
	}
	if !equal {
		return logical.ErrorResponse("key in certificate does not match stored key"), nil
	}

	inputBundle.PrivateKey = parsedCB.PrivateKey
	inputBundle.PrivateKeyType = parsedCB.PrivateKeyType
	inputBundle.PrivateKeyBytes = parsedCB.PrivateKeyBytes

	if !inputBundle.Certificate.IsCA {
		return logical.ErrorResponse("the given certificate is not marked for CA use and cannot be used with this backend"), nil
	}

	cb, err = inputBundle.ToCertBundle()
	if err != nil {
		return nil, fmt.Errorf("error converting raw values into cert bundle: %s", err)
	}

	entry, err = logical.StorageEntryJSON("config/ca_bundle", cb)
	if err != nil {
		return nil, err
	}
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	// For ease of later use, also store just the certificate at a known
	// location
	entry.Key = "ca"
	entry.Value = inputBundle.CertificateBytes
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	// Build a fresh CRL
	err = buildCRL(b, req)

	return nil, err
}

const pathGenerateIntermediateHelpSyn = `
Generate a new CSR and private key used for signing.
`

const pathGenerateIntermediateHelpDesc = `
See the API documentation for more information.
`

const pathSetSignedIntermediateHelpSyn = `
Provide the signed intermediate CA cert.
`

const pathSetSignedIntermediateHelpDesc = `
See the API documentation for more information.
`
<commit_msg>Typo in error message in path_intermediate.go<commit_after>package pki

import (
	"encoding/base64"
	"fmt"

	"github.com/hashicorp/vault/helper/certutil"
	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
)

func pathGenerateIntermediate(b *backend) *framework.Path {
	ret := &framework.Path{
		Pattern: "intermediate/generate/" + framework.GenericNameRegex("exported"),

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathGenerateIntermediate,
		},

		HelpSynopsis:    pathGenerateIntermediateHelpSyn,
		HelpDescription: pathGenerateIntermediateHelpDesc,
	}

	ret.Fields = addCACommonFields(map[string]*framework.FieldSchema{})
	ret.Fields = addCAKeyGenerationFields(ret.Fields)

	return ret
}

func pathSetSignedIntermediate(b *backend) *framework.Path {
	ret := &framework.Path{
		Pattern: "intermediate/set-signed",

		Fields: map[string]*framework.FieldSchema{
			"certificate": &framework.FieldSchema{
				Type: framework.TypeString,
				Description: `PEM-format certificate. This must be a CA
certificate with a public key matching the
previously-generated key from the generation
endpoint.`,
			},
		},

		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathSetSignedIntermediate,
		},

		HelpSynopsis:    pathSetSignedIntermediateHelpSyn,
		HelpDescription: pathSetSignedIntermediateHelpDesc,
	}

	return ret
}

func (b *backend) pathGenerateIntermediate(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	var err error

	exported, format, role, errorResp := b.getGenerationParams(data)
	if errorResp != nil {
		return errorResp, nil
	}

	var resp *logical.Response
	parsedBundle, err := generateIntermediateCSR(b, role, nil, req, data)
	if err != nil {
		switch err.(type) {
		case certutil.UserError:
			return logical.ErrorResponse(err.Error()), nil
		case certutil.InternalError:
			return nil, err
		}
	}

	csrb, err := parsedBundle.ToCSRBundle()
	if err != nil {
		return nil, fmt.Errorf("Error converting raw CSR bundle to CSR bundle: %s", err)
	}

	resp = &logical.Response{
		Data: map[string]interface{}{},
	}

	switch format {
	case "pem":
		resp.Data["csr"] = csrb.CSR
		if exported {
			resp.Data["private_key"] = csrb.PrivateKey
			resp.Data["private_key_type"] = csrb.PrivateKeyType
		}

	case "pem_bundle":
		resp.Data["csr"] = csrb.CSR
		if exported {
			resp.Data["csr"] = fmt.Sprintf("%s\n%s", csrb.PrivateKey, csrb.CSR)
			resp.Data["private_key"] = csrb.PrivateKey
			resp.Data["private_key_type"] = csrb.PrivateKeyType
		}

	case "der":
		resp.Data["csr"] = base64.StdEncoding.EncodeToString(parsedBundle.CSRBytes)
		if exported {
			resp.Data["private_key"] = base64.StdEncoding.EncodeToString(parsedBundle.PrivateKeyBytes)
			resp.Data["private_key_type"] = csrb.PrivateKeyType
		}
	}

	cb := &certutil.CertBundle{}
	cb.PrivateKey = csrb.PrivateKey
	cb.PrivateKeyType = csrb.PrivateKeyType

	entry, err := logical.StorageEntryJSON("config/ca_bundle", cb)
	if err != nil {
		return nil, err
	}
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func (b *backend) pathSetSignedIntermediate(
	req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
	cert := data.Get("certificate").(string)

	if cert == "" {
		return logical.ErrorResponse("no certificate provided in the \"certficate\" parameter"), nil
	}

	inputBundle, err := certutil.ParsePEMBundle(cert)
	if err != nil {
		switch err.(type) {
		case certutil.InternalError:
			return nil, err
		default:
			return logical.ErrorResponse(err.Error()), nil
		}
	}

	// If only one certificate is provided and it's a CA
	// the parsing will assign it to the IssuingCA, so move it over
	if inputBundle.Certificate == nil && inputBundle.IssuingCA != nil {
		inputBundle.Certificate = inputBundle.IssuingCA
		inputBundle.IssuingCA = nil
		inputBundle.CertificateBytes = inputBundle.IssuingCABytes
		inputBundle.IssuingCABytes = nil
	}

	if inputBundle.Certificate == nil {
		return logical.ErrorResponse("supplied certificate could not be successfully parsed"), nil
	}

	cb := &certutil.CertBundle{}
	entry, err := req.Storage.Get("config/ca_bundle")
	if err != nil {
		return nil, err
	}
	if entry == nil {
		return logical.ErrorResponse("could not find any existing entry with a private key"), nil
	}

	err = entry.DecodeJSON(cb)
	if err != nil {
		return nil, err
	}

	if len(cb.PrivateKey) == 0 || cb.PrivateKeyType == "" {
		return logical.ErrorResponse("could not find an existing private key"), nil
	}

	parsedCB, err := cb.ToParsedCertBundle()
	if err != nil {
		return nil, err
	}
	if parsedCB.PrivateKey == nil {
		return nil, fmt.Errorf("saved key could not be parsed successfully")
	}

	equal, err := certutil.ComparePublicKeys(parsedCB.PrivateKey.Public(), inputBundle.Certificate.PublicKey)
	if err != nil {
		return logical.ErrorResponse(fmt.Sprintf(
			"error matching public keys: %v", err)), nil
	}
	if !equal {
		return logical.ErrorResponse("key in certificate does not match stored key"), nil
	}

	inputBundle.PrivateKey = parsedCB.PrivateKey
	inputBundle.PrivateKeyType = parsedCB.PrivateKeyType
	inputBundle.PrivateKeyBytes = parsedCB.PrivateKeyBytes

	if !inputBundle.Certificate.IsCA {
		return logical.ErrorResponse("the given certificate is not marked for CA use and cannot be used with this backend"), nil
	}

	cb, err = inputBundle.ToCertBundle()
	if err != nil {
		return nil, fmt.Errorf("error converting raw values into cert bundle: %s", err)
	}

	entry, err = logical.StorageEntryJSON("config/ca_bundle", cb)
	if err != nil {
		return nil, err
	}
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	// For ease of later use, also store just the certificate at a known
	// location
	entry.Key = "ca"
	entry.Value = inputBundle.CertificateBytes
	err = req.Storage.Put(entry)
	if err != nil {
		return nil, err
	}

	// Build a fresh CRL
	err = buildCRL(b, req)

	return nil, err
}

const pathGenerateIntermediateHelpSyn = `
Generate a new CSR and private key used for signing.
`

const pathGenerateIntermediateHelpDesc = `
See the API documentation for more information.
`

const pathSetSignedIntermediateHelpSyn = `
Provide the signed intermediate CA cert.
`

const pathSetSignedIntermediateHelpDesc = `
See the API documentation for more information.
`
<|endoftext|>


<commit_before>package sconsify

import (
	"errors"
	"math/rand"
	"time"
)

type Playlists struct {
	playlists         map[string]*Playlist
	currentIndexTrack int
	currentPlaylist   string
	playMode          int
	premadeTracks     []*Track
}

const (
	NormalMode     = iota
	RandomMode     = iota
	AllRandomMode  = iota
	SequentialMode = iota
)

func InitPlaylists() *Playlists {
	rand.Seed(time.Now().Unix())

	playlists := &Playlists{
		playlists: make(map[string]*Playlist),
		playMode:  NormalMode,
	}
	return playlists
}

func (playlists *Playlists) Get(name string) *Playlist {
	return playlists.playlists[name]
}

func (playlists *Playlists) Playlists() int {
	return len(playlists.playlists)
}

func (playlists *Playlists) AddPlaylist(name string, playlist *Playlist) {
	playlists.playlists[name] = playlist
}

func (playlists *Playlists) Merge(newPlaylist *Playlists) {
	for key, value := range newPlaylist.playlists {
		playlists.playlists[key] = value
	}
}

func (playlists *Playlists) GetNames() []string {
	names := make([]string, playlists.Playlists())
	i := 0
	for name, _ := range playlists.playlists {
		names[i] = name
		i++
	}
	return names
}

func (playlists *Playlists) Tracks() int {
	numberOfTracks := 0
	for _, playlist := range playlists.playlists {
		numberOfTracks += playlist.Tracks()
	}
	return numberOfTracks
}

func (playlists *Playlists) PremadeTracks() int {
	return len(playlists.premadeTracks)
}

func (playlists *Playlists) buildPlaylistForNewMode() error {
	if playlists.isNormalMode() {
		playlists.premadeTracks = nil
		return nil
	}

	var numberOfTracks int
	var playlist *Playlist
	if playlists.isRandomMode() {
		playlist = playlists.Get(playlists.currentPlaylist)
		numberOfTracks = playlist.Tracks()
	} else {
		// all random and sequential
		numberOfTracks = playlists.Tracks()
	}

	if numberOfTracks == 0 {
		return errors.New("No tracks selected")
	}

	playlists.premadeTracks = make([]*Track, numberOfTracks)
	if playlists.isRandomMode() {
		playlists.buildRandomModeTracks(playlist, numberOfTracks)
	} else if playlists.isAllRandomMode() {
		playlists.buildAllRandomModeTracks(numberOfTracks)
	} else {
		// sequential
		playlists.buildSequentialModeTracks()
	}

	playlists.currentIndexTrack = -1

	return nil
}

func (playlists *Playlists) buildRandomModeTracks(playlist *Playlist, numberOfTracks int) {
	perm := getRandomPermutation(numberOfTracks)

	index := 0
	for i := 0; i < playlist.Tracks(); i++ {
		playlists.premadeTracks[perm[index]] = playlist.Track(i)
		index++
	}
}

func (playlists *Playlists) buildAllRandomModeTracks(numberOfTracks int) {
	perm := getRandomPermutation(numberOfTracks)

	index := 0
	for _, playlist := range playlists.playlists {
		for i := 0; i < playlist.Tracks(); i++ {
			playlists.premadeTracks[perm[index]] = playlist.Track(i)
			index++
		}
	}
}

func (playlists *Playlists) buildSequentialModeTracks() {
	index := 0
	for _, playlist := range playlists.playlists {
		for i := 0; i < playlist.Tracks(); i++ {
			playlists.premadeTracks[index] = playlist.Track(i)
			index++
		}
	}
}

func getRandomPermutation(numberOfTracks int) []int {
	return rand.Perm(numberOfTracks)
}

func (playlists *Playlists) GetRandomNextPlaylistAndTrack() (string, int) {
	index := rand.Intn(playlists.Playlists())
	count := 0
	var playlist *Playlist
	var newPlaylistName string
	for key, value := range playlists.playlists {
		if index == count {
			newPlaylistName = key
			playlist = value
			break
		}
		count++
	}
	return newPlaylistName, playlist.GetRandomNextTrack()
}

func (playlists *Playlists) GetModeAsString() string {
	if playlists.playMode == RandomMode {
		return "[Random] "
	}
	if playlists.playMode == AllRandomMode {
		return "[All Random] "
	}
	return ""
}

func (playlists *Playlists) SetCurrents(currentPlaylist string, currentIndexTrack int) {
	playlists.currentPlaylist = currentPlaylist
	playlists.currentIndexTrack = currentIndexTrack
}

func (playlists *Playlists) GetNext() (*Track, bool) {
	repeating := false
	if playlists.premadeTracks != nil {
		playlists.currentIndexTrack++
		if playlists.currentIndexTrack >= len(playlists.premadeTracks) {
			playlists.currentIndexTrack = 0
			repeating = true
		}
		return playlists.premadeTracks[playlists.currentIndexTrack], repeating
	}

	playlist := playlists.Get(playlists.currentPlaylist)
	playlists.currentIndexTrack = playlist.GetNextTrack(playlists.currentIndexTrack)

	return playlist.Track(playlists.currentIndexTrack), repeating
}

func (playlists *Playlists) SetMode(mode int) {
	playlists.playMode = mode
	playlists.buildPlaylistForNewMode()
}

func (playlists *Playlists) InvertMode(mode int) int {
	if mode == playlists.playMode {
		playlists.SetMode(NormalMode)
	} else {
		playlists.SetMode(mode)
	}
	return playlists.playMode
}

func (playlists *Playlists) HasPlaylistSelected() bool {
	return playlists.currentPlaylist != ""
}

func (playlists *Playlists) isAllRandomMode() bool {
	return playlists.playMode == AllRandomMode
}

func (playlists *Playlists) isRandomMode() bool {
	return playlists.playMode == RandomMode
}

func (playlists *Playlists) isNormalMode() bool {
	return playlists.playMode == NormalMode
}
<commit_msg>Sequential playlist in alphabetical order<commit_after>package sconsify

import (
	"errors"
	"math/rand"
	"sort"
	"time"
)

type Playlists struct {
	playlists         map[string]*Playlist
	currentIndexTrack int
	currentPlaylist   string
	playMode          int
	premadeTracks     []*Track
}

const (
	NormalMode     = iota
	RandomMode     = iota
	AllRandomMode  = iota
	SequentialMode = iota
)

func InitPlaylists() *Playlists {
	rand.Seed(time.Now().Unix())

	playlists := &Playlists{
		playlists: make(map[string]*Playlist),
		playMode:  NormalMode,
	}
	return playlists
}

func (playlists *Playlists) Get(name string) *Playlist {
	return playlists.playlists[name]
}

func (playlists *Playlists) Playlists() int {
	return len(playlists.playlists)
}

func (playlists *Playlists) AddPlaylist(name string, playlist *Playlist) {
	playlists.playlists[name] = playlist
}

func (playlists *Playlists) Merge(newPlaylist *Playlists) {
	for key, value := range newPlaylist.playlists {
		playlists.playlists[key] = value
	}
}

func (playlists *Playlists) GetNames() []string {
	names := make([]string, playlists.Playlists())
	i := 0
	for name, _ := range playlists.playlists {
		names[i] = name
		i++
	}
	return names
}

func (playlists *Playlists) Tracks() int {
	numberOfTracks := 0
	for _, playlist := range playlists.playlists {
		numberOfTracks += playlist.Tracks()
	}
	return numberOfTracks
}

func (playlists *Playlists) PremadeTracks() int {
	return len(playlists.premadeTracks)
}

func (playlists *Playlists) buildPlaylistForNewMode() error {
	if playlists.isNormalMode() {
		playlists.premadeTracks = nil
		return nil
	}

	var numberOfTracks int
	var playlist *Playlist
	if playlists.isRandomMode() {
		playlist = playlists.Get(playlists.currentPlaylist)
		numberOfTracks = playlist.Tracks()
	} else {
		// all random and sequential
		numberOfTracks = playlists.Tracks()
	}

	if numberOfTracks == 0 {
		return errors.New("No tracks selected")
	}

	playlists.premadeTracks = make([]*Track, numberOfTracks)
	if playlists.isRandomMode() {
		playlists.buildRandomModeTracks(playlist, numberOfTracks)
	} else if playlists.isAllRandomMode() {
		playlists.buildAllRandomModeTracks(numberOfTracks)
	} else {
		// sequential
		playlists.buildSequentialModeTracks()
	}

	playlists.currentIndexTrack = -1

	return nil
}

func (playlists *Playlists) buildRandomModeTracks(playlist *Playlist, numberOfTracks int) {
	perm := getRandomPermutation(numberOfTracks)

	index := 0
	for i := 0; i < playlist.Tracks(); i++ {
		playlists.premadeTracks[perm[index]] = playlist.Track(i)
		index++
	}
}

func (playlists *Playlists) buildAllRandomModeTracks(numberOfTracks int) {
	perm := getRandomPermutation(numberOfTracks)

	index := 0
	for _, playlist := range playlists.playlists {
		for i := 0; i < playlist.Tracks(); i++ {
			playlists.premadeTracks[perm[index]] = playlist.Track(i)
			index++
		}
	}
}

func (playlists *Playlists) buildSequentialModeTracks() {
	names := playlists.GetNames()
	sort.Strings(names)

	index := 0
	for _, name := range names {
		playlist := playlists.playlists[name]
		for i := 0; i < playlist.Tracks(); i++ {
			playlists.premadeTracks[index] = playlist.Track(i)
			index++
		}
	}
}

func getRandomPermutation(numberOfTracks int) []int {
	return rand.Perm(numberOfTracks)
}

func (playlists *Playlists) GetRandomNextPlaylistAndTrack() (string, int) {
	index := rand.Intn(playlists.Playlists())
	count := 0
	var playlist *Playlist
	var newPlaylistName string
	for key, value := range playlists.playlists {
		if index == count {
			newPlaylistName = key
			playlist = value
			break
		}
		count++
	}
	return newPlaylistName, playlist.GetRandomNextTrack()
}

func (playlists *Playlists) GetModeAsString() string {
	if playlists.playMode == RandomMode {
		return "[Random] "
	}
	if playlists.playMode == AllRandomMode {
		return "[All Random] "
	}
	return ""
}

func (playlists *Playlists) SetCurrents(currentPlaylist string, currentIndexTrack int) {
	playlists.currentPlaylist = currentPlaylist
	playlists.currentIndexTrack = currentIndexTrack
}

func (playlists *Playlists) GetNext() (*Track, bool) {
	repeating := false
	if playlists.premadeTracks != nil {
		playlists.currentIndexTrack++
		if playlists.currentIndexTrack >= len(playlists.premadeTracks) {
			playlists.currentIndexTrack = 0
			repeating = true
		}
		return playlists.premadeTracks[playlists.currentIndexTrack], repeating
	}

	playlist := playlists.Get(playlists.currentPlaylist)
	playlists.currentIndexTrack = playlist.GetNextTrack(playlists.currentIndexTrack)

	return playlist.Track(playlists.currentIndexTrack), repeating
}

func (playlists *Playlists) SetMode(mode int) {
	playlists.playMode = mode
	playlists.buildPlaylistForNewMode()
}

func (playlists *Playlists) InvertMode(mode int) int {
	if mode == playlists.playMode {
		playlists.SetMode(NormalMode)
	} else {
		playlists.SetMode(mode)
	}
	return playlists.playMode
}

func (playlists *Playlists) HasPlaylistSelected() bool {
	return playlists.currentPlaylist != ""
}

func (playlists *Playlists) isAllRandomMode() bool {
	return playlists.playMode == AllRandomMode
}

func (playlists *Playlists) isRandomMode() bool {
	return playlists.playMode == RandomMode
}

func (playlists *Playlists) isNormalMode() bool {
	return playlists.playMode == NormalMode
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/joeshaw/envdecode"
	"gopkg.in/mailgun/mailgun-go.v1"
)

const (
	mailDomain  = "list.brandur.org"
	fromAddress = "Brandur <brandur@brandur.org>"
)

// Conf contains configuration information for the command. It's extracted from
// environment variables.
type Conf struct {
	// MailgunAPIKey is a key for Mailgun used to send email.
	MailgunAPIKey string `env:"MAILGUN_API_KEY,required"`
}

// Left as a global for now for the sake of convenience, but it's not used in
// very many places and can probably be refactored as a local if desired.
var conf Conf

func renderAndSend(records [][]string, live bool) error {
	mg := mailgun.NewMailgun(mailDomain, conf.MailgunAPIKey, "")

	for _, record := range records {
		// skip empty lines
		if len(record) == 0 {
			continue
		}

		if len(record) < 2 {
			return fmt.Errorf("Record less than 2-width: %v", record)
		}

		name := record[0]
		recipient := record[1]

		subject := "I'm subscribing you to my newsletter"
		body := fmt.Sprintf(`%s,

One thing I've realized over the last few years is that I
don't do a very good job of keeping in touch with people.
On top of that, I also don't do much with social media, so
it's not even possible to passively stay appraised of what
I'm doing.

On a recent trip I was inspired to try and address this,
and to that end I'm trying something new: a newsletter.
Each issue will be a small compilation of stories and
thoughts. The bursts will be pretty infrequent; I'll send
out roughly as often as we get to witness a total solar
eclipse.

(This email is not the newsletter, but) I'm about to send
its first issue, and I've added you to the list to receive
it. If you don't want it, either reply to me here saying
so, or wait until I send it and click the very conspicuous
unsubscribe link (I won't get notified on an unsubscribe,
and even if I did, I wouldn't take it personally).

Thanks, and I hope you like it!

Brandur`,
			name,
		)

		if live {
			message := mailgun.NewMessage(fromAddress, subject, body, recipient)
			resp, _, err := mg.Send(message)
			if err != nil {
				log.Fatal(err)
			}
			log.Printf(`Sent to: %s (response: "%s")`, recipient, resp)
		} else {
			fmt.Printf("To: %v <%v>\n", name, recipient)
			fmt.Printf("Subject: %v\n\n", subject)
			fmt.Printf("%v\n---\n\n", body)
		}
	}

	return nil
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %v [-live] <recipient_file>\n", os.Args[0])
		flag.PrintDefaults()
		os.Exit(0)
	}

	live := flag.Bool("live", false,
		"Send to list (as opposed to dry run)")
	flag.Parse()

	if len(flag.Args()) != 1 {
		flag.Usage()
	}

	err := envdecode.Decode(&conf)
	if err != nil {
		log.Fatal(err)
	}

	f, err := os.Open(flag.Arg(0))
	if err != nil {
		log.Fatal(err)
	}

	r := csv.NewReader(f)
	r.Comment = '#'

	records, err := r.ReadAll()
	if err != nil {
		log.Fatal(err)
	}

	err = renderAndSend(records, *live)
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>More final form of copy<commit_after>package main

import (
	"encoding/csv"
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/joeshaw/envdecode"
	"gopkg.in/mailgun/mailgun-go.v1"
)

const (
	mailDomain  = "list.brandur.org"
	fromAddress = "Brandur <brandur@brandur.org>"
)

// Conf contains configuration information for the command. It's extracted from
// environment variables.
type Conf struct {
	// MailgunAPIKey is a key for Mailgun used to send email.
	MailgunAPIKey string `env:"MAILGUN_API_KEY,required"`
}

// Left as a global for now for the sake of convenience, but it's not used in
// very many places and can probably be refactored as a local if desired.
var conf Conf

func renderAndSend(records [][]string, live bool) error {
	mg := mailgun.NewMailgun(mailDomain, conf.MailgunAPIKey, "")

	for _, record := range records {
		// skip empty lines
		if len(record) == 0 {
			continue
		}

		if len(record) < 2 {
			return fmt.Errorf("Record less than 2-width: %v", record)
		}

		name := record[0]
		recipient := record[1]

		subject := "I'm subscribing you to my newsletter"
		body := fmt.Sprintf(`%s,

One thing I've realized over the last few years is that I
don't do a very good job of keeping up with old friends and
family. I don't really use Facebook, link only technical
writing on on Twitter, and the new age social media
platforms like Instagram and Snapchat are well beyond me,
so I'm not even staying in touch in a passive sense.

On a recent trip to Portland I was thinking about this
problem and what I might be able to do to about it, and as
I was walking the city's eclectic streets, I had an idea:
an email newsletter. Each issue will be a short compilation
of stories, photographs, and ideas. It will remind me to
send something to you, and hopefully remind you to send
something back.

In case you have a healthy fear of inbox overload, the
bursts will be pretty infrequent; I'll be competing with
total solar eclipses on time scale.

(This email is not the newsletter, but) I'm about to send
its first issue, and I've added you to the list to receive
it. If you don't want it, either reply to me here saying
so, or wait until I send it and click the very conspicuous
unsubscribe link (I won't get notified on an unsubscribe,
and even if I did, I wouldn't take it personally).

Thanks, and take care!

Brandur`,
			name,
		)

		if live {
			message := mailgun.NewMessage(fromAddress, subject, body, recipient)
			resp, _, err := mg.Send(message)
			if err != nil {
				log.Fatal(err)
			}
			log.Printf(`Sent to: %s (response: "%s")`, recipient, resp)
		} else {
			fmt.Printf("To: %v <%v>\n", name, recipient)
			fmt.Printf("Subject: %v\n\n", subject)
			fmt.Printf("%v\n---\n\n", body)
		}
	}

	return nil
}

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %v [-live] <recipient_file>\n", os.Args[0])
		flag.PrintDefaults()
		os.Exit(0)
	}

	live := flag.Bool("live", false,
		"Send to list (as opposed to dry run)")
	flag.Parse()

	if len(flag.Args()) != 1 {
		flag.Usage()
	}

	err := envdecode.Decode(&conf)
	if err != nil {
		log.Fatal(err)
	}

	f, err := os.Open(flag.Arg(0))
	if err != nil {
		log.Fatal(err)
	}

	r := csv.NewReader(f)
	r.Comment = '#'

	records, err := r.ReadAll()
	if err != nil {
		log.Fatal(err)
	}

	err = renderAndSend(records, *live)
	if err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package analysis

import (
	"fmt"
	"strings"

	"github.com/gonum/graph"

	osgraph "github.com/openshift/origin/pkg/api/graph"
	kubeedges "github.com/openshift/origin/pkg/api/kubegraph"
	kubegraph "github.com/openshift/origin/pkg/api/kubegraph/nodes"
)

const (
	DuelingRepliationControllerWarning = "DuelingReplicationControllers"
)

func FindDuelingReplicationControllers(g osgraph.Graph) []osgraph.Marker {
	markers := []osgraph.Marker{}

	for _, uncastRCNode := range g.NodesByKind(kubegraph.ReplicationControllerNodeKind) {
		rcNode := uncastRCNode.(*kubegraph.ReplicationControllerNode)

		for _, uncastPodNode := range g.PredecessorNodesByEdgeKind(rcNode, kubeedges.ManagedByRCEdgeKind) {
			podNode := uncastPodNode.(*kubegraph.PodNode)

			// check to see if this pod is managed by more than one RC
			uncastOwningRCs := g.SuccessorNodesByEdgeKind(podNode, kubeedges.ManagedByRCEdgeKind)
			if len(uncastOwningRCs) > 1 {
				involvedRCNames := []string{}
				relatedNodes := []graph.Node{uncastPodNode}

				for _, uncastOwningRC := range uncastOwningRCs {
					if uncastOwningRC.ID() == rcNode.ID() {
						continue
					}
					owningRC := uncastOwningRC.(*kubegraph.ReplicationControllerNode)
					involvedRCNames = append(involvedRCNames, owningRC.ResourceString())

					relatedNodes = append(relatedNodes, uncastOwningRC)
				}

				markers = append(markers, osgraph.Marker{
					Node:         rcNode,
					RelatedNodes: relatedNodes,

					Severity: osgraph.WarningSeverity,
					Key:      DuelingRepliationControllerWarning,
					Message:  fmt.Sprintf("%s is competing for %s with %s", rcNode.ResourceString(), podNode.ResourceString(), strings.Join(involvedRCNames, ", ")),
				})
			}
		}
	}

	return markers
}
<commit_msg>DuelingRepliationControllerWarning -> DuelingReplicationControllerWarning<commit_after>package analysis

import (
	"fmt"
	"strings"

	"github.com/gonum/graph"

	osgraph "github.com/openshift/origin/pkg/api/graph"
	kubeedges "github.com/openshift/origin/pkg/api/kubegraph"
	kubegraph "github.com/openshift/origin/pkg/api/kubegraph/nodes"
)

const (
	DuelingReplicationControllerWarning = "DuelingReplicationControllers"
)

func FindDuelingReplicationControllers(g osgraph.Graph) []osgraph.Marker {
	markers := []osgraph.Marker{}

	for _, uncastRCNode := range g.NodesByKind(kubegraph.ReplicationControllerNodeKind) {
		rcNode := uncastRCNode.(*kubegraph.ReplicationControllerNode)

		for _, uncastPodNode := range g.PredecessorNodesByEdgeKind(rcNode, kubeedges.ManagedByRCEdgeKind) {
			podNode := uncastPodNode.(*kubegraph.PodNode)

			// check to see if this pod is managed by more than one RC
			uncastOwningRCs := g.SuccessorNodesByEdgeKind(podNode, kubeedges.ManagedByRCEdgeKind)
			if len(uncastOwningRCs) > 1 {
				involvedRCNames := []string{}
				relatedNodes := []graph.Node{uncastPodNode}

				for _, uncastOwningRC := range uncastOwningRCs {
					if uncastOwningRC.ID() == rcNode.ID() {
						continue
					}
					owningRC := uncastOwningRC.(*kubegraph.ReplicationControllerNode)
					involvedRCNames = append(involvedRCNames, owningRC.ResourceString())

					relatedNodes = append(relatedNodes, uncastOwningRC)
				}

				markers = append(markers, osgraph.Marker{
					Node:         rcNode,
					RelatedNodes: relatedNodes,

					Severity: osgraph.WarningSeverity,
					Key:      DuelingReplicationControllerWarning,
					Message:  fmt.Sprintf("%s is competing for %s with %s", rcNode.ResourceString(), podNode.ResourceString(), strings.Join(involvedRCNames, ", ")),
				})
			}
		}
	}

	return markers
}
<|endoftext|>


<commit_before>package kaonashi

import (
	"database/sql"
	"log"
	"time"
)

func getNote(db *DB, noteID string) (Note, error) {
	note := Note{}
	err := db.Get(&note, `
	SELECT
	  id
	  ,title
	  ,body
	  ,updated
	  ,created
    FROM note
	WHERE id = $1
	`, noteID)
	if err != nil {
		if err == sql.ErrNoRows {
			log.Printf(
				"getNote: no rows round for id: %s", noteID)
			return note, err
		}
		log.Printf("getNote: %s", err)
		return note, err
	}
	return note, nil
}

func createNote(db *DB, note Note) error {
	_, err := db.Exec(`
	INSERT INTO note (title, body, created, updated)
	VALUES (?, ?, ?, ?)
	`, note.Title, note.Body, note.Created, note.Updated)
	if err != nil {
		log.Printf("createNote: %s", err)
		return err
	}
	return nil
}

func getNoteTitles(db *DB) ([]NoteTitle, error) {
	noteTitles := []NoteTitle{}
	err := db.Select(&noteTitles, `
	SELECT
	  id
	  ,title
	  ,updated
	  ,created
    FROM note
	ORDER BY updated DESC
	`)
	if err != nil {
		log.Printf("getNoteTitles: %s", err)
		return noteTitles, err
	}
	return noteTitles, nil
}

func deleteNote(db *DB, noteID string) error {
	_, err := db.Exec(`
	DELETE FROM note WHERE id = ?
	`, noteID)
	if err != nil {
		log.Printf("deleteNote: %s", err)
		return err
	}
	return nil
}

func updateNote(db *DB, note Note) error {
	_, err := db.Exec(`
	UPDATE note
	SET
	  title = ?
	  ,body = ?
	  ,updated = ?
	WHERE id = ?
	`, note.Title, note.Body, time.Now().String(), note.ID)
	if err != nil {
		log.Printf("updateNote: %s", err)
		return err
	}
	return nil
}

func createTables(db *DB) error {
	_, err := db.Exec(`
	CREATE TABLE note (
	  id INTEGER PRIMARY KEY AUTOINCREMENT
	  ,title TEXT
	  ,body TEXT
	  ,created TEXT NOT NULL
	  ,updated TEXT NOT NULL
	)
	`)
	if err != nil {
		log.Printf("createTables: %s", err)
		return err
	}
	return nil
}
<commit_msg>Use NamedExec for insert statement<commit_after>package kaonashi

import (
	"database/sql"
	"log"
	"time"
)

func getNote(db *DB, noteID string) (Note, error) {
	note := Note{}
	err := db.Get(&note, `
	SELECT
	  id
	  ,title
	  ,body
	  ,updated
	  ,created
    FROM note
	WHERE id = $1
	`, noteID)
	if err != nil {
		if err == sql.ErrNoRows {
			log.Printf(
				"getNote: no rows round for id: %s", noteID)
			return note, err
		}
		log.Printf("getNote: %s", err)
		return note, err
	}
	return note, nil
}

func createNote(db *DB, note Note) error {
	_, err := db.NamedExec(`
	INSERT INTO note (title, body, created, updated)
	VALUES (:title, :body, :created, :updated)
	`, note)
	if err != nil {
		log.Printf("createNote: %s", err)
		return err
	}
	return nil
}

func getNoteTitles(db *DB) ([]NoteTitle, error) {
	noteTitles := []NoteTitle{}
	err := db.Select(&noteTitles, `
	SELECT
	  id
	  ,title
	  ,updated
	  ,created
    FROM note
	ORDER BY updated DESC
	`)
	if err != nil {
		log.Printf("getNoteTitles: %s", err)
		return noteTitles, err
	}
	return noteTitles, nil
}

func deleteNote(db *DB, noteID string) error {
	_, err := db.Exec(`
	DELETE FROM note WHERE id = ?
	`, noteID)
	if err != nil {
		log.Printf("deleteNote: %s", err)
		return err
	}
	return nil
}

func updateNote(db *DB, note Note) error {
	_, err := db.Exec(`
	UPDATE note
	SET
	  title = ?
	  ,body = ?
	  ,updated = ?
	WHERE id = ?
	`, note.Title, note.Body, time.Now().String(), note.ID)
	if err != nil {
		log.Printf("updateNote: %s", err)
		return err
	}
	return nil
}

func createTables(db *DB) error {
	_, err := db.Exec(`
	CREATE TABLE note (
	  id INTEGER PRIMARY KEY AUTOINCREMENT
	  ,title TEXT
	  ,body TEXT
	  ,created TEXT NOT NULL
	  ,updated TEXT NOT NULL
	)
	`)
	if err != nil {
		log.Printf("createTables: %s", err)
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>package dockerscript

import (
	"github.com/dotcloud/docker/pkg/dockerscript/scanner"
	"fmt"
	"io"
	"strings"
)

type Command struct {
	Args []string
	Children []*Command
}

func Parse(src io.Reader) ([]*Command, error) {
	s := &scanner.Scanner{}
	s.Init(src)
	s.Whitespace = 1<<'\t' | 1<<' '
	s.Mode = scanner.ScanStrings | scanner.ScanRawStrings | scanner.ScanIdents
	expr, err := parse(s, "")
	if err != nil {
		return nil, fmt.Errorf("line %d:%d: %v\n", s.Pos().Line, s.Pos().Column, err)
	}
	return expr, nil
}

func (cmd *Command) subString(depth int) string {
	var prefix string
	for i:=0; i<depth; i++ {
		prefix += "  "
	}
	s := prefix + strings.Join(cmd.Args, ", ")
	if len(cmd.Children) > 0 {
		s += " {\n"
		for _, subcmd := range cmd.Children {
			s += subcmd.subString(depth + 1)
		}
		s += prefix + "}"
	}
	s += "\n"
	return s
}

func (cmd *Command) String() string {
	return cmd.subString(0)
}

func parseArgs(s *scanner.Scanner) ([]string, rune, error) {
	var parseError error
	// FIXME: we overwrite previously set error
	s.Error = func(s *scanner.Scanner, msg string) {
		parseError = fmt.Errorf(msg)
		// parseError = fmt.Errorf("line %d:%d: %s\n", s.Pos().Line, s.Pos().Column, msg)
	}
	var args []string
	tok := s.Scan()
	for tok != scanner.EOF {
		if parseError != nil {
			return args, tok, parseError
		}
		text := s.TokenText()
		if text == "{" || text == "}" || text == "\n" || text == "\r" || text == ";" {
			return args, tok, nil
		}
		args = append(args, text)
		tok = s.Scan()
	}
	return args, tok, nil
}

func parse(s *scanner.Scanner, opener string) (expr []*Command, err error) {
	/*
	defer func() {
		fmt.Printf("parse() returned %d commands:\n", len(expr))
		for _, c := range expr {
			fmt.Printf("\t----> %s\n", c)
		}
	}()
	*/
	for {
		args, tok, err := parseArgs(s)
		if err != nil {
			return nil, err
		}
		cmd := &Command{Args: args}
		afterArgs := s.TokenText()
		if afterArgs == "{" {
			children, err := parse(s, "{")
			if err != nil {
				return nil, err
			}
			cmd.Children = children
		} else if afterArgs == "}" && opener != "{" {
			return nil, fmt.Errorf("unexpected end of block '}'")
		}
		if len(cmd.Args) > 0 || len(cmd.Children) > 0 {
			expr = append(expr, cmd)
		}
		if tok == scanner.EOF || afterArgs == "}" {
			break
		}
	}
	return expr, nil
}
<commit_msg>dockerscript: support '#' line comments<commit_after>package dockerscript

import (
	"github.com/dotcloud/docker/pkg/dockerscript/scanner"
	"fmt"
	"io"
	"strings"
)

type Command struct {
	Args []string
	Children []*Command
}

type Scanner struct {
	scanner.Scanner
	commentLine bool
}

func Parse(src io.Reader) ([]*Command, error) {
	s := &Scanner{}
	s.Init(src)
	s.Whitespace = 1<<'\t' | 1<<' '
	s.Mode = scanner.ScanStrings | scanner.ScanRawStrings | scanner.ScanIdents
	expr, err := parse(s, "")
	if err != nil {
		return nil, fmt.Errorf("line %d:%d: %v\n", s.Pos().Line, s.Pos().Column, err)
	}
	return expr, nil
}

func (cmd *Command) subString(depth int) string {
	var prefix string
	for i:=0; i<depth; i++ {
		prefix += "  "
	}
	s := prefix + strings.Join(cmd.Args, ", ")
	if len(cmd.Children) > 0 {
		s += " {\n"
		for _, subcmd := range cmd.Children {
			s += subcmd.subString(depth + 1)
		}
		s += prefix + "}"
	}
	s += "\n"
	return s
}

func (cmd *Command) String() string {
	return cmd.subString(0)
}

func parseArgs(s *Scanner) ([]string, rune, error) {
	var parseError error
	// FIXME: we overwrite previously set error
	s.Error = func(s *scanner.Scanner, msg string) {
		parseError = fmt.Errorf(msg)
		// parseError = fmt.Errorf("line %d:%d: %s\n", s.Pos().Line, s.Pos().Column, msg)
	}
	var args []string
	tok := s.Scan()
	for tok != scanner.EOF {
		if parseError != nil {
			return args, tok, parseError
		}
		text := s.TokenText()
		// Toggle line comment
		if strings.HasPrefix(text, "#") {
			s.commentLine = true
		} else if text == "\n" || text == "\r" {
			s.commentLine = false
			return args, tok, nil
		}
		if !s.commentLine {
			if text == "{" || text == "}" || text == "\n" || text == "\r" || text == ";" {
				return args, tok, nil
			}
			args = append(args, text)
		}
		tok = s.Scan()
	}
	return args, tok, nil
}

func parse(s *Scanner, opener string) (expr []*Command, err error) {
	/*
	defer func() {
		fmt.Printf("parse() returned %d commands:\n", len(expr))
		for _, c := range expr {
			fmt.Printf("\t----> %s\n", c)
		}
	}()
	*/
	for {
		args, tok, err := parseArgs(s)
		if err != nil {
			return nil, err
		}
		cmd := &Command{Args: args}
		afterArgs := s.TokenText()
		if afterArgs == "{" {
			children, err := parse(s, "{")
			if err != nil {
				return nil, err
			}
			cmd.Children = children
		} else if afterArgs == "}" && opener != "{" {
			return nil, fmt.Errorf("unexpected end of block '}'")
		}
		if len(cmd.Args) > 0 || len(cmd.Children) > 0 {
			expr = append(expr, cmd)
		}
		if tok == scanner.EOF || afterArgs == "}" {
			break
		}
	}
	return expr, nil
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 support

import (
	"fmt"
	"testing"
)

var linter = Linter{}
var lintError LintError = fmt.Errorf("Foobar")

func TestRunLinterRule(t *testing.T) {
	var tests = []struct {
		Severity                int
		LintError               error
		ExpectedMessages        int
		ExpectedReturn          bool
		ExpectedHighestSeverity int
	}{
		{InfoSev, lintError, 1, false, InfoSev},
		{WarningSev, lintError, 2, false, WarningSev},
		{ErrorSev, lintError, 3, false, ErrorSev},
		// No error so it returns true
		{ErrorSev, nil, 3, true, ErrorSev},
		// Invalid severity values
		{4, lintError, 3, false, ErrorSev},
		{22, lintError, 3, false, ErrorSev},
		{-1, lintError, 3, false, ErrorSev},
	}

	for _, test := range tests {
		isValid := linter.RunLinterRule(test.Severity, test.LintError)
		if len(linter.Messages) != test.ExpectedMessages {
			t.Errorf("RunLinterRule(%d, %v), linter.Messages should now have %d message, we got %d", test.Severity, test.LintError, test.ExpectedMessages, len(linter.Messages))
		}

		if linter.HighestSeverity != test.ExpectedHighestSeverity {
			t.Errorf("RunLinterRule(%d, %v), linter.HighestSeverity should be %d, we got %d", test.Severity, test.LintError, test.ExpectedHighestSeverity, linter.HighestSeverity)
		}

		if isValid != test.ExpectedReturn {
			t.Errorf("RunLinterRule(%d, %v), should have returned %t but returned %t", test.Severity, test.LintError, test.ExpectedReturn, isValid)
		}
	}
}

func TestMessage(t *testing.T) {
	m := Message{ErrorSev, "Foo"}
	if m.String() != "[ERROR] Foo" {
		t.Errorf("Unexpected output: %s", m.String())
	}

	m = Message{WarningSev, "Bar"}
	if m.String() != "[WARNING] Bar" {
		t.Errorf("Unexpected output: %s", m.String())
	}

	m = Message{InfoSev, "FooBar"}
	if m.String() != "[INFO] FooBar" {
		t.Errorf("Unexpected output: %s", m.String())
	}
}
<commit_msg>Improve tests to ensure highest severity is retained<commit_after>/*
Copyright 2016 The Kubernetes Authors All rights reserved.

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 support

import (
	"fmt"
	"testing"
)

var linter = Linter{}
var lintError LintError = fmt.Errorf("Foobar")

func TestRunLinterRule(t *testing.T) {
	var tests = []struct {
		Severity                int
		LintError               error
		ExpectedMessages        int
		ExpectedReturn          bool
		ExpectedHighestSeverity int
	}{
		{InfoSev, lintError, 1, false, InfoSev},
		{WarningSev, lintError, 2, false, WarningSev},
		{ErrorSev, lintError, 3, false, ErrorSev},
		// No error so it returns true
		{ErrorSev, nil, 3, true, ErrorSev},
		// Retains highest severity
		{InfoSev, lintError, 4, false, ErrorSev},
		// Invalid severity values
		{4, lintError, 4, false, ErrorSev},
		{22, lintError, 4, false, ErrorSev},
		{-1, lintError, 4, false, ErrorSev},
	}

	for _, test := range tests {
		isValid := linter.RunLinterRule(test.Severity, test.LintError)
		if len(linter.Messages) != test.ExpectedMessages {
			t.Errorf("RunLinterRule(%d, %v), linter.Messages should now have %d message, we got %d", test.Severity, test.LintError, test.ExpectedMessages, len(linter.Messages))
		}

		if linter.HighestSeverity != test.ExpectedHighestSeverity {
			t.Errorf("RunLinterRule(%d, %v), linter.HighestSeverity should be %d, we got %d", test.Severity, test.LintError, test.ExpectedHighestSeverity, linter.HighestSeverity)
		}

		if isValid != test.ExpectedReturn {
			t.Errorf("RunLinterRule(%d, %v), should have returned %t but returned %t", test.Severity, test.LintError, test.ExpectedReturn, isValid)
		}
	}
}

func TestMessage(t *testing.T) {
	m := Message{ErrorSev, "Foo"}
	if m.String() != "[ERROR] Foo" {
		t.Errorf("Unexpected output: %s", m.String())
	}

	m = Message{WarningSev, "Bar"}
	if m.String() != "[WARNING] Bar" {
		t.Errorf("Unexpected output: %s", m.String())
	}

	m = Message{InfoSev, "FooBar"}
	if m.String() != "[INFO] FooBar" {
		t.Errorf("Unexpected output: %s", m.String())
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2021 The Knative 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 network

import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"

	"knative.dev/pkg/logging"

	ctrl "knative.dev/control-protocol/pkg"
	"knative.dev/control-protocol/pkg/service"
)

var listenConfig = net.ListenConfig{
	KeepAlive: 30 * time.Second,
}

type ControlServerOptions struct {
	port         int
	listenConfig *net.ListenConfig
}

type ControlServerOption func(*ControlServerOptions)

func WithPort(port int) ControlServerOption {
	return func(options *ControlServerOptions) {
		options.port = port
	}
}

type ControlServer struct {
	ctrl.Service
	closedCh <-chan struct{}
	port     int
}

// ClosedCh returns a channel which is closed after the server stopped listening
func (cs *ControlServer) ClosedCh() <-chan struct{} {
	return cs.closedCh
}

// ListeningPort is the port where the server is actually listening
func (cs *ControlServer) ListeningPort() int {
	return cs.port
}

func StartInsecureControlServer(ctx context.Context, options ...ControlServerOption) (*ControlServer, error) {
	return StartControlServer(ctx, nil, options...)
}

func StartControlServer(ctx context.Context, tlsConfigLoader func() (*tls.Config, error), options ...ControlServerOption) (*ControlServer, error) {
	opts := ControlServerOptions{
		port:         9000,
		listenConfig: &listenConfig,
	}

	for _, fn := range options {
		fn(&opts)
	}

	ln, err := opts.listenConfig.Listen(ctx, "tcp", fmt.Sprintf(":%d", opts.port))
	if err != nil {
		return nil, err
	}
	listeningAddress := ln.Addr().String()
	logging.FromContext(ctx).Infof("Started listener: %s", listeningAddress)

	// Parse the port
	port, err := strconv.Atoi(listeningAddress[strings.LastIndex(listeningAddress, ":")+1:])
	if err != nil {
		return nil, fmt.Errorf("cannot parse the listening port: %w", err)
	}

	tcpConn := newServerTcpConnection(ctx, ln, tlsConfigLoader)
	ctrlService := service.NewService(ctx, tcpConn)

	closedServerCh := make(chan struct{})

	tcpConn.startAcceptPolling(closedServerCh)

	ctrlServer := &ControlServer{
		Service:  ctrlService,
		closedCh: closedServerCh,
		port:     port,
	}

	return ctrlServer, nil
}

type serverTcpConnection struct {
	baseTcpConnection

	listener        net.Listener
	tlsConfigLoader func() (*tls.Config, error)
}

func newServerTcpConnection(ctx context.Context, listener net.Listener, loader func() (*tls.Config, error)) *serverTcpConnection {
	c := &serverTcpConnection{
		baseTcpConnection: baseTcpConnection{
			ctx:                    ctx,
			logger:                 logging.FromContext(ctx),
			outboundMessageChannel: make(chan *ctrl.OutboundMessage, 10),
			inboundMessageChannel:  make(chan *ctrl.InboundMessage, 10),
			errors:                 make(chan error, 10),
		},
		listener:        listener,
		tlsConfigLoader: loader,
	}
	return c
}

func (t *serverTcpConnection) startAcceptPolling(closedServerChannel chan struct{}) {
	// We have 2 goroutines:
	// * One pools the t.ctx and closes the listener
	// * One polls the listener to accept new conns. When done, it closes the connection channels
	go func() {
		<-t.ctx.Done()
		t.logger.Infof("Closing control server")
		err := t.listener.Close()
		t.logger.Infof("Listener closed")
		if err != nil {
			t.logger.Warnf("Error while closing the listener: %s", err)
		}
	}()
	go func() {
		// This returns when either the listener is closed by external signal
		// or catastrophic failure happened. In both cases, we want to close
		t.listenLoop()

		t.close()
		close(closedServerChannel)
	}()
}

func (t *serverTcpConnection) listenLoop() {
	for {
		select {
		case <-t.ctx.Done():
			return
		default:
			conn, err := t.listener.Accept()
			if err != nil {
				t.logger.Warnf("Error while accepting the connection, closing the accept loop: %s", err)
				return
			}
			if t.tlsConfigLoader != nil {
				t.logger.Debugf("Upgrading conn %v to tls", conn.RemoteAddr())
				tlsConf, err := t.tlsConfigLoader()
				if err != nil {
					t.logger.Warnf("Cannot load tls configuration: %v", err)
					t.errors <- err
					_ = conn.Close()
					continue
				}
				conn = tls.Server(conn, tlsConf)
			}
			t.logger.Debugf("Accepting new control connection from %s", conn.RemoteAddr())
			t.consumeConnection(conn)
		}
	}
}
<commit_msg>change arg name (#38)<commit_after>/*
Copyright 2021 The Knative 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 network

import (
	"context"
	"crypto/tls"
	"fmt"
	"net"
	"strconv"
	"strings"
	"time"

	"knative.dev/pkg/logging"

	ctrl "knative.dev/control-protocol/pkg"
	"knative.dev/control-protocol/pkg/service"
)

var listenConfig = net.ListenConfig{
	KeepAlive: 30 * time.Second,
}

type ControlServerOptions struct {
	port         int
	listenConfig *net.ListenConfig
}

type ControlServerOption func(*ControlServerOptions)

func WithPort(port int) ControlServerOption {
	return func(options *ControlServerOptions) {
		options.port = port
	}
}

type ControlServer struct {
	ctrl.Service
	closedCh <-chan struct{}
	port     int
}

// ClosedCh returns a channel which is closed after the server stopped listening
func (cs *ControlServer) ClosedCh() <-chan struct{} {
	return cs.closedCh
}

// ListeningPort is the port where the server is actually listening
func (cs *ControlServer) ListeningPort() int {
	return cs.port
}

func StartInsecureControlServer(ctx context.Context, options ...ControlServerOption) (*ControlServer, error) {
	return StartControlServer(ctx, nil, options...)
}

func StartControlServer(ctx context.Context, tlsConfigLoader func() (*tls.Config, error), options ...ControlServerOption) (*ControlServer, error) {
	opts := ControlServerOptions{
		port:         9000,
		listenConfig: &listenConfig,
	}

	for _, fn := range options {
		fn(&opts)
	}

	ln, err := opts.listenConfig.Listen(ctx, "tcp", fmt.Sprintf(":%d", opts.port))
	if err != nil {
		return nil, err
	}
	listeningAddress := ln.Addr().String()
	logging.FromContext(ctx).Infof("Started listener: %s", listeningAddress)

	// Parse the port
	port, err := strconv.Atoi(listeningAddress[strings.LastIndex(listeningAddress, ":")+1:])
	if err != nil {
		return nil, fmt.Errorf("cannot parse the listening port: %w", err)
	}

	tcpConn := newServerTcpConnection(ctx, ln, tlsConfigLoader)
	ctrlService := service.NewService(ctx, tcpConn)

	closedServerCh := make(chan struct{})

	tcpConn.startAcceptPolling(closedServerCh)

	ctrlServer := &ControlServer{
		Service:  ctrlService,
		closedCh: closedServerCh,
		port:     port,
	}

	return ctrlServer, nil
}

type serverTcpConnection struct {
	baseTcpConnection

	listener        net.Listener
	tlsConfigLoader func() (*tls.Config, error)
}

func newServerTcpConnection(ctx context.Context, listener net.Listener, tlsConfigLoader func() (*tls.Config, error)) *serverTcpConnection {
	c := &serverTcpConnection{
		baseTcpConnection: baseTcpConnection{
			ctx:                    ctx,
			logger:                 logging.FromContext(ctx),
			outboundMessageChannel: make(chan *ctrl.OutboundMessage, 10),
			inboundMessageChannel:  make(chan *ctrl.InboundMessage, 10),
			errors:                 make(chan error, 10),
		},
		listener:        listener,
		tlsConfigLoader: tlsConfigLoader,
	}
	return c
}

func (t *serverTcpConnection) startAcceptPolling(closedServerChannel chan struct{}) {
	// We have 2 goroutines:
	// * One pools the t.ctx and closes the listener
	// * One polls the listener to accept new conns. When done, it closes the connection channels
	go func() {
		<-t.ctx.Done()
		t.logger.Infof("Closing control server")
		err := t.listener.Close()
		t.logger.Infof("Listener closed")
		if err != nil {
			t.logger.Warnf("Error while closing the listener: %s", err)
		}
	}()
	go func() {
		// This returns when either the listener is closed by external signal
		// or catastrophic failure happened. In both cases, we want to close
		t.listenLoop()

		t.close()
		close(closedServerChannel)
	}()
}

func (t *serverTcpConnection) listenLoop() {
	for {
		select {
		case <-t.ctx.Done():
			return
		default:
			conn, err := t.listener.Accept()
			if err != nil {
				t.logger.Warnf("Error while accepting the connection, closing the accept loop: %s", err)
				return
			}
			if t.tlsConfigLoader != nil {
				t.logger.Debugf("Upgrading conn %v to tls", conn.RemoteAddr())
				tlsConf, err := t.tlsConfigLoader()
				if err != nil {
					t.logger.Warnf("Cannot load tls configuration: %v", err)
					t.errors <- err
					_ = conn.Close()
					continue
				}
				conn = tls.Server(conn, tlsConf)
			}
			t.logger.Debugf("Accepting new control connection from %s", conn.RemoteAddr())
			t.consumeConnection(conn)
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Content-Type header constant<commit_after><|endoftext|>


<commit_before>package vegeta

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

// Attacker is an attack executor which wraps an http.Client
type Attacker struct{ client http.Client }

var (
	// DefaultRedirects represents the number of times the DefaultAttacker
	// follows redirects
	DefaultRedirects = 10
	// DefaultTimeout represents the amount of time the DefaultAttacker waits
	// for a request before it times out
	DefaultTimeout = 30 * time.Second
	// DefaultLocalAddr is the local IP address the DefaultAttacker uses in its
	// requests
	DefaultLocalAddr = net.IPAddr{IP: net.IPv4zero}
)

// DefaultAttacker is the default Attacker used by Attack
var DefaultAttacker = NewAttacker(DefaultRedirects, DefaultTimeout, DefaultLocalAddr)

// NewAttacker returns a pointer to a new Attacker
//
// redirects is the max amount of redirects the attacker will follow.
// timeout is the client side timeout for each request.
// addr is the local IP address used for each request.
// If nil, a local IP address is automatically chosen.
func NewAttacker(redirects int, timeout time.Duration, laddr net.IPAddr) *Attacker {
	return &Attacker{http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   timeout,
				KeepAlive: 30 * time.Second,
				LocalAddr: &net.TCPAddr{IP: laddr.IP, Zone: laddr.Zone},
			}).Dial,
			ResponseHeaderTimeout: timeout,
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
			TLSHandshakeTimeout: 10 * time.Second,
		},
		CheckRedirect: func(_ *http.Request, via []*http.Request) error {
			if len(via) > redirects {
				return fmt.Errorf("stopped after %d redirects", redirects)
			}
			return nil
		},
	}}
}

// Attack hits the passed Targets (http.Requests) at the rate specified for
// duration time and then waits for all the requests to come back.
// The results of the attack are put into a slice which is returned.
//
// Attack is a wrapper around DefaultAttacker.Attack
func Attack(tgts Targets, rate uint64, du time.Duration) Results {
	return DefaultAttacker.Attack(tgts, rate, du)
}

// Attack attacks the passed Targets (http.Requests) at the rate specified for
// duration time and then waits for all the requests to come back.
// The results of the attack are put into a slice which is returned.
func (a *Attacker) Attack(tgts Targets, rate uint64, du time.Duration) Results {
	hits := int(rate * uint64(du.Seconds()))
	resc := make(chan Result)
	throttle := time.NewTicker(time.Duration(1e9 / rate))
	defer throttle.Stop()

	for i := 0; i < hits; i++ {
		<-throttle.C
		go func(tgt Target) { resc <- a.hit(tgt) }(tgts[i%len(tgts)])
	}

	results := make(Results, 0, hits)
	for len(results) < cap(results) {
		results = append(results, <-resc)
	}

	return results.Sort()
}

func (a *Attacker) hit(tgt Target) (res Result) {
	req, err := tgt.Request()
	if err != nil {
		res.Error = err.Error()
		return res
	}

	res.Timestamp = time.Now()
	r, err := a.client.Do(req)
	res.Latency = time.Since(res.Timestamp)
	if err != nil {
		res.Error = err.Error()
		return res
	}

	res.BytesOut = uint64(req.ContentLength)
	res.Code = uint16(r.StatusCode)
	if body, err := ioutil.ReadAll(r.Body); err != nil {
		if res.Code < 200 || res.Code >= 300 {
			res.Error = string(body)
		}
	} else {
		res.BytesIn = uint64(len(body))
	}
	res.Latency = time.Since(res.Timestamp)

	return res
}
<commit_msg>Make NewAttacker documentation clear and correct<commit_after>package vegeta

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

// Attacker is an attack executor which wraps an http.Client
type Attacker struct{ client http.Client }

var (
	// DefaultRedirects represents the number of times the DefaultAttacker
	// follows redirects
	DefaultRedirects = 10
	// DefaultTimeout represents the amount of time the DefaultAttacker waits
	// for a request before it times out
	DefaultTimeout = 30 * time.Second
	// DefaultLocalAddr is the local IP address the DefaultAttacker uses in its
	// requests
	DefaultLocalAddr = net.IPAddr{IP: net.IPv4zero}
)

// DefaultAttacker is the default Attacker used by Attack
var DefaultAttacker = NewAttacker(DefaultRedirects, DefaultTimeout, DefaultLocalAddr)

// NewAttacker returns a pointer to a new Attacker
//
// redirects is the max amount of redirects the attacker will follow.
// Use DefaultRedirects for a sensible default.
//
// timeout is the client side timeout for each request.
// Use DefaultTimeout for a sensible default.
//
// addr is the local IP address used for each request.
// Use DefaultLocalAddr for a sensible default.
func NewAttacker(redirects int, timeout time.Duration, laddr net.IPAddr) *Attacker {
	return &Attacker{http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   timeout,
				KeepAlive: 30 * time.Second,
				LocalAddr: &net.TCPAddr{IP: laddr.IP, Zone: laddr.Zone},
			}).Dial,
			ResponseHeaderTimeout: timeout,
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
			TLSHandshakeTimeout: 10 * time.Second,
		},
		CheckRedirect: func(_ *http.Request, via []*http.Request) error {
			if len(via) > redirects {
				return fmt.Errorf("stopped after %d redirects", redirects)
			}
			return nil
		},
	}}
}

// Attack hits the passed Targets (http.Requests) at the rate specified for
// duration time and then waits for all the requests to come back.
// The results of the attack are put into a slice which is returned.
//
// Attack is a wrapper around DefaultAttacker.Attack
func Attack(tgts Targets, rate uint64, du time.Duration) Results {
	return DefaultAttacker.Attack(tgts, rate, du)
}

// Attack attacks the passed Targets (http.Requests) at the rate specified for
// duration time and then waits for all the requests to come back.
// The results of the attack are put into a slice which is returned.
func (a *Attacker) Attack(tgts Targets, rate uint64, du time.Duration) Results {
	hits := int(rate * uint64(du.Seconds()))
	resc := make(chan Result)
	throttle := time.NewTicker(time.Duration(1e9 / rate))
	defer throttle.Stop()

	for i := 0; i < hits; i++ {
		<-throttle.C
		go func(tgt Target) { resc <- a.hit(tgt) }(tgts[i%len(tgts)])
	}

	results := make(Results, 0, hits)
	for len(results) < cap(results) {
		results = append(results, <-resc)
	}

	return results.Sort()
}

func (a *Attacker) hit(tgt Target) (res Result) {
	req, err := tgt.Request()
	if err != nil {
		res.Error = err.Error()
		return res
	}

	res.Timestamp = time.Now()
	r, err := a.client.Do(req)
	res.Latency = time.Since(res.Timestamp)
	if err != nil {
		res.Error = err.Error()
		return res
	}

	res.BytesOut = uint64(req.ContentLength)
	res.Code = uint16(r.StatusCode)
	if body, err := ioutil.ReadAll(r.Body); err != nil {
		if res.Code < 200 || res.Code >= 300 {
			res.Error = string(body)
		}
	} else {
		res.BytesIn = uint64(len(body))
	}
	res.Latency = time.Since(res.Timestamp)

	return res
}
<|endoftext|>


<commit_before>package resourcecollector

import (
	"fmt"

	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
)

func (r *ResourceCollector) serviceToBeCollected(
	object runtime.Unstructured,
) (bool, error) {
	metadata, err := meta.Accessor(object)
	if err != nil {
		return false, err
	}

	// Don't migrate the kubernetes service
	if metadata.GetName() == "kubernetes" {
		return false, nil
	}
	return true, nil
}

func (r *ResourceCollector) prepareServiceResourceForCollection(
	object runtime.Unstructured,
) error {
	var service v1.Service
	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(object.UnstructuredContent(), &service); err != nil {
		return fmt.Errorf("error converting to service: %v", err)
	}
	if service.Annotations != nil {
		if _, ok := service.Annotations[skipModifyResources]; ok {
			// Skip Modify annotation set don't modify specs for resource
			// Note: some metadata annotation resource will be deleted latet like
			// resourceVersion, UID
			return nil
		}
	}
	// Reset the clusterIP if it is set
	if service.Spec.ClusterIP != "None" {
		err := unstructured.SetNestedField(object.UnstructuredContent(), "", "spec", "clusterIP")
		if err != nil {
			return err
		}
	}
	// Reset the clusterIps to nil
	err := unstructured.SetNestedField(object.UnstructuredContent(), nil, "spec", "clusterIPs")
	if err != nil {
		return err
	}
	// Reset the loadBalancerIP
	return unstructured.SetNestedField(object.UnstructuredContent(), "", "spec", "loadBalancerIP")
}

func (r *ResourceCollector) updateService(
	object runtime.Unstructured,
) error {
	var service v1.Service
	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(object.UnstructuredContent(), &service); err != nil {
		return err
	}

	if service.Spec.Type == v1.ServiceTypeNodePort {
		for i := range service.Spec.Ports {
			service.Spec.Ports[i].NodePort = 0
		}
		o, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&service)
		if err != nil {
			return err
		}
		object.SetUnstructuredContent(o)
	}
	return nil
}
<commit_msg>pb-3131: Added load balancer service type as well to reset the nodeport in resourcecollector.<commit_after>package resourcecollector

import (
	"fmt"

	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime"
)

func (r *ResourceCollector) serviceToBeCollected(
	object runtime.Unstructured,
) (bool, error) {
	metadata, err := meta.Accessor(object)
	if err != nil {
		return false, err
	}

	// Don't migrate the kubernetes service
	if metadata.GetName() == "kubernetes" {
		return false, nil
	}
	return true, nil
}

func (r *ResourceCollector) prepareServiceResourceForCollection(
	object runtime.Unstructured,
) error {
	var service v1.Service
	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(object.UnstructuredContent(), &service); err != nil {
		return fmt.Errorf("error converting to service: %v", err)
	}
	if service.Annotations != nil {
		if _, ok := service.Annotations[skipModifyResources]; ok {
			// Skip Modify annotation set don't modify specs for resource
			// Note: some metadata annotation resource will be deleted latet like
			// resourceVersion, UID
			return nil
		}
	}
	// Reset the clusterIP if it is set
	if service.Spec.ClusterIP != "None" {
		err := unstructured.SetNestedField(object.UnstructuredContent(), "", "spec", "clusterIP")
		if err != nil {
			return err
		}
	}
	// Reset the clusterIps to nil
	err := unstructured.SetNestedField(object.UnstructuredContent(), nil, "spec", "clusterIPs")
	if err != nil {
		return err
	}
	// Reset the loadBalancerIP
	return unstructured.SetNestedField(object.UnstructuredContent(), "", "spec", "loadBalancerIP")
}

func (r *ResourceCollector) updateService(
	object runtime.Unstructured,
) error {
	var service v1.Service
	if err := runtime.DefaultUnstructuredConverter.FromUnstructured(object.UnstructuredContent(), &service); err != nil {
		return err
	}

	if service.Spec.Type == v1.ServiceTypeNodePort ||
		service.Spec.Type == v1.ServiceTypeLoadBalancer {
		for i := range service.Spec.Ports {
			service.Spec.Ports[i].NodePort = 0
		}
		o, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&service)
		if err != nil {
			return err
		}
		object.SetUnstructuredContent(o)
	}
	return nil
}
<|endoftext|>