<commit_before>package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"strings"

	"github.com/EngineerBetter/concourse-up/iaas"
	"github.com/asaskevich/govalidator"
)

const terraformStateFileName = "terraform.tfstate"
const configFilePath = "config.json"

// IClient is an interface for the config file client
type IClient interface {
	Load() (Config, error)
	DeleteAll(config Config) error
	LoadOrCreate(deployArgs *DeployArgs) (Config, bool, bool, error)
	Update(Config) error
	StoreAsset(filename string, contents []byte) error
	HasAsset(filename string) (bool, error)
	LoadAsset(filename string) ([]byte, error)
	DeleteAsset(filename string) error
}

// Client is a client for loading the config file  from S3
type Client struct {
	Iaas         iaas.Provider
	Project      string
	Namespace    string
	BucketName   string
	BucketExists bool
	BucketError  error
	Config       *Config
}

// New instantiates a new client
func New(iaas iaas.Provider, project, namespace string) *Client {
	namespace = determineNamespace(namespace, iaas.Region())
	bucketName, exists, err := determineBucketName(iaas, namespace, project)

	if !exists && err == nil {
		err = iaas.CreateBucket(bucketName)
	}

	return &Client{
		iaas,
		project,
		namespace,
		bucketName,
		exists,
		err,
		&Config{},
	}
}

// StoreAsset stores an associated configuration file
func (client *Client) StoreAsset(filename string, contents []byte) error {
	return client.Iaas.WriteFile(client.configBucket(),
		filename,
		contents,
	)
}

// LoadAsset loads an associated configuration file
func (client *Client) LoadAsset(filename string) ([]byte, error) {
	return client.Iaas.LoadFile(
		client.configBucket(),
		filename,
	)
}

// DeleteAsset deletes an associated configuration file
func (client *Client) DeleteAsset(filename string) error {
	return client.Iaas.DeleteFile(
		client.configBucket(),
		filename,
	)
}

// HasAsset returns true if an associated configuration file exists
func (client *Client) HasAsset(filename string) (bool, error) {
	return client.Iaas.HasFile(
		client.configBucket(),
		filename,
	)
}

// Update stores the conconcourse up config file to S3
func (client *Client) Update(config Config) error {
	bytes, err := json.Marshal(config)
	if err != nil {
		return err
	}

	return client.Iaas.WriteFile(client.configBucket(), configFilePath, bytes)
}

// DeleteAll deletes the entire configuration bucket
func (client *Client) DeleteAll(config Config) error {
	return client.Iaas.DeleteVersionedBucket(config.ConfigBucket)
}

// Load loads an existing config file from S3
func (client *Client) Load() (Config, error) {
	if client.BucketError != nil {
		return Config{}, client.BucketError
	}

	configBytes, err := client.Iaas.LoadFile(
		client.configBucket(),
		configFilePath,
	)
	if err != nil {
		return Config{}, err
	}

	conf := Config{}
	if err := json.Unmarshal(configBytes, &conf); err != nil {
		return Config{}, err
	}

	return conf, nil
}

// LoadOrCreate loads an existing config file from S3, or creates a default if one doesn't already exist
func (client *Client) LoadOrCreate(deployArgs *DeployArgs) (Config, bool, bool, error) {

	var isDomainUpdated bool

	if client.BucketError != nil {
		return Config{}, false, false, client.BucketError
	}

	config, err := generateDefaultConfig(
		client.Project,
		deployment(client.Project),
		client.configBucket(),
		client.Iaas.Region(),
		client.Namespace,
	)
	if err != nil {
		return Config{}, false, false, err
	}

	defaultConfigBytes, err := json.Marshal(&config)
	if err != nil {
		return Config{}, false, false, err
	}

	configBytes, newConfigCreated, err := client.Iaas.EnsureFileExists(
		client.configBucket(),
		configFilePath,
		defaultConfigBytes,
	)
	if err != nil {
		return Config{}, newConfigCreated, false, err
	}

	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		return Config{}, newConfigCreated, false, err
	}

	allow, err := parseCIDRBlocks(deployArgs.AllowIPs)
	if err != nil {
		return Config{}, newConfigCreated, false, err
	}

	config, err = updateAllowedIPs(config, allow)
	if err != nil {
		return Config{}, newConfigCreated, false, err
	}

	if newConfigCreated {
		config.IAAS = deployArgs.IAAS
	}

	if deployArgs.ZoneIsSet {
		// This is a safeguard for a redeployment where zone does not belong to the region where the original deployment has happened
		if !newConfigCreated && !strings.Contains(deployArgs.Zone, config.AvailabilityZone) {
			return Config{}, false, false, fmt.Errorf("Zone %s does not belong to region %s", deployArgs.Zone, config.AvailabilityZone)
		}
		config.AvailabilityZone = deployArgs.Zone
	}
	if newConfigCreated || deployArgs.WorkerCountIsSet {
		config.ConcourseWorkerCount = deployArgs.WorkerCount
	}
	if newConfigCreated || deployArgs.WorkerSizeIsSet {
		config.ConcourseWorkerSize = deployArgs.WorkerSize
	}
	if newConfigCreated || deployArgs.WebSizeIsSet {
		config.ConcourseWebSize = deployArgs.WebSize
	}
	if newConfigCreated || deployArgs.DBSizeIsSet {
		config.RDSInstanceClass = DBSizes[deployArgs.DBSize]
	}
	if newConfigCreated || deployArgs.GithubAuthIsSet {
		config.GithubClientID = deployArgs.GithubAuthClientID
		config.GithubClientSecret = deployArgs.GithubAuthClientSecret
		config.GithubAuthIsSet = deployArgs.GithubAuthIsSet
	}
	if newConfigCreated || deployArgs.TagsIsSet {
		config.Tags = deployArgs.Tags
	}
	if newConfigCreated || deployArgs.SpotIsSet {
		config.Spot = deployArgs.Spot
	}
	if newConfigCreated || deployArgs.WorkerTypeIsSet {
		config.WorkerType = deployArgs.WorkerType
	}

	if newConfigCreated || deployArgs.DomainIsSet {
		if config.Domain != deployArgs.Domain {
			isDomainUpdated = true
		}
		config.Domain = deployArgs.Domain
	} else {
		if govalidator.IsIPv4(config.Domain) {
			config.Domain = ""
		}
	}
	return config, newConfigCreated, isDomainUpdated, nil
}

func (client *Client) configBucket() string {
	return client.BucketName
}

func deployment(project string) string {
	return fmt.Sprintf("concourse-up-%s", project)
}

func createBucketName(deployment, extension string) string {
	return fmt.Sprintf("%s-%s-config", deployment, extension)
}

func determineBucketName(iaas iaas.Provider, namespace, project string) (string, bool, error) {
	regionBucketName := createBucketName(deployment(project), iaas.Region())
	namespaceBucketName := createBucketName(deployment(project), namespace)

	foundRegionNamedBucket, err := iaas.BucketExists(regionBucketName)
	if err != nil {
		return "", false, err
	}
	foundNamespacedBucket, err := iaas.BucketExists(namespaceBucketName)
	if err != nil {
		return "", false, err
	}

	foundOne := foundRegionNamedBucket || foundNamespacedBucket

	switch {
	case !foundRegionNamedBucket && foundNamespacedBucket:
		return namespaceBucketName, foundOne, nil
	case foundRegionNamedBucket && !foundNamespacedBucket:
		return regionBucketName, foundOne, nil
	default:
		return namespaceBucketName, foundOne, nil
	}
}

type cidrBlocks []*net.IPNet

func parseCIDRBlocks(s string) (cidrBlocks, error) {
	var x cidrBlocks
	for _, ip := range strings.Split(s, ",") {
		ip = strings.TrimSpace(ip)
		_, ipNet, err := net.ParseCIDR(ip)
		if err != nil {
			ipNet = &net.IPNet{
				IP:   net.ParseIP(ip),
				Mask: net.CIDRMask(32, 32),
			}
		}
		if ipNet.IP == nil {
			return nil, fmt.Errorf("could not parse %q as an IP address or CIDR range", ip)
		}
		x = append(x, ipNet)
	}
	return x, nil
}

func (b cidrBlocks) String() (string, error) {
	var buf bytes.Buffer
	for i, ipNet := range b {
		if i > 0 {
			_, err := fmt.Fprintf(&buf, ", %q", ipNet)
			if err != nil {
				return "", err
			}
		} else {
			_, err := fmt.Fprintf(&buf, "%q", ipNet)
			if err != nil {
				return "", err
			}
		}
	}
	return buf.String(), nil
}

func determineNamespace(namespace, region string) string {
	if namespace == "" {
		return region
	}
	return namespace
}
<commit_msg>cannot change zone on existing deployment<commit_after>package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"strings"

	"github.com/EngineerBetter/concourse-up/iaas"
	"github.com/asaskevich/govalidator"
)

const terraformStateFileName = "terraform.tfstate"
const configFilePath = "config.json"

// IClient is an interface for the config file client
type IClient interface {
	Load() (Config, error)
	DeleteAll(config Config) error
	LoadOrCreate(deployArgs *DeployArgs) (Config, bool, bool, error)
	Update(Config) error
	StoreAsset(filename string, contents []byte) error
	HasAsset(filename string) (bool, error)
	LoadAsset(filename string) ([]byte, error)
	DeleteAsset(filename string) error
}

// Client is a client for loading the config file  from S3
type Client struct {
	Iaas         iaas.Provider
	Project      string
	Namespace    string
	BucketName   string
	BucketExists bool
	BucketError  error
	Config       *Config
}

// New instantiates a new client
func New(iaas iaas.Provider, project, namespace string) *Client {
	namespace = determineNamespace(namespace, iaas.Region())
	bucketName, exists, err := determineBucketName(iaas, namespace, project)

	if !exists && err == nil {
		err = iaas.CreateBucket(bucketName)
	}

	return &Client{
		iaas,
		project,
		namespace,
		bucketName,
		exists,
		err,
		&Config{},
	}
}

// StoreAsset stores an associated configuration file
func (client *Client) StoreAsset(filename string, contents []byte) error {
	return client.Iaas.WriteFile(client.configBucket(),
		filename,
		contents,
	)
}

// LoadAsset loads an associated configuration file
func (client *Client) LoadAsset(filename string) ([]byte, error) {
	return client.Iaas.LoadFile(
		client.configBucket(),
		filename,
	)
}

// DeleteAsset deletes an associated configuration file
func (client *Client) DeleteAsset(filename string) error {
	return client.Iaas.DeleteFile(
		client.configBucket(),
		filename,
	)
}

// HasAsset returns true if an associated configuration file exists
func (client *Client) HasAsset(filename string) (bool, error) {
	return client.Iaas.HasFile(
		client.configBucket(),
		filename,
	)
}

// Update stores the conconcourse up config file to S3
func (client *Client) Update(config Config) error {
	bytes, err := json.Marshal(config)
	if err != nil {
		return err
	}

	return client.Iaas.WriteFile(client.configBucket(), configFilePath, bytes)
}

// DeleteAll deletes the entire configuration bucket
func (client *Client) DeleteAll(config Config) error {
	return client.Iaas.DeleteVersionedBucket(config.ConfigBucket)
}

