<commit_before>package setup_instruments

import (
	"database/sql"
	"log"

	"github.com/sjmudd/pstop/lib"
)

// Error 1142: UPDATE command denied to user
const UPDATE_FAILED = "Error 1142"

type setup_instruments_row struct {
	NAME    string
	ENABLED string
	TIMED   string
}

type SetupInstruments struct {
	update_succeeded bool
	rows []setup_instruments_row
}

// Change settings to monitor wait/synch/mutex/%
func (si *SetupInstruments) EnableMutexMonitoring(dbh *sql.DB) {
	si.rows = make([]setup_instruments_row, 0, 100)

	// populate the rows which are not set
	sql := "SELECT NAME, ENABLED, TIMED FROM setup_instruments WHERE NAME LIKE 'wait/synch/mutex/%' AND ( enabled <> 'YES' OR timed <> 'YES' )"

	lib.Logger.Println("Collecting p_s.setup_instruments wait/synch/mutex configuration settings")

	rows, err := dbh.Query(sql)
	if err != nil {
		log.Fatal(err)

	}
	defer rows.Close()

	count := 0
	for rows.Next() {
		var r setup_instruments_row
		if err := rows.Scan(
			&r.NAME,
			&r.ENABLED,
			&r.TIMED); err != nil {
			log.Fatal(err)
		}
		// we collect all information even if it's mainly empty as we may reference it later
		si.rows = append(si.rows, r)
		count++
	}
	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
	lib.Logger.Println("- found", count, "rows whose configuration need changing")

	// update the rows which need to be set - do multiple updates but I don't care
	lib.Logger.Println("Updating p_s.setup_instruments to allow wait/synch/mutex configuration")

	count = 0
	for i := range si.rows {
		sql := "UPDATE setup_instruments SET enabled = 'YES', TIMED = 'YES' WHERE NAME = '" + si.rows[i].NAME + "'"
		if _, err := dbh.Exec(sql); err == nil {
			si.update_succeeded = true
		} else {
			if err.Error()[0:10] != UPDATE_FAILED {
				log.Fatal(err)
			}
			break

		}
		count++
	}
	lib.Logger.Println(count, "rows changed in p_s.setup_instruments")
}

// restore any changed rows back to their original state
func (si *SetupInstruments) Restore(dbh *sql.DB) {
	// If the previous update didn't work then don't try to restore
	if ! si.update_succeeded {
		lib.Logger.Println("Not restoring p_s.setup_instruments to its original settings as previous UPDATE had failed")
		return
	} else {
		lib.Logger.Println("Restoring p_s.setup_instruments to its original settings")
	}

	// update the rows which need to be set - do multiple updates but I don't care
	count := 0
	for i := range si.rows {
		sql := "UPDATE setup_instruments SET enabled = '" + si.rows[i].ENABLED + "', TIMED = '" + si.rows[i].TIMED + "' WHERE NAME = '" + si.rows[i].NAME + "'"
		if _, err := dbh.Exec(sql); err != nil {
			log.Fatal(err)
		}
		count++
	}
	lib.Logger.Println(count, "rows changed in p_s.setup_instruments")
}
<commit_msg>log success/failure to change ps.setup_instruments<commit_after>package setup_instruments

import (
	"database/sql"
	"log"

	"github.com/sjmudd/pstop/lib"
)

// Error 1142: UPDATE command denied to user
const UPDATE_FAILED = "Error 1142"

type setup_instruments_row struct {
	NAME    string
	ENABLED string
	TIMED   string
}

type SetupInstruments struct {
	update_succeeded bool
	rows []setup_instruments_row
}

// Change settings to monitor wait/synch/mutex/%
func (si *SetupInstruments) EnableMutexMonitoring(dbh *sql.DB) {
	si.rows = make([]setup_instruments_row, 0, 100)

	// populate the rows which are not set
	sql := "SELECT NAME, ENABLED, TIMED FROM setup_instruments WHERE NAME LIKE 'wait/synch/mutex/%' AND ( enabled <> 'YES' OR timed <> 'YES' )"

	lib.Logger.Println("Collecting p_s.setup_instruments wait/synch/mutex configuration settings")

	rows, err := dbh.Query(sql)
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	count := 0
	for rows.Next() {
		var r setup_instruments_row
		if err := rows.Scan(
			&r.NAME,
			&r.ENABLED,
			&r.TIMED); err != nil {
			log.Fatal(err)
		}
		// we collect all information even if it's mainly empty as we may reference it later
		si.rows = append(si.rows, r)
		count++
	}
	if err := rows.Err(); err != nil {
		log.Fatal(err)
	}
	lib.Logger.Println("- found", count, "rows whose configuration need changing")

	// update the rows which need to be set - do multiple updates but I don't care
	lib.Logger.Println("Updating p_s.setup_instruments to allow wait/synch/mutex configuration")

	count = 0
	for i := range si.rows {
		sql := "UPDATE setup_instruments SET enabled = 'YES', TIMED = 'YES' WHERE NAME = '" + si.rows[i].NAME + "'"
		if _, err := dbh.Exec(sql); err == nil {
			si.update_succeeded = true
		} else {
			if err.Error()[0:10] != UPDATE_FAILED {
				log.Fatal(err)
			}
			break
		}
		count++
	}
	if si.update_succeeded {
		lib.Logger.Println(count, "rows changed in p_s.setup_instruments")
	} else {
		lib.Logger.Println( "Insufficient privileges to UPDATE setup_instruments: " . err.String() )
	}
}

// restore any changed rows back to their original state
func (si *SetupInstruments) Restore(dbh *sql.DB) {
	// If the previous update didn't work then don't try to restore
	if ! si.update_succeeded {
		lib.Logger.Println("Not restoring p_s.setup_instruments to its original settings as previous UPDATE had failed")
		return
	} else {
		lib.Logger.Println("Restoring p_s.setup_instruments to its original settings")
	}

	// update the rows which need to be set - do multiple updates but I don't care
	count := 0
	for i := range si.rows {
		sql := "UPDATE setup_instruments SET enabled = '" + si.rows[i].ENABLED + "', TIMED = '" + si.rows[i].TIMED + "' WHERE NAME = '" + si.rows[i].NAME + "'"
		if _, err := dbh.Exec(sql); err != nil {
			log.Fatal(err)
		}
		count++
	}
	lib.Logger.Println(count, "rows changed in p_s.setup_instruments")
}
<|endoftext|>


<commit_before>// Copyright The OpenTelemetry 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 exporterhelper

import (
	"context"

	"go.uber.org/zap"

	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/config/configmodels"
	"go.opentelemetry.io/collector/consumer/consumerdata"
	"go.opentelemetry.io/collector/consumer/consumererror"
	"go.opentelemetry.io/collector/consumer/pdata"
	"go.opentelemetry.io/collector/obsreport"
)

// NumTimeSeries returns the number of timeseries in a MetricsData.
func NumTimeSeries(md consumerdata.MetricsData) int {
	receivedTimeSeries := 0
	for _, metric := range md.Metrics {
		receivedTimeSeries += len(metric.GetTimeseries())
	}
	return receivedTimeSeries
}

// PushMetricsData is a helper function that is similar to ConsumeMetricsData but also returns
// the number of dropped metrics.
type PushMetricsData func(ctx context.Context, md pdata.Metrics) (droppedTimeSeries int, err error)

type metricsRequest struct {
	baseRequest
	md     pdata.Metrics
	pusher PushMetricsData
}

func newMetricsRequest(ctx context.Context, md pdata.Metrics, pusher PushMetricsData) request {
	return &metricsRequest{
		baseRequest: baseRequest{ctx: ctx},
		md:          md,
		pusher:      pusher,
	}
}

func (req *metricsRequest) onPartialError(partialErr consumererror.PartialError) request {
	return newMetricsRequest(req.ctx, partialErr.GetMetrics(), req.pusher)
}

func (req *metricsRequest) export(ctx context.Context) (int, error) {
	return req.pusher(ctx, req.md)
}

func (req *metricsRequest) count() int {
	_, numPoints := req.md.MetricAndDataPointCount()
	return numPoints
}

type metricsExporter struct {
	*baseExporter
	pusher PushMetricsData
}

func (mexp *metricsExporter) ConsumeMetrics(ctx context.Context, md pdata.Metrics) error {
	if mexp.baseExporter.convertResourceToTelemetry {
		md = convertResourceToLabels(md)
	}
	exporterCtx := obsreport.ExporterContext(ctx, mexp.cfg.Name())
	req := newMetricsRequest(exporterCtx, md, mexp.pusher)
	_, err := mexp.sender.send(req)
	return err
}

// NewMetricsExporter creates an MetricsExporter that records observability metrics and wraps every request with a Span.
func NewMetricsExporter(
	cfg configmodels.Exporter,
	logger *zap.Logger,
	pushMetricsData PushMetricsData,
	options ...ExporterOption,
) (component.MetricsExporter, error) {
	if cfg == nil {
		return nil, errNilConfig
	}

	if pushMetricsData == nil {
		return nil, errNilPushMetricsData
	}

	be := newBaseExporter(cfg, logger, options...)
	be.wrapConsumerSender(func(nextSender requestSender) requestSender {
		return &metricsSenderWithObservability{
			exporterName: cfg.Name(),
			nextSender:   nextSender,
		}
	})

	return &metricsExporter{
		baseExporter: be,
		pusher:       pushMetricsData,
	}, nil
}

type metricsSenderWithObservability struct {
	exporterName string
	nextSender   requestSender
}

