<commit_before>package stripe

import (
	"encoding/json"
)

// CheckoutSessionSubmitType is the list of allowed values for the `submit_type`
// of a Session.
type CheckoutSessionSubmitType string

// List of values that CheckoutSessionSubmitType can take.
const (
	CheckoutSessionSubmitTypeAuto   CheckoutSessionSubmitType = "auto"
	CheckoutSessionSubmitTypeBook   CheckoutSessionSubmitType = "book"
	CheckoutSessionSubmitTypeDonate CheckoutSessionSubmitType = "donate"
	CheckoutSessionSubmitTypePay    CheckoutSessionSubmitType = "pay"
)

// CheckoutSessionMode is the list of allowed values for the mode on a Session.
type CheckoutSessionMode string

// List of values that CheckoutSessionMode can take.
const (
	CheckoutSessionModePayment      CheckoutSessionMode = "payment"
	CheckoutSessionModeSetup        CheckoutSessionMode = "setup"
	CheckoutSessionModeSubscription CheckoutSessionMode = "subscription"
)

// CheckoutSessionLineItemPriceDataProductDataParams is the set of parameters that can be used when
// creating a product created inline for a line item.
type CheckoutSessionLineItemPriceDataProductDataParams struct {
	Description *string           `form:"description"`
	Images      []*string         `form:"images"`
	Metadata    map[string]string `form:"metadata"`
	Name        *string           `form:"name"`
}

// CheckoutSessionLineItemPriceDataRecurringParams is the set of parameters for the recurring
// components of a price created inline for a line item.
type CheckoutSessionLineItemPriceDataRecurringParams struct {
	AggregateUsage  *string `form:"aggregate_usage"`
	Interval        *string `form:"interval"`
	IntervalCount   *int64  `form:"interval_count"`
	TrialPeriodDays *int64  `form:"trial_period_days"`
	UsageType       *string `form:"usage_type"`
}

// CheckoutSessionLineItemPriceDataParams is a structure representing the parameters to create
// an inline price for a line item.
type CheckoutSessionLineItemPriceDataParams struct {
	Currency          *string                                            `form:"currency"`
	Product           *string                                            `form:"product"`
	ProductData       *CheckoutSessionLineItemPriceDataProductDataParams `form:"product_data"`
	Recurring         *CheckoutSessionLineItemPriceDataRecurringParams   `form:"recurring"`
	UnitAmount        *int64                                             `form:"unit_amount"`
	UnitAmountDecimal *float64                                           `form:"unit_amount_decimal,high_precision"`
}

// CheckoutSessionLineItemParams is the set of parameters allowed for a line item
// on a checkout session.
type CheckoutSessionLineItemParams struct {
	Amount      *int64                                  `form:"amount"`
	Currency    *string                                 `form:"currency"`
	Description *string                                 `form:"description"`
	Images      []*string                               `form:"images"`
	Name        *string                                 `form:"name"`
	Price       *string                                 `form:"price"`
	PriceData   *CheckoutSessionLineItemPriceDataParams `form:"price_data"`
	Quantity    *int64                                  `form:"quantity"`
	TaxRates    []*string                               `form:"tax_rates"`
}

// CheckoutSessionPaymentIntentDataTransferDataParams is the set of parameters allowed for the
// transfer_data hash.
type CheckoutSessionPaymentIntentDataTransferDataParams struct {
	Amount      *int64  `form:"amount"`
	Destination *string `form:"destination"`
}

// CheckoutSessionPaymentIntentDataParams is the set of parameters allowed for the
// payment intent creation on a checkout session.
type CheckoutSessionPaymentIntentDataParams struct {
	Params                    `form:"*"`
	ApplicationFeeAmount      *int64                                              `form:"application_fee_amount"`
	CaptureMethod             *string                                             `form:"capture_method"`
	Description               *string                                             `form:"description"`
	Metadata                  map[string]string                                   `form:"metadata"`
	OnBehalfOf                *string                                             `form:"on_behalf_of"`
	ReceiptEmail              *string                                             `form:"receipt_email"`
	SetupFutureUsage          *string                                             `form:"setup_future_usage"`
	Shipping                  *ShippingDetailsParams                              `form:"shipping"`
	StatementDescriptor       *string                                             `form:"statement_descriptor"`
	StatementDescriptorSuffix *string                                             `form:"statement_descriptor_suffix"`
	TransferData              *CheckoutSessionPaymentIntentDataTransferDataParams `form:"transfer_data"`
	TransferGroup             *string                                             `form:"transfer_group"`
}

// CheckoutSessionSetupIntentDataParams is the set of parameters allowed for the setup intent
// creation on a checkout session.
type CheckoutSessionSetupIntentDataParams struct {
	Params      `form:"*"`
	Description *string `form:"description"`
	OnBehalfOf  *string `form:"on_behalf_of"`
}

// CheckoutSessionShippingAddressCollectionParams is the set of parameters allowed for the
// shipping address collection.
type CheckoutSessionShippingAddressCollectionParams struct {
	AllowedCountries []*string `form:"allowed_countries"`
}

// CheckoutSessionSubscriptionDataItemsParams is the set of parameters allowed for one item on a
// checkout session associated with a subscription.
type CheckoutSessionSubscriptionDataItemsParams struct {
	Plan     *string   `form:"plan"`
	Quantity *int64    `form:"quantity"`
	TaxRates []*string `form:"tax_rates"`
}

// CheckoutSessionSubscriptionDataParams is the set of parameters allowed for the subscription
// creation on a checkout session.
type CheckoutSessionSubscriptionDataParams struct {
	Params                `form:"*"`
	ApplicationFeePercent *float64                                      `form:"application_fee_percent"`
	Coupon                *string                                       `form:"coupon"`
	DefaultTaxRates       []*string                                     `form:"default_tax_rates"`
	Items                 []*CheckoutSessionSubscriptionDataItemsParams `form:"items"`
	Metadata              map[string]string                             `form:"metadata"`
	TrialEnd              *int64                                        `form:"trial_end"`
	TrialFromPlan         *bool                                         `form:"trial_from_plan"`
	TrialPeriodDays       *int64                                        `form:"trial_period_days"`
}

// CheckoutSessionParams is the set of parameters that can be used when creating
// a checkout session.
// For more details see https://stripe.com/docs/api/checkout/sessions/create
type CheckoutSessionParams struct {
	Params                    `form:"*"`
	AllowPromotionCodes       *bool                                           `form:"allow_promotion_codes"`
	BillingAddressCollection  *string                                         `form:"billing_address_collection"`
	CancelURL                 *string                                         `form:"cancel_url"`
	ClientReferenceID         *string                                         `form:"client_reference_id"`
	Customer                  *string                                         `form:"customer"`
	CustomerEmail             *string                                         `form:"customer_email"`
	LineItems                 []*CheckoutSessionLineItemParams                `form:"line_items"`
	Locale                    *string                                         `form:"locale"`
	Mode                      *string                                         `form:"mode"`
	PaymentIntentData         *CheckoutSessionPaymentIntentDataParams         `form:"payment_intent_data"`
	PaymentMethodTypes        []*string                                       `form:"payment_method_types"`
	SetupIntentData           *CheckoutSessionSetupIntentDataParams           `form:"setup_intent_data"`
	ShippingAddressCollection *CheckoutSessionShippingAddressCollectionParams `form:"shipping_address_collection"`
	SubscriptionData          *CheckoutSessionSubscriptionDataParams          `form:"subscription_data"`
	SubmitType                *string                                         `form:"submit_type"`
	SuccessURL                *string                                         `form:"success_url"`
}

// CheckoutSessionListLineItemsParams is the set of parameters that can be
// used when listing line items on a session.
type CheckoutSessionListLineItemsParams struct {
	ListParams `form:"*"`
	Session    *string `form:"-"` // Included in URL
}

// CheckoutSessionListParams is the set of parameters that can be
// used when listing sessions.
// For more details see: https://stripe.com/docs/api/checkout/sessions/list
type CheckoutSessionListParams struct {
	ListParams    `form:"*"`
	PaymentIntent *string `form:"payment_intent"`
	Subscription  *string `form:"subscription"`
}

// CheckoutSessionShippingAddressCollection is the set of parameters allowed for the
// shipping address collection.
type CheckoutSessionShippingAddressCollection struct {
	AllowedCountries []string `json:"allowed_countries"`
}

// CheckoutSessionTotalDetailsBreakdownDiscount represent the details of one discount applied to a session.
type CheckoutSessionTotalDetailsBreakdownDiscount struct {
	Amount   int64     `json:"amount"`
	Discount *Discount `json:"discount"`
}

// CheckoutSessionTotalDetailsBreakdownTax represent the details of tax rate applied to a session.
type CheckoutSessionTotalDetailsBreakdownTax struct {
	Amount  int64    `json:"amount"`
	TaxRate *TaxRate `json:"tax_rate"`
}

// CheckoutSessionTotalDetailsBreakdown is the set of properties detailing a breakdown of taxes and discounts applied to a session if any.
type CheckoutSessionTotalDetailsBreakdown struct {
	Discounts []*CheckoutSessionTotalDetailsBreakdownDiscount `json:"discounts"`
	Taxes     []*CheckoutSessionTotalDetailsBreakdownTax      `json:"taxes"`
}

// CheckoutSessionTotalDetails is the set of properties detailing how the amounts were calculated.
type CheckoutSessionTotalDetails struct {
	AmountDiscount int64                                 `json:"amount_discount"`
	AmountTax      int64                                 `json:"amount_tax"`
	Breakdown      *CheckoutSessionTotalDetailsBreakdown `json:"breakdown"`
}

// CheckoutSession is the resource representing a Stripe checkout session.
// For more details see https://stripe.com/docs/api/checkout/sessions/object
type CheckoutSession struct {
	APIResource
	AllowPromotionCodes       bool                                      `json:"allow_promotion_codes"`
	CancelURL                 string                                    `json:"cancel_url"`
	AmountSubtotal            int64                                     `json:"amount_subtotal"`
	AmountTotal               int64                                     `json:"amount_total"`
	ClientReferenceID         string                                    `json:"client_reference_id"`
	Currency                  Currency                                  `json:"currency"`
	Customer                  *Customer                                 `json:"customer"`
	CustomerEmail             string                                    `json:"customer_email"`
	Deleted                   bool                                      `json:"deleted"`
	ID                        string                                    `json:"id"`
	LineItems                 *LineItemList                             `json:"line_items"`
	Livemode                  bool                                      `json:"livemode"`
	Locale                    string                                    `json:"locale"`
	Metadata                  map[string]string                         `json:"metadata"`
	Mode                      CheckoutSessionMode                       `json:"mode"`
	Object                    string                                    `json:"object"`
	PaymentIntent             *PaymentIntent                            `json:"payment_intent"`
	PaymentMethodTypes        []string                                  `json:"payment_method_types"`
	SetupIntent               *SetupIntent                              `json:"setup_intent"`
	Shipping                  *ShippingDetails                          `json:"shipping"`
	ShippingAddressCollection *CheckoutSessionShippingAddressCollection `json:"shipping_address_collection"`
	Subscription              *Subscription                             `json:"subscription"`
	SubmitType                CheckoutSessionSubmitType                 `json:"submit_type"`
	SuccessURL                string                                    `json:"success_url"`
	TotalDetails              *CheckoutSessionTotalDetails              `json:"total_details"`
}