// Load loads an existing config file from S3
func (client *Client) Load() (Config, error) {
	if client.BucketError != nil {
		return Config{}, client.BucketError
	}

	configBytes, err := client.Iaas.LoadFile(
		client.configBucket(),
		configFilePath,
	)
	if err != nil {
		return Config{}, err
	}

	conf := Config{}
	if err := json.Unmarshal(configBytes, &conf); err != nil {
		return Config{}, err
	}

	return conf, nil
}

// LoadOrCreate loads an existing config file from S3, or creates a default if one doesn't already exist
func (client *Client) LoadOrCreate(deployArgs *DeployArgs) (Config, bool, bool, error) {

	var isDomainUpdated bool

	if client.BucketError != nil {
		return Config{}, false, false, client.BucketError
	}

	config, err := generateDefaultConfig(
		client.Project,
		deployment(client.Project),
		client.configBucket(),
		client.Iaas.Region(),
		client.Namespace,
	)
	if err != nil {
		return Config{}, false, false, err
	}

	defaultConfigBytes, err := json.Marshal(&config)
	if err != nil {
		return Config{}, false, false, err
	}

	configBytes, newConfigCreated, err := client.Iaas.EnsureFileExists(
		client.configBucket(),
		configFilePath,
		defaultConfigBytes,
	)
	if err != nil {
		return Config{}, newConfigCreated, false, err
	}

	err = json.Unmarshal(configBytes, &config)
	if err != nil {
		return Config{}, newConfigCreated, false, err
	}

	allow, err := parseCIDRBlocks(deployArgs.AllowIPs)
	if err != nil {
		return Config{}, newConfigCreated, false, err
	}

	config, err = updateAllowedIPs(config, allow)
	if err != nil {
		return Config{}, newConfigCreated, false, err
	}

	if newConfigCreated {
		config.IAAS = deployArgs.IAAS
	}

	if deployArgs.ZoneIsSet {
		// This is a safeguard for a redeployment where zone does not belong to the region where the original deployment has happened
		if !newConfigCreated && deployArgs.Zone != config.AvailabilityZone {
			return Config{}, false, false, fmt.Errorf("Existing deployment uses zone %s and cannot change to zone %s", config.AvailabilityZone, deployArgs.Zone)
		}
		config.AvailabilityZone = deployArgs.Zone
	}
	if newConfigCreated || deployArgs.WorkerCountIsSet {
		config.ConcourseWorkerCount = deployArgs.WorkerCount
	}
	if newConfigCreated || deployArgs.WorkerSizeIsSet {
		config.ConcourseWorkerSize = deployArgs.WorkerSize
	}
	if newConfigCreated || deployArgs.WebSizeIsSet {
		config.ConcourseWebSize = deployArgs.WebSize
	}
	if newConfigCreated || deployArgs.DBSizeIsSet {
		config.RDSInstanceClass = DBSizes[deployArgs.DBSize]
	}
	if newConfigCreated || deployArgs.GithubAuthIsSet {
		config.GithubClientID = deployArgs.GithubAuthClientID
		config.GithubClientSecret = deployArgs.GithubAuthClientSecret
		config.GithubAuthIsSet = deployArgs.GithubAuthIsSet
	}
	if newConfigCreated || deployArgs.TagsIsSet {
		config.Tags = deployArgs.Tags
	}
	if newConfigCreated || deployArgs.SpotIsSet {
		config.Spot = deployArgs.Spot
	}
	if newConfigCreated || deployArgs.WorkerTypeIsSet {
		config.WorkerType = deployArgs.WorkerType
	}

	if newConfigCreated || deployArgs.DomainIsSet {
		if config.Domain != deployArgs.Domain {
			isDomainUpdated = true
		}
		config.Domain = deployArgs.Domain
	} else {
		if govalidator.IsIPv4(config.Domain) {
			config.Domain = ""
		}
	}
	return config, newConfigCreated, isDomainUpdated, nil
}

func (client *Client) configBucket() string {
	return client.BucketName
}

func deployment(project string) string {
	return fmt.Sprintf("concourse-up-%s", project)
}

func createBucketName(deployment, extension string) string {
	return fmt.Sprintf("%s-%s-config", deployment, extension)
}

func determineBucketName(iaas iaas.Provider, namespace, project string) (string, bool, error) {
	regionBucketName := createBucketName(deployment(project), iaas.Region())
	namespaceBucketName := createBucketName(deployment(project), namespace)

	foundRegionNamedBucket, err := iaas.BucketExists(regionBucketName)
	if err != nil {
		return "", false, err
	}
	foundNamespacedBucket, err := iaas.BucketExists(namespaceBucketName)
	if err != nil {
		return "", false, err
	}

	foundOne := foundRegionNamedBucket || foundNamespacedBucket

	switch {
	case !foundRegionNamedBucket && foundNamespacedBucket:
		return namespaceBucketName, foundOne, nil
	case foundRegionNamedBucket && !foundNamespacedBucket:
		return regionBucketName, foundOne, nil
	default:
		return namespaceBucketName, foundOne, nil
	}
}

type cidrBlocks []*net.IPNet

func parseCIDRBlocks(s string) (cidrBlocks, error) {
	var x cidrBlocks
	for _, ip := range strings.Split(s, ",") {
		ip = strings.TrimSpace(ip)
		_, ipNet, err := net.ParseCIDR(ip)
		if err != nil {
			ipNet = &net.IPNet{
				IP:   net.ParseIP(ip),
				Mask: net.CIDRMask(32, 32),
			}
		}
		if ipNet.IP == nil {
			return nil, fmt.Errorf("could not parse %q as an IP address or CIDR range", ip)
		}
		x = append(x, ipNet)
	}
	return x, nil
}

func (b cidrBlocks) String() (string, error) {
	var buf bytes.Buffer
	for i, ipNet := range b {
		if i > 0 {
			_, err := fmt.Fprintf(&buf, ", %q", ipNet)
			if err != nil {
				return "", err
			}
		} else {
			_, err := fmt.Fprintf(&buf, "%q", ipNet)
			if err != nil {
				return "", err
			}
		}
	}
	return buf.String(), nil
}

func determineNamespace(namespace, region string) string {
	if namespace == "" {
		return region
	}
	return namespace
}
<|endoftext|>


<commit_before>package config

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

	homedir "github.com/mitchellh/go-homedir"
)

type iobeamConfig struct {
	Name string `json:"profile"`
}

const (
	// CLIVersion is the version of the CLI.
	CLIVersion = "0.7.1"
	// DefaultApiServer is the default iobeam server.
	DefaultApiServer = "https://api.iobeam.com"

	pathSeparator   = string(os.PathSeparator)
	dotDirName      = ".iobeam"
	defaultConfig   = "profile"
	profileFileName = "profile.config"
)

// InitConfig sets up the default config.
func InitConfig() (*iobeamConfig, error) {
	c := &iobeamConfig{
		Name: "default",
	}
	err := c.save()
	if err != nil {
		return nil, err
	}
	return c, nil
}

func getDotDir() string {
	homeDir, err := homedir.Dir()

	if err != nil {
		// We cannot gracefully use the temp directory with profiles.
		panic(err)
	}

	return homeDir + pathSeparator + dotDirName
}

func defaultConfigPath() string {
	return getDotDir() + pathSeparator + defaultConfig
}

func makeAllOnPath(path string) error {
	err := os.MkdirAll(path, 0700)
	if err != nil {
		return err
	}
	return nil
}

func saveJson(path string, obj interface{}) error {
	_ = os.Remove(path) // error only if it does not exist, ignore.

	file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		return err
	}

	defer file.Close()
	return json.NewEncoder(file).Encode(obj)
}

func readJson(path string, obj interface{}) error {
	file, err := os.Open(path)

	if err != nil {
		return err
	}

	defer file.Close()
	return json.NewDecoder(file).Decode(obj)
}

// save writes the config to disk in the user's .iobeam directory.
func (c *iobeamConfig) save() error {
	err := makeAllOnPath(getDotDir())
	if err != nil {
		return err
	}
	return saveJson(defaultConfigPath(), c)
}

func (c *iobeamConfig) read(path string) error {
	return readJson(path, c)
}

func readConfig(path string) (*iobeamConfig, error) {
	c := new(iobeamConfig)

	err := c.read(path)
	if err != nil {
		return nil, err
	}

	return c, err
}

func ReadDefaultConfig() (*iobeamConfig, error) {
	return readConfig(defaultConfigPath())
}

// Profile represents a CLI profile, which is similar to a workspace
// that tracks active user, project, and other metadata.
type Profile struct {
	Name            string `json:"-"`
	Server          string `json:"server"`
	ActiveProject   uint64 `json:"active_project"`
	ActiveUser      uint64 `json:"active_user"`
	ActiveUserEmail string `json:"activer_user_email"`
	// TODO: Don't export active fields.
}

// InitProfile creates a new profile on the system named 'name'.
func InitProfile(name string) (*Profile, error) {
	return InitProfileWithServer(name, DefaultApiServer)
}

// InitProfileWithServer creates a new profile on the system named
// 'name' and uses 'server' for the API server.
func InitProfileWithServer(name, server string) (*Profile, error) {
	p := &Profile{
		Name:          name,
		Server:        server,
		ActiveProject: 0,
		ActiveUser:    0,
	}
	err := p.save()
	if err != nil {
		return nil, err
	}
	return p, nil
}

func baseProfilePath(name string) string {
	return getDotDir() + pathSeparator + name
}

func profilePath(name string) string {
	// e.x. ~user/.iobeam/default/profile.config
	return baseProfilePath(name) + pathSeparator + profileFileName
}

func (p *Profile) save() error {
	err := makeAllOnPath(p.GetDir())
	if err != nil {
		return err
	}
	return saveJson(profilePath(p.Name), p)
}

func (p *Profile) read() error {
	return readJson(p.GetFile(), p)
}

// GetDir returns the path to where p's data is stored.
func (p *Profile) GetDir() string {
	return baseProfilePath(p.Name)
}

// GetFile returns the path to where p's metadata is stored.
func (p *Profile) GetFile() string {
	return profilePath(p.Name)
}

// UpdateActiveUser changes the active user id and email of p.
func (p *Profile) UpdateActiveUser(uid uint64, email string) error {
	p.ActiveUser = uid
	p.ActiveUserEmail = email
	return p.save()
}

// UpdateActiveProject changes the active project id of p.
func (p *Profile) UpdateActiveProject(pid uint64) error {
	p.ActiveProject = pid
	return p.save()
}

// ReadProfile attempts to read and create a *Profile object.
func ReadProfile(name string) (*Profile, error) {
	p := new(Profile)
	p.Name = name

	err := p.read()
	if err != nil {
		return nil, err
	}

	return p, nil
}

// GetProfileList returns a list of available profiles.
func GetProfileList() ([]string, error) {
	files, err := ioutil.ReadDir(getDotDir())
	if err != nil {
		return nil, err
	}

	var list []string
	for _, f := range files {
		if f.IsDir() {
			list = append(list, f.Name())
		}
	}

	return list, nil
}

// SwitchProfile attempts to change the active profile.
func SwitchProfile(name string) error {
	path := baseProfilePath(name)
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		return fmt.Errorf("Profile '%s' does not exist", name)
	}

	if err == nil {
		c := &iobeamConfig{
			Name: name,
		}
		err = c.save()
	}
	return err
}