func (mewo *metricsSenderWithObservability) send(req request) (int, error) {
	req.setContext(obsreport.StartMetricsExportOp(req.context(), mewo.exporterName))
	_, err := mewo.nextSender.send(req)

	// TODO: this is not ideal: it should come from the next function itself.
	// 	temporarily loading it from internal format. Once full switch is done
	// 	to new metrics will remove this.
	mReq := req.(*metricsRequest)
	numReceivedMetrics, numPoints := mReq.md.MetricAndDataPointCount()

	obsreport.EndMetricsExportOp(req.context(), numPoints, err)
	return numReceivedMetrics, err
}
<commit_msg>Remove unused public function, usage in contrib will be soon removed (#2118)<commit_after>// Copyright The OpenTelemetry 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 exporterhelper

import (
	"context"

	"go.uber.org/zap"

	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/config/configmodels"
	"go.opentelemetry.io/collector/consumer/consumererror"
	"go.opentelemetry.io/collector/consumer/pdata"
	"go.opentelemetry.io/collector/obsreport"
)

// PushMetricsData is a helper function that is similar to ConsumeMetricsData but also returns
// the number of dropped metrics.
type PushMetricsData func(ctx context.Context, md pdata.Metrics) (droppedTimeSeries int, err error)

type metricsRequest struct {
	baseRequest
	md     pdata.Metrics
	pusher PushMetricsData
}

func newMetricsRequest(ctx context.Context, md pdata.Metrics, pusher PushMetricsData) request {
	return &metricsRequest{
		baseRequest: baseRequest{ctx: ctx},
		md:          md,
		pusher:      pusher,
	}
}

func (req *metricsRequest) onPartialError(partialErr consumererror.PartialError) request {
	return newMetricsRequest(req.ctx, partialErr.GetMetrics(), req.pusher)
}

func (req *metricsRequest) export(ctx context.Context) (int, error) {
	return req.pusher(ctx, req.md)
}

func (req *metricsRequest) count() int {
	_, numPoints := req.md.MetricAndDataPointCount()
	return numPoints
}

type metricsExporter struct {
	*baseExporter
	pusher PushMetricsData
}

func (mexp *metricsExporter) ConsumeMetrics(ctx context.Context, md pdata.Metrics) error {
	if mexp.baseExporter.convertResourceToTelemetry {
		md = convertResourceToLabels(md)
	}
	exporterCtx := obsreport.ExporterContext(ctx, mexp.cfg.Name())
	req := newMetricsRequest(exporterCtx, md, mexp.pusher)
	_, err := mexp.sender.send(req)
	return err
}

// NewMetricsExporter creates an MetricsExporter that records observability metrics and wraps every request with a Span.
func NewMetricsExporter(
	cfg configmodels.Exporter,
	logger *zap.Logger,
	pushMetricsData PushMetricsData,
	options ...ExporterOption,
) (component.MetricsExporter, error) {
	if cfg == nil {
		return nil, errNilConfig
	}

	if pushMetricsData == nil {
		return nil, errNilPushMetricsData
	}

	be := newBaseExporter(cfg, logger, options...)
	be.wrapConsumerSender(func(nextSender requestSender) requestSender {
		return &metricsSenderWithObservability{
			exporterName: cfg.Name(),
			nextSender:   nextSender,
		}
	})

	return &metricsExporter{
		baseExporter: be,
		pusher:       pushMetricsData,
	}, nil
}

type metricsSenderWithObservability struct {
	exporterName string
	nextSender   requestSender
}

func (mewo *metricsSenderWithObservability) send(req request) (int, error) {
	req.setContext(obsreport.StartMetricsExportOp(req.context(), mewo.exporterName))
	_, err := mewo.nextSender.send(req)

	// TODO: this is not ideal: it should come from the next function itself.
	// 	temporarily loading it from internal format. Once full switch is done
	// 	to new metrics will remove this.
	mReq := req.(*metricsRequest)
	numReceivedMetrics, numPoints := mReq.md.MetricAndDataPointCount()

	obsreport.EndMetricsExportOp(req.context(), numPoints, err)
	return numReceivedMetrics, err
}
<|endoftext|>


<commit_before>package command

import (
	"flag"
	"fmt"
	"net"
	"strings"
	"time"

	"github.com/Shopify/sarama"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/gocli"
)

type TopBroker struct {
	Ui  cli.Ui
	Cmd string

	zone, cluster, topic string
	drawMode             bool
	interval             time.Duration

	offsets     map[string]int64 // host => offset sum
	lastOffsets map[string]int64
}

func (this *TopBroker) Run(args []string) (exitCode int) {
	cmdFlags := flag.NewFlagSet("topbroker", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&this.zone, "z", ctx.ZkDefaultZone(), "")
	cmdFlags.StringVar(&this.cluster, "c", "", "")
	cmdFlags.StringVar(&this.topic, "t", "", "")
	cmdFlags.BoolVar(&this.drawMode, "g", false, "")
	cmdFlags.DurationVar(&this.interval, "i", time.Second*5, "refresh interval")

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	this.offsets = make(map[string]int64)
	this.lastOffsets = make(map[string]int64)

	if this.interval.Seconds() < 1 {
		this.interval = time.Second
	}

	zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone)))
	zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
		if !patternMatched(zkcluster.Name(), this.cluster) {
			return
		}

		go this.clusterTopProducers(zkcluster)
	})

	ticker := time.NewTicker(this.interval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			refreshScreen()
			this.showAndResetCounters()

		}
	}

	return
}

func (this *TopBroker) showAndResetCounters() {
	d := this.interval.Seconds()
	for host, offset := range this.offsets {
		qps := float64(0)
		if lastOffset, present := this.lastOffsets[host]; present {
			qps = float64(offset-lastOffset) / d
		}

		this.Ui.Output(fmt.Sprintf("%20s %.2f", host, qps))
	}

	for host, offset := range this.offsets {
		this.lastOffsets[host] = offset
	}
	this.offsets = make(map[string]int64)
}

func (this *TopBroker) clusterTopProducers(zkcluster *zk.ZkCluster) {
	kfk, err := sarama.NewClient(zkcluster.BrokerList(), sarama.NewConfig())
	if err != nil {
		return
	}
	defer kfk.Close()

	for {
		topics, err := kfk.Topics()
		swallow(err)

		for _, topic := range topics {
			if !patternMatched(topic, this.topic) {
				continue
			}

			partions, err := kfk.WritablePartitions(topic)
			swallow(err)
			for _, partitionID := range partions {
				leader, err := kfk.Leader(topic, partitionID)
				swallow(err)

				latestOffset, err := kfk.GetOffset(topic, partitionID,
					sarama.OffsetNewest)
				if err != nil {
					panic(err)
				}

				host, _, err := net.SplitHostPort(leader.Addr())
				swallow(err)

				host = shortIp(host)
				if _, present := this.offsets[host]; !present {
					this.offsets[host] = 0
				}
				this.offsets[host] += latestOffset
			}
		}

		time.Sleep(time.Second)
		kfk.RefreshMetadata(topics...)
	}
}

func (*TopBroker) Synopsis() string {
	return "Unix “top” like utility for kafka brokers"
}

func (this *TopBroker) Help() string {
	help := fmt.Sprintf(`
Usage: %s topbroker [options]

    Unix “top” like utility for kafka brokers

Options:

    -z zone
      Default %s

    -c cluster pattern

    -t topic pattern

    -i interval
      Refresh interval in seconds.
      e,g. 5s

`, this.Cmd)
	return strings.TrimSpace(help)
}
<commit_msg>add lock<commit_after>package command

import (
	"flag"
	"fmt"
	"net"
	"strings"
	"sync"
	"time"

	"github.com/Shopify/sarama"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gafka/zk"
	"github.com/funkygao/gocli"
)

type TopBroker struct {
	Ui  cli.Ui
	Cmd string

	mu sync.Mutex

	zone, cluster, topic string
	drawMode             bool
	interval             time.Duration
	shortIp              bool

	offsets     map[string]int64 // host => offset sum
	lastOffsets map[string]int64
}

func (this *TopBroker) Run(args []string) (exitCode int) {
	cmdFlags := flag.NewFlagSet("topbroker", flag.ContinueOnError)
	cmdFlags.Usage = func() { this.Ui.Output(this.Help()) }
	cmdFlags.StringVar(&this.zone, "z", ctx.ZkDefaultZone(), "")
	cmdFlags.StringVar(&this.cluster, "c", "", "")
	cmdFlags.StringVar(&this.topic, "t", "", "")
	cmdFlags.BoolVar(&this.drawMode, "g", false, "")
	cmdFlags.BoolVar(&this.shortIp, "shortip", false, "")
	cmdFlags.DurationVar(&this.interval, "i", time.Second*5, "refresh interval")

	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	this.offsets = make(map[string]int64)
	this.lastOffsets = make(map[string]int64)

	if this.interval.Seconds() < 1 {
		this.interval = time.Second
	}

	zkzone := zk.NewZkZone(zk.DefaultConfig(this.zone, ctx.ZoneZkAddrs(this.zone)))
	zkzone.ForSortedClusters(func(zkcluster *zk.ZkCluster) {
		if !patternMatched(zkcluster.Name(), this.cluster) {
			return
		}

		go this.clusterTopProducers(zkcluster)
	})

	ticker := time.NewTicker(this.interval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			refreshScreen()
			this.showAndResetCounters()

		}
	}

	return
}

func (this *TopBroker) showAndResetCounters() {
	this.mu.Lock()
	defer this.mu.Unlock()

	d := this.interval.Seconds()
	for host, offset := range this.offsets {
		qps := float64(0)
		if lastOffset, present := this.lastOffsets[host]; present {
			qps = float64(offset-lastOffset) / d
		}

		this.Ui.Output(fmt.Sprintf("%20s %.2f", host, qps))
	}

	for host, offset := range this.offsets {
		this.lastOffsets[host] = offset
	}
	this.offsets = make(map[string]int64)
}

func (this *TopBroker) clusterTopProducers(zkcluster *zk.ZkCluster) {
	kfk, err := sarama.NewClient(zkcluster.BrokerList(), sarama.NewConfig())
	if err != nil {
		return
	}
	defer kfk.Close()

	for {
		topics, err := kfk.Topics()
		swallow(err)

		for _, topic := range topics {
			if !patternMatched(topic, this.topic) {
				continue
			}

			partions, err := kfk.WritablePartitions(topic)
			swallow(err)
			for _, partitionID := range partions {
				leader, err := kfk.Leader(topic, partitionID)
				swallow(err)

				latestOffset, err := kfk.GetOffset(topic, partitionID,
					sarama.OffsetNewest)
				if err != nil {
					panic(err)
				}

				host, _, err := net.SplitHostPort(leader.Addr())
				swallow(err)

				if this.shortIp {
					host = shortIp(host)
				}

				this.mu.Lock()
				if _, present := this.offsets[host]; !present {
					this.offsets[host] = 0
				}
				this.offsets[host] += latestOffset
				this.mu.Unlock()
			}
		}

		time.Sleep(time.Second)
		kfk.RefreshMetadata(topics...)
	}
}

func (*TopBroker) Synopsis() string {
	return "Unix “top” like utility for kafka brokers"
}

func (this *TopBroker) Help() string {
	help := fmt.Sprintf(`
Usage: %s topbroker [options]

    Unix “top” like utility for kafka brokers

Options:

    -z zone
      Default %s

    -c cluster pattern

    -t topic pattern

    -i interval
      Refresh interval in seconds.
      e,g. 5s

    -shortip

`, this.Cmd)
	return strings.TrimSpace(help)
}
<|endoftext|>


<commit_before>package softlayer

import (
	"errors"
	"os"
	"time"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
	"github.com/softlayer/softlayer-go/session"
)

func Provider() terraform.ResourceProvider {
	defaultSoftLayerSession := session.New()
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"username": {
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					return defaultSoftLayerSession.UserName, nil
				},
				Description: "The user name for SoftLayer API operations.",
			},
			"api_key": {
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					return defaultSoftLayerSession.APIKey, nil
				},
				Description: "The API key for SoftLayer API operations.",
			},
			"endpoint_url": {
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					return defaultSoftLayerSession.Endpoint, nil
				},
				Description: "The endpoint url for the SoftLayer API.",
			},
			"timeout": {
				Type:        schema.TypeInt,
				Optional:    true,
				Description: "The timeout (in seconds) to set for any SoftLayer API calls made.",
			},
		},

		DataSourcesMap: map[string]*schema.Resource{
			"softlayer_ssh_key":        dataSourceSoftLayerSSHKey(),
			"softlayer_image_template": dataSourceSoftLayerImageTemplate(),
			"softlayer_vlan":           dataSourceSoftLayerVlan(),
		},

		ResourcesMap: map[string]*schema.Resource{
			"softlayer_virtual_guest":          resourceSoftLayerVirtualGuest(),
			"softlayer_bare_metal":             resourceSoftLayerBareMetal(),
			"softlayer_ssh_key":                resourceSoftLayerSSHKey(),
			"softlayer_dns_domain_record":      resourceSoftLayerDnsDomainRecord(),
			"softlayer_dns_domain":             resourceSoftLayerDnsDomain(),
			"softlayer_lb_vpx":                 resourceSoftLayerLbVpx(),
			"softlayer_lb_vpx_vip":             resourceSoftLayerLbVpxVip(),
			"softlayer_lb_vpx_service":         resourceSoftLayerLbVpxService(),
			"softlayer_lb_local":               resourceSoftLayerLbLocal(),
			"softlayer_lb_local_service_group": resourceSoftLayerLbLocalServiceGroup(),
			"softlayer_lb_local_service":       resourceSoftLayerLbLocalService(),
			"softlayer_security_certificate":   resourceSoftLayerSecurityCertificate(),
			"softlayer_user":                   resourceSoftLayerUser(),
			"softlayer_objectstorage_account":  resourceSoftLayerObjectStorageAccount(),
			"softlayer_provisioning_hook":      resourceSoftLayerProvisioningHook(),
			"softlayer_scale_policy":           resourceSoftLayerScalePolicy(),
			"softlayer_scale_group":            resourceSoftLayerScaleGroup(),
			"softlayer_basic_monitor":          resourceSoftLayerBasicMonitor(),
			"softlayer_vlan":                   resourceSoftLayerVlan(),
			"softlayer_global_ip":              resourceSoftLayerGlobalIp(),
		},

		ConfigureFunc: providerConfigure,
	}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
	sess := session.Session{
		UserName: d.Get("username").(string),
		APIKey:   d.Get("api_key").(string),
		Endpoint: d.Get("endpoint_url").(string),
	}

	if rawTimeout, ok := d.GetOk("timeout"); ok {
		timeout := rawTimeout.(int)
		sess.Timeout = time.Duration(timeout)
	}

	if sess.UserName == "" || sess.APIKey == "" {
		return nil, errors.New(
			"No SoftLayer credentials were found. Please ensure you have specified" +
				" them in the provider or in the environment (see the documentation).",
		)
	}

	if os.Getenv("TF_LOG") != "" {
		sess.Debug = true
	}

	return &sess, nil
}
<commit_msg>Add vpx_ha resource to provider<commit_after>package softlayer