// CheckoutSessionList is a list of sessions as retrieved from a list endpoint.
type CheckoutSessionList struct {
	APIResource
	ListMeta
	Data []*CheckoutSession `json:"data"`
}

// UnmarshalJSON handles deserialization of a checkout session.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (p *CheckoutSession) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		p.ID = id
		return nil
	}

	type session CheckoutSession
	var v session
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*p = CheckoutSession(v)
	return nil
}
<commit_msg>Add support for `PaymentStatus` on Checkout `Session`<commit_after>package stripe

import (
	"encoding/json"
)

// CheckoutSessionMode is the list of allowed values for the mode on a Session.
type CheckoutSessionMode string

// List of values that CheckoutSessionMode can take.
const (
	CheckoutSessionModePayment      CheckoutSessionMode = "payment"
	CheckoutSessionModeSetup        CheckoutSessionMode = "setup"
	CheckoutSessionModeSubscription CheckoutSessionMode = "subscription"
)

// CheckoutSessionPaymentStatus is the list of allowed values for the payment status on a Session.`
type CheckoutSessionPaymentStatus string

// List of values that CheckoutSessionPaymentStatus can take.
const (
	CheckoutSessionPaymentStatusNoPaymentRequired CheckoutSessionPaymentStatus = "no_payment_required"
	CheckoutSessionPaymentStatusPaid              CheckoutSessionPaymentStatus = "paid"
	CheckoutSessionPaymentStatusUnpaid            CheckoutSessionPaymentStatus = "unpaid"
)

// CheckoutSessionSubmitType is the list of allowed values for the submit type on  a Session.
type CheckoutSessionSubmitType string

// List of values that CheckoutSessionSubmitType can take.
const (
	CheckoutSessionSubmitTypeAuto   CheckoutSessionSubmitType = "auto"
	CheckoutSessionSubmitTypeBook   CheckoutSessionSubmitType = "book"
	CheckoutSessionSubmitTypeDonate CheckoutSessionSubmitType = "donate"
	CheckoutSessionSubmitTypePay    CheckoutSessionSubmitType = "pay"
)

// CheckoutSessionLineItemPriceDataProductDataParams is the set of parameters that can be used when
// creating a product created inline for a line item.
type CheckoutSessionLineItemPriceDataProductDataParams struct {
	Description *string           `form:"description"`
	Images      []*string         `form:"images"`
	Metadata    map[string]string `form:"metadata"`
	Name        *string           `form:"name"`
}

// CheckoutSessionLineItemPriceDataRecurringParams is the set of parameters for the recurring
// components of a price created inline for a line item.
type CheckoutSessionLineItemPriceDataRecurringParams struct {
	AggregateUsage  *string `form:"aggregate_usage"`
	Interval        *string `form:"interval"`
	IntervalCount   *int64  `form:"interval_count"`
	TrialPeriodDays *int64  `form:"trial_period_days"`
	UsageType       *string `form:"usage_type"`
}

// CheckoutSessionLineItemPriceDataParams is a structure representing the parameters to create
// an inline price for a line item.
type CheckoutSessionLineItemPriceDataParams struct {
	Currency          *string                                            `form:"currency"`
	Product           *string                                            `form:"product"`
	ProductData       *CheckoutSessionLineItemPriceDataProductDataParams `form:"product_data"`
	Recurring         *CheckoutSessionLineItemPriceDataRecurringParams   `form:"recurring"`
	UnitAmount        *int64                                             `form:"unit_amount"`
	UnitAmountDecimal *float64                                           `form:"unit_amount_decimal,high_precision"`
}

// CheckoutSessionLineItemParams is the set of parameters allowed for a line item
// on a checkout session.
type CheckoutSessionLineItemParams struct {
	Amount      *int64                                  `form:"amount"`
	Currency    *string                                 `form:"currency"`
	Description *string                                 `form:"description"`
	Images      []*string                               `form:"images"`
	Name        *string                                 `form:"name"`
	Price       *string                                 `form:"price"`
	PriceData   *CheckoutSessionLineItemPriceDataParams `form:"price_data"`
	Quantity    *int64                                  `form:"quantity"`
	TaxRates    []*string                               `form:"tax_rates"`
}

// CheckoutSessionPaymentIntentDataTransferDataParams is the set of parameters allowed for the
// transfer_data hash.
type CheckoutSessionPaymentIntentDataTransferDataParams struct {
	Amount      *int64  `form:"amount"`
	Destination *string `form:"destination"`
}

// CheckoutSessionPaymentIntentDataParams is the set of parameters allowed for the
// payment intent creation on a checkout session.
type CheckoutSessionPaymentIntentDataParams struct {
	Params                    `form:"*"`
	ApplicationFeeAmount      *int64                                              `form:"application_fee_amount"`
	CaptureMethod             *string                                             `form:"capture_method"`
	Description               *string                                             `form:"description"`
	Metadata                  map[string]string                                   `form:"metadata"`
	OnBehalfOf                *string                                             `form:"on_behalf_of"`
	ReceiptEmail              *string                                             `form:"receipt_email"`
	SetupFutureUsage          *string                                             `form:"setup_future_usage"`
	Shipping                  *ShippingDetailsParams                              `form:"shipping"`
	StatementDescriptor       *string                                             `form:"statement_descriptor"`
	StatementDescriptorSuffix *string                                             `form:"statement_descriptor_suffix"`
	TransferData              *CheckoutSessionPaymentIntentDataTransferDataParams `form:"transfer_data"`
	TransferGroup             *string                                             `form:"transfer_group"`
}

// CheckoutSessionSetupIntentDataParams is the set of parameters allowed for the setup intent
// creation on a checkout session.
type CheckoutSessionSetupIntentDataParams struct {
	Params      `form:"*"`
	Description *string `form:"description"`
	OnBehalfOf  *string `form:"on_behalf_of"`
}

// CheckoutSessionShippingAddressCollectionParams is the set of parameters allowed for the
// shipping address collection.
type CheckoutSessionShippingAddressCollectionParams struct {
	AllowedCountries []*string `form:"allowed_countries"`
}

// CheckoutSessionSubscriptionDataItemsParams is the set of parameters allowed for one item on a
// checkout session associated with a subscription.
type CheckoutSessionSubscriptionDataItemsParams struct {
	Plan     *string   `form:"plan"`
	Quantity *int64    `form:"quantity"`
	TaxRates []*string `form:"tax_rates"`
}

// CheckoutSessionSubscriptionDataParams is the set of parameters allowed for the subscription
// creation on a checkout session.
type CheckoutSessionSubscriptionDataParams struct {
	Params                `form:"*"`
	ApplicationFeePercent *float64                                      `form:"application_fee_percent"`
	Coupon                *string                                       `form:"coupon"`
	DefaultTaxRates       []*string                                     `form:"default_tax_rates"`
	Items                 []*CheckoutSessionSubscriptionDataItemsParams `form:"items"`
	Metadata              map[string]string                             `form:"metadata"`
	TrialEnd              *int64                                        `form:"trial_end"`
	TrialFromPlan         *bool                                         `form:"trial_from_plan"`
	TrialPeriodDays       *int64                                        `form:"trial_period_days"`
}

// CheckoutSessionParams is the set of parameters that can be used when creating
// a checkout session.
// For more details see https://stripe.com/docs/api/checkout/sessions/create
type CheckoutSessionParams struct {
	Params                    `form:"*"`
	AllowPromotionCodes       *bool                                           `form:"allow_promotion_codes"`
	BillingAddressCollection  *string                                         `form:"billing_address_collection"`
	CancelURL                 *string                                         `form:"cancel_url"`
	ClientReferenceID         *string                                         `form:"client_reference_id"`
	Customer                  *string                                         `form:"customer"`
	CustomerEmail             *string                                         `form:"customer_email"`
	LineItems                 []*CheckoutSessionLineItemParams                `form:"line_items"`
	Locale                    *string                                         `form:"locale"`
	Mode                      *string                                         `form:"mode"`
	PaymentIntentData         *CheckoutSessionPaymentIntentDataParams         `form:"payment_intent_data"`
	PaymentMethodTypes        []*string                                       `form:"payment_method_types"`
	SetupIntentData           *CheckoutSessionSetupIntentDataParams           `form:"setup_intent_data"`
	ShippingAddressCollection *CheckoutSessionShippingAddressCollectionParams `form:"shipping_address_collection"`
	SubscriptionData          *CheckoutSessionSubscriptionDataParams          `form:"subscription_data"`
	SubmitType                *string                                         `form:"submit_type"`
	SuccessURL                *string                                         `form:"success_url"`
}

// CheckoutSessionListLineItemsParams is the set of parameters that can be
// used when listing line items on a session.
type CheckoutSessionListLineItemsParams struct {
	ListParams `form:"*"`
	Session    *string `form:"-"` // Included in URL
}

// CheckoutSessionListParams is the set of parameters that can be
// used when listing sessions.
// For more details see: https://stripe.com/docs/api/checkout/sessions/list
type CheckoutSessionListParams struct {
	ListParams    `form:"*"`
	PaymentIntent *string `form:"payment_intent"`
	Subscription  *string `form:"subscription"`
}

// CheckoutSessionShippingAddressCollection is the set of parameters allowed for the
// shipping address collection.
type CheckoutSessionShippingAddressCollection struct {
	AllowedCountries []string `json:"allowed_countries"`
}

// CheckoutSessionTotalDetailsBreakdownDiscount represent the details of one discount applied to a session.
type CheckoutSessionTotalDetailsBreakdownDiscount struct {
	Amount   int64     `json:"amount"`
	Discount *Discount `json:"discount"`
}

// CheckoutSessionTotalDetailsBreakdownTax represent the details of tax rate applied to a session.
type CheckoutSessionTotalDetailsBreakdownTax struct {
	Amount  int64    `json:"amount"`
	TaxRate *TaxRate `json:"tax_rate"`
}

// CheckoutSessionTotalDetailsBreakdown is the set of properties detailing a breakdown of taxes and discounts applied to a session if any.
type CheckoutSessionTotalDetailsBreakdown struct {
	Discounts []*CheckoutSessionTotalDetailsBreakdownDiscount `json:"discounts"`
	Taxes     []*CheckoutSessionTotalDetailsBreakdownTax      `json:"taxes"`
}

// CheckoutSessionTotalDetails is the set of properties detailing how the amounts were calculated.
type CheckoutSessionTotalDetails struct {
	AmountDiscount int64                                 `json:"amount_discount"`
	AmountTax      int64                                 `json:"amount_tax"`
	Breakdown      *CheckoutSessionTotalDetailsBreakdown `json:"breakdown"`
}