// DeleteProfile removes a profile from the system.
func DeleteProfile(name string) error {
	path := baseProfilePath(name)
	_, err := os.Stat(path)
	if err == nil {
		return os.RemoveAll(path)
	} else if os.IsNotExist(err) {
		return fmt.Errorf("Profile '%s' does not exist", name)
	} else {
		return err
	}
}
<commit_msg>release: v0.7.2<commit_after>package config

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

	homedir "github.com/mitchellh/go-homedir"
)

type iobeamConfig struct {
	Name string `json:"profile"`
}

const (
	// CLIVersion is the version of the CLI.
	CLIVersion = "0.7.2"
	// DefaultApiServer is the default iobeam server.
	DefaultApiServer = "https://api.iobeam.com"

	pathSeparator   = string(os.PathSeparator)
	dotDirName      = ".iobeam"
	defaultConfig   = "profile"
	profileFileName = "profile.config"
)

// InitConfig sets up the default config.
func InitConfig() (*iobeamConfig, error) {
	c := &iobeamConfig{
		Name: "default",
	}
	err := c.save()
	if err != nil {
		return nil, err
	}
	return c, nil
}

func getDotDir() string {
	homeDir, err := homedir.Dir()

	if err != nil {
		// We cannot gracefully use the temp directory with profiles.
		panic(err)
	}

	return homeDir + pathSeparator + dotDirName
}

func defaultConfigPath() string {
	return getDotDir() + pathSeparator + defaultConfig
}

func makeAllOnPath(path string) error {
	err := os.MkdirAll(path, 0700)
	if err != nil {
		return err
	}
	return nil
}

func saveJson(path string, obj interface{}) error {
	_ = os.Remove(path) // error only if it does not exist, ignore.

	file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0600)
	if err != nil {
		return err
	}

	defer file.Close()
	return json.NewEncoder(file).Encode(obj)
}

func readJson(path string, obj interface{}) error {
	file, err := os.Open(path)

	if err != nil {
		return err
	}

	defer file.Close()
	return json.NewDecoder(file).Decode(obj)
}

// save writes the config to disk in the user's .iobeam directory.
func (c *iobeamConfig) save() error {
	err := makeAllOnPath(getDotDir())
	if err != nil {
		return err
	}
	return saveJson(defaultConfigPath(), c)
}

func (c *iobeamConfig) read(path string) error {
	return readJson(path, c)
}

func readConfig(path string) (*iobeamConfig, error) {
	c := new(iobeamConfig)

	err := c.read(path)
	if err != nil {
		return nil, err
	}

	return c, err
}

func ReadDefaultConfig() (*iobeamConfig, error) {
	return readConfig(defaultConfigPath())
}

// Profile represents a CLI profile, which is similar to a workspace
// that tracks active user, project, and other metadata.
type Profile struct {
	Name            string `json:"-"`
	Server          string `json:"server"`
	ActiveProject   uint64 `json:"active_project"`
	ActiveUser      uint64 `json:"active_user"`
	ActiveUserEmail string `json:"activer_user_email"`
	// TODO: Don't export active fields.
}

// InitProfile creates a new profile on the system named 'name'.
func InitProfile(name string) (*Profile, error) {
	return InitProfileWithServer(name, DefaultApiServer)
}

// InitProfileWithServer creates a new profile on the system named
// 'name' and uses 'server' for the API server.
func InitProfileWithServer(name, server string) (*Profile, error) {
	p := &Profile{
		Name:          name,
		Server:        server,
		ActiveProject: 0,
		ActiveUser:    0,
	}
	err := p.save()
	if err != nil {
		return nil, err
	}
	return p, nil
}

func baseProfilePath(name string) string {
	return getDotDir() + pathSeparator + name
}

func profilePath(name string) string {
	// e.x. ~user/.iobeam/default/profile.config
	return baseProfilePath(name) + pathSeparator + profileFileName
}

func (p *Profile) save() error {
	err := makeAllOnPath(p.GetDir())
	if err != nil {
		return err
	}
	return saveJson(profilePath(p.Name), p)
}

func (p *Profile) read() error {
	return readJson(p.GetFile(), p)
}

// GetDir returns the path to where p's data is stored.
func (p *Profile) GetDir() string {
	return baseProfilePath(p.Name)
}

// GetFile returns the path to where p's metadata is stored.
func (p *Profile) GetFile() string {
	return profilePath(p.Name)
}

// UpdateActiveUser changes the active user id and email of p.
func (p *Profile) UpdateActiveUser(uid uint64, email string) error {
	p.ActiveUser = uid
	p.ActiveUserEmail = email
	return p.save()
}

// UpdateActiveProject changes the active project id of p.
func (p *Profile) UpdateActiveProject(pid uint64) error {
	p.ActiveProject = pid
	return p.save()
}

// ReadProfile attempts to read and create a *Profile object.
func ReadProfile(name string) (*Profile, error) {
	p := new(Profile)
	p.Name = name

	err := p.read()
	if err != nil {
		return nil, err
	}

	return p, nil
}

// GetProfileList returns a list of available profiles.
func GetProfileList() ([]string, error) {
	files, err := ioutil.ReadDir(getDotDir())
	if err != nil {
		return nil, err
	}

	var list []string
	for _, f := range files {
		if f.IsDir() {
			list = append(list, f.Name())
		}
	}

	return list, nil
}

// SwitchProfile attempts to change the active profile.
func SwitchProfile(name string) error {
	path := baseProfilePath(name)
	_, err := os.Stat(path)
	if os.IsNotExist(err) {
		return fmt.Errorf("Profile '%s' does not exist", name)
	}

	if err == nil {
		c := &iobeamConfig{
			Name: name,
		}
		err = c.save()
	}
	return err
}

// DeleteProfile removes a profile from the system.
func DeleteProfile(name string) error {
	path := baseProfilePath(name)
	_, err := os.Stat(path)
	if err == nil {
		return os.RemoveAll(path)
	} else if os.IsNotExist(err) {
		return fmt.Errorf("Profile '%s' does not exist", name)
	} else {
		return err
	}
}
<|endoftext|>


<commit_before>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 cli

import (
	"bytes"
	"os"

	"github.com/spf13/cobra"
	"mynewt.apache.org/newt/newt/builder"
	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/util"
)

const TARGET_TEST_NAME = "unittest"

func pkgIsTestable(pack *pkg.LocalPackage) bool {
	return util.NodeExist(pack.BasePath() + "/src/test")
}

func buildRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, nil)
	}

	t := ResolveTarget(args[0])
	if t == nil {
		NewtUsage(cmd, util.NewNewtError("invalid target name: "+args[0]))
	}

	b, err := builder.NewBuilder(t)
	if err != nil {
		NewtUsage(nil, err)
	}
	err = b.Build()
	if err != nil {
		NewtUsage(nil, err)
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "App successfully built: %s\n",
		b.AppElfPath())
}

func cleanRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify target"))
	}

	cleanAll := false
	targets := []*target.Target{}
	for _, arg := range args {
		if arg == TARGET_KEYWORD_ALL {
			cleanAll = true
		} else {
			t := ResolveTarget(arg)
			if t == nil {
				NewtUsage(cmd, util.NewNewtError("invalid target name: "+arg))
			}
			targets = append(targets, t)
		}
	}

	if cleanAll {
		path := builder.BinRoot()
		util.StatusMessage(util.VERBOSITY_VERBOSE,
			"Cleaning directory %s\n", path)

		err := os.RemoveAll(path)
		if err != nil {
			NewtUsage(cmd, err)
		}
	} else {
		for _, t := range targets {
			b, err := builder.NewBuilder(t)
			if err != nil {
				NewtUsage(cmd, err)
			}
			err = b.Clean()
			if err != nil {
				NewtUsage(cmd, err)
			}
		}
	}
}

func testRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, nil)
	}

	// Verify and resolve each specified package.
	testAll := false
	packs := []*pkg.LocalPackage{}
	for _, pkgName := range args {
		pack, err := ResolvePackage(pkgName)
		if err != nil {
			NewtUsage(cmd, err)
		}

		packs = append(packs, pack)
	}

	// Test each specified package.
	t := ResolveTarget(TARGET_TEST_NAME)
	if t == nil {
		NewtUsage(nil, util.NewNewtError("Can't find unit test target: "+
			TARGET_TEST_NAME))
	}

	if testAll {
		packs = []*pkg.LocalPackage{}
		for _, repoHash := range project.GetProject().PackageList() {
			for _, pack := range *repoHash {
				lclPack := pack.(*pkg.LocalPackage)

				if pkgIsTestable(lclPack) {
					packs = append(packs, lclPack)
				}
			}
		}
	}

	failedPkgs := []*pkg.LocalPackage{}
	for _, pack := range packs {
		b, err := builder.NewBuilder(t)
		if err != nil {
			NewtUsage(nil, err)
		}

		util.StatusMessage(util.VERBOSITY_DEFAULT, "Testing package %s\n",
			pack.Name())
		err = b.Test(pack)
		if err != nil {
			failedPkgs = append(failedPkgs, pack)
		}

		// Reset the global project for the next test.
		project.ResetProject()
	}

	if len(failedPkgs) > 0 {
		var buffer bytes.Buffer
		for i, pack := range failedPkgs {
			if i != 0 {
				buffer.WriteString(" ")
			}
			buffer.WriteString(pack.Name())
		}
		NewtUsage(nil, util.NewNewtError("Tests failed for: ["+buffer.String()+
			"]"))
	}
	util.StatusMessage(util.VERBOSITY_DEFAULT, "All tests passed\n")
}

func downloadRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify target"))
	}

	t := ResolveTarget(args[0])
	if t == nil {
		NewtUsage(cmd, util.NewNewtError("Invalid target name: "+args[0]))
	}

	b, err := builder.NewBuilder(t)
	if err != nil {
		NewtUsage(cmd, err)
	}

	err = b.Download()
	if err != nil {
		NewtUsage(cmd, err)
	}
}

func debugRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify target"))
	}

	t := ResolveTarget(args[0])
	if t == nil {
		NewtUsage(cmd, util.NewNewtError("Invalid target name: "+args[0]))
	}

	b, err := builder.NewBuilder(t)
	if err != nil {
		NewtUsage(cmd, err)
	}

	err = b.Debug()
	if err != nil {
		NewtUsage(cmd, err)
	}
}

func sizeRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify target"))
	}

	t := ResolveTarget(args[0])
	if t == nil {
		NewtUsage(cmd, util.NewNewtError("Invalid target name: "+args[0]))
	}

	b, err := builder.NewBuilder(t)
	if err != nil {
		NewtUsage(cmd, err)
	}

	err = b.Size()
	if err != nil {
		NewtUsage(cmd, err)
	}
}