import (
	"errors"
	"os"
	"time"

	"github.com/hashicorp/terraform/helper/schema"
	"github.com/hashicorp/terraform/terraform"
	"github.com/softlayer/softlayer-go/session"
)

func Provider() terraform.ResourceProvider {
	defaultSoftLayerSession := session.New()
	return &schema.Provider{
		Schema: map[string]*schema.Schema{
			"username": {
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					return defaultSoftLayerSession.UserName, nil
				},
				Description: "The user name for SoftLayer API operations.",
			},
			"api_key": {
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					return defaultSoftLayerSession.APIKey, nil
				},
				Description: "The API key for SoftLayer API operations.",
			},
			"endpoint_url": {
				Type:     schema.TypeString,
				Required: true,
				DefaultFunc: func() (interface{}, error) {
					return defaultSoftLayerSession.Endpoint, nil
				},
				Description: "The endpoint url for the SoftLayer API.",
			},
			"timeout": {
				Type:        schema.TypeInt,
				Optional:    true,
				Description: "The timeout (in seconds) to set for any SoftLayer API calls made.",
			},
		},

		DataSourcesMap: map[string]*schema.Resource{
			"softlayer_ssh_key":        dataSourceSoftLayerSSHKey(),
			"softlayer_image_template": dataSourceSoftLayerImageTemplate(),
			"softlayer_vlan":           dataSourceSoftLayerVlan(),
		},

		ResourcesMap: map[string]*schema.Resource{
			"softlayer_virtual_guest":          resourceSoftLayerVirtualGuest(),
			"softlayer_bare_metal":             resourceSoftLayerBareMetal(),
			"softlayer_ssh_key":                resourceSoftLayerSSHKey(),
			"softlayer_dns_domain_record":      resourceSoftLayerDnsDomainRecord(),
			"softlayer_dns_domain":             resourceSoftLayerDnsDomain(),
			"softlayer_lb_vpx":                 resourceSoftLayerLbVpx(),
			"softlayer_lb_vpx_vip":             resourceSoftLayerLbVpxVip(),
			"softlayer_lb_vpx_service":         resourceSoftLayerLbVpxService(),
			"softlayer_lb_vpx_ha":              resourceSoftLayerLbVpxHa(),
			"softlayer_lb_local":               resourceSoftLayerLbLocal(),
			"softlayer_lb_local_service_group": resourceSoftLayerLbLocalServiceGroup(),
			"softlayer_lb_local_service":       resourceSoftLayerLbLocalService(),
			"softlayer_security_certificate":   resourceSoftLayerSecurityCertificate(),
			"softlayer_user":                   resourceSoftLayerUser(),
			"softlayer_objectstorage_account":  resourceSoftLayerObjectStorageAccount(),
			"softlayer_provisioning_hook":      resourceSoftLayerProvisioningHook(),
			"softlayer_scale_policy":           resourceSoftLayerScalePolicy(),
			"softlayer_scale_group":            resourceSoftLayerScaleGroup(),
			"softlayer_basic_monitor":          resourceSoftLayerBasicMonitor(),
			"softlayer_vlan":                   resourceSoftLayerVlan(),
			"softlayer_global_ip":              resourceSoftLayerGlobalIp(),
		},

		ConfigureFunc: providerConfigure,
	}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
	sess := session.Session{
		UserName: d.Get("username").(string),
		APIKey:   d.Get("api_key").(string),
		Endpoint: d.Get("endpoint_url").(string),
	}

	if rawTimeout, ok := d.GetOk("timeout"); ok {
		timeout := rawTimeout.(int)
		sess.Timeout = time.Duration(timeout)
	}

	if sess.UserName == "" || sess.APIKey == "" {
		return nil, errors.New(
			"No SoftLayer credentials were found. Please ensure you have specified" +
				" them in the provider or in the environment (see the documentation).",
		)
	}

	if os.Getenv("TF_LOG") != "" {
		sess.Debug = true
	}

	return &sess, nil
}
<|endoftext|>


<commit_before>// Package errs provides a simple error package with stack traces.
package errs

import (
	"fmt"
	"io"
	"runtime"
)

// Namer is implemented by all errors returned in this package. It returns a
// name for the class of error it is, and a boolean indicating if the name is
// valid.
type Namer interface{ Name() (string, bool) }

// Causer is implemented by all errors returned in this package. It returns
// the underlying cause of the error, or nil if there is no underlying cause.
type Causer interface{ Cause() error }

// New returns an error not contained in any class. This is the same as calling
// fmt.Errorf(...) except it captures a stack trace on creation.
func New(format string, args ...interface{}) error {
	return (*Class).create(nil, 3, fmt.Errorf(format, args...))
}

// Wrap returns an error not contained in any class. It just associates a stack
// trace with the error. Wrap returns nil if err is nil.
func Wrap(err error) error {
	return (*Class).create(nil, 3, err)
}

// Unwrap returns the underlying error, if any, or just the error.
func Unwrap(err error) error {
	// we call Cause as much as possible. Since comparing arbitrary interfaces
	// with equality isn't panic safe, we only loop up to 100 times to ensure
	// that a poor implementation that loops does not cause a hang.
	for i := 0; err != nil && i < 100; i++ {
		causer, ok := err.(Causer)
		if !ok {
			break
		}

		// if the cause of some error is nil, we return it.
		nerr := causer.Cause()
		if nerr == nil {
			return err
		}
		err = nerr
	}

	return err
}

// Classes returns all the classes that have wrapped the error.
func Classes(err error) []*Class {
	if err, ok := err.(*errorT); ok && err != nil {
		return append([]*Class(nil), err.classes...)
	}
	return nil
}

//
// error classes
//

// Class represents a class of errors. You can construct errors, and check if
// errors are part of the class.
type Class string

// Has returns true if the passed in error was wrapped by this class.
func (c *Class) Has(err error) bool {
	if err, ok := err.(*errorT); ok {
		for _, k := range err.classes {
			if k == c {
				return true
			}
		}
	}
	return false
}

// New constructs an error with the format string that will be contained by
// this class. This is the same as calling Wrap(fmt.Errorf(...)).
func (c *Class) New(format string, args ...interface{}) error {
	return c.create(3, fmt.Errorf(format, args...))
}

// Wrap returns a new error based on the passed in error that is contained in
// this class. Wrap returns nil if err is nil.
func (c *Class) Wrap(err error) error {
	return c.create(3, err)
}

// create constructs the error, or just adds the class to the error, keeping
// track of the stack if it needs to construct it.
func (c *Class) create(depth int, err error) error {
	if err == nil {
		return nil
	}

	if err, ok := err.(*errorT); ok {
		if c != nil && err.outerClass() != c {
			err.classes = append(err.classes, c)
		}
		return err
	}

	var pcs [256]uintptr
	n := runtime.Callers(depth, pcs[:])

	var classes []*Class
	if c != nil {
		classes = []*Class{c}
	}

	return &errorT{
		classes: classes,
		err:     err,
		pcs:     pcs[:n:n],
	}
}

//
// errors
//

// errorT is the type of errors returned from this package.
type errorT struct {
	classes []*Class
	pcs     []uintptr
	err     error
}

var ( // ensure *errorT implements the helper interfaces.
	_ Namer  = (*errorT)(nil)
	_ Causer = (*errorT)(nil)
	_ error  = (*errorT)(nil)
)

// outerClass returns the outermost wrapping class of the error.
func (e *errorT) outerClass() *Class {
	if len(e.classes) == 0 {
		return nil
	}
	return e.classes[len(e.classes)-1]
}

// errorT implements the error interface.
func (e *errorT) Error() string {
	return fmt.Sprintf("%v", e)
}

// Format handles the formatting of the error. Using a "+" on the format string
// specifier will also write the stack trace.
func (e *errorT) Format(f fmt.State, c rune) {
	var printSeparator bool
	for i := len(e.classes) - 1; i >= 0; i-- {
		name := string(*e.classes[i])
		if len(name) > 0 {
			if printSeparator {
				fmt.Fprint(f, ": ")
			}
			printSeparator = true
			fmt.Fprint(f, name)
		}
	}
	if len(e.err.Error()) > 0 {
		if printSeparator {
			fmt.Fprint(f, ": ")
		}
		fmt.Fprintf(f, "%v", e.err)
	}

	if f.Flag(int('+')) {
		summarizeStack(f, e.pcs)
	}
}

// Cause implements the interface wrapping errors are expected to implement
// to allow getting at underlying causes.
func (e *errorT) Cause() error {
	return e.err
}

// Name returns the name for the error, which is the first wrapping class.
func (e *errorT) Name() (string, bool) {
	outer := e.outerClass()
	if outer == nil {
		return "", false
	}
	return string(*outer), true
}

// summarizeStack writes stack line entries to the writer.
func summarizeStack(w io.Writer, pcs []uintptr) {
	frames := runtime.CallersFrames(pcs)
	for {
		frame, more := frames.Next()
		if !more {
			return
		}
		fmt.Fprintf(w, "\n\t%s:%d", frame.Function, frame.Line)
	}
}
<commit_msg>Avoid double error formatting<commit_after>// Package errs provides a simple error package with stack traces.
package errs

import (
	"fmt"
	"io"
	"runtime"
)

// Namer is implemented by all errors returned in this package. It returns a
// name for the class of error it is, and a boolean indicating if the name is
// valid.
type Namer interface{ Name() (string, bool) }

// Causer is implemented by all errors returned in this package. It returns
// the underlying cause of the error, or nil if there is no underlying cause.
type Causer interface{ Cause() error }

// New returns an error not contained in any class. This is the same as calling
// fmt.Errorf(...) except it captures a stack trace on creation.
func New(format string, args ...interface{}) error {
	return (*Class).create(nil, 3, fmt.Errorf(format, args...))
}

// Wrap returns an error not contained in any class. It just associates a stack
// trace with the error. Wrap returns nil if err is nil.
func Wrap(err error) error {
	return (*Class).create(nil, 3, err)
}

// Unwrap returns the underlying error, if any, or just the error.
func Unwrap(err error) error {
	// we call Cause as much as possible. Since comparing arbitrary interfaces
	// with equality isn't panic safe, we only loop up to 100 times to ensure
	// that a poor implementation that loops does not cause a hang.
	for i := 0; err != nil && i < 100; i++ {
		causer, ok := err.(Causer)
		if !ok {
			break
		}

		// if the cause of some error is nil, we return it.
		nerr := causer.Cause()
		if nerr == nil {
			return err
		}
		err = nerr
	}

	return err
}