// CheckoutSession is the resource representing a Stripe checkout session.
// For more details see https://stripe.com/docs/api/checkout/sessions/object
type CheckoutSession struct {
	APIResource
	AllowPromotionCodes       bool                                      `json:"allow_promotion_codes"`
	CancelURL                 string                                    `json:"cancel_url"`
	AmountSubtotal            int64                                     `json:"amount_subtotal"`
	AmountTotal               int64                                     `json:"amount_total"`
	ClientReferenceID         string                                    `json:"client_reference_id"`
	Currency                  Currency                                  `json:"currency"`
	Customer                  *Customer                                 `json:"customer"`
	CustomerEmail             string                                    `json:"customer_email"`
	Deleted                   bool                                      `json:"deleted"`
	ID                        string                                    `json:"id"`
	LineItems                 *LineItemList                             `json:"line_items"`
	Livemode                  bool                                      `json:"livemode"`
	Locale                    string                                    `json:"locale"`
	Metadata                  map[string]string                         `json:"metadata"`
	Mode                      CheckoutSessionMode                       `json:"mode"`
	Object                    string                                    `json:"object"`
	PaymentIntent             *PaymentIntent                            `json:"payment_intent"`
	PaymentMethodTypes        []string                                  `json:"payment_method_types"`
	PaymentStatus             CheckoutSessionPaymentStatus              `json:"payment_status"`
	SetupIntent               *SetupIntent                              `json:"setup_intent"`
	Shipping                  *ShippingDetails                          `json:"shipping"`
	ShippingAddressCollection *CheckoutSessionShippingAddressCollection `json:"shipping_address_collection"`
	Subscription              *Subscription                             `json:"subscription"`
	SubmitType                CheckoutSessionSubmitType                 `json:"submit_type"`
	SuccessURL                string                                    `json:"success_url"`
	TotalDetails              *CheckoutSessionTotalDetails              `json:"total_details"`
}

// CheckoutSessionList is a list of sessions as retrieved from a list endpoint.
type CheckoutSessionList struct {
	APIResource
	ListMeta
	Data []*CheckoutSession `json:"data"`
}

// UnmarshalJSON handles deserialization of a checkout session.
// This custom unmarshaling is needed because the resulting
// property may be an id or the full struct if it was expanded.
func (p *CheckoutSession) UnmarshalJSON(data []byte) error {
	if id, ok := ParseID(data); ok {
		p.ID = id
		return nil
	}

	type session CheckoutSession
	var v session
	if err := json.Unmarshal(data, &v); err != nil {
		return err
	}

	*p = CheckoutSession(v)
	return nil
}
<|endoftext|>


<commit_before>package merge

import (
	"runtime"
	"sort"
	"sync"
)

func sortBucket(comparators Comparators) {
	sort.Sort(comparators)
}

func copyChunk(chunk []Comparators) []Comparators {
	cp := make([]Comparators, len(chunk))
	copy(cp, chunk)
	return cp
}

// MultithreadedSortComparators will take a list of comparators
// and sort it using as many threads as are available.  The list
// is split into buckets for a bucket sort and then recursively
// merged using SymMerge.
func MultithreadedSortComparators(comparators Comparators) Comparators {
	toBeSorted := make(Comparators, len(comparators))
	copy(toBeSorted, comparators)

	var wg sync.WaitGroup

	numCPU := int64(runtime.NumCPU())
	if numCPU%2 == 1 { // single core machine
		numCPU++
	}

	chunks := chunk(toBeSorted, numCPU)
	wg.Add(len(chunks))
	for i := 0; i < len(chunks); i++ {
		go func(i int) {
			sortBucket(chunks[i])
			wg.Done()
		}(i)
	}

	wg.Wait()
	todo := make([]Comparators, len(chunks)/2)
	for {
		todo = todo[:len(chunks)/2]
		wg.Add(len(chunks) / 2)
		for i := 0; i < len(chunks); i += 2 {
			go func(i int) {
				todo[i/2] = SymMerge(chunks[i], chunks[i+1])
				wg.Done()
			}(i)
		}

		wg.Wait()

		chunks = copyChunk(todo)
		if len(chunks) == 1 {
			break
		}
	}

	return chunks[0]
}

func chunk(comparators Comparators, numParts int64) []Comparators {
	parts := make([]Comparators, numParts)
	for i := int64(0); i < numParts; i++ {
		parts[i] = comparators[i*int64(len(comparators))/numParts : (i+1)*int64(len(comparators))/numParts]
	}
	return parts
}

func returnInts() []int {
	numCalls := 10
	var wg sync.WaitGroup
	wg.Add(numCalls)
	ints := make([]int, numCalls)

	for i := 0; i < numCalls; i++ {
		go func(i int) {
			result := someRandomDatastoreCall()
			ints[i] = result
			wg.Done()
		}(i)
	}

	wg.Wait()

	return ints
}
<commit_msg>Remove unused code.<commit_after>package merge

import (
	"runtime"
	"sort"
	"sync"
)

func sortBucket(comparators Comparators) {
	sort.Sort(comparators)
}

func copyChunk(chunk []Comparators) []Comparators {
	cp := make([]Comparators, len(chunk))
	copy(cp, chunk)
	return cp
}

// MultithreadedSortComparators will take a list of comparators
// and sort it using as many threads as are available.  The list
// is split into buckets for a bucket sort and then recursively
// merged using SymMerge.
func MultithreadedSortComparators(comparators Comparators) Comparators {
	toBeSorted := make(Comparators, len(comparators))
	copy(toBeSorted, comparators)

	var wg sync.WaitGroup

	numCPU := int64(runtime.NumCPU())
	if numCPU%2 == 1 { // single core machine
		numCPU++
	}

	chunks := chunk(toBeSorted, numCPU)
	wg.Add(len(chunks))
	for i := 0; i < len(chunks); i++ {
		go func(i int) {
			sortBucket(chunks[i])
			wg.Done()
		}(i)
	}

	wg.Wait()
	todo := make([]Comparators, len(chunks)/2)
	for {
		todo = todo[:len(chunks)/2]
		wg.Add(len(chunks) / 2)
		for i := 0; i < len(chunks); i += 2 {
			go func(i int) {
				todo[i/2] = SymMerge(chunks[i], chunks[i+1])
				wg.Done()
			}(i)
		}

		wg.Wait()

		chunks = copyChunk(todo)
		if len(chunks) == 1 {
			break
		}
	}

	return chunks[0]
}

func chunk(comparators Comparators, numParts int64) []Comparators {
	parts := make([]Comparators, numParts)
	for i := int64(0); i < numParts; i++ {
		parts[i] = comparators[i*int64(len(comparators))/numParts : (i+1)*int64(len(comparators))/numParts]
	}
	return parts
}
<|endoftext|>


<commit_before>package consul

import (
	"fmt"
	"log"
	"runtime"
	"sort"
	"strings"
	"time"

	"github.com/hashicorp/consul/api"
)

// watchServices monitors the consul health checks and creates a new configuration
// on every change.
func watchServices(client *api.Client, tagPrefix string, config chan string) {
	var lastIndex uint64

	for {
		q := &api.QueryOptions{RequireConsistent: true, WaitIndex: lastIndex}
		checks, meta, err := client.Health().State("any", q)
		if err != nil {
			log.Printf("[WARN] consul: Error fetching health state. %v", err)
			time.Sleep(time.Second)
			continue
		}

		log.Printf("[INFO] consul: Health changed to #%d", meta.LastIndex)
		config <- servicesConfig(client, passingServices(checks), tagPrefix)
		lastIndex = meta.LastIndex
	}
}

// servicesConfig determines which service instances have passing health checks
// and then finds the ones which have tags with the right prefix to build the config from.
func servicesConfig(client *api.Client, checks []*api.HealthCheck, tagPrefix string) string {
	// map service name to list of service passing for which the health check is ok
	m := map[string]map[string]bool{}
	for _, check := range checks {
		name, id := check.ServiceName, check.ServiceID

		if _, ok := m[name]; !ok {
			m[name] = map[string]bool{}
		}
		m[name][id] = true
	}

	var config []string
	for name, passing := range m {
		cfg := serviceConfig(client, name, passing, tagPrefix)
		config = append(config, cfg...)
	}

	// sort config in reverse order to sort most specific config to the top
	sort.Sort(sort.Reverse(sort.StringSlice(config)))

	return strings.Join(config, "\n")
}

// serviceConfig constructs the config for all good instances of a single service.
func serviceConfig(client *api.Client, name string, passing map[string]bool, tagPrefix string) (config []string) {
	if name == "" || len(passing) == 0 {
		return nil
	}

	q := &api.QueryOptions{RequireConsistent: true}
	svcs, _, err := client.Catalog().Service(name, "", q)
	if err != nil {
		log.Printf("[WARN] consul: Error getting catalog service %s. %v", name, err)
		return nil
	}

	for _, svc := range svcs {
		// check if the instance is in the list of instances
		// which passed the health check
		if _, ok := passing[svc.ServiceID]; !ok {
			continue
		}

		for _, tag := range svc.ServiceTags {
			if host, path, ok := parseURLPrefixTag(tag, tagPrefix); ok {
				name, addr, port := svc.ServiceName, svc.ServiceAddress, svc.ServicePort
				if runtime.GOOS == "darwin" && !strings.Contains(addr, ".") {
					addr += ".local"
				}
				config = append(config, fmt.Sprintf("route add %s %s%s http://%s:%d/ tags %q", name, host, path, addr, port, strings.Join(svc.ServiceTags, ",")))
			}
		}
	}
	return config
}
<commit_msg>Add .local suffix on OSX only if it isn't there already<commit_after>package consul

import (
	"fmt"
	"log"
	"runtime"
	"sort"
	"strings"
	"time"

	"github.com/hashicorp/consul/api"
)

// watchServices monitors the consul health checks and creates a new configuration
// on every change.
func watchServices(client *api.Client, tagPrefix string, config chan string) {
	var lastIndex uint64

	for {
		q := &api.QueryOptions{RequireConsistent: true, WaitIndex: lastIndex}
		checks, meta, err := client.Health().State("any", q)
		if err != nil {
			log.Printf("[WARN] consul: Error fetching health state. %v", err)
			time.Sleep(time.Second)
			continue
		}

		log.Printf("[INFO] consul: Health changed to #%d", meta.LastIndex)
		config <- servicesConfig(client, passingServices(checks), tagPrefix)
		lastIndex = meta.LastIndex
	}
}

// servicesConfig determines which service instances have passing health checks
// and then finds the ones which have tags with the right prefix to build the config from.
func servicesConfig(client *api.Client, checks []*api.HealthCheck, tagPrefix string) string {
	// map service name to list of service passing for which the health check is ok
	m := map[string]map[string]bool{}
	for _, check := range checks {
		name, id := check.ServiceName, check.ServiceID

		if _, ok := m[name]; !ok {
			m[name] = map[string]bool{}
		}
		m[name][id] = true
	}

	var config []string
	for name, passing := range m {
		cfg := serviceConfig(client, name, passing, tagPrefix)
		config = append(config, cfg...)
	}

	// sort config in reverse order to sort most specific config to the top
	sort.Sort(sort.Reverse(sort.StringSlice(config)))

	return strings.Join(config, "\n")
}