func AddBuildCommands(cmd *cobra.Command) {
	buildHelpText := ""
	buildHelpEx := ""
	buildCmd := &cobra.Command{
		Use:     "build",
		Short:   "Builds one or more apps.",
		Long:    buildHelpText,
		Example: buildHelpEx,
		Run:     buildRunCmd,
	}

	cmd.AddCommand(buildCmd)

	cleanHelpText := ""
	cleanHelpEx := ""
	cleanCmd := &cobra.Command{
		Use:     "clean",
		Short:   "Deletes app build artifacts.",
		Long:    cleanHelpText,
		Example: cleanHelpEx,
		Run:     cleanRunCmd,
	}

	cmd.AddCommand(cleanCmd)

	testHelpText := ""
	testHelpEx := ""
	testCmd := &cobra.Command{
		Use:     "test",
		Short:   "Executes unit tests for one or more packages",
		Long:    testHelpText,
		Example: testHelpEx,
		Run:     testRunCmd,
	}

	cmd.AddCommand(testCmd)

	downloadHelpText := "Download app image to target for <target-name>."
	downloadHelpEx := "  newt download <target-name>\n"

	downloadCmd := &cobra.Command{
		Use:     "download",
		Short:   "Download built target to board",
		Long:    downloadHelpText,
		Example: downloadHelpEx,
		Run:     downloadRunCmd,
	}
	cmd.AddCommand(downloadCmd)

	debugHelpText := "Open debugger session for <target-name>."
	debugHelpEx := "  newt debug <target-name>\n"

	debugCmd := &cobra.Command{
		Use:     "debug",
		Short:   "Open debugger session to target",
		Long:    debugHelpText,
		Example: debugHelpEx,
		Run:     debugRunCmd,
	}
	cmd.AddCommand(debugCmd)

	sizeHelpText := "Calculate the size of target components specified by " +
		"<target-name>."
	sizeHelpEx := "  newt size <target-name>\n"

	sizeCmd := &cobra.Command{
		Use:     "size",
		Short:   "Size of target components",
		Long:    sizeHelpText,
		Example: sizeHelpEx,
		Run:     sizeRunCmd,
	}
	cmd.AddCommand(sizeCmd)
}
<commit_msg>Fix testing of multiple packages.<commit_after>/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 cli

import (
	"bytes"
	"os"

	"github.com/spf13/cobra"
	"mynewt.apache.org/newt/newt/builder"
	"mynewt.apache.org/newt/newt/pkg"
	"mynewt.apache.org/newt/newt/project"
	"mynewt.apache.org/newt/newt/target"
	"mynewt.apache.org/newt/util"
)

const TARGET_TEST_NAME = "unittest"

func pkgIsTestable(pack *pkg.LocalPackage) bool {
	return util.NodeExist(pack.BasePath() + "/src/test")
}

func buildRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, nil)
	}

	t := ResolveTarget(args[0])
	if t == nil {
		NewtUsage(cmd, util.NewNewtError("invalid target name: "+args[0]))
	}

	b, err := builder.NewBuilder(t)
	if err != nil {
		NewtUsage(nil, err)
	}
	err = b.Build()
	if err != nil {
		NewtUsage(nil, err)
	}

	util.StatusMessage(util.VERBOSITY_DEFAULT, "App successfully built: %s\n",
		b.AppElfPath())
}

func cleanRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify target"))
	}

	cleanAll := false
	targets := []*target.Target{}
	for _, arg := range args {
		if arg == TARGET_KEYWORD_ALL {
			cleanAll = true
		} else {
			t := ResolveTarget(arg)
			if t == nil {
				NewtUsage(cmd, util.NewNewtError("invalid target name: "+arg))
			}
			targets = append(targets, t)
		}
	}

	if cleanAll {
		path := builder.BinRoot()
		util.StatusMessage(util.VERBOSITY_VERBOSE,
			"Cleaning directory %s\n", path)

		err := os.RemoveAll(path)
		if err != nil {
			NewtUsage(cmd, err)
		}
	} else {
		for _, t := range targets {
			b, err := builder.NewBuilder(t)
			if err != nil {
				NewtUsage(cmd, err)
			}
			err = b.Clean()
			if err != nil {
				NewtUsage(cmd, err)
			}
		}
	}
}

func testRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, nil)
	}

	// Verify and resolve each specified package.
	testAll := false
	packs := []*pkg.LocalPackage{}
	for _, pkgName := range args {
		if pkgName == "all" {
			testAll = true
		} else {
			pack, err := ResolvePackage(pkgName)
			if err != nil {
				NewtUsage(cmd, err)
			}

			packs = append(packs, pack)
		}
	}

	if testAll {
		packs = []*pkg.LocalPackage{}
		for _, repoHash := range project.GetProject().PackageList() {
			for _, pack := range *repoHash {
				lclPack := pack.(*pkg.LocalPackage)

				if pkgIsTestable(lclPack) {
					packs = append(packs, lclPack)
				}
			}
		}
	}

	failedPkgs := []*pkg.LocalPackage{}
	for _, pack := range packs {
		// Reset the global project for the next test.
		project.ResetProject()

		// Use the standard unit test target for all tests.
		t := ResolveTarget(TARGET_TEST_NAME)
		if t == nil {
			NewtUsage(nil, util.NewNewtError("Can't find unit test target: "+
				TARGET_TEST_NAME))
		}

		b, err := builder.NewBuilder(t)
		if err != nil {
			NewtUsage(nil, err)
		}

		util.StatusMessage(util.VERBOSITY_DEFAULT, "Testing package %s\n",
			pack.Name())

		// The package under test needs to be resolved again now that the
		// project has been reset.
		pack, err = ResolvePackage(pack.Name())
		if err == nil {
			err = b.Test(pack)
		}
		if err != nil {
			failedPkgs = append(failedPkgs, pack)
		}
	}

	if len(failedPkgs) > 0 {
		var buffer bytes.Buffer
		for i, pack := range failedPkgs {
			if i != 0 {
				buffer.WriteString(" ")
			}
			buffer.WriteString(pack.Name())
		}
		NewtUsage(nil, util.NewNewtError("Tests failed for: ["+buffer.String()+
			"]"))
	}
	util.StatusMessage(util.VERBOSITY_DEFAULT, "All tests passed\n")
}

func downloadRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify target"))
	}

	t := ResolveTarget(args[0])
	if t == nil {
		NewtUsage(cmd, util.NewNewtError("Invalid target name: "+args[0]))
	}

	b, err := builder.NewBuilder(t)
	if err != nil {
		NewtUsage(cmd, err)
	}

	err = b.Download()
	if err != nil {
		NewtUsage(cmd, err)
	}
}

func debugRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify target"))
	}

	t := ResolveTarget(args[0])
	if t == nil {
		NewtUsage(cmd, util.NewNewtError("Invalid target name: "+args[0]))
	}

	b, err := builder.NewBuilder(t)
	if err != nil {
		NewtUsage(cmd, err)
	}

	err = b.Debug()
	if err != nil {
		NewtUsage(cmd, err)
	}
}

func sizeRunCmd(cmd *cobra.Command, args []string) {
	if len(args) < 1 {
		NewtUsage(cmd, util.NewNewtError("Must specify target"))
	}

	t := ResolveTarget(args[0])
	if t == nil {
		NewtUsage(cmd, util.NewNewtError("Invalid target name: "+args[0]))
	}

	b, err := builder.NewBuilder(t)
	if err != nil {
		NewtUsage(cmd, err)
	}

	err = b.Size()
	if err != nil {
		NewtUsage(cmd, err)
	}
}

func AddBuildCommands(cmd *cobra.Command) {
	buildHelpText := ""
	buildHelpEx := ""
	buildCmd := &cobra.Command{
		Use:     "build",
		Short:   "Builds one or more apps.",
		Long:    buildHelpText,
		Example: buildHelpEx,
		Run:     buildRunCmd,
	}

	cmd.AddCommand(buildCmd)

	cleanHelpText := ""
	cleanHelpEx := ""
	cleanCmd := &cobra.Command{
		Use:     "clean",
		Short:   "Deletes app build artifacts.",
		Long:    cleanHelpText,
		Example: cleanHelpEx,
		Run:     cleanRunCmd,
	}

	cmd.AddCommand(cleanCmd)

	testHelpText := ""
	testHelpEx := ""
	testCmd := &cobra.Command{
		Use:     "test",
		Short:   "Executes unit tests for one or more packages",
		Long:    testHelpText,
		Example: testHelpEx,
		Run:     testRunCmd,
	}

	cmd.AddCommand(testCmd)

	downloadHelpText := "Download app image to target for <target-name>."
	downloadHelpEx := "  newt download <target-name>\n"

	downloadCmd := &cobra.Command{
		Use:     "download",
		Short:   "Download built target to board",
		Long:    downloadHelpText,
		Example: downloadHelpEx,
		Run:     downloadRunCmd,
	}
	cmd.AddCommand(downloadCmd)

	debugHelpText := "Open debugger session for <target-name>."
	debugHelpEx := "  newt debug <target-name>\n"

	debugCmd := &cobra.Command{
		Use:     "debug",
		Short:   "Open debugger session to target",
		Long:    debugHelpText,
		Example: debugHelpEx,
		Run:     debugRunCmd,
	}
	cmd.AddCommand(debugCmd)

	sizeHelpText := "Calculate the size of target components specified by " +
		"<target-name>."
	sizeHelpEx := "  newt size <target-name>\n"

	sizeCmd := &cobra.Command{
		Use:     "size",
		Short:   "Size of target components",
		Long:    sizeHelpText,
		Example: sizeHelpEx,
		Run:     sizeRunCmd,
	}
	cmd.AddCommand(sizeCmd)
}
<|endoftext|>


<commit_before>package arel

type DeleteStatement struct {
	BaseNode
}
<commit_msg>DeleteStatement -> DeleteStatementNode<commit_after>package arel

type DeleteStatementNode struct {
	BaseNode
}
<|endoftext|>


<commit_before>// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package backends

import (
	"math/big"

	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core"
	"github.com/ethereum/go-ethereum/core/state"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/core/vm"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/event"
)

// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
var chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)}

// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
var _ bind.ContractBackend = (*SimulatedBackend)(nil)

// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
// the background. Its main purpose is to allow easily testing contract bindings.
type SimulatedBackend struct {
	database   ethdb.Database   // In memory database to store our testing data
	blockchain *core.BlockChain // Ethereum blockchain to handle the consensus

	pendingBlock *types.Block   // Currently pending block that will be imported on request
	pendingState *state.StateDB // Currently pending state that will be the active on on request
}

// NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes.
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
	database, _ := ethdb.NewMemDatabase()
	core.WriteGenesisBlockForTesting(database, accounts...)
	blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux))

	backend := &SimulatedBackend{
		database:   database,
		blockchain: blockchain,
	}
	backend.Rollback()

	return backend
}

// Commit imports all the pending transactions as a single block and starts a
// fresh new state.
func (b *SimulatedBackend) Commit() {
	if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil {
		panic(err) // This cannot happen unless the simulator is wrong, fail in that case
	}
	b.Rollback()
}

// Rollback aborts all pending transactions, reverting to the last committed state.
func (b *SimulatedBackend) Rollback() {
	blocks, _ := core.GenerateChain(b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})

	b.pendingBlock = blocks[0]
	b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)
}