// Classes returns all the classes that have wrapped the error.
func Classes(err error) []*Class {
	if err, ok := err.(*errorT); ok && err != nil {
		return append([]*Class(nil), err.classes...)
	}
	return nil
}

//
// error classes
//

// Class represents a class of errors. You can construct errors, and check if
// errors are part of the class.
type Class string

// Has returns true if the passed in error was wrapped by this class.
func (c *Class) Has(err error) bool {
	if err, ok := err.(*errorT); ok {
		for _, k := range err.classes {
			if k == c {
				return true
			}
		}
	}
	return false
}

// New constructs an error with the format string that will be contained by
// this class. This is the same as calling Wrap(fmt.Errorf(...)).
func (c *Class) New(format string, args ...interface{}) error {
	return c.create(3, fmt.Errorf(format, args...))
}

// Wrap returns a new error based on the passed in error that is contained in
// this class. Wrap returns nil if err is nil.
func (c *Class) Wrap(err error) error {
	return c.create(3, err)
}

// create constructs the error, or just adds the class to the error, keeping
// track of the stack if it needs to construct it.
func (c *Class) create(depth int, err error) error {
	if err == nil {
		return nil
	}

	if err, ok := err.(*errorT); ok {
		if c != nil && err.outerClass() != c {
			err.classes = append(err.classes, c)
		}
		return err
	}

	var pcs [256]uintptr
	n := runtime.Callers(depth, pcs[:])

	var classes []*Class
	if c != nil {
		classes = []*Class{c}
	}

	return &errorT{
		classes: classes,
		err:     err,
		pcs:     pcs[:n:n],
	}
}

//
// errors
//

// errorT is the type of errors returned from this package.
type errorT struct {
	classes []*Class
	pcs     []uintptr
	err     error
}

var ( // ensure *errorT implements the helper interfaces.
	_ Namer  = (*errorT)(nil)
	_ Causer = (*errorT)(nil)
	_ error  = (*errorT)(nil)
)

// outerClass returns the outermost wrapping class of the error.
func (e *errorT) outerClass() *Class {
	if len(e.classes) == 0 {
		return nil
	}
	return e.classes[len(e.classes)-1]
}

// errorT implements the error interface.
func (e *errorT) Error() string {
	return fmt.Sprintf("%v", e)
}

// Format handles the formatting of the error. Using a "+" on the format string
// specifier will also write the stack trace.
func (e *errorT) Format(f fmt.State, c rune) {
	var printSeparator bool
	for i := len(e.classes) - 1; i >= 0; i-- {
		name := string(*e.classes[i])
		if len(name) > 0 {
			if printSeparator {
				fmt.Fprint(f, ": ")
			}
			printSeparator = true
			fmt.Fprint(f, name)
		}
	}
	if text := e.err.Error(); len(text) > 0 {
		if printSeparator {
			fmt.Fprint(f, ": ")
		}
		fmt.Fprintf(f, "%v", text)
	}

	if f.Flag(int('+')) {
		summarizeStack(f, e.pcs)
	}
}

// Cause implements the interface wrapping errors are expected to implement
// to allow getting at underlying causes.
func (e *errorT) Cause() error {
	return e.err
}

// Name returns the name for the error, which is the first wrapping class.
func (e *errorT) Name() (string, bool) {
	outer := e.outerClass()
	if outer == nil {
		return "", false
	}
	return string(*outer), true
}

// summarizeStack writes stack line entries to the writer.
func summarizeStack(w io.Writer, pcs []uintptr) {
	frames := runtime.CallersFrames(pcs)
	for {
		frame, more := frames.Next()
		if !more {
			return
		}
		fmt.Fprintf(w, "\n\t%s:%d", frame.Function, frame.Line)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

type Etcd struct{}

type members struct {
	Members []struct {
		ClientURLs []string `json:"clientURLs"`
		ID         string   `json:"id"`
		Name       string   `json:"name"`
		PeerURLs   []string `json:"peerURLs"`
	} `json:"members"`
}

// Read all members of an etcd cluster
func etcdMembers(url string) (error, *members) {
	resp, err := http.Get(url + "/v2/members")
	if err != nil {
		return err, nil
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err, nil
	}

	members := &members{}

	err = json.Unmarshal(body, &members)
	if err != nil {
		return err, nil
	}

	return nil, members
}

// Iterate over all members looking for health
func (e *Etcd) Check(url string) (bool, error) {
	health := false

	err, members := etcdMembers(url)
	if err != nil {
		return health, err
	}

	for _, m := range members.Members {
		for _, url := range m.ClientURLs {
			resp, err := http.Get(url + "/health")
			if err != nil {
				log.Printf("failed to check health of member %s on %s: %v\n", m.ID, url, err)
				continue
			}

			result := struct{ Health string }{}
			d := json.NewDecoder(resp.Body)
			err = d.Decode(&result)
			resp.Body.Close()
			if err != nil {
				fmt.Printf("failed to check the health of member %s on %s: %v\n", m.ID, url, err)
				continue
			}

			if result.Health == "true" {
				health = true
				// fmt.Printf("member %s is healthy: got healthy result from %s\n", m.ID, url)
			} else {
				fmt.Printf("member %s is unhealthy: got unhealthy result from %s\n", m.ID, url)
			}

			break
		}
	}

	return health, nil
}
<commit_msg>simplify members structure so we can instantiate one for testing<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

type Etcd struct{}

type memb struct {
	ClientURLs []string `json:"clientURLs"`
	ID         string   `json:"id"`
	Name       string   `json:"name"`
	PeerURLs   []string `json:"peerURLs"`
}

type members struct {
	Members []memb `json:"members"`
}

// Read all members of an etcd cluster
func etcdMembers(url string) (error, *members) {
	resp, err := http.Get(url + "/v2/members")
	if err != nil {
		return err, nil
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err, nil
	}

	members := &members{}

	err = json.Unmarshal(body, &members)
	if err != nil {
		return err, nil
	}

	return nil, members
}

// Iterate over all members looking for health
func (e *Etcd) Check(url string) (bool, error) {
	health := false

	err, members := etcdMembers(url)
	if err != nil {
		return health, err
	}

	for _, m := range members.Members {
		for _, url := range m.ClientURLs {
			resp, err := http.Get(url + "/health")
			if err != nil {
				log.Printf("failed to check health of member %s on %s: %v\n", m.ID, url, err)
				continue
			}

			result := struct{ Health string }{}
			d := json.NewDecoder(resp.Body)
			err = d.Decode(&result)
			resp.Body.Close()
			if err != nil {
				fmt.Printf("failed to check the health of member %s on %s: %v\n", m.ID, url, err)
				continue
			}

			if result.Health == "true" {
				health = true
				// fmt.Printf("member %s is healthy: got healthy result from %s\n", m.ID, url)
			} else {
				fmt.Printf("member %s is unhealthy: got unhealthy result from %s\n", m.ID, url)
			}

			break
		}
	}

	return health, nil
}
<|endoftext|>


<commit_before>package hookah

import (
	"errors"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/hashicorp/go-multierror"
)

// HookExec represents a call to a hook
type HookExec struct {
	RootDir string

	Owner string
	Repo  string

	Event string
	Data  io.ReadSeeker

	HookServer *HookServer
}

// GetPathExecs fetches the executable filenames for the given path
func (h *HookExec) GetPathExecs() ([]string, error) {
	path := filepath.Join(h.RootDir, h.Owner, h.Repo, h.Event)

	files := []string{}

	fs, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return files, nil
		}

		return files, err
	}

	if fs.IsDir() {
		d, err := os.Open(path)
		defer d.Close()
		if err != nil {
			return files, err
		}

		fi, err := d.Readdir(-1)
		if err != nil {
			return files, err
		}

		for _, fi := range fi {
			if isExecFile(fi) {
				// fmt.Println(fi.Name(), fi.Size(), "bytes")
				files = append(files, filepath.Join(path, fi.Name()))
			}
		}

	} else if isExecFile(fs) {
		// fmt.Println(fs.Name(), fs.Size(), "bytes")
		files = append(files, filepath.Join(path, fs.Name()))
	} else {
		return files, errors.New("bad file mumbo jumbo")
	}

	return files, nil
}

// Exec triggers the execution of all scripts associated with the given Hook
func (h *HookExec) Exec(timeout time.Duration) error {
	files, err := h.GetPathExecs()
	if err != nil {
		return err
	}

	var result error

	h.HookServer.Lock()
	defer h.HookServer.Unlock()

	for _, f := range files {
		cmd := exec.Command(f)

		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr

		stdin, err := cmd.StdinPipe()
		if err != nil {
			multierror.Append(result, err)
			continue
		}
		defer stdin.Close()

		// io.Copy( cmd.StdinPipe
		err = cmd.Start()
		if err != nil {
			multierror.Append(result, err)
			continue
		}

		h.Data.Seek(0, 0)
		io.Copy(stdin, h.Data)
		stdin.Close()

		timer := time.AfterFunc(timeout, func() {
			cmd.Process.Kill()
		})

		err = cmd.Wait()
		timer.Stop()

		if err != nil {
			multierror.Append(result, err)
			continue
		}
	}

	return result
}

// todo: base this on OS
func isExecFile(fi os.FileInfo) bool {
	return fi.Mode().IsRegular() && fi.Mode()|0111 == fi.Mode()
}
<commit_msg>Small refactor<commit_after>package hookah

import (
	"errors"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"time"

	"github.com/hashicorp/go-multierror"
)

// HookExec represents a call to a hook
type HookExec struct {
	RootDir string

	Owner string
	Repo  string

	Event string
	Data  io.ReadSeeker

	HookServer *HookServer
}

// GetPathExecs fetches the executable filenames for the given path
func (h *HookExec) GetPathExecs() ([]string, error) {
	path := filepath.Join(h.RootDir, h.Owner, h.Repo, h.Event)

	files := []string{}

	fs, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return files, nil
		}

		return files, err
	}

	if fs.IsDir() {
		d, err := os.Open(path)
		defer d.Close()
		if err != nil {
			return files, err
		}

		fi, err := d.Readdir(-1)
		if err != nil {
			return files, err
		}

		for _, fi := range fi {
			if isExecFile(fi) {
				// fmt.Println(fi.Name(), fi.Size(), "bytes")
				files = append(files, filepath.Join(path, fi.Name()))
			}
		}

	} else if isExecFile(fs) {
		// fmt.Println(fs.Name(), fs.Size(), "bytes")
		files = append(files, filepath.Join(path, fs.Name()))
	} else {
		return files, errors.New("bad file mumbo jumbo")
	}

	return files, nil
}

// Exec triggers the execution of all scripts associated with the given Hook
func (h *HookExec) Exec(timeout time.Duration) error {
	files, err := h.GetPathExecs()
	if err != nil {
		return err
	}

	var result error

	h.HookServer.Lock()
	defer h.HookServer.Unlock()

	for _, f := range files {
		err := execFile(f, h, timeout)
		multierror.Append(result, err)
	}

	return result
}

func execFile(f string, h *HookExec, timeout time.Duration) error {
	cmd := exec.Command(f)

	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}
	defer stdin.Close()

	err = cmd.Start()
	if err != nil {
		return err
	}

	h.Data.Seek(0, 0)
	io.Copy(stdin, h.Data)
	stdin.Close()

	timer := time.AfterFunc(timeout, func() {
		cmd.Process.Kill()
	})

	err = cmd.Wait()
	timer.Stop()

	if err != nil {
		return err
	}

	return nil
}

// todo: base this on OS
func isExecFile(fi os.FileInfo) bool {
	return fi.Mode().IsRegular() && fi.Mode()|0111 == fi.Mode()
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/exec"
	"runtime"
	"syscall"
)

var cmdBase = []string{"sh", "-c"}

func init() {
	if runtime.GOOS == "windows" {
		cmdBase = []string{"cmd", "/c"}
	}
}