// serviceConfig constructs the config for all good instances of a single service.
func serviceConfig(client *api.Client, name string, passing map[string]bool, tagPrefix string) (config []string) {
	if name == "" || len(passing) == 0 {
		return nil
	}

	q := &api.QueryOptions{RequireConsistent: true}
	svcs, _, err := client.Catalog().Service(name, "", q)
	if err != nil {
		log.Printf("[WARN] consul: Error getting catalog service %s. %v", name, err)
		return nil
	}

	for _, svc := range svcs {
		// check if the instance is in the list of instances
		// which passed the health check
		if _, ok := passing[svc.ServiceID]; !ok {
			continue
		}

		for _, tag := range svc.ServiceTags {
			if host, path, ok := parseURLPrefixTag(tag, tagPrefix); ok {
				name, addr, port := svc.ServiceName, svc.ServiceAddress, svc.ServicePort
				// add .local suffix on OSX for simple host names w/o domain
				if runtime.GOOS == "darwin" && !strings.Contains(addr, ".") && !strings.HasSuffix(addr, ".local") {
					addr += ".local"
				}

				config = append(config, fmt.Sprintf("route add %s %s%s http://%s:%d/ tags %q", name, host, path, addr, port, strings.Join(svc.ServiceTags, ",")))
			}
		}
	}
	return config
}
<|endoftext|>


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

package gosym

import (
	"debug/elf"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"testing"
)

var pclinetestBinary string

func dotest() bool {
	// For now, only works on ELF platforms.
	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
		return false
	}
	if pclinetestBinary != "" {
		return true
	}
	// This command builds pclinetest from pclinetest.asm;
	// the resulting binary looks like it was built from pclinetest.s,
	// but we have renamed it to keep it away from the go tool.
	pclinetestBinary = os.TempDir() + "/pclinetest"
	cmd := exec.Command("sh", "-c", "go tool 6a pclinetest.asm && go tool 6l -E main -o "+pclinetestBinary+" pclinetest.6")
	if err := cmd.Run(); err != nil {
		panic(err)
	}
	return true
}

func getTable(t *testing.T) *Table {
	f, tab := crack(os.Args[0], t)
	f.Close()
	return tab
}

func crack(file string, t *testing.T) (*elf.File, *Table) {
	// Open self
	f, err := elf.Open(file)
	if err != nil {
		t.Fatal(err)
	}
	return parse(file, f, t)
}

func parse(file string, f *elf.File, t *testing.T) (*elf.File, *Table) {
	symdat, err := f.Section(".gosymtab").Data()
	if err != nil {
		f.Close()
		t.Fatalf("reading %s gosymtab: %v", file, err)
	}
	pclndat, err := f.Section(".gopclntab").Data()
	if err != nil {
		f.Close()
		t.Fatalf("reading %s gopclntab: %v", file, err)
	}

	pcln := NewLineTable(pclndat, f.Section(".text").Addr)
	tab, err := NewTable(symdat, pcln)
	if err != nil {
		f.Close()
		t.Fatalf("parsing %s gosymtab: %v", file, err)
	}

	return f, tab
}

var goarch = os.Getenv("O")

func TestLineFromAline(t *testing.T) {
	if !dotest() {
		return
	}

	tab := getTable(t)

	// Find the sym package
	pkg := tab.LookupFunc("debug/gosym.TestLineFromAline").Obj
	if pkg == nil {
		t.Fatalf("nil pkg")
	}

	// Walk every absolute line and ensure that we hit every
	// source line monotonically
	lastline := make(map[string]int)
	final := -1
	for i := 0; i < 10000; i++ {
		path, line := pkg.lineFromAline(i)
		// Check for end of object
		if path == "" {
			if final == -1 {
				final = i - 1
			}
			continue
		} else if final != -1 {
			t.Fatalf("reached end of package at absolute line %d, but absolute line %d mapped to %s:%d", final, i, path, line)
		}
		// It's okay to see files multiple times (e.g., sys.a)
		if line == 1 {
			lastline[path] = 1
			continue
		}
		// Check that the is the next line in path
		ll, ok := lastline[path]
		if !ok {
			t.Errorf("file %s starts on line %d", path, line)
		} else if line != ll+1 {
			t.Errorf("expected next line of file %s to be %d, got %d", path, ll+1, line)
		}
		lastline[path] = line
	}
	if final == -1 {
		t.Errorf("never reached end of object")
	}
}

func TestLineAline(t *testing.T) {
	if !dotest() {
		return
	}

	tab := getTable(t)

	for _, o := range tab.Files {
		// A source file can appear multiple times in a
		// object.  alineFromLine will always return alines in
		// the first file, so track which lines we've seen.
		found := make(map[string]int)
		for i := 0; i < 1000; i++ {
			path, line := o.lineFromAline(i)
			if path == "" {
				break
			}

			// cgo files are full of 'Z' symbols, which we don't handle
			if len(path) > 4 && path[len(path)-4:] == ".cgo" {
				continue
			}

			if minline, ok := found[path]; path != "" && ok {
				if minline >= line {
					// We've already covered this file
					continue
				}
			}
			found[path] = line

			a, err := o.alineFromLine(path, line)
			if err != nil {
				t.Errorf("absolute line %d in object %s maps to %s:%d, but mapping that back gives error %s", i, o.Paths[0].Name, path, line, err)
			} else if a != i {
				t.Errorf("absolute line %d in object %s maps to %s:%d, which maps back to absolute line %d\n", i, o.Paths[0].Name, path, line, a)
			}
		}
	}
}

func TestPCLine(t *testing.T) {
	if !dotest() {
		return
	}

	f, tab := crack(pclinetestBinary, t)
	text := f.Section(".text")
	textdat, err := text.Data()
	if err != nil {
		t.Fatalf("reading .text: %v", err)
	}

	// Test PCToLine
	sym := tab.LookupFunc("linefrompc")
	wantLine := 0
	for pc := sym.Entry; pc < sym.End; pc++ {
		file, line, fn := tab.PCToLine(pc)
		off := pc - text.Addr // TODO(rsc): should not need off; bug in 8g
		wantLine += int(textdat[off])
		t.Logf("off is %d", off)
		if fn == nil {
			t.Errorf("failed to get line of PC %#x", pc)
		} else if !strings.HasSuffix(file, "pclinetest.s") {
			t.Errorf("expected %s (%s) at PC %#x, got %s (%s)", "pclinetest.s", sym.Name, pc, file, fn.Name)
		} else if line != wantLine || fn != sym {
			t.Errorf("expected :%d (%s) at PC %#x, got :%d (%s)", wantLine, sym.Name, pc, line, fn.Name)
		}
	}

	// Test LineToPC
	sym = tab.LookupFunc("pcfromline")
	lookupline := -1
	wantLine = 0
	off := uint64(0) // TODO(rsc): should not need off; bug in 8g
	for pc := sym.Value; pc < sym.End; pc += 2 + uint64(textdat[off]) {
		file, line, fn := tab.PCToLine(pc)
		off = pc - text.Addr
		wantLine += int(textdat[off])
		if line != wantLine {
			t.Errorf("expected line %d at PC %#x in pcfromline, got %d", wantLine, pc, line)
			off = pc + 1 - text.Addr
			continue
		}
		if lookupline == -1 {
			lookupline = line
		}
		for ; lookupline <= line; lookupline++ {
			pc2, fn2, err := tab.LineToPC(file, lookupline)
			if lookupline != line {
				// Should be nothing on this line
				if err == nil {
					t.Errorf("expected no PC at line %d, got %#x (%s)", lookupline, pc2, fn2.Name)
				}
			} else if err != nil {
				t.Errorf("failed to get PC of line %d: %s", lookupline, err)
			} else if pc != pc2 {
				t.Errorf("expected PC %#x (%s) at line %d, got PC %#x (%s)", pc, fn.Name, line, pc2, fn2.Name)
			}
		}
		off = pc + 1 - text.Addr
	}
}
<commit_msg>debug/gosym: dump 6a/6l output to process stdout/stderr so we can see failures.<commit_after>// Copyright 2009 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gosym

import (
	"debug/elf"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"testing"
)

var pclinetestBinary string

func dotest() bool {
	// For now, only works on ELF platforms.
	if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
		return false
	}
	if pclinetestBinary != "" {
		return true
	}
	// This command builds pclinetest from pclinetest.asm;
	// the resulting binary looks like it was built from pclinetest.s,
	// but we have renamed it to keep it away from the go tool.
	pclinetestBinary = os.TempDir() + "/pclinetest"
	cmd := exec.Command("sh", "-c", "go tool 6a pclinetest.asm && go tool 6l -E main -o "+pclinetestBinary+" pclinetest.6")
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		panic(err)
	}
	return true
}

func getTable(t *testing.T) *Table {
	f, tab := crack(os.Args[0], t)
	f.Close()
	return tab
}

func crack(file string, t *testing.T) (*elf.File, *Table) {
	// Open self
	f, err := elf.Open(file)
	if err != nil {
		t.Fatal(err)
	}
	return parse(file, f, t)
}

func parse(file string, f *elf.File, t *testing.T) (*elf.File, *Table) {
	symdat, err := f.Section(".gosymtab").Data()
	if err != nil {
		f.Close()
		t.Fatalf("reading %s gosymtab: %v", file, err)
	}
	pclndat, err := f.Section(".gopclntab").Data()
	if err != nil {
		f.Close()
		t.Fatalf("reading %s gopclntab: %v", file, err)
	}

	pcln := NewLineTable(pclndat, f.Section(".text").Addr)
	tab, err := NewTable(symdat, pcln)
	if err != nil {
		f.Close()
		t.Fatalf("parsing %s gosymtab: %v", file, err)
	}

	return f, tab
}

var goarch = os.Getenv("O")

func TestLineFromAline(t *testing.T) {
	if !dotest() {
		return
	}

	tab := getTable(t)

	// Find the sym package
	pkg := tab.LookupFunc("debug/gosym.TestLineFromAline").Obj
	if pkg == nil {
		t.Fatalf("nil pkg")
	}

	// Walk every absolute line and ensure that we hit every
	// source line monotonically
	lastline := make(map[string]int)
	final := -1
	for i := 0; i < 10000; i++ {
		path, line := pkg.lineFromAline(i)
		// Check for end of object
		if path == "" {
			if final == -1 {
				final = i - 1
			}
			continue
		} else if final != -1 {
			t.Fatalf("reached end of package at absolute line %d, but absolute line %d mapped to %s:%d", final, i, path, line)
		}
		// It's okay to see files multiple times (e.g., sys.a)
		if line == 1 {
			lastline[path] = 1
			continue
		}
		// Check that the is the next line in path
		ll, ok := lastline[path]
		if !ok {
			t.Errorf("file %s starts on line %d", path, line)
		} else if line != ll+1 {
			t.Errorf("expected next line of file %s to be %d, got %d", path, ll+1, line)
		}
		lastline[path] = line
	}
	if final == -1 {
		t.Errorf("never reached end of object")
	}
}

func TestLineAline(t *testing.T) {
	if !dotest() {
		return
	}

	tab := getTable(t)

	for _, o := range tab.Files {
		// A source file can appear multiple times in a
		// object.  alineFromLine will always return alines in
		// the first file, so track which lines we've seen.
		found := make(map[string]int)
		for i := 0; i < 1000; i++ {
			path, line := o.lineFromAline(i)
			if path == "" {
				break
			}

			// cgo files are full of 'Z' symbols, which we don't handle
			if len(path) > 4 && path[len(path)-4:] == ".cgo" {
				continue
			}

			if minline, ok := found[path]; path != "" && ok {
				if minline >= line {
					// We've already covered this file
					continue
				}
			}
			found[path] = line

			a, err := o.alineFromLine(path, line)
			if err != nil {
				t.Errorf("absolute line %d in object %s maps to %s:%d, but mapping that back gives error %s", i, o.Paths[0].Name, path, line, err)
			} else if a != i {
				t.Errorf("absolute line %d in object %s maps to %s:%d, which maps back to absolute line %d\n", i, o.Paths[0].Name, path, line, a)
			}
		}
	}
}