// ContractCall implements ContractCaller.ContractCall, executing the specified
// contract with the given input data.
func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error) {
	// Create a copy of the current state db to screw around with
	var (
		block   *types.Block
		statedb *state.StateDB
	)
	if pending {
		block, statedb = b.pendingBlock, b.pendingState.Copy()
	} else {
		block = b.blockchain.CurrentBlock()
		statedb, _ = b.blockchain.State()
	}
	// Set infinite balance to the a fake caller account
	from := statedb.GetOrNewStateObject(common.Address{})
	from.SetBalance(common.MaxBig)

	// Assemble the call invocation to measure the gas usage
	msg := callmsg{
		from:     from,
		to:       &contract,
		gasPrice: new(big.Int),
		gasLimit: common.MaxBig,
		value:    new(big.Int),
		data:     data,
	}
	// Execute the call and return
	vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
	gaspool := new(core.GasPool).AddGas(common.MaxBig)

	out, _, err := core.ApplyMessage(vmenv, msg, gaspool)
	return out, err
}

// PendingAccountNonce implements ContractTransactor.PendingAccountNonce, retrieving
// the nonce currently pending for the account.
func (b *SimulatedBackend) PendingAccountNonce(account common.Address) (uint64, error) {
	return b.pendingState.GetOrNewStateObject(account).Nonce(), nil
}

// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
// chain doens't have miners, we just return a gas price of 1 for any call.
func (b *SimulatedBackend) SuggestGasPrice() (*big.Int, error) {
	return big.NewInt(1), nil
}

// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, executing the
// requested code against the currently pending block/state and returning the used
// gas.
func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) {
	// Create a copy of the currently pending state db to screw around with
	var (
		block   = b.pendingBlock
		statedb = b.pendingState.Copy()
	)

	// Set infinite balance to the a fake caller account
	from := statedb.GetOrNewStateObject(sender)
	from.SetBalance(common.MaxBig)

	// Assemble the call invocation to measure the gas usage
	msg := callmsg{
		from:     from,
		to:       contract,
		gasPrice: new(big.Int),
		gasLimit: common.MaxBig,
		value:    value,
		data:     data,
	}
	// Execute the call and return
	vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
	gaspool := new(core.GasPool).AddGas(common.MaxBig)

	_, gas, err := core.ApplyMessage(vmenv, msg, gaspool)
	return gas, err
}

// SendTransaction implements ContractTransactor.SendTransaction, delegating the raw
// transaction injection to the remote node.
func (b *SimulatedBackend) SendTransaction(tx *types.Transaction) error {
	blocks, _ := core.GenerateChain(b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
		for _, tx := range b.pendingBlock.Transactions() {
			block.AddTx(tx)
		}
		block.AddTx(tx)
	})
	b.pendingBlock = blocks[0]
	b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)

	return nil
}

// callmsg implements core.Message to allow passing it as a transaction simulator.
type callmsg struct {
	from     *state.StateObject
	to       *common.Address
	gasLimit *big.Int
	gasPrice *big.Int
	value    *big.Int
	data     []byte
}

func (m callmsg) From() (common.Address, error)         { return m.from.Address(), nil }
func (m callmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
func (m callmsg) Nonce() uint64                         { return m.from.Nonce() }
func (m callmsg) To() *common.Address                   { return m.to }
func (m callmsg) GasPrice() *big.Int                    { return m.gasPrice }
func (m callmsg) Gas() *big.Int                         { return m.gasLimit }
func (m callmsg) Value() *big.Int                       { return m.value }
func (m callmsg) Data() []byte                          { return m.data }
<commit_msg>accounts/abi/bind/backends: estimate needed gas, not used<commit_after>// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package backends

import (
	"math/big"

	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core"
	"github.com/ethereum/go-ethereum/core/state"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/core/vm"
	"github.com/ethereum/go-ethereum/ethdb"
	"github.com/ethereum/go-ethereum/event"
)

// Default chain configuration which sets homestead phase at block 0 (i.e. no frontier)
var chainConfig = &core.ChainConfig{HomesteadBlock: big.NewInt(0)}

// This nil assignment ensures compile time that SimulatedBackend implements bind.ContractBackend.
var _ bind.ContractBackend = (*SimulatedBackend)(nil)

// SimulatedBackend implements bind.ContractBackend, simulating a blockchain in
// the background. Its main purpose is to allow easily testing contract bindings.
type SimulatedBackend struct {
	database   ethdb.Database   // In memory database to store our testing data
	blockchain *core.BlockChain // Ethereum blockchain to handle the consensus

	pendingBlock *types.Block   // Currently pending block that will be imported on request
	pendingState *state.StateDB // Currently pending state that will be the active on on request
}

// NewSimulatedBackend creates a new binding backend using a simulated blockchain
// for testing purposes.
func NewSimulatedBackend(accounts ...core.GenesisAccount) *SimulatedBackend {
	database, _ := ethdb.NewMemDatabase()
	core.WriteGenesisBlockForTesting(database, accounts...)
	blockchain, _ := core.NewBlockChain(database, chainConfig, new(core.FakePow), new(event.TypeMux))

	backend := &SimulatedBackend{
		database:   database,
		blockchain: blockchain,
	}
	backend.Rollback()

	return backend
}

// Commit imports all the pending transactions as a single block and starts a
// fresh new state.
func (b *SimulatedBackend) Commit() {
	if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}); err != nil {
		panic(err) // This cannot happen unless the simulator is wrong, fail in that case
	}
	b.Rollback()
}

// Rollback aborts all pending transactions, reverting to the last committed state.
func (b *SimulatedBackend) Rollback() {
	blocks, _ := core.GenerateChain(b.blockchain.CurrentBlock(), b.database, 1, func(int, *core.BlockGen) {})

	b.pendingBlock = blocks[0]
	b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)
}

// ContractCall implements ContractCaller.ContractCall, executing the specified
// contract with the given input data.
func (b *SimulatedBackend) ContractCall(contract common.Address, data []byte, pending bool) ([]byte, error) {
	// Create a copy of the current state db to screw around with
	var (
		block   *types.Block
		statedb *state.StateDB
	)
	if pending {
		block, statedb = b.pendingBlock, b.pendingState.Copy()
	} else {
		block = b.blockchain.CurrentBlock()
		statedb, _ = b.blockchain.State()
	}
	// Set infinite balance to the a fake caller account
	from := statedb.GetOrNewStateObject(common.Address{})
	from.SetBalance(common.MaxBig)

	// Assemble the call invocation to measure the gas usage
	msg := callmsg{
		from:     from,
		to:       &contract,
		gasPrice: new(big.Int),
		gasLimit: common.MaxBig,
		value:    new(big.Int),
		data:     data,
	}
	// Execute the call and return
	vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
	gaspool := new(core.GasPool).AddGas(common.MaxBig)

	out, _, err := core.ApplyMessage(vmenv, msg, gaspool)
	return out, err
}

// PendingAccountNonce implements ContractTransactor.PendingAccountNonce, retrieving
// the nonce currently pending for the account.
func (b *SimulatedBackend) PendingAccountNonce(account common.Address) (uint64, error) {
	return b.pendingState.GetOrNewStateObject(account).Nonce(), nil
}

// SuggestGasPrice implements ContractTransactor.SuggestGasPrice. Since the simulated
// chain doens't have miners, we just return a gas price of 1 for any call.
func (b *SimulatedBackend) SuggestGasPrice() (*big.Int, error) {
	return big.NewInt(1), nil
}

// EstimateGasLimit implements ContractTransactor.EstimateGasLimit, executing the
// requested code against the currently pending block/state and returning the used
// gas.
func (b *SimulatedBackend) EstimateGasLimit(sender common.Address, contract *common.Address, value *big.Int, data []byte) (*big.Int, error) {
	// Create a copy of the currently pending state db to screw around with
	var (
		block   = b.pendingBlock
		statedb = b.pendingState.Copy()
	)

	// Set infinite balance to the a fake caller account
	from := statedb.GetOrNewStateObject(sender)
	from.SetBalance(common.MaxBig)

	// Assemble the call invocation to measure the gas usage
	msg := callmsg{
		from:     from,
		to:       contract,
		gasPrice: new(big.Int),
		gasLimit: common.MaxBig,
		value:    value,
		data:     data,
	}
	// Execute the call and return
	vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
	gaspool := new(core.GasPool).AddGas(common.MaxBig)

	_, gas, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
	return gas, err
}

// SendTransaction implements ContractTransactor.SendTransaction, delegating the raw
// transaction injection to the remote node.
func (b *SimulatedBackend) SendTransaction(tx *types.Transaction) error {
	blocks, _ := core.GenerateChain(b.blockchain.CurrentBlock(), b.database, 1, func(number int, block *core.BlockGen) {
		for _, tx := range b.pendingBlock.Transactions() {
			block.AddTx(tx)
		}
		block.AddTx(tx)
	})
	b.pendingBlock = blocks[0]
	b.pendingState, _ = state.New(b.pendingBlock.Root(), b.database)

	return nil
}

// callmsg implements core.Message to allow passing it as a transaction simulator.
type callmsg struct {
	from     *state.StateObject
	to       *common.Address
	gasLimit *big.Int
	gasPrice *big.Int
	value    *big.Int
	data     []byte
}

func (m callmsg) From() (common.Address, error)         { return m.from.Address(), nil }
func (m callmsg) FromFrontier() (common.Address, error) { return m.from.Address(), nil }
func (m callmsg) Nonce() uint64                         { return m.from.Nonce() }
func (m callmsg) To() *common.Address                   { return m.to }
func (m callmsg) GasPrice() *big.Int                    { return m.gasPrice }
func (m callmsg) Gas() *big.Int                         { return m.gasLimit }
func (m callmsg) Value() *big.Int                       { return m.value }
func (m callmsg) Data() []byte                          { return m.data }
<|endoftext|>


<commit_before>package valente

import (
	"log"

	"golang.org/x/net/websocket"
)

//HandlerFunc is a function of handle an event received into websocket.Conn
type HandlerFunc func(*websocket.Conn, *App)

//Form represents the unit of user interaction
type Form interface {
	AddEventHandler(evt string, f HandlerFunc) Form
	Run(ws *websocket.Conn, app *App) error
	Initialize(ws *websocket.Conn) Form
}

//FormImpl its a simple Form
type FormImpl struct {
	trans map[string]HandlerFunc
}

//AddEventHandler add an f function to handle evt event
func (form FormImpl) AddEventHandler(evt string, f HandlerFunc) Form {
	if form.trans == nil {
		form.trans = map[string]HandlerFunc{}
	}
	form.trans[evt] = f
	return form
}

//Run execs the form
func (form FormImpl) Run(ws *websocket.Conn, app *App) error {
	msg := ""
	err := websocket.Message.Receive(ws, &msg)
	if err != nil {
		log.Println("Error on WS Receive", err)
		return err
	}
	println(msg, form.trans)
	f, present := form.trans[msg]
	if present {
		f(ws, app)
	} else {
		log.Println("Evt not found")
	}
	return nil
}

//Initialize inits the form
func (form FormImpl) Initialize(ws *websocket.Conn) Form {
	log.Println("FormImpl Initialize")
	return form
}

//App is a Web Application representation
type App struct {
	WS          *websocket.Conn
	Forms       map[string]Form
	Data        map[string]interface{}
	CurrentForm Form
}

//GoTo replace the current form into app
func (app *App) GoTo(formName string) error {
	log.Println("App goto", formName)
	form, present := app.Forms[formName]
	if present {
		app.CurrentForm = form.Initialize(app.WS)
	} else {
		log.Println("[ERROR] Form not registred", formName)
	}
	return nil
}