func Exec() error {
	sh, err := exec.LookPath(cmdBase[0])
	if err != nil {
		return err
	}
	configPath := "~/.config/fillin/fillin.json"
	cmd, err := Run(configPath, os.Args[1:], nil)
	if err != nil {
		return err
	}
	if err := syscall.Exec(sh, append(cmdBase, cmd), os.Environ()); err != nil {
		return err
	}
	return nil
}
<commit_msg>add comment<commit_after>package main

import (
	"os"
	"os/exec"
	"runtime"
	"syscall"
)

var cmdBase = []string{"sh", "-c"}

func init() {
	if runtime.GOOS == "windows" {
		cmdBase = []string{"cmd", "/c"}
	}
}

// Exec fillin
func Exec() error {
	sh, err := exec.LookPath(cmdBase[0])
	if err != nil {
		return err
	}
	configPath := "~/.config/fillin/fillin.json"
	cmd, err := Run(configPath, os.Args[1:], nil)
	if err != nil {
		return err
	}
	if err := syscall.Exec(sh, append(cmdBase, cmd), os.Environ()); err != nil {
		return err
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Copyright 2017 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 mount

import "k8s.io/utils/exec"

// NewOsExec returns a new Exec interface implementation based on exec()
func NewOsExec() Exec {
	return &osExec{}
}

// Real implementation of Exec interface that uses simple utils.Exec
type osExec struct{}

var _ Exec = &osExec{}

func (e *osExec) Run(cmd string, args ...string) ([]byte, error) {
	exe := exec.New()
	return exe.Command(cmd, args...).CombinedOutput()
}

// NewFakeExec returns a new FakeExec
func NewFakeExec(run runHook) *FakeExec {
	return &FakeExec{runHook: run}
}

// FakeExec for testing.
type FakeExec struct {
	runHook runHook
}
type runHook func(cmd string, args ...string) ([]byte, error)

// Run executes the command using the optional runhook, if given
func (f *FakeExec) Run(cmd string, args ...string) ([]byte, error) {
	if f.runHook != nil {
		return f.runHook(cmd, args...)
	}
	return nil, nil
}
<commit_msg>Rename mount.NewOsExec to mount.NewOSExec<commit_after>/*
Copyright 2017 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 mount

import "k8s.io/utils/exec"

// NewOSExec returns a new Exec interface implementation based on exec()
func NewOSExec() Exec {
	return &osExec{}
}

// Real implementation of Exec interface that uses simple utils.Exec
type osExec struct{}

var _ Exec = &osExec{}

func (e *osExec) Run(cmd string, args ...string) ([]byte, error) {
	exe := exec.New()
	return exe.Command(cmd, args...).CombinedOutput()
}

// NewFakeExec returns a new FakeExec
func NewFakeExec(run runHook) *FakeExec {
	return &FakeExec{runHook: run}
}

// FakeExec for testing.
type FakeExec struct {
	runHook runHook
}
type runHook func(cmd string, args ...string) ([]byte, error)

// Run executes the command using the optional runhook, if given
func (f *FakeExec) Run(cmd string, args ...string) ([]byte, error) {
	if f.runHook != nil {
		return f.runHook(cmd, args...)
	}
	return nil, nil
}
<|endoftext|>


<commit_before>package squirrel

import (
	"fmt"
	"io"
	"reflect"
	"strings"
)

type expr struct {
	sql string
	args []interface{}
}

// Expr builds value expressions for InsertBuilder and UpdateBuilder.
//
// Ex:
//     .Values(Expr("FROM_UNIXTIME(?)", t))
func Expr(sql string, args ...interface{}) expr {
	return expr{sql: sql, args: args}
}

func (e expr) ToSql() (sql string, args []interface{}, err error) {
	return e.sql, e.args, nil
}

type exprs []expr

func (es exprs) AppendToSql(w io.Writer, sep string, args []interface{}) ([]interface{}, error) {
	for i, e := range es {
		if i > 0 {
			_, err := io.WriteString(w, sep)
			if err != nil {
				return nil, err
			}
		}
		_, err := io.WriteString(w, e.sql)
		if err != nil {
			return nil, err
		}
		args = append(args, e.args...)
	}
	return args, nil
}

// Eq is syntactic sugar for use with Where/Having/Set methods.
// Ex:
//     .Where(Eq{"id": 1})
type Eq map[string]interface{}

func (eq Eq) ToSql() (sql string, args []interface{}, err error) {
	var exprs []string
	for key, val := range eq {
		expr := ""
		if val == nil {
			expr = fmt.Sprintf("%s IS NULL", key)
		} else {
			valVal := reflect.ValueOf(val)
			if valVal.Kind() == reflect.Array || valVal.Kind() == reflect.Slice {
				placeholders := make([]string, valVal.Len())
				for i := 0; i < valVal.Len(); i++ {
					placeholders[i] = "?"
					args = append(args, valVal.Index(i).Interface())
				}
				placeholdersStr := strings.Join(placeholders, ",")
				expr = fmt.Sprintf("%s IN (%s)", key, placeholdersStr)
			} else {
				expr = fmt.Sprintf("%s = ?", key)
				args = append(args, val)
			}
		}
		exprs = append(exprs, expr)
	}
	sql = strings.Join(exprs, " AND ")
	return
}

type conj []Sqlizer

func (c conj) join(sep string) (sql string, args []interface{}, err error) {
	sqlParts := make([]string, len(c))
	for i, sqlizer := range c {
		partSql, partArgs, err := sqlizer.ToSql()
		if err != nil {
			return "", nil, err
		}
		sqlParts[i] = partSql
		args = append(args, partArgs...)
	}
	sql = fmt.Sprintf("(%s)", strings.Join(sqlParts, sep))
	return
}

type And conj

func (a And) ToSql() (string, []interface{}, error) {
	return conj(a).join(" AND ")
}

type Or conj

func (o Or) ToSql() (string, []interface{}, error) {
	return conj(o).join(" OR ")
}
<commit_msg>Omit empty expressions from Or{} and And{}<commit_after>package squirrel

import (
	"fmt"
	"io"
	"reflect"
	"strings"
)

type expr struct {
	sql string
	args []interface{}
}

// Expr builds value expressions for InsertBuilder and UpdateBuilder.
//
// Ex:
//     .Values(Expr("FROM_UNIXTIME(?)", t))
func Expr(sql string, args ...interface{}) expr {
	return expr{sql: sql, args: args}
}

func (e expr) ToSql() (sql string, args []interface{}, err error) {
	return e.sql, e.args, nil
}

type exprs []expr

func (es exprs) AppendToSql(w io.Writer, sep string, args []interface{}) ([]interface{}, error) {
	for i, e := range es {
		if i > 0 {
			_, err := io.WriteString(w, sep)
			if err != nil {
				return nil, err
			}
		}
		_, err := io.WriteString(w, e.sql)
		if err != nil {
			return nil, err
		}
		args = append(args, e.args...)
	}
	return args, nil
}

// Eq is syntactic sugar for use with Where/Having/Set methods.
// Ex:
//     .Where(Eq{"id": 1})
type Eq map[string]interface{}

func (eq Eq) ToSql() (sql string, args []interface{}, err error) {
	var exprs []string
	for key, val := range eq {
		expr := ""
		if val == nil {
			expr = fmt.Sprintf("%s IS NULL", key)
		} else {
			valVal := reflect.ValueOf(val)
			if valVal.Kind() == reflect.Array || valVal.Kind() == reflect.Slice {
				placeholders := make([]string, valVal.Len())
				for i := 0; i < valVal.Len(); i++ {
					placeholders[i] = "?"
					args = append(args, valVal.Index(i).Interface())
				}
				placeholdersStr := strings.Join(placeholders, ",")
				expr = fmt.Sprintf("%s IN (%s)", key, placeholdersStr)
			} else {
				expr = fmt.Sprintf("%s = ?", key)
				args = append(args, val)
			}
		}
		exprs = append(exprs, expr)
	}
	sql = strings.Join(exprs, " AND ")
	return
}

type conj []Sqlizer

func (c conj) join(sep string) (sql string, args []interface{}, err error) {
	var sqlParts []string
	for _, sqlizer := range c {
		partSql, partArgs, err := sqlizer.ToSql()
		if err != nil {
			return "", nil, err
		}
		if partSql != "" {
			sqlParts = append(sqlParts, partSql)
			args = append(args, partArgs...)
		}
	}
	if len(sqlParts) > 0 {
		sql = fmt.Sprintf("(%s)", strings.Join(sqlParts, sep))
	}
	return
}

type And conj

func (a And) ToSql() (string, []interface{}, error) {
	return conj(a).join(" AND ")
}

type Or conj

func (o Or) ToSql() (string, []interface{}, error) {
	return conj(o).join(" OR ")
}
<|endoftext|>


<commit_before>//  Copyright (c) 2014 Couchbase, Inc.
//  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 cbgt

import (
	"fmt"
	"io"
)

// A Feed interface represents an abstract data source.  A Feed
// instance is hooked up to one-or-more Dest instances.  When incoming
// data is received by a Feed, the Feed will invoke relvate methods on
// the relevant Dest instances.
//
// In this codebase, the words "index source", "source" and "data
// source" are often associated with and used roughly as synonyms with
// "feed".
type Feed interface {
	Name() string
	IndexName() string
	Start() error
	Close() error
	Dests() map[string]Dest // Key is partition identifier.

	// Writes stats as JSON to the given writer.
	Stats(io.Writer) error
}

// Default values for feed parameters.
const FEED_SLEEP_MAX_MS = 10000
const FEED_SLEEP_INIT_MS = 100
const FEED_BACKOFF_FACTOR = 1.5

// FeedTypes is a global registry of available feed types and is
// initialized on startup.  It should be immutable after startup time.
var FeedTypes = make(map[string]*FeedType) // Key is sourceType.

// A FeedType represents an immutable registration of a single feed
// type or data source type.
type FeedType struct {
	Start           FeedStartFunc
	Partitions      FeedPartitionsFunc
	Public          bool
	Description     string
	StartSample     interface{}
	StartSampleDocs map[string]string
}

// A FeedStartFunc is part of a FeedType registration as is invoked by
// a Manager when a new feed instance needs to be started.
type FeedStartFunc func(mgr *Manager, feedName, indexName, indexUUID string,
	sourceType, sourceName, sourceUUID, sourceParams string,
	dests map[string]Dest) error

// Each Feed or data-source type knows of the data partitions for a
// data source.
type FeedPartitionsFunc func(sourceType, sourceName, sourceUUID, sourceParams,
	server string) ([]string, error)

// RegisterFeedType is invoked at init/startup time to register a
// FeedType.
func RegisterFeedType(sourceType string, f *FeedType) {
	FeedTypes[sourceType] = f
}

// DataSourcePartitions is a helper function that returns the data
// source partitions for a named data source or feed type.
func DataSourcePartitions(sourceType, sourceName, sourceUUID, sourceParams,
	server string) ([]string, error) {
	feedType, exists := FeedTypes[sourceType]
	if !exists || feedType == nil {
		return nil, fmt.Errorf("feed: unknown sourceType: %s", sourceType)
	}

	return feedType.Partitions(sourceType, sourceName, sourceUUID,
		sourceParams, server)
}
<commit_msg>added FeedPartitionSeqsFunc to FeedType<commit_after>//  Copyright (c) 2014 Couchbase, Inc.
//  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 cbgt

import (
	"fmt"
	"io"
)

// A Feed interface represents an abstract data source.  A Feed
// instance is hooked up to one-or-more Dest instances.  When incoming
// data is received by a Feed, the Feed will invoke relvate methods on
// the relevant Dest instances.
//
// In this codebase, the words "index source", "source" and "data
// source" are often associated with and used roughly as synonyms with
// "feed".
type Feed interface {
	Name() string
	IndexName() string
	Start() error
	Close() error
	Dests() map[string]Dest // Key is partition identifier.

	// Writes stats as JSON to the given writer.
	Stats(io.Writer) error
}

// Default values for feed parameters.
const FEED_SLEEP_MAX_MS = 10000
const FEED_SLEEP_INIT_MS = 100
const FEED_BACKOFF_FACTOR = 1.5

// FeedTypes is a global registry of available feed types and is
// initialized on startup.  It should be immutable after startup time.
var FeedTypes = make(map[string]*FeedType) // Key is sourceType.

// A FeedType represents an immutable registration of a single feed
// type or data source type.
type FeedType struct {
	Start           FeedStartFunc
	Partitions      FeedPartitionsFunc
	PartitionSeqs   FeedPartitionSeqsFunc
	Public          bool
	Description     string
	StartSample     interface{}
	StartSampleDocs map[string]string
}

// A FeedStartFunc is part of a FeedType registration as is invoked by
// a Manager when a new feed instance needs to be started.
type FeedStartFunc func(mgr *Manager,
	feedName, indexName, indexUUID string,
	sourceType, sourceName, sourceUUID, sourceParams string,
	dests map[string]Dest) error

// Each Feed or data-source type knows of the data partitions for a
// data source.
type FeedPartitionsFunc func(sourceType, sourceName, sourceUUID,
	sourceParams, server string) ([]string, error)

// Returns the current partitions and their seq's.
type FeedPartitionSeqsFunc func(sourceType, sourceName, sourceUUID,
	sourceParams, server string) (map[string]UUIDSeq, error)

// A UUIDSeq associates a uuid (such as a partition uuid) with a seq.
type UUIDSeq struct {
	UUID string
	Seq  uint64
}

// RegisterFeedType is invoked at init/startup time to register a
// FeedType.
func RegisterFeedType(sourceType string, f *FeedType) {
	FeedTypes[sourceType] = f
}

// DataSourcePartitions is a helper function that returns the data
// source partitions for a named data source or feed type.
func DataSourcePartitions(sourceType, sourceName, sourceUUID, sourceParams,
	server string) ([]string, error) {
	feedType, exists := FeedTypes[sourceType]
	if !exists || feedType == nil {
		return nil, fmt.Errorf("feed: unknown sourceType: %s", sourceType)
	}

	return feedType.Partitions(sourceType, sourceName, sourceUUID,
		sourceParams, server)
}
<|endoftext|>


<commit_before>package main

import (
	"archive/zip"
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

// Download the zip file at the given URL to a temporary local directory.
// Returns the absolute path to the downloaded zip file.
// IMPORTANT: You must call "defer os.RemoveAll(dir)" in the calling function when done with the downloaded zip file!
func downloadGithubZipFile(gitHubCommit GitHubCommit, gitHubToken string, instance GitHubInstance) (string, *FetchError) {

	var zipFilePath string

	// Create a temp directory
	// Note that ioutil.TempDir has a peculiar interface. We need not specify any meaningful values to achieve our
	// goal of getting a temporary directory.
	tempDir, err := ioutil.TempDir("", "")
	if err != nil {
		return zipFilePath, wrapError(err)
	}

	// Download the zip file, possibly using the GitHub oAuth Token
	httpClient := &http.Client{}
	req, err := MakeGitHubZipFileRequest(gitHubCommit, gitHubToken, instance)
	if err != nil {
		return zipFilePath, wrapError(err)
	}

	resp, err := httpClient.Do(req)
	if err != nil {
		return zipFilePath, wrapError(err)
	}
	if resp.StatusCode != http.StatusOK {
		return zipFilePath, newError(failedToDownloadFile, fmt.Sprintf("Failed to download file at the url %s. Received HTTP Response %d.", req.URL.String(), resp.StatusCode))
	}
	if resp.Header.Get("Content-Type") != "application/zip" {
		return zipFilePath, newError(failedToDownloadFile, fmt.Sprintf("Failed to download file at the url %s. Expected HTTP Response's \"Content-Type\" header to be \"application/zip\", but was \"%s\"", req.URL.String(), resp.Header.Get("Content-Type")))
	}

	// Copy the contents of the downloaded file to our empty file
	respBodyBuffer := new(bytes.Buffer)
	_, err = respBodyBuffer.ReadFrom(resp.Body)
	if err != nil {
		return zipFilePath, wrapError(err)
	}

	err = ioutil.WriteFile(filepath.Join(tempDir, "repo.zip"), respBodyBuffer.Bytes(), 0644)
	if err != nil {
		return zipFilePath, wrapError(err)
	}

	zipFilePath = filepath.Join(tempDir, "repo.zip")

	return zipFilePath, nil
}

func shouldExtractPathInZip(pathPrefix string, zipPath *zip.File) bool {
	//
	// We need to return true (i.e extract file) based on the following conditions:
	//
	// The current archive item is a directory.
	//     Archive item's path name will always be appended with a "/", so we use
	//     this fact to ensure we are working with a full directory name.
	//     Extract the file if (pathPrefix + "/") is a prefix in path name
	//
	// The current archive item is a file.
	// 		There are two things possible here:
	//		1  User specified a filename that is an exact match for the current archive file,
	//         we need to extract this file.
	//      2  The current archive filename is not a exact match to the user supplied filename.
	//		   Check if (pathPrefix + "/") is a prefix in f.Name, if yes, we extract this file.

	zipPathIsFile := !zipPath.FileInfo().IsDir()
	return (zipPathIsFile && zipPath.Name == pathPrefix) || strings.Index(zipPath.Name, pathPrefix+"/") == 0
}

// Decompress the file at zipFileAbsPath and move only those files under filesToExtractFromZipPath to localPath
func extractFiles(zipFilePath, filesToExtractFromZipPath, localPath string) (int, error) {

	// Open the zip file for reading.
	r, err := zip.OpenReader(zipFilePath)
	if err != nil {
		return 0, err
	}
	defer r.Close()

	// pathPrefix represents the portion of the local file path we will ignore when copying the file to localPath
	// E.g. full path = fetch-test-public-0.0.3/folder/file1.txt
	//      path prefix = fetch-test-public-0.0.3
	//      file that will eventually get written = <localPath>/folder/file1.txt

	// By convention, the first file in the zip file is the top-level directory
	pathPrefix := r.File[0].Name

	// Add the path from which we will extract files to the path prefix so we can exclude the appropriate files
	pathPrefix = filepath.Join(pathPrefix, filesToExtractFromZipPath)

	// Count the number of files (not directories) unpacked
	fileCount := 0

	// Iterate through the files in the archive,
	// printing some of their contents.
	for _, f := range r.File {

		// check if current archive file needs to be extracted
		if shouldExtractPathInZip(pathPrefix, f) {

			if f.FileInfo().IsDir() {
				// Create a directory
				path := filepath.Join(localPath, strings.TrimPrefix(f.Name, pathPrefix))
				err = os.MkdirAll(path, 0777)
				if err != nil {
					return 0, fmt.Errorf("Failed to create local directory %s: %s", path, err)
				}
			} else {
				// Read the file into a byte array
				readCloser, err := f.Open()
				if err != nil {
					return 0, fmt.Errorf("Failed to open file %s: %s", f.Name, err)
				}

				byteArray, err := ioutil.ReadAll(readCloser)
				if err != nil {
					return 0, fmt.Errorf("Failed to read file %s: %s", f.Name, err)
				}

				// Write the file
				err = ioutil.WriteFile(filepath.Join(localPath, strings.TrimPrefix(f.Name, pathPrefix)), byteArray, 0644)
				if err != nil {
					return 0, fmt.Errorf("Failed to write file: %s", err)
				}
				fileCount++
			}
		}
	}

	return fileCount, nil
}

// Return an HTTP request that will fetch the given GitHub repo's zip file for the given tag, possibly with the gitHubOAuthToken in the header
// Respects the GitHubCommit hierachy as defined in the code comments for GitHubCommit (e.g. GitTag > CommitSha)
func MakeGitHubZipFileRequest(gitHubCommit GitHubCommit, gitHubToken string, instance GitHubInstance) (*http.Request, error) {
	var request *http.Request

	// This represents either a commit, branch, or git tag
	var gitRef string
	if gitHubCommit.CommitSha != "" {
		gitRef = gitHubCommit.CommitSha
	} else if gitHubCommit.BranchName != "" {
		gitRef = gitHubCommit.BranchName
	} else if gitHubCommit.GitTag != "" {
		gitRef = gitHubCommit.GitTag
	} else {
		return request, fmt.Errorf("Neither a GitCommitSha nor a GitTag nor a BranchName were specified so impossible to identify a specific commit to download.")
	}

	url := fmt.Sprintf("https://%s/repos/%s/%s/zipball/%s", instance.ApiUrl, gitHubCommit.Repo.Owner, gitHubCommit.Repo.Name, gitRef)

	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return request, wrapError(err)
	}

	if gitHubToken != "" {
		request.Header.Set("Authorization", fmt.Sprintf("token %s", gitHubToken))
	}

	return request, nil
}
<commit_msg>Return number of files in all cases<commit_after>package main

import (
	"archive/zip"
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

// Download the zip file at the given URL to a temporary local directory.
// Returns the absolute path to the downloaded zip file.
// IMPORTANT: You must call "defer os.RemoveAll(dir)" in the calling function when done with the downloaded zip file!
func downloadGithubZipFile(gitHubCommit GitHubCommit, gitHubToken string, instance GitHubInstance) (string, *FetchError) {

	var zipFilePath string

	// Create a temp directory
	// Note that ioutil.TempDir has a peculiar interface. We need not specify any meaningful values to achieve our
	// goal of getting a temporary directory.
	tempDir, err := ioutil.TempDir("", "")
	if err != nil {
		return zipFilePath, wrapError(err)
	}

	// Download the zip file, possibly using the GitHub oAuth Token
	httpClient := &http.Client{}
	req, err := MakeGitHubZipFileRequest(gitHubCommit, gitHubToken, instance)
	if err != nil {
		return zipFilePath, wrapError(err)
	}

	resp, err := httpClient.Do(req)
	if err != nil {
		return zipFilePath, wrapError(err)
	}
	if resp.StatusCode != http.StatusOK {
		return zipFilePath, newError(failedToDownloadFile, fmt.Sprintf("Failed to download file at the url %s. Received HTTP Response %d.", req.URL.String(), resp.StatusCode))
	}
	if resp.Header.Get("Content-Type") != "application/zip" {
		return zipFilePath, newError(failedToDownloadFile, fmt.Sprintf("Failed to download file at the url %s. Expected HTTP Response's \"Content-Type\" header to be \"application/zip\", but was \"%s\"", req.URL.String(), resp.Header.Get("Content-Type")))
	}

	// Copy the contents of the downloaded file to our empty file
	respBodyBuffer := new(bytes.Buffer)
	_, err = respBodyBuffer.ReadFrom(resp.Body)
	if err != nil {
		return zipFilePath, wrapError(err)
	}

	err = ioutil.WriteFile(filepath.Join(tempDir, "repo.zip"), respBodyBuffer.Bytes(), 0644)
	if err != nil {
		return zipFilePath, wrapError(err)
	}

	zipFilePath = filepath.Join(tempDir, "repo.zip")

	return zipFilePath, nil
}

func shouldExtractPathInZip(pathPrefix string, zipPath *zip.File) bool {
	//
	// We need to return true (i.e extract file) based on the following conditions:
	//
	// The current archive item is a directory.
	//     Archive item's path name will always be appended with a "/", so we use
	//     this fact to ensure we are working with a full directory name.
	//     Extract the file if (pathPrefix + "/") is a prefix in path name
	//
	// The current archive item is a file.
	// 		There are two things possible here:
	//		1  User specified a filename that is an exact match for the current archive file,
	//         we need to extract this file.
	//      2  The current archive filename is not a exact match to the user supplied filename.
	//		   Check if (pathPrefix + "/") is a prefix in f.Name, if yes, we extract this file.

	zipPathIsFile := !zipPath.FileInfo().IsDir()
	return (zipPathIsFile && zipPath.Name == pathPrefix) || strings.Index(zipPath.Name, pathPrefix+"/") == 0
}

// Decompress the file at zipFileAbsPath and move only those files under filesToExtractFromZipPath to localPath
func extractFiles(zipFilePath, filesToExtractFromZipPath, localPath string) (int, error) {

	// Open the zip file for reading.
	r, err := zip.OpenReader(zipFilePath)
	if err != nil {
		return 0, err
	}
	defer r.Close()

	// pathPrefix represents the portion of the local file path we will ignore when copying the file to localPath
	// E.g. full path = fetch-test-public-0.0.3/folder/file1.txt
	//      path prefix = fetch-test-public-0.0.3
	//      file that will eventually get written = <localPath>/folder/file1.txt

	// By convention, the first file in the zip file is the top-level directory
	pathPrefix := r.File[0].Name

	// Add the path from which we will extract files to the path prefix so we can exclude the appropriate files
	pathPrefix = filepath.Join(pathPrefix, filesToExtractFromZipPath)

	// Count the number of files (not directories) unpacked
	fileCount := 0

	// Iterate through the files in the archive,
	// printing some of their contents.
	for _, f := range r.File {

		// check if current archive file needs to be extracted
		if shouldExtractPathInZip(pathPrefix, f) {

			if f.FileInfo().IsDir() {
				// Create a directory
				path := filepath.Join(localPath, strings.TrimPrefix(f.Name, pathPrefix))
				err = os.MkdirAll(path, 0777)
				if err != nil {
					return fileCount, fmt.Errorf("Failed to create local directory %s: %s", path, err)
				}
			} else {
				// Read the file into a byte array
				readCloser, err := f.Open()
				if err != nil {
					return fileCount, fmt.Errorf("Failed to open file %s: %s", f.Name, err)
				}

				byteArray, err := ioutil.ReadAll(readCloser)
				if err != nil {
					return fileCount, fmt.Errorf("Failed to read file %s: %s", f.Name, err)
				}

				// Write the file
				err = ioutil.WriteFile(filepath.Join(localPath, strings.TrimPrefix(f.Name, pathPrefix)), byteArray, 0644)
				if err != nil {
					return fileCount, fmt.Errorf("Failed to write file: %s", err)
				}
				fileCount++
			}
		}
	}

	return fileCount, nil
}

// Return an HTTP request that will fetch the given GitHub repo's zip file for the given tag, possibly with the gitHubOAuthToken in the header
// Respects the GitHubCommit hierachy as defined in the code comments for GitHubCommit (e.g. GitTag > CommitSha)
func MakeGitHubZipFileRequest(gitHubCommit GitHubCommit, gitHubToken string, instance GitHubInstance) (*http.Request, error) {
	var request *http.Request

	// This represents either a commit, branch, or git tag
	var gitRef string
	if gitHubCommit.CommitSha != "" {
		gitRef = gitHubCommit.CommitSha
	} else if gitHubCommit.BranchName != "" {
		gitRef = gitHubCommit.BranchName
	} else if gitHubCommit.GitTag != "" {
		gitRef = gitHubCommit.GitTag
	} else {
		return request, fmt.Errorf("Neither a GitCommitSha nor a GitTag nor a BranchName were specified so impossible to identify a specific commit to download.")
	}

	url := fmt.Sprintf("https://%s/repos/%s/%s/zipball/%s", instance.ApiUrl, gitHubCommit.Repo.Owner, gitHubCommit.Repo.Name, gitRef)

	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return request, wrapError(err)
	}

	if gitHubToken != "" {
		request.Header.Set("Authorization", fmt.Sprintf("token %s", gitHubToken))
	}

	return request, nil
}
<|endoftext|>


<commit_before>package bongo

import (
	"github.com/maxwellhealth/mgo"
	"log"
	"math"
	"time"
)

type ResultSet struct {
	Query      *mgo.Query
	Iter       *mgo.Iter
	loadedIter bool
	Collection *Collection
	Error      error
	Params     interface{}
}

type PaginationInfo struct {
	Current       int `json:"current"`
	TotalPages    int `json:"totalPages"`
	PerPage       int `json:"perPage"`
	TotalRecords  int `json:"totalRecords"`
	RecordsOnPage int `json:"recordsOnPage"`
}

func (r *ResultSet) Next(mod interface{}) bool {

	// Check if the iter has been instantiated yet
	if !r.loadedIter {
		r.Iter = r.Query.Iter()
		r.loadedIter = true
	}

	gotResult := r.Iter.Next(mod)

	if gotResult {

		if hook, ok := mod.(interface {
			AfterFind(*Collection)
		}); ok {
			hook.AfterFind(r.Collection)
		}

		if newt, ok := mod.(NewTracker); ok {
			newt.SetIsNew(false)
		}
		return true
	}

	err := r.Iter.Err()
	if err != nil {
		r.Error = err
	}

	return false
}

func (r *ResultSet) Free() error {
	if r.loadedIter {
		if err := r.Iter.Close(); err != nil {
			return err
		}
	}

	return nil
}

// Set skip + limit on the current query and generates a PaginationInfo struct with info for your front end
func (r *ResultSet) Paginate(perPage, page int) (*PaginationInfo, error) {
	start := time.Now()
	elapsed := time.Since(start)

	log.Printf("Line 74: %s", elapsed)
	info := new(PaginationInfo)

	// Get count of current query
	// count, err := r.Query.Count()

	sess := r.Collection.Connection.Session.Copy()
	defer sess.Close()

	elapsed = time.Since(start)

	log.Printf("Line 85: %s", elapsed)
	count, err := sess.DB(r.Collection.Connection.Config.Database).C(r.Collection.Name).Find(r.Params).Count()
	// count, err := r.Collection.Collection().Count()

	if err != nil {
		return info, err
	}

	elapsed = time.Since(start)

	log.Printf("Line 95: %s", elapsed)

	// Calculate how many pages
	totalPages := int(math.Ceil(float64(count) / float64(perPage)))

	if page < 1 {
		page = 1
	} else if page > totalPages {
		page = totalPages
	}

	elapsed = time.Since(start)

	log.Printf("Line 108: %s", elapsed)

	skip := (page - 1) * perPage

	r.Query.Skip(skip).Limit(perPage)

	info.TotalPages = totalPages
	info.PerPage = perPage
	info.Current = page
	info.TotalRecords = count

	if info.Current < info.TotalPages {
		info.RecordsOnPage = info.PerPage
	} else {

		info.RecordsOnPage = int(math.Mod(float64(count), float64(perPage)))

		if info.RecordsOnPage == 0 && count > 0 {
			info.RecordsOnPage = perPage
		}

	}

	elapsed = time.Since(start)

	log.Printf("Line 133: %s", elapsed)

	return info, nil
}
<commit_msg>Took out logging<commit_after>package bongo

import (
	"github.com/maxwellhealth/mgo"
	"math"
)

type ResultSet struct {
	Query      *mgo.Query
	Iter       *mgo.Iter
	loadedIter bool
	Collection *Collection
	Error      error
	Params     interface{}
}

type PaginationInfo struct {
	Current       int `json:"current"`
	TotalPages    int `json:"totalPages"`
	PerPage       int `json:"perPage"`
	TotalRecords  int `json:"totalRecords"`
	RecordsOnPage int `json:"recordsOnPage"`
}

func (r *ResultSet) Next(mod interface{}) bool {

	// Check if the iter has been instantiated yet
	if !r.loadedIter {
		r.Iter = r.Query.Iter()
		r.loadedIter = true
	}

	gotResult := r.Iter.Next(mod)

	if gotResult {

		if hook, ok := mod.(interface {
			AfterFind(*Collection)
		}); ok {
			hook.AfterFind(r.Collection)
		}

		if newt, ok := mod.(NewTracker); ok {
			newt.SetIsNew(false)
		}
		return true
	}

	err := r.Iter.Err()
	if err != nil {
		r.Error = err
	}

	return false
}

func (r *ResultSet) Free() error {
	if r.loadedIter {
		if err := r.Iter.Close(); err != nil {
			return err
		}
	}

	return nil
}

// Set skip + limit on the current query and generates a PaginationInfo struct with info for your front end
func (r *ResultSet) Paginate(perPage, page int) (*PaginationInfo, error) {

	info := new(PaginationInfo)

	// Get count of current query
	// count, err := r.Query.Count()

	sess := r.Collection.Connection.Session.Copy()
	defer sess.Close()

	count, err := sess.DB(r.Collection.Connection.Config.Database).C(r.Collection.Name).Find(r.Params).Count()
	// count, err := r.Collection.Collection().Count()

	if err != nil {
		return info, err
	}

	// Calculate how many pages
	totalPages := int(math.Ceil(float64(count) / float64(perPage)))

	if page < 1 {
		page = 1
	} else if page > totalPages {
		page = totalPages
	}

	skip := (page - 1) * perPage

	r.Query.Skip(skip).Limit(perPage)

	info.TotalPages = totalPages
	info.PerPage = perPage
	info.Current = page
	info.TotalRecords = count

	if info.Current < info.TotalPages {
		info.RecordsOnPage = info.PerPage
	} else {

		info.RecordsOnPage = int(math.Mod(float64(count), float64(perPage)))

		if info.RecordsOnPage == 0 && count > 0 {
			info.RecordsOnPage = perPage
		}

	}

	return info, nil
}
<|endoftext|>


<commit_before>package cli

import (
	"flag"
	"fmt"
	"strconv"
	"strings"
)

// This flag enables bash-completion for all commands and subcommands
var BashCompletionFlag = BoolFlag{"generate-bash-completion", ""}

// This flag prints the version for the application
var VersionFlag = BoolFlag{"version, v", "print the version"}

// This flag prints the help for all commands and subcommands
var HelpFlag = BoolFlag{"help, h", "show help"}

// Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recomended that
// this interface be implemented.
type Flag interface {
	fmt.Stringer
	// Apply Flag settings to the given flag set
	Apply(*flag.FlagSet)
	getName() string
}

func flagSet(name string, flags []Flag) *flag.FlagSet {
	set := flag.NewFlagSet(name, flag.ContinueOnError)

	for _, f := range flags {
		f.Apply(set)
	}
	return set
}

func eachName(longName string, fn func(string)) {
	parts := strings.Split(longName, ",")
	for _, name := range parts {
		name = strings.Trim(name, " ")
		fn(name)
	}
}

// Generic is a generic parseable type identified by a specific flag
type Generic interface {
	Set(value string) error
	String() string
}

// GenericFlag is the flag type for types implementing Generic
type GenericFlag struct {
	Name  string
	Value Generic
	Usage string
}

func (f GenericFlag) String() string {
	return fmt.Sprintf("%s%s %v\t`%v` %s", prefixFor(f.Name), f.Name, f.Value, "-"+f.Name+" option -"+f.Name+" option", f.Usage)
}

func (f GenericFlag) Apply(set *flag.FlagSet) {
	eachName(f.Name, func(name string) {
		set.Var(f.Value, name, f.Usage)
	})
}

func (f GenericFlag) getName() string {
	return f.Name
}

type StringSlice []string

func (f *StringSlice) Set(value string) error {
	*f = append(*f, value)
	return nil
}

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

func (f *StringSlice) Value() []string {
	return *f
}

type StringSliceFlag struct {
	Name  string
	Value *StringSlice
	Usage string
}

func (f StringSliceFlag) String() string {
	firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
	pref := prefixFor(firstName)
	return fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)
}

func (f StringSliceFlag) Apply(set *flag.FlagSet) {
	eachName(f.Name, func(name string) {
		set.Var(f.Value, name, f.Usage)
	})
}

func (f StringSliceFlag) getName() string {
	return f.Name
}

type IntSlice []int

func (f *IntSlice) Set(value string) error {

	tmp, err := strconv.Atoi(value)
	if err != nil {
		return err
	} else {
		*f = append(*f, tmp)
	}
	return nil
}

func (f *IntSlice) String() string {
	return fmt.Sprintf("%d", *f)
}

func (f *IntSlice) Value() []int {
	return *f
}

type IntSliceFlag struct {
	Name  string
	Value *IntSlice
	Usage string
}

func (f IntSliceFlag) String() string {
	firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
	pref := prefixFor(firstName)
	return fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage)
}

func (f IntSliceFlag) Apply(set *flag.FlagSet) {
	eachName(f.Name, func(name string) {
		set.Var(f.Value, name, f.Usage)
	})
}

func (f IntSliceFlag) getName() string {
	return f.Name
}

type BoolFlag struct {
	Name  string
	Usage string
}

func (f BoolFlag) String() string {
	return fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage)
}

func (f BoolFlag) Apply(set *flag.FlagSet) {
	eachName(f.Name, func(name string) {
		set.Bool(name, false, f.Usage)
	})
}

func (f BoolFlag) getName() string {
	return f.Name
}

type BoolTFlag struct {
	Name  string
	Usage string
}

func (f BoolTFlag) String() string {
	return fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage)
}

func (f BoolTFlag) Apply(set *flag.FlagSet) {
	eachName(f.Name, func(name string) {
		set.Bool(name, true, f.Usage)
	})
}

func (f BoolTFlag) getName() string {
	return f.Name
}

type StringFlag struct {
	Name  string
	Value string
	Usage string
}

func (f StringFlag) String() string {
	var fmtString string
	fmtString = "%s %v\t%v"

	if len(f.Value) > 0 {
		fmtString = "%s '%v'\t%v"
	} else {
		fmtString = "%s %v\t%v"
	}

	return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage)
}

func (f StringFlag) Apply(set *flag.FlagSet) {
	eachName(f.Name, func(name string) {
		set.String(name, f.Value, f.Usage)
	})
}

func (f StringFlag) getName() string {
	return f.Name
}

type IntFlag struct {
	Name  string
	Value int
	Usage string
}

func (f IntFlag) String() string {
	return fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage)
}

func (f IntFlag) Apply(set *flag.FlagSet) {
	eachName(f.Name, func(name string) {
		set.Int(name, f.Value, f.Usage)
	})
}

func (f IntFlag) getName() string {
	return f.Name
}

type Float64Flag struct {
	Name  string
	Value float64
	Usage string
}

func (f Float64Flag) String() string {
	return fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage)
}

func (f Float64Flag) Apply(set *flag.FlagSet) {
	eachName(f.Name, func(name string) {
		set.Float64(name, f.Value, f.Usage)
	})
}

func (f Float64Flag) getName() string {
	return f.Name
}

func prefixFor(name string) (prefix string) {
	if len(name) == 1 {
		prefix = "-"
	} else {
		prefix = "--"
	}

	return
}

func prefixedNames(fullName string) (prefixed string) {
	parts := strings.Split(fullName, ",")
	for i, name := range parts {
		name = strings.Trim(name, " ")
		prefixed += prefixFor(name) + name
		if i < len(parts)-1 {
			prefixed += ", "
		}
	}
	return
}
<commit_msg>Starting to hack in some env var configuration goodness<commit_after>package cli

import (
	"flag"
	"fmt"
	"os"
	"strconv"
	"strings"
)

// This flag enables bash-completion for all commands and subcommands
var BashCompletionFlag = BoolFlag{"generate-bash-completion", "", ""}

// This flag prints the version for the application
var VersionFlag = BoolFlag{"version, v", "print the version", ""}

// This flag prints the help for all commands and subcommands
var HelpFlag = BoolFlag{"help, h", "show help", ""}

// Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recomended that
// this interface be implemented.
type Flag interface {
	fmt.Stringer
	// Apply Flag settings to the given flag set
	Apply(*flag.FlagSet)
	getName() string
}

func flagSet(name string, flags []Flag) *flag.FlagSet {
	set := flag.NewFlagSet(name, flag.ContinueOnError)

	for _, f := range flags {
		f.Apply(set)
	}
	return set
}

func eachName(longName string, fn func(string)) {
	parts := strings.Split(longName, ",")
	for _, name := range parts {
		name = strings.Trim(name, " ")
		fn(name)
	}
}

// Generic is a generic parseable type identified by a specific flag
type Generic interface {
	Set(value string) error
	String() string
}

// GenericFlag is the flag type for types implementing Generic
type GenericFlag struct {
	Name   string
	Value  Generic
	Usage  string
	EnvVar string
}

func (f GenericFlag) String() string {
	return withEnvHint(f.EnvVar, fmt.Sprintf("%s%s %v\t`%v` %s", prefixFor(f.Name), f.Name, f.Value, "-"+f.Name+" option -"+f.Name+" option", f.Usage))
}

func (f GenericFlag) Apply(set *flag.FlagSet) {
	val := f.Value
	if f.EnvVar != "" {
		if envVal := os.Getenv(f.EnvVar); envVal != "" {
			val.Set(envVal)
		}
	}

	eachName(f.Name, func(name string) {
		set.Var(f.Value, name, f.Usage)
	})
}

func (f GenericFlag) getName() string {
	return f.Name
}

type StringSlice []string

func (f *StringSlice) Set(value string) error {
	*f = append(*f, value)
	return nil
}

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

func (f *StringSlice) Value() []string {
	return *f
}

type StringSliceFlag struct {
	Name   string
	Value  *StringSlice
	Usage  string
	EnvVar string
}

func (f StringSliceFlag) String() string {
	firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
	pref := prefixFor(firstName)
	return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
}

func (f StringSliceFlag) Apply(set *flag.FlagSet) {
	if f.EnvVar != "" {
		if envVal := os.Getenv(f.EnvVar); envVal != "" {
			newVal := &StringSlice{}
			for _, s := range strings.Split(envVal, ",") {
				newVal.Set(s)
			}
			f.Value = newVal
		}
	}

	eachName(f.Name, func(name string) {
		set.Var(f.Value, name, f.Usage)
	})
}

func (f StringSliceFlag) getName() string {
	return f.Name
}

type IntSlice []int

func (f *IntSlice) Set(value string) error {

	tmp, err := strconv.Atoi(value)
	if err != nil {
		return err
	} else {
		*f = append(*f, tmp)
	}
	return nil
}

func (f *IntSlice) String() string {
	return fmt.Sprintf("%d", *f)
}

func (f *IntSlice) Value() []int {
	return *f
}

type IntSliceFlag struct {
	Name   string
	Value  *IntSlice
	Usage  string
	EnvVar string
}

func (f IntSliceFlag) String() string {
	firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
	pref := prefixFor(firstName)
	return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
}

func (f IntSliceFlag) Apply(set *flag.FlagSet) {
	if f.EnvVar != "" {
		if envVal := os.Getenv(f.EnvVar); envVal != "" {
			newVal := &IntSlice{}
			for _, s := range strings.Split(envVal, ",") {
				err := newVal.Set(s)
				if err != nil {
					fmt.Fprintf(os.Stderr, err.Error())
				}
			}
			f.Value = newVal
		}
	}

	eachName(f.Name, func(name string) {
		set.Var(f.Value, name, f.Usage)
	})
}

func (f IntSliceFlag) getName() string {
	return f.Name
}

type BoolFlag struct {
	Name   string
	Usage  string
	EnvVar string
}

func (f BoolFlag) String() string {
	return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
}

func (f BoolFlag) Apply(set *flag.FlagSet) {
	val := false
	if f.EnvVar != "" {
		if envVal := os.Getenv(f.EnvVar); envVal != "" {
			envValBool, err := strconv.ParseBool(envVal)
			if err == nil {
				val = envValBool
			}
		}
	}

	eachName(f.Name, func(name string) {
		set.Bool(name, val, f.Usage)
	})
}

func (f BoolFlag) getName() string {
	return f.Name
}

type BoolTFlag struct {
	Name   string
	Usage  string
	EnvVar string
}

func (f BoolTFlag) String() string {
	return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
}

func (f BoolTFlag) Apply(set *flag.FlagSet) {
	val := true
	if f.EnvVar != "" {
		if envVal := os.Getenv(f.EnvVar); envVal != "" {
			envValBool, err := strconv.ParseBool(envVal)
			if err == nil {
				val = envValBool
			}
		}
	}

	eachName(f.Name, func(name string) {
		set.Bool(name, val, f.Usage)
	})
}

func (f BoolTFlag) getName() string {
	return f.Name
}

type StringFlag struct {
	Name   string
	Value  string
	Usage  string
	EnvVar string
}

func (f StringFlag) String() string {
	var fmtString string
	fmtString = "%s %v\t%v"

	if len(f.Value) > 0 {
		fmtString = "%s '%v'\t%v"
	} else {
		fmtString = "%s %v\t%v"
	}

	return withEnvHint(f.EnvVar, fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage))
}

func (f StringFlag) Apply(set *flag.FlagSet) {
	if f.EnvVar != "" {
		if envVal := os.Getenv(f.EnvVar); envVal != "" {
			f.Value = envVal
		}
	}

	eachName(f.Name, func(name string) {
		set.String(name, f.Value, f.Usage)
	})
}

func (f StringFlag) getName() string {
	return f.Name
}

type IntFlag struct {
	Name   string
	Value  int
	Usage  string
	EnvVar string
}

func (f IntFlag) String() string {
	return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage))
}

func (f IntFlag) Apply(set *flag.FlagSet) {
	if f.EnvVar != "" {
		if envVal := os.Getenv(f.EnvVar); envVal != "" {
			envValInt, err := strconv.ParseUint(envVal, 10, 64)
			if err == nil {
				f.Value = int(envValInt)
			}
		}
	}

	eachName(f.Name, func(name string) {
		set.Int(name, f.Value, f.Usage)
	})
}

func (f IntFlag) getName() string {
	return f.Name
}

type Float64Flag struct {
	Name   string
	Value  float64
	Usage  string
	EnvVar string
}

func (f Float64Flag) String() string {
	return withEnvHint(f.EnvVar, fmt.Sprintf("%s '%v'\t%v", prefixedNames(f.Name), f.Value, f.Usage))
}

func (f Float64Flag) Apply(set *flag.FlagSet) {
	if f.EnvVar != "" {
		if envVal := os.Getenv(f.EnvVar); envVal != "" {
			envValFloat, err := strconv.ParseFloat(envVal, 10)
			if err == nil {
				f.Value = float64(envValFloat)
			}
		}
	}

	eachName(f.Name, func(name string) {
		set.Float64(name, f.Value, f.Usage)
	})
}

func (f Float64Flag) getName() string {
	return f.Name
}

func prefixFor(name string) (prefix string) {
	if len(name) == 1 {
		prefix = "-"
	} else {
		prefix = "--"
	}

	return
}

func prefixedNames(fullName string) (prefixed string) {
	parts := strings.Split(fullName, ",")
	for i, name := range parts {
		name = strings.Trim(name, " ")
		prefixed += prefixFor(name) + name
		if i < len(parts)-1 {
			prefixed += ", "
		}
	}
	return
}

func withEnvHint(envVar, str string) string {
	envText := ""
	if envVar != "" {
		envText = fmt.Sprintf(" [$%s]", envVar)
	}
	return str + envText
}
<|endoftext|>