func TestPCLine(t *testing.T) {
	if !dotest() {
		return
	}

	f, tab := crack(pclinetestBinary, t)
	text := f.Section(".text")
	textdat, err := text.Data()
	if err != nil {
		t.Fatalf("reading .text: %v", err)
	}

	// Test PCToLine
	sym := tab.LookupFunc("linefrompc")
	wantLine := 0
	for pc := sym.Entry; pc < sym.End; pc++ {
		file, line, fn := tab.PCToLine(pc)
		off := pc - text.Addr // TODO(rsc): should not need off; bug in 8g
		wantLine += int(textdat[off])
		t.Logf("off is %d", off)
		if fn == nil {
			t.Errorf("failed to get line of PC %#x", pc)
		} else if !strings.HasSuffix(file, "pclinetest.s") {
			t.Errorf("expected %s (%s) at PC %#x, got %s (%s)", "pclinetest.s", sym.Name, pc, file, fn.Name)
		} else if line != wantLine || fn != sym {
			t.Errorf("expected :%d (%s) at PC %#x, got :%d (%s)", wantLine, sym.Name, pc, line, fn.Name)
		}
	}

	// Test LineToPC
	sym = tab.LookupFunc("pcfromline")
	lookupline := -1
	wantLine = 0
	off := uint64(0) // TODO(rsc): should not need off; bug in 8g
	for pc := sym.Value; pc < sym.End; pc += 2 + uint64(textdat[off]) {
		file, line, fn := tab.PCToLine(pc)
		off = pc - text.Addr
		wantLine += int(textdat[off])
		if line != wantLine {
			t.Errorf("expected line %d at PC %#x in pcfromline, got %d", wantLine, pc, line)
			off = pc + 1 - text.Addr
			continue
		}
		if lookupline == -1 {
			lookupline = line
		}
		for ; lookupline <= line; lookupline++ {
			pc2, fn2, err := tab.LineToPC(file, lookupline)
			if lookupline != line {
				// Should be nothing on this line
				if err == nil {
					t.Errorf("expected no PC at line %d, got %#x (%s)", lookupline, pc2, fn2.Name)
				}
			} else if err != nil {
				t.Errorf("failed to get PC of line %d: %s", lookupline, err)
			} else if pc != pc2 {
				t.Errorf("expected PC %#x (%s) at line %d, got PC %#x (%s)", pc, fn.Name, line, pc2, fn2.Name)
			}
		}
		off = pc + 1 - text.Addr
	}
}
<|endoftext|>


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

package types

import (
	"exec"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"
)

var gcName, gcPath string // compiler name and path

func init() {
	// find a compiler
	for _, char := range []string{"5", "6", "8"} {
		var err os.Error
		gcName = char + "g"
		gcPath, err = exec.LookPath(gcName)
		if err == nil {
			return
		}
	}
}

func compile(t *testing.T, dirname, filename string) {
	cmd, err := exec.Run(gcPath, []string{gcPath, filename}, nil, dirname, exec.DevNull, exec.Pipe, exec.MergeWithStdout)
	if err != nil {
		t.Errorf("%s %s failed: %s", gcName, filename, err)
		return
	}
	defer cmd.Close()

	msg, err := cmd.Wait(0)
	if err != nil {
		t.Errorf("%s %s failed: %s", gcName, filename, err)
		return
	}

	if !msg.Exited() || msg.ExitStatus() != 0 {
		t.Errorf("%s %s failed: exit status = %d", gcName, filename, msg.ExitStatus())
		output, _ := ioutil.ReadAll(cmd.Stdout)
		t.Log(string(output))
	}
}

func testPath(t *testing.T, path string) bool {
	_, _, err := GcImporter(path)
	if err != nil {
		t.Errorf("testPath(%s): %s", path, err)
		return false
	}
	return true
}

const maxTime = 3e9 // maximum allotted testing time in ns

func testDir(t *testing.T, dir string, endTime int64) (nimports int) {
	dirname := filepath.Join(pkgRoot, dir)
	list, err := ioutil.ReadDir(dirname)
	if err != nil {
		t.Errorf("testDir(%s): %s", dirname, err)
	}
	for _, f := range list {
		if time.Nanoseconds() >= endTime {
			t.Log("testing time used up")
			return
		}
		switch {
		case f.IsRegular():
			// try extensions
			for _, ext := range pkgExts {
				if strings.HasSuffix(f.Name, ext) {
					name := f.Name[0 : len(f.Name)-len(ext)] // remove extension
					if testPath(t, filepath.Join(dir, name)) {
						nimports++
					}
				}
			}
		case f.IsDirectory():
			nimports += testDir(t, filepath.Join(dir, f.Name), endTime)
		}
	}
	return
}

func TestGcImport(t *testing.T) {
	compile(t, "testdata", "exports.go")

	nimports := 0
	if testPath(t, "./testdata/exports") {
		nimports++
	}
	nimports += testDir(t, "", time.Nanoseconds()+maxTime) // installed packages
	t.Logf("tested %d imports", nimports)
}
<commit_msg>go/types: fix build: use the right compiler to compile test case<commit_after>// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types

import (
	"exec"
	"io/ioutil"
	"path/filepath"
	"runtime"
	"strings"
	"testing"
	"time"
)

var gcName, gcPath string // compiler name and path

func init() {
	// determine compiler
	switch runtime.GOARCH {
	case "386":
		gcName = "8g"
	case "amd64":
		gcName = "6g"
	case "arm":
		gcName = "5g"
	default:
		gcName = "unknown-GOARCH-compiler"
		gcPath = gcName
		return
	}
	gcPath, _ = exec.LookPath(gcName)
}

func compile(t *testing.T, dirname, filename string) {
	cmd, err := exec.Run(gcPath, []string{gcPath, filename}, nil, dirname, exec.DevNull, exec.Pipe, exec.MergeWithStdout)
	if err != nil {
		t.Errorf("%s %s failed: %s", gcName, filename, err)
		return
	}
	defer cmd.Close()

	msg, err := cmd.Wait(0)
	if err != nil {
		t.Errorf("%s %s failed: %s", gcName, filename, err)
		return
	}

	if !msg.Exited() || msg.ExitStatus() != 0 {
		t.Errorf("%s %s failed: exit status = %d", gcName, filename, msg.ExitStatus())
		output, _ := ioutil.ReadAll(cmd.Stdout)
		t.Log(string(output))
	}
}

func testPath(t *testing.T, path string) bool {
	_, _, err := GcImporter(path)
	if err != nil {
		t.Errorf("testPath(%s): %s", path, err)
		return false
	}
	return true
}

const maxTime = 3e9 // maximum allotted testing time in ns

func testDir(t *testing.T, dir string, endTime int64) (nimports int) {
	dirname := filepath.Join(pkgRoot, dir)
	list, err := ioutil.ReadDir(dirname)
	if err != nil {
		t.Errorf("testDir(%s): %s", dirname, err)
	}
	for _, f := range list {
		if time.Nanoseconds() >= endTime {
			t.Log("testing time used up")
			return
		}
		switch {
		case f.IsRegular():
			// try extensions
			for _, ext := range pkgExts {
				if strings.HasSuffix(f.Name, ext) {
					name := f.Name[0 : len(f.Name)-len(ext)] // remove extension
					if testPath(t, filepath.Join(dir, name)) {
						nimports++
					}
				}
			}
		case f.IsDirectory():
			nimports += testDir(t, filepath.Join(dir, f.Name), endTime)
		}
	}
	return
}

func TestGcImport(t *testing.T) {
	compile(t, "testdata", "exports.go")

	nimports := 0
	if testPath(t, "./testdata/exports") {
		nimports++
	}
	nimports += testDir(t, "", time.Nanoseconds()+maxTime) // installed packages
	t.Logf("tested %d imports", nimports)
}
<|endoftext|>


<commit_before>package pachyderm

import (
	"context"
	"errors"
	"fmt"
	"time"

	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
	pclient "github.com/pachyderm/pachyderm/src/client"
	"github.com/pachyderm/pachyderm/src/client/auth"
)

func (b *backend) loginPath() *framework.Path {
	return &framework.Path{
		Pattern: "login",
		Fields: map[string]*framework.FieldSchema{
			"username": &framework.FieldSchema{
				Type: framework.TypeString,
			},
		},
		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathAuthLogin,
		},
	}
}

func (b *backend) pathAuthLogin(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	username := d.Get("username").(string)
	if len(username) == 0 {
		return nil, logical.ErrInvalidRequest
	}

	config, err := b.Config(ctx, req.Storage)
	if err != nil {
		return nil, err
	}
	if len(config.AdminToken) == 0 {
		return nil, errors.New("plugin is missing admin_token")
	}
	if len(config.PachdAddress) == 0 {
		return nil, errors.New("plugin is missing pachd_address")
	}
	if len(config.TTL) == 0 {
		return nil, errors.New("plugin is missing ttl")
	}

	ttl, _, err := b.SanitizeTTLStr(config.TTL, DefaultTTL)
	if err != nil {
		return nil, err
	}

	userToken, err := b.generateUserCredentials(ctx, config.PachdAddress, config.AdminToken, username, ttl)
	if err != nil {
		return nil, err
	}

	// Compose the response
	return &logical.Response{
		Auth: &logical.Auth{
			InternalData: map[string]interface{}{
				"user_token": userToken,
			},
			Metadata: map[string]string{
				"user_token":    userToken,
				"pachd_address": config.PachdAddress,
			},
			LeaseOptions: logical.LeaseOptions{
				TTL:       ttl,
				Renewable: true,
			},
		},
	}, nil
}

// generateUserCredentials uses the vault plugin's Admin credentials to generate
// a new Pachyderm authentication token for 'username' (i.e. the user who is
// currently requesting a Pachyderm token from Vault).
func (b *backend) generateUserCredentials(ctx context.Context, pachdAddress string, adminToken string, username string, ttl time.Duration) (string, error) {
	// Setup a single use client w the given admin token / address
	client, err := pclient.NewFromAddress(pachdAddress)
	if err != nil {
		return "", err
	}
	client = client.WithCtx(ctx)
	client.SetAuthToken(adminToken)
	fmt.Printf("login using auth token (%v)\n", adminToken)

	resp, err := client.AuthAPIClient.GetAuthToken(client.Ctx(), &auth.GetAuthTokenRequest{
		Subject: username,
		TTL:     int64(ttl.Seconds()),
	})
	if err != nil {
		return "", err
	}

	return resp.Token, nil
}
<commit_msg>Remove debug output<commit_after>package pachyderm

import (
	"context"
	"errors"
	"time"

	"github.com/hashicorp/vault/logical"
	"github.com/hashicorp/vault/logical/framework"
	pclient "github.com/pachyderm/pachyderm/src/client"
	"github.com/pachyderm/pachyderm/src/client/auth"
)

func (b *backend) loginPath() *framework.Path {
	return &framework.Path{
		Pattern: "login",
		Fields: map[string]*framework.FieldSchema{
			"username": &framework.FieldSchema{
				Type: framework.TypeString,
			},
		},
		Callbacks: map[logical.Operation]framework.OperationFunc{
			logical.UpdateOperation: b.pathAuthLogin,
		},
	}
}