//Run handle events
func (app *App) Run() {
	app.Data = map[string]interface{}{}
	for {
		err := app.CurrentForm.Run(app.WS, app)
		if err != nil {
			return
		}
	}
}

//Initialize inits the App
func (app *App) Initialize() {
	log.Println("App Initialize")
}

//AddForm add a new form to App
func (app *App) AddForm(name string, f Form) {
	if app.Forms == nil {
		app.Forms = map[string]Form{}
	}

	app.Forms[name] = f
}
<commit_msg>change log<commit_after>package valente

import (
	"log"

	"golang.org/x/net/websocket"
)

//HandlerFunc is a function of handle an event received into websocket.Conn
type HandlerFunc func(*websocket.Conn, *App)

//Form represents the unit of user interaction
type Form interface {
	AddEventHandler(evt string, f HandlerFunc) Form
	Run(ws *websocket.Conn, app *App) error
	Initialize(ws *websocket.Conn) Form
}

//FormImpl its a simple Form
type FormImpl struct {
	trans map[string]HandlerFunc
}

//AddEventHandler add an f function to handle evt event
func (form FormImpl) AddEventHandler(evt string, f HandlerFunc) Form {
	if form.trans == nil {
		form.trans = map[string]HandlerFunc{}
	}
	form.trans[evt] = f
	return form
}

//Run execs the form
func (form FormImpl) Run(ws *websocket.Conn, app *App) error {
	msg := ""
	err := websocket.Message.Receive(ws, &msg)
	if err != nil {
		log.Println("Error on WS Receive", err)
		return err
	}
	println(msg, form.trans)
	f, present := form.trans[msg]
	if present {
		f(ws, app)
	} else {
		log.Println("Evt not found", msg)
	}
	return nil
}

//Initialize inits the form
func (form FormImpl) Initialize(ws *websocket.Conn) Form {
	log.Println("FormImpl Initialize")
	return form
}

//App is a Web Application representation
type App struct {
	WS          *websocket.Conn
	Forms       map[string]Form
	Data        map[string]interface{}
	CurrentForm Form
}

//GoTo replace the current form into app
func (app *App) GoTo(formName string) error {
	log.Println("App goto", formName)
	form, present := app.Forms[formName]
	if present {
		app.CurrentForm = form.Initialize(app.WS)
	} else {
		log.Println("[ERROR] Form not registred", formName)
	}
	return nil
}

//Run handle events
func (app *App) Run() {
	app.Data = map[string]interface{}{}
	for {
		err := app.CurrentForm.Run(app.WS, app)
		if err != nil {
			return
		}
	}
}

//Initialize inits the App
func (app *App) Initialize() {
	log.Println("App Initialize")
}

//AddForm add a new form to App
func (app *App) AddForm(name string, f Form) {
	if app.Forms == nil {
		app.Forms = map[string]Form{}
	}

	app.Forms[name] = f
}
<|endoftext|>


<commit_before>package main

const Name string = "packer-post-processor-vagrant-metadata"
const Version string = "0.1.2"

// GitCommit describes latest commit hash.
// This value is extracted by git command when building.
// To set this from outside, use go build -ldflags "-X main.GitCommit \"$(COMMIT)\""
var GitCommit string
<commit_msg>bump version to 0.2.0<commit_after>package main

const Name string = "packer-post-processor-vagrant-metadata"
const Version string = "0.2.0"

// GitCommit describes latest commit hash.
// This value is extracted by git command when building.
// To set this from outside, use go build -ldflags "-X main.GitCommit \"$(COMMIT)\""
var GitCommit string
<|endoftext|>


<commit_before>package main

const VERSION = "0.1.1"
<commit_msg>Bump version<commit_after>package main

const VERSION = "0.2.0"
<|endoftext|>


<commit_before>// Copyright (c) 2016, Ben Morgan. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

package main

import (
	"text/template"

	"github.com/cassava/repoctl/internal/term"
	"github.com/spf13/cobra"
)

func init() {
	MainCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:                   "version",
	Short:                 "Show version information and current configuration",
	Long:                  "Show version information of repoctl, as well as the current configuration.",
	ValidArgsFunction:     completeNoFiles,
	Args:                  cobra.ExactArgs(0),
	DisableFlagsInUseLine: true,
	Run: func(cmd *cobra.Command, args []string) {
		exceptQuiet()

		var progInfo = struct {
			Name      string
			Author    string
			Email     string
			Version   string
			Date      string
			Homepage  string
			Copyright string
			License   string
		}{
			Name:      "repoctl",
			Author:    "Ben Morgan",
			Email:     "neembi@gmail.com",
			Version:   "0.21 pre-release",
			Date:      "16 August, 2020",
			Copyright: "2016-2020",
			Homepage:  "https://github.com/cassava/repoctl",
			License:   "MIT",
		}
		versionTmpl.Execute(term.StdOut, progInfo)

		// Print the current configuration.
		term.Println()
		Conf.WriteProperties(term.StdOut)
	},
}

var versionTmpl = template.Must(template.New("version").Parse(
	`{{.Name}} version {{.Version}} ({{.Date}})
Copyright {{.Copyright}}, {{.Author}} <{{.Email}}>

You may find {{.Name}} on the Internet at
    {{.Homepage}}
Please report any bugs you may encounter.

The source code of {{.Name}} is licensed under the {{.License}} license.
`))
<commit_msg>Release version 0.21<commit_after>// Copyright (c) 2016, Ben Morgan. All rights reserved.
// Use of this source code is governed by an MIT license
// that can be found in the LICENSE file.

package main

import (
	"text/template"

	"github.com/cassava/repoctl/internal/term"
	"github.com/spf13/cobra"
)

func init() {
	MainCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:                   "version",
	Short:                 "Show version information and current configuration",
	Long:                  "Show version information of repoctl, as well as the current configuration.",
	ValidArgsFunction:     completeNoFiles,
	Args:                  cobra.ExactArgs(0),
	DisableFlagsInUseLine: true,
	Run: func(cmd *cobra.Command, args []string) {
		exceptQuiet()

		var progInfo = struct {
			Name      string
			Author    string
			Email     string
			Version   string
			Date      string
			Homepage  string
			Copyright string
			License   string
		}{
			Name:      "repoctl",
			Author:    "Ben Morgan",
			Email:     "cassava@iexu.de",
			Version:   "0.21",
			Date:      "30 August, 2020",
			Copyright: "2016-2020",
			Homepage:  "https://github.com/cassava/repoctl",
			License:   "MIT",
		}
		versionTmpl.Execute(term.StdOut, progInfo)

		// Print the current configuration.
		term.Println()
		Conf.WriteProperties(term.StdOut)
	},
}

var versionTmpl = template.Must(template.New("version").Parse(
	`{{.Name}} version {{.Version}} ({{.Date}})
Copyright {{.Copyright}}, {{.Author}} <{{.Email}}>

You may find {{.Name}} on the Internet at
    {{.Homepage}}
Please report any bugs you may encounter.

The source code of {{.Name}} is licensed under the {{.License}} license.
`))
<|endoftext|>


<commit_before>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2021

package instana

// Version is the version of Instana sensor
const Version = "1.28.1"
<commit_msg>Bump version to v1.29.0<commit_after>// (c) Copyright IBM Corp. 2021
// (c) Copyright Instana Inc. 2021

package instana

// Version is the version of Instana sensor
const Version = "1.29.0"
<|endoftext|>


<commit_before>package dns

import "fmt"

// Version is current version of this library.
var Version = v{1, 1, 39}

// v holds the version of this library.
type v struct {
	Major, Minor, Patch int
}

func (v v) String() string {
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
<commit_msg>Release 1.1.40<commit_after>package dns

import "fmt"

// Version is current version of this library.
var Version = v{1, 1, 40}

// v holds the version of this library.
type v struct {
	Major, Minor, Patch int
}

func (v v) String() string {
	return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Patch)
}
<|endoftext|>


<commit_before>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.5.1"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""
<commit_msg>Update version<commit_after>package main

// The git commit that was compiled. This will be filled in by the compiler.
var GitCommit string
var GitDescribe string

// The main version number that is being run at the moment.
const Version = "0.5.2"

// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = ""
<|endoftext|>


<commit_before>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

// Package buildlog provides a build log viewer for Spyglass
package buildlog

import (
	"bytes"
	"encoding/json"
	"fmt"
	"html/template"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/sirupsen/logrus"
	"k8s.io/test-infra/prow/spyglass/lenses"
)

const (
	name            = "buildlog"
	title           = "Build Log"
	priority        = 10
	neighborLines   = 5 // number of "important" lines to be displayed in either direction
	minLinesSkipped = 5
)

// Lens implements the build lens.
type Lens struct{}

// Name returns the name.
func (lens Lens) Name() string {
	return name
}

// Title returns the title.
func (lens Lens) Title() string {
	return title
}

// Priority returns the priority.
func (lens Lens) Priority() int {
	return priority
}

// Header executes the "header" section of the template.
func (lens Lens) Header(artifacts []lenses.Artifact, resourceDir string) string {
	return executeTemplate(resourceDir, "header", BuildLogsView{})
}

// errRE matches keywords and glog error messages
var errRE = regexp.MustCompile(`(?i)(\s|^)timed out\b|(\s|^)error(s)?\b|(\s|^)fail(ure|ed)?\b|(\s|^)fatal\b|(\s|^)panic\b|^E\d{4} \d\d:\d\d:\d\d\.\d\d\d]`)

func init() {
	lenses.RegisterLens(Lens{})
}

// SubLine represents an substring within a LogLine. It it used so error terms can be highlighted.
type SubLine struct {
	Highlighted bool
	Text        string
}

// LogLine represents a line displayed in the LogArtifactView.
type LogLine struct {
	Number      int
	Length      int
	Highlighted bool
	Skip        bool
	SubLines    []SubLine
}

// LineGroup holds multiple lines that can be collapsed/expanded as a block
type LineGroup struct {
	Skip                   bool
	Start, End             int // closed, open
	ByteOffset, ByteLength int
	LogLines               []LogLine
}

// LineRequest represents a request for output lines from an artifact. If Offset is 0 and Length
// is -1, all lines will be fetched.
type LineRequest struct {
	Artifact  string `json:"artifact"`
	Offset    int64  `json:"offset"`
	Length    int64  `json:"length"`
	StartLine int    `json:"startLine"`
}

// LinesSkipped returns the number of lines skipped in a line group.
func (g LineGroup) LinesSkipped() int {
	return g.End - g.Start
}

// LogArtifactView holds a single log file's view
type LogArtifactView struct {
	ArtifactName string
	ArtifactLink string
	LineGroups   []LineGroup
	ViewAll      bool
}

// BuildLogsView holds each log file view
type BuildLogsView struct {
	LogViews           []LogArtifactView
	RawGetAllRequests  map[string]string
	RawGetMoreRequests map[string]string
}

// Body returns the <body> content for a build log (or multiple build logs)
func (lens Lens) Body(artifacts []lenses.Artifact, resourceDir string, data string) string {
	buildLogsView := BuildLogsView{
		LogViews:           []LogArtifactView{},
		RawGetAllRequests:  make(map[string]string),
		RawGetMoreRequests: make(map[string]string),
	}

	// Read log artifacts and construct template structs
	for _, a := range artifacts {
		av := LogArtifactView{
			ArtifactName: a.JobPath(),
			ArtifactLink: a.CanonicalLink(),
		}
		lines, err := logLinesAll(a)
		if err != nil {
			logrus.WithError(err).Error("Error reading log.")
			continue
		}
		av.LineGroups = groupLines(highlightLines(lines, 0))
		av.ViewAll = true
		buildLogsView.LogViews = append(buildLogsView.LogViews, av)
	}

	return executeTemplate(resourceDir, "body", buildLogsView)
}

// Callback is used to retrieve new log segments
func (lens Lens) Callback(artifacts []lenses.Artifact, resourceDir string, data string) string {
	var request LineRequest
	err := json.Unmarshal([]byte(data), &request)
	if err != nil {
		return "failed to unmarshal request"
	}
	artifact, ok := artifactByName(artifacts, request.Artifact)
	if !ok {
		return "no artifact named " + request.Artifact
	}

	var lines []string
	if request.Offset == 0 && request.Length == -1 {
		lines, err = logLinesAll(artifact)
	} else {
		lines, err = logLines(artifact, request.Offset, request.Length)
	}
	if err != nil {
		return fmt.Sprintf("failed to retrieve log lines: %v", err)
	}

	logLines := highlightLines(lines, request.StartLine)
	return executeTemplate(resourceDir, "line group", logLines)
}

func artifactByName(artifacts []lenses.Artifact, name string) (lenses.Artifact, bool) {
	for _, a := range artifacts {
		if a.JobPath() == name {
			return a, true
		}
	}
	return nil, false
}

// logLinesAll reads all of an artifact and splits it into lines.
func logLinesAll(artifact lenses.Artifact) ([]string, error) {
	read, err := artifact.ReadAll()
	if err != nil {
		return nil, fmt.Errorf("failed to read log %q: %v", artifact.JobPath(), err)
	}
	logLines := strings.Split(string(read), "\n")

	return logLines, nil
}

func logLines(artifact lenses.Artifact, offset, length int64) ([]string, error) {
	b := make([]byte, length)
	_, err := artifact.ReadAt(b, offset)
	if err != nil {
		if err != lenses.ErrGzipOffsetRead {
			return nil, fmt.Errorf("couldn't read requested bytes: %v", err)
		}
		moreBytes, err := artifact.ReadAtMost(offset + length)
		if err != nil {
			return nil, fmt.Errorf("couldn't handle reading gzipped file: %v", err)
		}
		b = moreBytes[offset:]
	}
	return strings.Split(string(b), "\n"), nil
}

func highlightLines(lines []string, startLine int) []LogLine {
	// mark highlighted lines
	logLines := make([]LogLine, 0, len(lines))
	for i, text := range lines {
		length := len(text)
		subLines := []SubLine{}
		loc := errRE.FindStringIndex(text)
		for loc != nil {
			subLines = append(subLines, SubLine{false, text[:loc[0]]})
			subLines = append(subLines, SubLine{true, text[loc[0]:loc[1]]})
			text = text[loc[1]:]
			loc = errRE.FindStringIndex(text)
		}
		subLines = append(subLines, SubLine{false, text})
		logLines = append(logLines, LogLine{
			Length:      length + 1, // counting the "\n"
			SubLines:    subLines,
			Number:      startLine + i + 1,
			Highlighted: len(subLines) > 1,
			Skip:        true,
		})
	}
	return logLines
}

// breaks lines into important/unimportant groups
func groupLines(logLines []LogLine) []LineGroup {
	// show highlighted lines and their neighboring lines
	for i, line := range logLines {
		if line.Highlighted {
			for d := -neighborLines; d <= neighborLines; d++ {
				if i+d < 0 {
					continue
				}
				if i+d >= len(logLines) {
					break
				}
				logLines[i+d].Skip = false
			}
		}
	}
	// break into groups
	currentOffset := 0
	previousOffset := 0
	var lineGroups []LineGroup
	curGroup := LineGroup{}
	for i, line := range logLines {
		if line.Skip == curGroup.Skip {
			curGroup.LogLines = append(curGroup.LogLines, line)
			currentOffset += line.Length
		} else {
			curGroup.End = i
			curGroup.ByteLength = currentOffset - previousOffset - 1 // -1 for trailing newline
			previousOffset = currentOffset
			if curGroup.Skip {
				if curGroup.LinesSkipped() < minLinesSkipped {
					curGroup.Skip = false
				}
			}
			if len(curGroup.LogLines) > 0 {
				lineGroups = append(lineGroups, curGroup)
			}
			curGroup = LineGroup{
				Skip:       line.Skip,
				Start:      i,
				LogLines:   []LogLine{line},
				ByteOffset: currentOffset,
			}
			currentOffset += line.Length
		}
	}
	curGroup.End = len(logLines)
	curGroup.ByteLength = currentOffset - previousOffset - 1
	if curGroup.Skip {
		if curGroup.LinesSkipped() < minLinesSkipped {
			curGroup.Skip = false
		}
	}
	if len(curGroup.LogLines) > 0 {
		lineGroups = append(lineGroups, curGroup)
	}
	return lineGroups
}