func (b *backend) pathAuthLogin(ctx context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
	username := d.Get("username").(string)
	if len(username) == 0 {
		return nil, logical.ErrInvalidRequest
	}

	config, err := b.Config(ctx, req.Storage)
	if err != nil {
		return nil, err
	}
	if len(config.AdminToken) == 0 {
		return nil, errors.New("plugin is missing admin_token")
	}
	if len(config.PachdAddress) == 0 {
		return nil, errors.New("plugin is missing pachd_address")
	}
	if len(config.TTL) == 0 {
		return nil, errors.New("plugin is missing ttl")
	}

	ttl, _, err := b.SanitizeTTLStr(config.TTL, DefaultTTL)
	if err != nil {
		return nil, err
	}

	userToken, err := b.generateUserCredentials(ctx, config.PachdAddress, config.AdminToken, username, ttl)
	if err != nil {
		return nil, err
	}

	// Compose the response
	return &logical.Response{
		Auth: &logical.Auth{
			InternalData: map[string]interface{}{
				"user_token": userToken,
			},
			Metadata: map[string]string{
				"user_token":    userToken,
				"pachd_address": config.PachdAddress,
			},
			LeaseOptions: logical.LeaseOptions{
				TTL:       ttl,
				Renewable: true,
			},
		},
	}, nil
}

// generateUserCredentials uses the vault plugin's Admin credentials to generate
// a new Pachyderm authentication token for 'username' (i.e. the user who is
// currently requesting a Pachyderm token from Vault).
func (b *backend) generateUserCredentials(ctx context.Context, pachdAddress string, adminToken string, username string, ttl time.Duration) (string, error) {
	// Setup a single use client w the given admin token / address
	client, err := pclient.NewFromAddress(pachdAddress)
	if err != nil {
		return "", err
	}
	client = client.WithCtx(ctx)
	client.SetAuthToken(adminToken)

	resp, err := client.AuthAPIClient.GetAuthToken(client.Ctx(), &auth.GetAuthTokenRequest{
		Subject: username,
		TTL:     int64(ttl.Seconds()),
	})
	if err != nil {
		return "", err
	}

	return resp.Token, nil
}
<|endoftext|>


<commit_before>/*
Collection is a container class for organizing raw line coordinate data.

Collection containers are hierarchical.  A Collection contains one or more Axis
objects. And each Axis contains one or more Line objects. So, if you only need
a single "Collection", a default is provided using:

    collection.Default().

Since collections exist to help with plotting line data, there is one
convenience function for plotting. To generate an image representing the
collection data, use:

		collection.Plot()
*/
package collection

import (
	"encoding/hex"
	"image/color"
	"io"
	"math"
	"time"

	// third party
	"github.com/stephen-soltesz/go/plotter"
)

var defaultCollection *Collection

// A Collection is the root container.
// Axes is a map, so that Axis objects can be referred to by name, see GetAxis().
type Collection struct {
	Title string
	Axes  map[string]*Axis
}

// A Collection contains one or more Axis objects.
type Axis struct {
	Name   string
	XLabel string
	YLabel string
	Lines  map[string]*Line
}

// An Axis contains one or more Line objects.
// The X and Y arrays contain coordinates of each point on the Line.
type Line struct {
	Name  string
	Style plotter.Style
	X     []float64
	Y     []float64

	// internal book keeping
	xyrange
}

type xyrange struct {
	// internal book keeping
	max_x float64
	min_x float64
	max_y float64
	min_y float64
}

func initXYrange() xyrange {
	return xyrange{math.SmallestNonzeroFloat64, math.MaxFloat64,
		math.SmallestNonzeroFloat64, math.MaxFloat64}
}

func (xy *xyrange) updateXYrange(x, y float64) {
	xy.min_x = math.Min(x, xy.min_x)
	xy.max_x = math.Max(x, xy.max_x)

	xy.min_y = math.Min(y, xy.min_y)
	xy.max_y = math.Max(y, xy.max_y)
}

func New() *Collection {
	c := &Collection{}
	c.Axes = make(map[string]*Axis)
	return c
}

func Default() *Collection {
	if defaultCollection == nil {
		defaultCollection = New()
	}
	return defaultCollection
}

// Returns the Axis associated with given name. If no Axis exists, a new Axis
// is created and associated with given name.
func (c *Collection) GetAxis(name string) *Axis {
	// TODO: make thread safe
	if axis, ok := c.Axes[name]; !ok {
		return c.AddAxis(name, "", "")
	} else {
		return axis
	}
}

func (c *Collection) AddAxis(name, xlabel, ylabel string) *Axis {
	axis := &Axis{name, xlabel, ylabel, make(map[string]*Line)}
	c.Axes[name] = axis
	return axis
}

func (ax *Axis) GetLine(name string) *Line {
	// TODO: make thread safe
	if line, ok := ax.Lines[name]; !ok {
		return ax.AddLine(name)
	} else {
		return line
	}
}

func (ax *Axis) AddLine(name string) *Line {
	line := &Line{}
	line.Name = name
	line.Style = plotter.NextStyle()
	line.xyrange = initXYrange()
	ax.Lines[name] = line
	return line
}

func (line *Line) SetColor(hexColor string) {
	if len(hexColor) > 0 && hexColor[0] == '#' {
		hexColor = hexColor[1:]
	}
	if len(hexColor) == 6 {
		rgb, err := hex.DecodeString(hexColor)
		if err != nil {
			return
		}
		r, g, b := rgb[0], rgb[1], rgb[2]
		line.Style.SymbolColor = color.RGBA{r, g, b, 255}
		line.Style.LineColor = color.RGBA{r, g, b, 255}
		line.Style.FillColor = color.RGBA{r, g, b, 255}
	}
}

// Append adds a new x,y coordinate to the end of the Line.
func (line *Line) Append(x, y float64) {
	line.X = append(line.X, x)
	line.Y = append(line.Y, y)
	line.xyrange.updateXYrange(x, y)
}

// Count returns the length of Line X and Y coordinates.
func (line *Line) Count() (int, int) {
	return len(line.X), len(line.Y)
}

func (line *Line) RangeX() (float64, float64) {
	min := line.xyrange.min_x - 0.1
	max := line.xyrange.max_x + 0.1
	return min, max
}

func (line *Line) RangeY() (float64, float64) {
	min := line.xyrange.min_y - 0.1
	max := line.xyrange.max_y + 0.1
	return min, max
}

// MaxX returns the greatest X coordinate for all Lines in this Axis.
func (ax *Axis) MaxX() float64 {
	xmax := 0.0
	if len(ax.Lines) == 0 {
		return xmax
	}
	for _, line := range ax.Lines {
		xlen, _ := line.Count()
		if xlen == 0 {
			continue
		}
		_, lmax := line.RangeX()
		xmax = math.Max(lmax, xmax)
	}
	return xmax
}

// TODO: add a 'Window' argument to specify the data view to plot.
func (c *Collection) Plot(writer io.Writer, width, height int, usetime bool) error {

	fig := plotter.NewFigure()
	for _, ax := range c.Axes {
		xmax := 0.0
		if usetime {
			// continuously update plot with most current time.
			// TODO: make this an option.
			xmax = float64(time.Now().Unix())
		} else {
			xmax = ax.MaxX()
		}
		chart := fig.AddChart(c.Title, ax.XLabel, ax.YLabel, xmax-240, xmax, usetime)
		for _, line := range ax.Lines {
			if xc, _ := line.Count(); xc > 0 {
				chart.AddData(line.Name, line.X, line.Y, line.Style)
			}
		}
	}

	return fig.Render(writer, width, height)
}
<commit_msg>render svg by default.<commit_after>/*
Collection is a container class for organizing raw line coordinate data.

Collection containers are hierarchical.  A Collection contains one or more Axis
objects. And each Axis contains one or more Line objects. So, if you only need
a single "Collection", a default is provided using:

    collection.Default().

Since collections exist to help with plotting line data, there is one
convenience function for plotting. To generate an image representing the
collection data, use:

		collection.Plot()
*/
package collection

import (
	"encoding/hex"
	"image/color"
	"io"
	"math"
	"time"

	// third party
	"github.com/stephen-soltesz/go/plotter"
)

var defaultCollection *Collection

// A Collection is the root container.
// Axes is a map, so that Axis objects can be referred to by name, see GetAxis().
type Collection struct {
	Title string
	Axes  map[string]*Axis
}

// A Collection contains one or more Axis objects.
type Axis struct {
	Name   string
	XLabel string
	YLabel string
	Lines  map[string]*Line
}

// An Axis contains one or more Line objects.
// The X and Y arrays contain coordinates of each point on the Line.
type Line struct {
	Name  string
	Style plotter.Style
	X     []float64
	Y     []float64

	// internal book keeping
	xyrange
}

type xyrange struct {
	// internal book keeping
	max_x float64
	min_x float64
	max_y float64
	min_y float64
}

func initXYrange() xyrange {
	return xyrange{math.SmallestNonzeroFloat64, math.MaxFloat64,
		math.SmallestNonzeroFloat64, math.MaxFloat64}
}

func (xy *xyrange) updateXYrange(x, y float64) {
	xy.min_x = math.Min(x, xy.min_x)
	xy.max_x = math.Max(x, xy.max_x)

	xy.min_y = math.Min(y, xy.min_y)
	xy.max_y = math.Max(y, xy.max_y)
}

func New() *Collection {
	c := &Collection{}
	c.Axes = make(map[string]*Axis)
	return c
}

func Default() *Collection {
	if defaultCollection == nil {
		defaultCollection = New()
	}
	return defaultCollection
}

// Returns the Axis associated with given name. If no Axis exists, a new Axis
// is created and associated with given name.
func (c *Collection) GetAxis(name string) *Axis {
	// TODO: make thread safe
	if axis, ok := c.Axes[name]; !ok {
		return c.AddAxis(name, "", "")
	} else {
		return axis
	}
}

func (c *Collection) AddAxis(name, xlabel, ylabel string) *Axis {
	axis := &Axis{name, xlabel, ylabel, make(map[string]*Line)}
	c.Axes[name] = axis
	return axis
}

func (ax *Axis) GetLine(name string) *Line {
	// TODO: make thread safe
	if line, ok := ax.Lines[name]; !ok {
		return ax.AddLine(name)
	} else {
		return line
	}
}

func (ax *Axis) AddLine(name string) *Line {
	line := &Line{}
	line.Name = name
	line.Style = plotter.NextStyle()
	line.xyrange = initXYrange()
	ax.Lines[name] = line
	return line
}

func (line *Line) SetColor(hexColor string) {
	if len(hexColor) > 0 && hexColor[0] == '#' {
		hexColor = hexColor[1:]
	}
	if len(hexColor) == 6 {
		rgb, err := hex.DecodeString(hexColor)
		if err != nil {
			return
		}
		r, g, b := rgb[0], rgb[1], rgb[2]
		line.Style.SymbolColor = color.RGBA{r, g, b, 255}
		line.Style.LineColor = color.RGBA{r, g, b, 255}
		line.Style.FillColor = color.RGBA{r, g, b, 255}
	}
}