// LogViewTemplate executes the log viewer template ready for rendering
func executeTemplate(resourceDir, templateName string, data interface{}) string {
	t := template.New("template.html")
	_, err := t.ParseFiles(filepath.Join(resourceDir, "template.html"))
	if err != nil {
		return fmt.Sprintf("Failed to load template: %v", err)
	}
	var buf bytes.Buffer
	if err := t.ExecuteTemplate(&buf, templateName, data); err != nil {
		logrus.WithError(err).Error("Error executing template.")
	}
	return buf.String()
}
<commit_msg>Spyglass: Do not consider EOF on gcs files an error<commit_after>/*
Copyright 2018 The Kubernetes Authors.

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

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

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

// Package buildlog provides a build log viewer for Spyglass
package buildlog

import (
	"bytes"
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/sirupsen/logrus"
	"k8s.io/test-infra/prow/spyglass/lenses"
)

const (
	name            = "buildlog"
	title           = "Build Log"
	priority        = 10
	neighborLines   = 5 // number of "important" lines to be displayed in either direction
	minLinesSkipped = 5
)

// Lens implements the build lens.
type Lens struct{}

// Name returns the name.
func (lens Lens) Name() string {
	return name
}

// Title returns the title.
func (lens Lens) Title() string {
	return title
}

// Priority returns the priority.
func (lens Lens) Priority() int {
	return priority
}

// Header executes the "header" section of the template.
func (lens Lens) Header(artifacts []lenses.Artifact, resourceDir string) string {
	return executeTemplate(resourceDir, "header", BuildLogsView{})
}

// errRE matches keywords and glog error messages
var errRE = regexp.MustCompile(`(?i)(\s|^)timed out\b|(\s|^)error(s)?\b|(\s|^)fail(ure|ed)?\b|(\s|^)fatal\b|(\s|^)panic\b|^E\d{4} \d\d:\d\d:\d\d\.\d\d\d]`)

func init() {
	lenses.RegisterLens(Lens{})
}

// SubLine represents an substring within a LogLine. It it used so error terms can be highlighted.
type SubLine struct {
	Highlighted bool
	Text        string
}

// LogLine represents a line displayed in the LogArtifactView.
type LogLine struct {
	Number      int
	Length      int
	Highlighted bool
	Skip        bool
	SubLines    []SubLine
}

// LineGroup holds multiple lines that can be collapsed/expanded as a block
type LineGroup struct {
	Skip                   bool
	Start, End             int // closed, open
	ByteOffset, ByteLength int
	LogLines               []LogLine
}

// LineRequest represents a request for output lines from an artifact. If Offset is 0 and Length
// is -1, all lines will be fetched.
type LineRequest struct {
	Artifact  string `json:"artifact"`
	Offset    int64  `json:"offset"`
	Length    int64  `json:"length"`
	StartLine int    `json:"startLine"`
}

// LinesSkipped returns the number of lines skipped in a line group.
func (g LineGroup) LinesSkipped() int {
	return g.End - g.Start
}

// LogArtifactView holds a single log file's view
type LogArtifactView struct {
	ArtifactName string
	ArtifactLink string
	LineGroups   []LineGroup
	ViewAll      bool
}

// BuildLogsView holds each log file view
type BuildLogsView struct {
	LogViews           []LogArtifactView
	RawGetAllRequests  map[string]string
	RawGetMoreRequests map[string]string
}

// Body returns the <body> content for a build log (or multiple build logs)
func (lens Lens) Body(artifacts []lenses.Artifact, resourceDir string, data string) string {
	buildLogsView := BuildLogsView{
		LogViews:           []LogArtifactView{},
		RawGetAllRequests:  make(map[string]string),
		RawGetMoreRequests: make(map[string]string),
	}

	// Read log artifacts and construct template structs
	for _, a := range artifacts {
		av := LogArtifactView{
			ArtifactName: a.JobPath(),
			ArtifactLink: a.CanonicalLink(),
		}
		lines, err := logLinesAll(a)
		if err != nil {
			logrus.WithError(err).Error("Error reading log.")
			continue
		}
		av.LineGroups = groupLines(highlightLines(lines, 0))
		av.ViewAll = true
		buildLogsView.LogViews = append(buildLogsView.LogViews, av)
	}

	return executeTemplate(resourceDir, "body", buildLogsView)
}

// Callback is used to retrieve new log segments
func (lens Lens) Callback(artifacts []lenses.Artifact, resourceDir string, data string) string {
	var request LineRequest
	err := json.Unmarshal([]byte(data), &request)
	if err != nil {
		return "failed to unmarshal request"
	}
	artifact, ok := artifactByName(artifacts, request.Artifact)
	if !ok {
		return "no artifact named " + request.Artifact
	}

	var lines []string
	if request.Offset == 0 && request.Length == -1 {
		lines, err = logLinesAll(artifact)
	} else {
		lines, err = logLines(artifact, request.Offset, request.Length)
	}
	if err != nil {
		return fmt.Sprintf("failed to retrieve log lines: %v", err)
	}

	logLines := highlightLines(lines, request.StartLine)
	return executeTemplate(resourceDir, "line group", logLines)
}

func artifactByName(artifacts []lenses.Artifact, name string) (lenses.Artifact, bool) {
	for _, a := range artifacts {
		if a.JobPath() == name {
			return a, true
		}
	}
	return nil, false
}

// logLinesAll reads all of an artifact and splits it into lines.
func logLinesAll(artifact lenses.Artifact) ([]string, error) {
	read, err := artifact.ReadAll()
	if err != nil {
		return nil, fmt.Errorf("failed to read log %q: %v", artifact.JobPath(), err)
	}
	logLines := strings.Split(string(read), "\n")

	return logLines, nil
}

func logLines(artifact lenses.Artifact, offset, length int64) ([]string, error) {
	b := make([]byte, length)
	_, err := artifact.ReadAt(b, offset)
	if err != nil && err != io.EOF {
		if err != lenses.ErrGzipOffsetRead {
			return nil, fmt.Errorf("couldn't read requested bytes: %v", err)
		}
		moreBytes, err := artifact.ReadAtMost(offset + length)
		if err != nil && err != io.EOF {
			return nil, fmt.Errorf("couldn't handle reading gzipped file: %v", err)
		}
		b = moreBytes[offset:]
	}
	return strings.Split(string(b), "\n"), nil
}

func highlightLines(lines []string, startLine int) []LogLine {
	// mark highlighted lines
	logLines := make([]LogLine, 0, len(lines))
	for i, text := range lines {
		length := len(text)
		subLines := []SubLine{}
		loc := errRE.FindStringIndex(text)
		for loc != nil {
			subLines = append(subLines, SubLine{false, text[:loc[0]]})
			subLines = append(subLines, SubLine{true, text[loc[0]:loc[1]]})
			text = text[loc[1]:]
			loc = errRE.FindStringIndex(text)
		}
		subLines = append(subLines, SubLine{false, text})
		logLines = append(logLines, LogLine{
			Length:      length + 1, // counting the "\n"
			SubLines:    subLines,
			Number:      startLine + i + 1,
			Highlighted: len(subLines) > 1,
			Skip:        true,
		})
	}
	return logLines
}

// breaks lines into important/unimportant groups
func groupLines(logLines []LogLine) []LineGroup {
	// show highlighted lines and their neighboring lines
	for i, line := range logLines {
		if line.Highlighted {
			for d := -neighborLines; d <= neighborLines; d++ {
				if i+d < 0 {
					continue
				}
				if i+d >= len(logLines) {
					break
				}
				logLines[i+d].Skip = false
			}
		}
	}
	// break into groups
	currentOffset := 0
	previousOffset := 0
	var lineGroups []LineGroup
	curGroup := LineGroup{}
	for i, line := range logLines {
		if line.Skip == curGroup.Skip {
			curGroup.LogLines = append(curGroup.LogLines, line)
			currentOffset += line.Length
		} else {
			curGroup.End = i
			curGroup.ByteLength = currentOffset - previousOffset - 1 // -1 for trailing newline
			previousOffset = currentOffset
			if curGroup.Skip {
				if curGroup.LinesSkipped() < minLinesSkipped {
					curGroup.Skip = false
				}
			}
			if len(curGroup.LogLines) > 0 {
				lineGroups = append(lineGroups, curGroup)
			}
			curGroup = LineGroup{
				Skip:       line.Skip,
				Start:      i,
				LogLines:   []LogLine{line},
				ByteOffset: currentOffset,
			}
			currentOffset += line.Length
		}
	}
	curGroup.End = len(logLines)
	curGroup.ByteLength = currentOffset - previousOffset - 1
	if curGroup.Skip {
		if curGroup.LinesSkipped() < minLinesSkipped {
			curGroup.Skip = false
		}
	}
	if len(curGroup.LogLines) > 0 {
		lineGroups = append(lineGroups, curGroup)
	}
	return lineGroups
}

// LogViewTemplate executes the log viewer template ready for rendering
func executeTemplate(resourceDir, templateName string, data interface{}) string {
	t := template.New("template.html")
	_, err := t.ParseFiles(filepath.Join(resourceDir, "template.html"))
	if err != nil {
		return fmt.Sprintf("Failed to load template: %v", err)
	}
	var buf bytes.Buffer
	if err := t.ExecuteTemplate(&buf, templateName, data); err != nil {
		logrus.WithError(err).Error("Error executing template.")
	}
	return buf.String()
}
<|endoftext|>


<commit_before>package gobot

const version = "0.12.1"

// Version returns the current Gobot version
func Version() string {
	return version
}
<commit_msg>release: update to version 0.13.0<commit_after>package gobot

const version = "0.13.0"

// Version returns the current Gobot version
func Version() string {
	return version
}
<|endoftext|>


<commit_before>package sdk

const VERSION = "v1.4.3"
<commit_msg>Incremented version.<commit_after>package sdk

const VERSION = "v1.5.0"
<|endoftext|>


<commit_before>package gotermBox

import (
	"io"

	"github.com/antongulenko/golib"
	"github.com/antongulenko/goterm"
)

// CliLogBox can display a box spanning over the entire command-line screen
// containing arbitrary content that can be updated from outside, and an additional
// section at the bottom containing log messages captured using a LogBuffer.
type CliLogBox struct {
	// LogBuffer provides the underlying functionality for capturing log messages.
	// CliLogBox acts like an extension of LogBuffer. After calling Init(),
	// the log capturing must be taken care of using RegisterMessageHooks(),
	// InterceptLogger() and RestoreLogger().
	*LogBuffer

	// NoUtf8 can be set to true to replace UTF8 border drawing characters with
	// regular ASCII characters.
	NoUtf8 bool

	// LogLines configures the minimum number of log entries that must remain visible
	// in the lower part of the console box. The log entries are appended directly
	// to the actual output and usually take the rest of the screen. If the box content
	// is so long, that it would leave less than LogLines log entries, the content is
	// truncated. The truncation is visualized by three dots in the separator line
	// between the content and the log entries.
	LogLines int

	// MessageBuffer configures the number of messages stored in the underlying LogBuffer.
	MessageBuffer int
}

// Init initializes the underlying LogBuffer and should be called before any other methods.
func (box *CliLogBox) Init() {
	box.LogBuffer = NewDefaultLogBuffer(box.MessageBuffer)
}

// Updates refreshes the entire display output. It can be called in arbitrary time intervals,
// but should never be called concurrently. The content must be written by the given function,
// which also receives the width of the screen. If it prints lines that are longer than the screen
// width, they will be cut off. It can produce an arbitrary number of lines.
func (box *CliLogBox) Update(writeContent func(out io.Writer, width int)) {
	console := golib.GetTerminalSize()
	gotermBox := goterm.NewBox(int(console.Col), int(console.Row), 0)

	gotermBox.Height -= 1 // Line with cursor
	var separator, dots string
	if box.NoUtf8 {
		gotermBox.Border = "- | - - - -"
		separator = "-"
		dots = "... "
	} else {
		gotermBox.Border = "═ ║ ╔ ╗ ╚ ╝"
		separator = "═"
		dots = "··· "
	}
	lines := gotermBox.Height - 3 // borders + separator

	counter := newlineCounter{out: gotermBox}
	if box.LogLines > 0 {
		counter.max_lines = lines - box.LogLines
	}
	writeContent(&counter, gotermBox.Width)
	lines -= counter.num

	if counter.num > 0 {
		i := 0
		if counter.truncated {
			gotermBox.Write([]byte(dots))
			i += len(dots)
		}
		for i := 0; i < gotermBox.Width; i++ {
			gotermBox.Write([]byte(separator))
		}
		gotermBox.Write([]byte("\n"))
	}
	box.PrintMessages(gotermBox, lines)
	goterm.MoveCursor(1, 1)
	goterm.Print(gotermBox)
	goterm.Flush()
}

type newlineCounter struct {
	out       io.Writer
	num       int
	max_lines int
	truncated bool
}

func (counter *newlineCounter) Write(data []byte) (int, error) {
	total := len(data)
	if counter.max_lines <= 0 || counter.num < counter.max_lines {
		written := 0
		start := 0
		for i, char := range data {
			if char == '\n' {
				counter.num++
				num, err := counter.out.Write(data[start : i+1])
				written += num
				start = i + 1
				if err != nil {
					return written, err
				}
				if counter.max_lines > 0 && counter.num >= counter.max_lines {
					return total, err
				}
			}
		}
		num, err := counter.out.Write(data[start:])
		written += num
		if err != nil {
			return written, err
		}
	} else {
		counter.truncated = true
	}
	return total, nil
}
<commit_msg>Fixing console box printing<commit_after>package gotermBox

import (
	"bytes"
	"io"

	"github.com/antongulenko/goterm"
)

// CliLogBox can display a box spanning over the entire command-line screen
// containing arbitrary content that can be updated from outside, and an additional
// section at the bottom containing log messages captured using a LogBuffer.
type CliLogBox struct {
	// LogBuffer provides the underlying functionality for capturing log messages.
	// CliLogBox acts like an extension of LogBuffer. After calling Init(),
	// the log capturing must be taken care of using RegisterMessageHooks(),
	// InterceptLogger() and RestoreLogger().
	*LogBuffer

	// NoUtf8 can be set to true to replace UTF8 border drawing characters with
	// regular ASCII characters.
	NoUtf8 bool

	// LogLines configures the minimum number of log entries that must remain visible
	// in the lower part of the console box. The log entries are appended directly
	// to the actual output and usually take the rest of the screen. If the box content
	// is so long, that it would leave less than LogLines log entries, the content is
	// truncated. The truncation is visualized by three dots in the separator line
	// between the content and the log entries.
	LogLines int

	// MessageBuffer configures the number of messages stored in the underlying LogBuffer.
	MessageBuffer int
}

// Init initializes the underlying LogBuffer and should be called before any other methods.
func (box *CliLogBox) Init() {
	box.LogBuffer = NewDefaultLogBuffer(box.MessageBuffer)
}

// Updates refreshes the entire display output. It can be called in arbitrary time intervals,
// but should never be called concurrently. The content must be written by the given function,
// which also receives the width of the screen. If it prints lines that are longer than the screen
// width, they will be cut off. It can produce an arbitrary number of lines.
func (box *CliLogBox) Update(writeContent func(out io.Writer, width int)) {
	gotermBox := goterm.Box{
		Buf:      new(bytes.Buffer),
		Width:    goterm.Width(),
		Height:   goterm.Height() - 1, // Subtract 1 for the line with cursor
		PaddingX: 1,
		PaddingY: 0,
	}
	var separator, dots string
	if box.NoUtf8 {
		gotermBox.Border = "- | - - - -"
		separator = "-"
		dots = "... "
	} else {
		gotermBox.Border = "═ ║ ╔ ╗ ╚ ╝"
		separator = "═"
		dots = "··· "
	}
	lines := gotermBox.Height - 3 // borders + separator

	counter := newlineCounter{out: &gotermBox}
	if box.LogLines > 0 {
		counter.max_lines = lines - box.LogLines
	}
	writeContent(&counter, gotermBox.Width)
	lines -= counter.num

	if counter.num > 0 {
		i := 0
		if counter.truncated {
			gotermBox.Write([]byte(dots))
			i += len(dots)
		}
		for i := 0; i < gotermBox.Width; i++ {
			gotermBox.Write([]byte(separator))
		}
		gotermBox.Write([]byte("\n"))
	}
	box.PrintMessages(&gotermBox, lines)
	goterm.MoveCursor(1, 1)
	goterm.Print(gotermBox)
	goterm.Flush()
}

type newlineCounter struct {
	out       io.Writer
	num       int
	max_lines int
	truncated bool
}

func (counter *newlineCounter) Write(data []byte) (int, error) {
	total := len(data)
	if counter.max_lines <= 0 || counter.num < counter.max_lines {
		written := 0
		start := 0
		for i, char := range data {
			if char == '\n' {
				counter.num++
				num, err := counter.out.Write(data[start : i+1])
				written += num
				start = i + 1
				if err != nil {
					return written, err
				}
				if counter.max_lines > 0 && counter.num >= counter.max_lines {
					return total, err
				}
			}
		}
		num, err := counter.out.Write(data[start:])
		written += num
		if err != nil {
			return written, err
		}
	} else {
		counter.truncated = true
	}
	return total, nil
}
<|endoftext|>