// Append adds a new x,y coordinate to the end of the Line.
func (line *Line) Append(x, y float64) {
	line.X = append(line.X, x)
	line.Y = append(line.Y, y)
	line.xyrange.updateXYrange(x, y)
}

// Count returns the length of Line X and Y coordinates.
func (line *Line) Count() (int, int) {
	return len(line.X), len(line.Y)
}

func (line *Line) RangeX() (float64, float64) {
	min := line.xyrange.min_x - 0.1
	max := line.xyrange.max_x + 0.1
	return min, max
}

func (line *Line) RangeY() (float64, float64) {
	min := line.xyrange.min_y - 0.1
	max := line.xyrange.max_y + 0.1
	return min, max
}

// MaxX returns the greatest X coordinate for all Lines in this Axis.
func (ax *Axis) MaxX() float64 {
	xmax := 0.0
	if len(ax.Lines) == 0 {
		return xmax
	}
	for _, line := range ax.Lines {
		xlen, _ := line.Count()
		if xlen == 0 {
			continue
		}
		_, lmax := line.RangeX()
		xmax = math.Max(lmax, xmax)
	}
	return xmax
}

// TODO: add a 'Window' argument to specify the data view to plot.
func (c *Collection) Plot(writer io.Writer, width, height int, usetime bool) error {

	fig := plotter.NewFigure()
	for _, ax := range c.Axes {
		xmax := 0.0
		if usetime {
			// continuously update plot with most current time.
			// TODO: make this an option.
			xmax = float64(time.Now().Unix())
		} else {
			xmax = ax.MaxX()
		}
		chart := fig.AddChart(c.Title, ax.XLabel, ax.YLabel, xmax-240, xmax, usetime)
		for _, line := range ax.Lines {
			if xc, _ := line.Count(); xc > 0 {
				chart.AddData(line.Name, line.X, line.Y, line.Style)
			}
		}
	}

	return fig.RenderSVG(writer, width, height)
}
<|endoftext|>


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

package log

import (
	"fmt"
	"os"
	"time"
)

func (me *Logging) pre() {
	// Modify the log defaults,
	// all of the log objects will be synchronized to the default value.
	if isResetDefault && me.isDefaultConf {
		if !me.setPriority {
			me.SetPriority(defaultPriority)
		}
		if !me.setLayouts {
			me.SetLayouts(defaultLayout)
		}
		if !me.setOutputs {
			me.SetOutputs(defaultOutput)
		}
	}
	// The function executed before the log is printed and executed only once.
	if !me.hasSettings && me.Settings != nil {
		me.hasSettings = true
		me.Settings()
	}
}

func (me *Logging) setConsoleLogger() {
	me.console = NewLogger(os.Stderr)
	me.console.SetPriority(me.priority)
	if me.layouts > 0 {
		me.console.SetLayouts(me.layouts)
	}
	me.console.SetPrefix(me.prefix)
}

func (me *Logging) resetConsoleLogger() {
	if me.outputs&Oconsole != 0 {
		if me.console == nil {
			me.setConsoleLogger()
		}
	}
}

func (me *Logging) getDailyFileName() string {
	date := time.Now().Format("2006-01-02")
	format := "./%s/daily.%s.log"
	return fmt.Sprintf(format, defaultDir, date)
}

func (me *Logging) setDailyFileLogger() {
	me.dailyfilename = me.getDailyFileName()
	if me.isExist(me.dailyfilename) {
		f, err := os.OpenFile(me.dailyfilename, os.O_APPEND|os.O_RDWR, 0666)
		if err != nil {
			fmt.Println(err.Error())
		}
		me.dailyfile = NewLogger(f)
	} else {
		os.Mkdir(defaultDir, 0666)
		f, err := os.Create(me.dailyfilename)
		if err != nil {
			fmt.Println(err.Error())
		} else {
			date := time.Now().Format("2006/01/02 15:04:05")
			_, err = f.WriteString("[log] Print " + date + " Create file：time\r\n")
			if err != nil {
				fmt.Println(err.Error())
			}
		}
		me.dailyfile = NewLogger(f)
	}
	me.dailyfile.SetPriority(me.priority)
	if me.layouts > 0 {
		me.dailyfile.SetLayouts(me.layouts)
	}
	me.dailyfile.SetPrefix(me.prefix)
}

// Reports whether the specified file exists.
// Returns true if the file exists, false if it does not exist.
func (me *Logging) isExist(filename string) bool {
	_, err := os.Stat(filename)
	if err == nil {
		return true
	}
	return os.IsExist(err)
}

func (me *Logging) resetDailyFileLogger() {
	if me.outputs&Odailyfile != 0 {
		if me.dailyfilename != me.getDailyFileName() {
			me.setDailyFileLogger()
		}
	}
}
<commit_msg>Simplify the configuration code<commit_after>// Copyright 2014 The goyy Authors.  All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package log

import (
	"fmt"
	"os"
	"time"
)

func (me *Logging) pre() {
	// Modify the log defaults,
	// all of the log objects will be synchronized to the default value.
	if isResetDefault && me.isDefaultConf {
		if !me.setPriority {
			me.SetPriority(defaultPriority)
		}
		if !me.setLayouts {
			me.SetLayouts(defaultLayout)
		}
		if !me.setOutputs {
			me.SetOutputs(defaultOutput)
		}
	}
	// The function executed before the log is printed and executed only once.
	if !me.hasSettings && me.Settings != nil {
		me.hasSettings = true
		me.Settings()
	}
}

func (me *Logging) setConsoleLogger() {
	me.console = NewLogger(os.Stderr)
	me.console.SetPriority(me.priority)
	if me.layouts > 0 {
		me.console.SetLayouts(me.layouts)
	}
	me.console.SetPrefix(me.prefix)
}

func (me *Logging) resetConsoleLogger() {
	if me.outputs&Oconsole != 0 {
		if me.console == nil {
			me.setConsoleLogger()
		}
	}
}

func (me *Logging) getDailyFileName() string {
	date := time.Now().Format("2006-01-02")
	format := "%s/daily.%s.log"
	return fmt.Sprintf(format, defaultDir, date)
}

func (me *Logging) setDailyFileLogger() {
	me.dailyfilename = me.getDailyFileName()
	if me.isExist(me.dailyfilename) {
		f, err := os.OpenFile(me.dailyfilename, os.O_APPEND|os.O_RDWR, 0666)
		if err != nil {
			fmt.Println(err.Error())
		}
		me.dailyfile = NewLogger(f)
	} else {
		os.Mkdir(defaultDir, 0666)
		f, err := os.Create(me.dailyfilename)
		if err != nil {
			fmt.Println(err.Error())
		} else {
			date := time.Now().Format("2006/01/02 15:04:05")
			_, err = f.WriteString("[log] Print " + date + " Create file：time\r\n")
			if err != nil {
				fmt.Println(err.Error())
			}
		}
		me.dailyfile = NewLogger(f)
	}
	me.dailyfile.SetPriority(me.priority)
	if me.layouts > 0 {
		me.dailyfile.SetLayouts(me.layouts)
	}
	me.dailyfile.SetPrefix(me.prefix)
}

// Reports whether the specified file exists.
// Returns true if the file exists, false if it does not exist.
func (me *Logging) isExist(filename string) bool {
	_, err := os.Stat(filename)
	if err == nil {
		return true
	}
	return os.IsExist(err)
}

func (me *Logging) resetDailyFileLogger() {
	if me.outputs&Odailyfile != 0 {
		if me.dailyfilename != me.getDailyFileName() {
			me.setDailyFileLogger()
		}
	}
}
<|endoftext|>


<commit_before>package build

import (
	"flag"
	"fmt"
	"github.com/mitchellh/packer/packer"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"strings"
	"sync"
)

type Command byte

func (Command) Help() string {
	return strings.TrimSpace(helpText)
}

func (c Command) Run(env packer.Environment, args []string) int {
	var cfgOnly []string

	cmdFlags := flag.NewFlagSet("build", flag.ContinueOnError)
	cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
	cmdFlags.Var((*stringSliceValue)(&cfgOnly), "only", "only build the given builds by name")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) != 1 {
		cmdFlags.Usage()
		return 1
	}

	// Read the file into a byte array so that we can parse the template
	log.Printf("Reading template: %s", args[0])
	tplData, err := ioutil.ReadFile(args[0])
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to read template file: %s", err))
		return 1
	}

	// Parse the template into a machine-usable format
	log.Println("Parsing template...")
	tpl, err := packer.ParseTemplate(tplData)
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err))
		return 1
	}

	// The component finder for our builds
	components := &packer.ComponentFinder{
		Builder:     env.Builder,
		Hook:        env.Hook,
		Provisioner: env.Provisioner,
	}

	// Go through each builder and compile the builds that we care about
	buildNames := tpl.BuildNames()
	builds := make([]packer.Build, 0, len(buildNames))
	for _, buildName := range buildNames {
		if len(cfgOnly) > 0 {
			found := false
			for _, only := range cfgOnly {
				if buildName == only {
					found = true
					break
				}
			}

			if !found {
				log.Printf("Skipping build '%s' because not specified by -only.", buildName)
				continue
			}
		}

		log.Printf("Creating build: %s", buildName)
		build, err := tpl.Build(buildName, components)
		if err != nil {
			env.Ui().Error(fmt.Sprintf("Failed to create build '%s': \n\n%s", buildName, err))
			return 1
		}

		builds = append(builds, build)
	}

	// Compile all the UIs for the builds
	colors := [5]packer.UiColor{
		packer.UiColorGreen,
		packer.UiColorYellow,
		packer.UiColorBlue,
		packer.UiColorMagenta,
		packer.UiColorCyan,
	}

	buildUis := make(map[string]packer.Ui)
	for i, b := range builds {
		var ui packer.Ui

		ui = &packer.ColoredUi{
			colors[i%len(colors)],
			env.Ui(),
		}

		ui = &packer.PrefixedUi{
			fmt.Sprintf("==> %s", b.Name()),
			fmt.Sprintf("    %s", b.Name()),
			ui,
		}

		buildUis[b.Name()] = ui
		ui.Say(fmt.Sprintf("%s output will be in this color.", b.Name()))
	}

	// Prepare all the builds
	for _, b := range builds {
		log.Printf("Preparing build: %s", b.Name())
		err := b.Prepare(buildUis[b.Name()])
		if err != nil {
			env.Ui().Error(err.Error())
			return 1
		}
	}

	// Run all the builds in parallel and wait for them to complete
	var wg sync.WaitGroup
	artifacts := make(map[string]packer.Artifact)
	for _, b := range builds {
		log.Printf("Starting build run: %s", b.Name())

		// Increment the waitgroup so we wait for this item to finish properly
		wg.Add(1)

		// Run the build in a goroutine
		go func() {
			defer wg.Done()
			artifacts[b.Name()] = b.Run(buildUis[b.Name()])
		}()
	}

	// Handle signals
	var interruptWg sync.WaitGroup
	interrupted := false
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt)

	go func() {
		<-sigCh
		interruptWg.Add(1)
		defer interruptWg.Done()
		interrupted = true

		log.Println("Interrupted! Cancelling builds...")

		var wg sync.WaitGroup
		for _, b := range builds {
			wg.Add(1)

			go func() {
				defer wg.Done()

				log.Printf("Stopping build: %s", b.Name())
				b.Cancel()
			}()
		}

		wg.Wait()
	}()

	// Wait for both the builds to complete and the interrupt handler,
	// if it is interrupted.
	wg.Wait()
	interruptWg.Wait()

	if interrupted {
		env.Ui().Say("Cleanly cancelled builds after being interrupted.")
		return 1
	}

	// Output all the artifacts
	env.Ui().Say("\n==> The build completed! The artifacts created were:")
	for name, artifact := range artifacts {
		env.Ui().Say(fmt.Sprintf("--> %s:", name))

		if artifact != nil {
			env.Ui().Say(artifact.String())
		} else {
			env.Ui().Say("<nothing>")
		}
	}

	return 0
}

func (Command) Synopsis() string {
	return "build image(s) from template"
}
<commit_msg>command/build: Lexical scoping bug to get the right build<commit_after>package build

import (
	"flag"
	"fmt"
	"github.com/mitchellh/packer/packer"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"strings"
	"sync"
)

type Command byte

func (Command) Help() string {
	return strings.TrimSpace(helpText)
}

func (c Command) Run(env packer.Environment, args []string) int {
	var cfgOnly []string

	cmdFlags := flag.NewFlagSet("build", flag.ContinueOnError)
	cmdFlags.Usage = func() { env.Ui().Say(c.Help()) }
	cmdFlags.Var((*stringSliceValue)(&cfgOnly), "only", "only build the given builds by name")
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) != 1 {
		cmdFlags.Usage()
		return 1
	}

	// Read the file into a byte array so that we can parse the template
	log.Printf("Reading template: %s", args[0])
	tplData, err := ioutil.ReadFile(args[0])
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to read template file: %s", err))
		return 1
	}

	// Parse the template into a machine-usable format
	log.Println("Parsing template...")
	tpl, err := packer.ParseTemplate(tplData)
	if err != nil {
		env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err))
		return 1
	}

	// The component finder for our builds
	components := &packer.ComponentFinder{
		Builder:     env.Builder,
		Hook:        env.Hook,
		Provisioner: env.Provisioner,
	}

	// Go through each builder and compile the builds that we care about
	buildNames := tpl.BuildNames()
	builds := make([]packer.Build, 0, len(buildNames))
	for _, buildName := range buildNames {
		if len(cfgOnly) > 0 {
			found := false
			for _, only := range cfgOnly {
				if buildName == only {
					found = true
					break
				}
			}

			if !found {
				log.Printf("Skipping build '%s' because not specified by -only.", buildName)
				continue
			}
		}

		log.Printf("Creating build: %s", buildName)
		build, err := tpl.Build(buildName, components)
		if err != nil {
			env.Ui().Error(fmt.Sprintf("Failed to create build '%s': \n\n%s", buildName, err))
			return 1
		}

		builds = append(builds, build)
	}

	// Compile all the UIs for the builds
	colors := [5]packer.UiColor{
		packer.UiColorGreen,
		packer.UiColorYellow,
		packer.UiColorBlue,
		packer.UiColorMagenta,
		packer.UiColorCyan,
	}

	buildUis := make(map[string]packer.Ui)
	for i, b := range builds {
		var ui packer.Ui

		ui = &packer.ColoredUi{
			colors[i%len(colors)],
			env.Ui(),
		}

		ui = &packer.PrefixedUi{
			fmt.Sprintf("==> %s", b.Name()),
			fmt.Sprintf("    %s", b.Name()),
			ui,
		}

		buildUis[b.Name()] = ui
		ui.Say(fmt.Sprintf("%s output will be in this color.", b.Name()))
	}

	// Prepare all the builds
	for _, b := range builds {
		log.Printf("Preparing build: %s", b.Name())
		err := b.Prepare(buildUis[b.Name()])
		if err != nil {
			env.Ui().Error(err.Error())
			return 1
		}
	}

	// Run all the builds in parallel and wait for them to complete
	var wg sync.WaitGroup
	artifacts := make(map[string]packer.Artifact)
	for _, b := range builds {
		// Increment the waitgroup so we wait for this item to finish properly
		wg.Add(1)

		// Run the build in a goroutine
		go func(b packer.Build) {
			defer wg.Done()

			log.Printf("Starting build run: %s", b.Name())
			artifacts[b.Name()] = b.Run(buildUis[b.Name()])
		}(b)
	}

	// Handle signals
	var interruptWg sync.WaitGroup
	interrupted := false
	sigCh := make(chan os.Signal, 1)
	signal.Notify(sigCh, os.Interrupt)

	go func() {
		<-sigCh
		interruptWg.Add(1)
		defer interruptWg.Done()
		interrupted = true

		log.Println("Interrupted! Cancelling builds...")

		var wg sync.WaitGroup
		for _, b := range builds {
			wg.Add(1)

			go func() {
				defer wg.Done()

				log.Printf("Stopping build: %s", b.Name())
				b.Cancel()
			}()
		}

		wg.Wait()
	}()

	// Wait for both the builds to complete and the interrupt handler,
	// if it is interrupted.
	wg.Wait()
	interruptWg.Wait()

	if interrupted {
		env.Ui().Say("Cleanly cancelled builds after being interrupted.")
		return 1
	}

	// Output all the artifacts
	env.Ui().Say("\n==> The build completed! The artifacts created were:")
	for name, artifact := range artifacts {
		env.Ui().Say(fmt.Sprintf("--> %s:", name))

		if artifact != nil {
			env.Ui().Say(artifact.String())
		} else {
			env.Ui().Say("<nothing>")
		}
	}

	return 0
}

func (Command) Synopsis() string {
	return "build image(s) from template"
}
<|endoftext|>


<commit_before>package command

import (
	"github.com/mattn/go-colorable"
	"github.com/mattn/go-isatty"
	"gopkg.in/urfave/cli.v2"
	"io"
	"io/ioutil"
	"os"
)

type Option struct {
	AccessToken       string
	AccessTokenSecret string
	Zone              string
	TraceMode         bool
	Format            string
	In                io.Reader
	Out               io.Writer
	Progress          io.Writer
	Err               io.Writer
	Validated         bool
	Valid             bool
	ValidationResults []error
}

var GlobalOption = &Option{
	In:       os.Stdin,
	Out:      os.Stdout,
	Progress: os.Stderr,
	Err:      os.Stderr,
}

func init() {

	if !(isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())) {
		GlobalOption.Out = ioutil.Discard
	} else {
		GlobalOption.Out = colorable.NewColorableStdout()
	}
	if !(isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) {
		GlobalOption.Progress = ioutil.Discard
	} else {
		GlobalOption.Progress = colorable.NewColorableStderr()
	}
}

var GlobalFlags = []cli.Flag{
	&cli.StringFlag{
		Name:        "token",
		Usage:       "API Token of SakuraCloud",
		EnvVars:     []string{"SAKURACLOUD_ACCESS_TOKEN"},
		DefaultText: "none",
		Destination: &GlobalOption.AccessToken,
	},
	&cli.StringFlag{
		Name:        "secret",
		Usage:       "API Secret of SakuraCloud",
		EnvVars:     []string{"SAKURACLOUD_ACCESS_TOKEN_SECRET"},
		DefaultText: "none",
		Destination: &GlobalOption.AccessTokenSecret,
	},
	&cli.StringFlag{
		Name:        "zone",
		Usage:       "Target zone of SakuraCloud",
		EnvVars:     []string{"SAKURACLOUD_ZONE"},
		Value:       "tk1a",
		DefaultText: "tk1a",
		Destination: &GlobalOption.Zone,
	},
	&cli.BoolFlag{
		Name:        "trace",
		Usage:       "Flag of SakuraCloud debug-mode",
		EnvVars:     []string{"SAKURACLOUD_TRACE_MODE"},
		Destination: &GlobalOption.TraceMode,
		Value:       false,
		Hidden:      true,
	},
}

var allowZones = []string{"is1a", "is1b", "tk1a", "tk1v"}

func (o *Option) Validate(skipAuth bool) []error {
	var errs []error

	// token/secret
	needAuth := !skipAuth
	if needAuth {
		errs = append(errs, validateRequired("token", o.AccessToken)...)
		errs = append(errs, validateRequired("secret", o.AccessTokenSecret)...)
		errs = append(errs, validateRequired("zone", o.Zone)...)
		errs = append(errs, validateInStrValues("zone", o.Zone, allowZones...)...)
	}

	o.Validated = true
	o.Valid = len(errs) == 0
	o.ValidationResults = errs

	return errs
}
<commit_msg>Bugfix - don't use ioutil.Discard for stdout<commit_after>package command

import (
	"github.com/mattn/go-colorable"
	"github.com/mattn/go-isatty"
	"gopkg.in/urfave/cli.v2"
	"io"
	"io/ioutil"
	"os"
)

type Option struct {
	AccessToken       string
	AccessTokenSecret string
	Zone              string
	TraceMode         bool
	Format            string
	In                io.Reader
	Out               io.Writer
	Progress          io.Writer
	Err               io.Writer
	Validated         bool
	Valid             bool
	ValidationResults []error
}

var GlobalOption = &Option{
	In:       os.Stdin,
	Out:      colorable.NewColorableStdout(),
	Progress: colorable.NewColorableStderr(),
	Err:      colorable.NewColorableStderr(),
}

func init() {
	if !(isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) {
		GlobalOption.Progress = ioutil.Discard
	}
}

var GlobalFlags = []cli.Flag{
	&cli.StringFlag{
		Name:        "token",
		Usage:       "API Token of SakuraCloud",
		EnvVars:     []string{"SAKURACLOUD_ACCESS_TOKEN"},
		DefaultText: "none",
		Destination: &GlobalOption.AccessToken,
	},
	&cli.StringFlag{
		Name:        "secret",
		Usage:       "API Secret of SakuraCloud",
		EnvVars:     []string{"SAKURACLOUD_ACCESS_TOKEN_SECRET"},
		DefaultText: "none",
		Destination: &GlobalOption.AccessTokenSecret,
	},
	&cli.StringFlag{
		Name:        "zone",
		Usage:       "Target zone of SakuraCloud",
		EnvVars:     []string{"SAKURACLOUD_ZONE"},
		Value:       "tk1a",
		DefaultText: "tk1a",
		Destination: &GlobalOption.Zone,
	},
	&cli.BoolFlag{
		Name:        "trace",
		Usage:       "Flag of SakuraCloud debug-mode",
		EnvVars:     []string{"SAKURACLOUD_TRACE_MODE"},
		Destination: &GlobalOption.TraceMode,
		Value:       false,
		Hidden:      true,
	},
}

var allowZones = []string{"is1a", "is1b", "tk1a", "tk1v"}

func (o *Option) Validate(skipAuth bool) []error {
	var errs []error

	// token/secret
	needAuth := !skipAuth
	if needAuth {
		errs = append(errs, validateRequired("token", o.AccessToken)...)
		errs = append(errs, validateRequired("secret", o.AccessTokenSecret)...)
		errs = append(errs, validateRequired("zone", o.Zone)...)
		errs = append(errs, validateInStrValues("zone", o.Zone, allowZones...)...)
	}

	o.Validated = true
	o.Valid = len(errs) == 0
	o.ValidationResults = errs

	return errs
}
<|endoftext|>