<commit_before>// Copyright (c) 2017 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package wallet

import (
	"github.com/decred/dcrd/chaincfg"
	"github.com/decred/dcrd/txscript"
	"github.com/decred/dcrutil"
	"github.com/decred/dcrutil/hdkeychain"
	"github.com/decred/dcrwallet/apperrors"
	"github.com/decred/dcrwallet/wallet/txauthor"
	"github.com/decred/dcrwallet/wallet/udb"
	"github.com/decred/dcrwallet/walletdb"
)

// DefaultGapLimit is the default unused address gap limit defined by BIP0044.
const DefaultGapLimit = 20

type addressBufferError int

type addressBuffer struct {
	branchXpub *hdkeychain.ExtendedKey
	lastUsed   uint32
	cursor     uint32 // added to lastUsed to derive child index
}

type bip0044AccountData struct {
	albExternal addressBuffer
	albInternal addressBuffer
}

func (w *Wallet) nextAddress(account, branch uint32) (dcrutil.Address, error) {
	defer w.addressBuffersMu.Unlock()
	w.addressBuffersMu.Lock()
	ad, ok := w.addressBuffers[account]
	if !ok {
		const str = "account not found"
		return nil, apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
	}

	var alb *addressBuffer
	switch branch {
	case udb.ExternalBranch:
		alb = &ad.albExternal
	case udb.InternalBranch:
		alb = &ad.albInternal
	default:
		const str = "branch must be external (0) or internal (1)"
		err := apperrors.E{ErrorCode: apperrors.ErrBranch, Description: str, Err: nil}
		return nil, err
	}

	if alb.cursor >= uint32(w.gapLimit) {
		const str = "deriving additional addresses violates the unused address gap limit"
		err := apperrors.E{ErrorCode: apperrors.ErrExceedsGapLimit, Description: str, Err: nil}
		return nil, err
	}

	for {
		childIndex := alb.lastUsed + alb.cursor
		if childIndex >= hdkeychain.HardenedKeyStart {
			const str = "no more addresses can be derived for the account"
			err := apperrors.E{ErrorCode: apperrors.ErrExhaustedAccount, Description: str, Err: nil}
			return nil, err
		}
		child, err := alb.branchXpub.Child(childIndex)
		if err != nil {
			return nil, err
		}
		addr, err := child.Address(w.chainParams)
		switch err {
		case nil:
			alb.cursor++
			return addr, nil
		case hdkeychain.ErrInvalidChild:
			alb.cursor++
			continue
		default:
			return nil, err
		}
	}
}

func minUint32(a, b uint32) uint32 {
	if a < b {
		return a
	}
	return b
}

// markUsedAddress updates the database, recording that the previously looked up
// managed address has been publicly used.  After recording this usage, new
// addresses are derived and saved to the db.
func (w *Wallet) markUsedAddress(dbtx walletdb.ReadWriteTx, addr udb.ManagedAddress) error {
	ns := dbtx.ReadWriteBucket(waddrmgrNamespaceKey)
	account := addr.Account()
	err := w.Manager.MarkUsed(ns, addr.Address())
	if err != nil {
		return err
	}
	if account == udb.ImportedAddrAccount {
		return nil
	}
	props, err := w.Manager.AccountProperties(ns, account)
	if err != nil {
		return err
	}
	lastUsed := props.LastUsedExternalIndex
	branch := udb.ExternalBranch
	if addr.Internal() {
		lastUsed = props.LastUsedInternalIndex
		branch = udb.InternalBranch
	}
	return w.Manager.SyncAccountToAddrIndex(ns, account,
		minUint32(hdkeychain.HardenedKeyStart-1, lastUsed+uint32(w.gapLimit)),
		branch)
}

func (w *Wallet) watchFutureAddresses(dbtx walletdb.ReadTx) error {
	// TODO: There is room here for optimization.  Improvements could be made by
	// keeping track of all accounts that have been updated and how many more
	// addresses must be generated when marking addresses as used so only those
	// need to be updated.

	client, err := w.requireChainClient()
	if err != nil {
		return err
	}

	type children struct {
		external uint32
		internal uint32
	}
	ns := dbtx.ReadBucket(waddrmgrNamespaceKey)
	lastAccount, err := w.Manager.LastAccount(ns)
	if err != nil {
		return err
	}
	m := make(map[uint32]children, lastAccount+1)
	var lastUsedExt, lastUsedInt uint32
	for account := uint32(0); account <= lastAccount; account++ {
		for branch := udb.ExternalBranch; branch <= udb.InternalBranch; branch++ {
			props, err := w.Manager.AccountProperties(ns, account)
			if err != nil {
				return err
			}
			switch branch {
			case udb.ExternalBranch:
				lastUsedExt = props.LastUsedExternalIndex
			case udb.InternalBranch:
				lastUsedInt = props.LastUsedInternalIndex
			}
		}
		m[account] = children{lastUsedExt, lastUsedInt}
	}

	// Update the buffer's last used child if it was updated, and then update
	// the cursor to point to the same child index relative to the new last used
	// index.  Request transaction notifications for future addresses that will
	// be returned by the buffer.
	loadFilterErrs := make(chan error, len(m))
	defer w.addressBuffersMu.Unlock()
	w.addressBuffersMu.Lock()
	for account, a := range w.addressBuffers {
		storedLastUsed := m[account]
		var childExt, childInt uint32

		deriveExt := storedLastUsed.external - a.albExternal.lastUsed
		deriveInt := storedLastUsed.internal - a.albInternal.lastUsed
		if deriveExt >= 0 {
			a.albExternal.lastUsed = storedLastUsed.external
			a.albExternal.cursor -= minUint32(a.albExternal.cursor, deriveExt)
			if a.albExternal.cursor == 0 {
				// Derive the next address after the last used one
				a.albExternal.cursor = 1
			}
			childExt = a.albExternal.lastUsed + a.albExternal.cursor
		}
		if deriveInt >= 0 {
			a.albInternal.lastUsed = storedLastUsed.internal
			a.albInternal.cursor -= minUint32(a.albInternal.cursor, deriveInt)
			if a.albInternal.cursor == 0 {
				// Derive the next address after the last used one
				a.albInternal.cursor = 1
			}
			childInt = a.albInternal.lastUsed + a.albInternal.cursor
		}

		xpubBranchExt := a.albExternal.branchXpub
		xpubBranchInt := a.albInternal.branchXpub

		addrs := make([]dcrutil.Address, 0, deriveExt+deriveInt)
		for i := uint32(0); i < deriveExt; i, childExt = i+1, childExt+1 {
			// Only derive non-hardened keys.
			if childExt >= hdkeychain.HardenedKeyStart {
				break
			}
			childXpub, err := xpubBranchExt.Child(childExt)
			switch err {
			case nil:
			case hdkeychain.ErrInvalidChild:
				// Skip to the next child while still generating the same number
				// of addresses
				i--
				continue
			default:
				return err
			}
			addr, err := childXpub.Address(w.chainParams)
			if err != nil {
				return err
			}
			addrs = append(addrs, addr)
		}
		for i := uint32(0); i < deriveInt; i, childInt = i+1, childInt+1 {
			// As above but derive for the internal branch.
			if childInt >= hdkeychain.HardenedKeyStart {
				break
			}
			childXpub, err := xpubBranchInt.Child(childInt)
			switch err {
			case nil:
			case hdkeychain.ErrInvalidChild:
				i--
				continue
			default:
				return err
			}
			addr, err := childXpub.Address(w.chainParams)
			if err != nil {
				return err
			}
			addrs = append(addrs, addr)
		}

		go func() {
			loadFilterErrs <- client.LoadTxFilter(false, addrs, nil)
		}()
	}

	for i := 0; i < cap(loadFilterErrs); i++ {
		err := <-loadFilterErrs
		if err != nil {
			return err
		}
	}
	return nil
}

// NewExternalAddress returns an unused external address.
func (w *Wallet) NewExternalAddress(account uint32) (dcrutil.Address, error) {
	return w.nextAddress(account, udb.ExternalBranch)
}

// NewInternalAddress returns an unused internal address.
func (w *Wallet) NewInternalAddress(account uint32) (dcrutil.Address, error) {
	return w.nextAddress(account, udb.InternalBranch)
}

// BIP0044BranchIndexes returns the current external and internal branch child
// indexes of an account.
func (w *Wallet) BIP0044BranchIndexes(account uint32) (extChild, intChild uint32, err error) {
	defer w.addressBuffersMu.Unlock()
	w.addressBuffersMu.Lock()

	acctData, ok := w.addressBuffers[account]
	if !ok {
		const str = "account not found"
		return 0, 0, apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
	}
	extChild = acctData.albExternal.lastUsed + acctData.albExternal.cursor
	intChild = acctData.albInternal.lastUsed + acctData.albInternal.cursor
	return extChild, intChild, nil
}

// ExtendWatchedAddresses derives and watches additional addresses for an
// account branch they have not yet been derived.  This does not modify the next
// generated address for the branch.
func (w *Wallet) ExtendWatchedAddresses(account, branch, child uint32) error {
	var (
		branchXpub *hdkeychain.ExtendedKey
		lastUsed   uint32
	)
	err := walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
		defer w.addressBuffersMu.Unlock()
		w.addressBuffersMu.Lock()

		acctData, ok := w.addressBuffers[account]
		if !ok {
			const str = "account not found"
			return apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
		}
		var alb *addressBuffer
		switch branch {
		case udb.ExternalBranch:
			alb = &acctData.albInternal
		case udb.InternalBranch:
			alb = &acctData.albInternal
		default:
			const str = "branch must be external or internal"
			return apperrors.E{ErrorCode: apperrors.ErrBranch, Description: str, Err: nil}
		}

		branchXpub = alb.branchXpub
		lastUsed = alb.lastUsed

		if child < lastUsed+uint32(w.gapLimit) {
			return nil
		}
		ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
		return w.Manager.SyncAccountToAddrIndex(ns, account, child, branch)
	})
	if err != nil {
		return err
	}

	if client := w.ChainClient(); client != nil {
		gapLimit := uint32(w.gapLimit)
		lastWatched := lastUsed + gapLimit - 1
		additionalAddrs := child - lastWatched
		addrs, err := deriveChildAddresses(branchXpub, lastUsed+gapLimit,
			additionalAddrs, w.chainParams)
		if err != nil {
			return err
		}
		err = client.LoadTxFilter(false, addrs, nil)
		if err != nil {
			return err
		}
	}

	return nil
}

func (w *Wallet) changeSource(account uint32) txauthor.ChangeSource {
	return func() ([]byte, uint16, error) {
		changeAddress, err := w.changeAddress(account)
		if err != nil {
			return nil, 0, err
		}
		script, err := txscript.PayToAddrScript(changeAddress)
		return script, txscript.DefaultScriptVersion, err
	}
}

func (w *Wallet) changeAddress(account uint32) (dcrutil.Address, error) {
	// Addresses can not be generated for the default account, so as a
	// workaround, change is sent to the first account.
	//
	// Yep, our accounts are broken.
	if account == udb.ImportedAddrAccount {
		account = udb.DefaultAccountNum
	}
	return w.NewInternalAddress(account)
}

func deriveChildren(key *hdkeychain.ExtendedKey, startIndex, count uint32) ([]*hdkeychain.ExtendedKey, error) {
	children := make([]*hdkeychain.ExtendedKey, 0, count)
	for i := uint32(0); i < count; i++ {
		child, err := key.Child(i)
		if err == hdkeychain.ErrInvalidChild {
			continue
		}
		if err != nil {
			return nil, err
		}
		children = append(children, child)
	}
	return children, nil
}

func deriveChildAddresses(key *hdkeychain.ExtendedKey, startIndex, count uint32, params *chaincfg.Params) ([]dcrutil.Address, error) {
	addresses := make([]dcrutil.Address, 0, count)
	for i := uint32(0); i < count; i++ {
		child, err := key.Child(startIndex + i)
		if err == hdkeychain.ErrInvalidChild {
			continue
		}
		if err != nil {
			return nil, err
		}
		addr, err := child.Address(params)
		if err != nil {
			return nil, err
		}
		addresses = append(addresses, addr)
	}
	return addresses, nil
}

func deriveChildAddress(key *hdkeychain.ExtendedKey, child uint32, params *chaincfg.Params) (dcrutil.Address, error) {
	childKey, err := key.Child(child)
	if err != nil {
		return nil, err
	}
	return childKey.Address(params)
}

func deriveBranches(acctXpub *hdkeychain.ExtendedKey) (extKey, intKey *hdkeychain.ExtendedKey, err error) {
	extKey, err = acctXpub.Child(udb.ExternalBranch)
	if err != nil {
		return
	}
	intKey, err = acctXpub.Child(udb.InternalBranch)
	return
}
<commit_msg>Revert to old wraparound behavior.<commit_after>// Copyright (c) 2017 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package wallet

import (
	"github.com/decred/dcrd/chaincfg"
	"github.com/decred/dcrd/txscript"
	"github.com/decred/dcrutil"
	"github.com/decred/dcrutil/hdkeychain"
	"github.com/decred/dcrwallet/apperrors"
	"github.com/decred/dcrwallet/wallet/txauthor"
	"github.com/decred/dcrwallet/wallet/udb"
	"github.com/decred/dcrwallet/walletdb"
)

// DefaultGapLimit is the default unused address gap limit defined by BIP0044.
const DefaultGapLimit = 20

type addressBufferError int

type addressBuffer struct {
	branchXpub *hdkeychain.ExtendedKey
	lastUsed   uint32
	cursor     uint32 // added to lastUsed to derive child index
}

type bip0044AccountData struct {
	albExternal addressBuffer
	albInternal addressBuffer
}

func (w *Wallet) nextAddress(account, branch uint32) (dcrutil.Address, error) {
	defer w.addressBuffersMu.Unlock()
	w.addressBuffersMu.Lock()
	ad, ok := w.addressBuffers[account]
	if !ok {
		const str = "account not found"
		return nil, apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
	}

	var alb *addressBuffer
	switch branch {
	case udb.ExternalBranch:
		alb = &ad.albExternal
	case udb.InternalBranch:
		alb = &ad.albInternal
	default:
		const str = "branch must be external (0) or internal (1)"
		err := apperrors.E{ErrorCode: apperrors.ErrBranch, Description: str, Err: nil}
		return nil, err
	}

	if alb.cursor >= uint32(w.gapLimit) {
		// TODO: Ideally the user would be presented with this error and then
		// given the choice to either violate the gap limit and continue
		// deriving more addresses, or to wrap around to a previously generated
		// address.  Older wallet versions used wraparound without user consent,
		// so this behavior was kept.
		//
		//const str = "deriving additional addresses violates the unused address gap limit"
		//err := apperrors.E{ErrorCode: apperrors.ErrExceedsGapLimit, Description: str, Err: nil}
		//return nil, err
		alb.cursor = 1
	}

	for {
		childIndex := alb.lastUsed + alb.cursor
		if childIndex >= hdkeychain.HardenedKeyStart {
			const str = "no more addresses can be derived for the account"
			err := apperrors.E{ErrorCode: apperrors.ErrExhaustedAccount, Description: str, Err: nil}
			return nil, err
		}
		child, err := alb.branchXpub.Child(childIndex)
		if err != nil {
			return nil, err
		}
		addr, err := child.Address(w.chainParams)
		switch err {
		case nil:
			alb.cursor++
			return addr, nil
		case hdkeychain.ErrInvalidChild:
			alb.cursor++
			continue
		default:
			return nil, err
		}
	}
}

func minUint32(a, b uint32) uint32 {
	if a < b {
		return a
	}
	return b
}

// markUsedAddress updates the database, recording that the previously looked up
// managed address has been publicly used.  After recording this usage, new
// addresses are derived and saved to the db.
func (w *Wallet) markUsedAddress(dbtx walletdb.ReadWriteTx, addr udb.ManagedAddress) error {
	ns := dbtx.ReadWriteBucket(waddrmgrNamespaceKey)
	account := addr.Account()
	err := w.Manager.MarkUsed(ns, addr.Address())
	if err != nil {
		return err
	}
	if account == udb.ImportedAddrAccount {
		return nil
	}
	props, err := w.Manager.AccountProperties(ns, account)
	if err != nil {
		return err
	}
	lastUsed := props.LastUsedExternalIndex
	branch := udb.ExternalBranch
	if addr.Internal() {
		lastUsed = props.LastUsedInternalIndex
		branch = udb.InternalBranch
	}
	return w.Manager.SyncAccountToAddrIndex(ns, account,
		minUint32(hdkeychain.HardenedKeyStart-1, lastUsed+uint32(w.gapLimit)),
		branch)
}

func (w *Wallet) watchFutureAddresses(dbtx walletdb.ReadTx) error {
	// TODO: There is room here for optimization.  Improvements could be made by
	// keeping track of all accounts that have been updated and how many more
	// addresses must be generated when marking addresses as used so only those
	// need to be updated.

	client, err := w.requireChainClient()
	if err != nil {
		return err
	}

	type children struct {
		external uint32
		internal uint32
	}
	ns := dbtx.ReadBucket(waddrmgrNamespaceKey)
	lastAccount, err := w.Manager.LastAccount(ns)
	if err != nil {
		return err
	}
	m := make(map[uint32]children, lastAccount+1)
	var lastUsedExt, lastUsedInt uint32
	for account := uint32(0); account <= lastAccount; account++ {
		for branch := udb.ExternalBranch; branch <= udb.InternalBranch; branch++ {
			props, err := w.Manager.AccountProperties(ns, account)
			if err != nil {
				return err
			}
			switch branch {
			case udb.ExternalBranch:
				lastUsedExt = props.LastUsedExternalIndex
			case udb.InternalBranch:
				lastUsedInt = props.LastUsedInternalIndex
			}
		}
		m[account] = children{lastUsedExt, lastUsedInt}
	}

	// Update the buffer's last used child if it was updated, and then update
	// the cursor to point to the same child index relative to the new last used
	// index.  Request transaction notifications for future addresses that will
	// be returned by the buffer.
	loadFilterErrs := make(chan error, len(m))
	defer w.addressBuffersMu.Unlock()
	w.addressBuffersMu.Lock()
	for account, a := range w.addressBuffers {
		storedLastUsed := m[account]
		var childExt, childInt uint32

		deriveExt := storedLastUsed.external - a.albExternal.lastUsed
		deriveInt := storedLastUsed.internal - a.albInternal.lastUsed
		if deriveExt >= 0 {
			a.albExternal.lastUsed = storedLastUsed.external
			a.albExternal.cursor -= minUint32(a.albExternal.cursor, deriveExt)
			if a.albExternal.cursor == 0 {
				// Derive the next address after the last used one
				a.albExternal.cursor = 1
			}
			childExt = a.albExternal.lastUsed + a.albExternal.cursor
		}
		if deriveInt >= 0 {
			a.albInternal.lastUsed = storedLastUsed.internal
			a.albInternal.cursor -= minUint32(a.albInternal.cursor, deriveInt)
			if a.albInternal.cursor == 0 {
				// Derive the next address after the last used one
				a.albInternal.cursor = 1
			}
			childInt = a.albInternal.lastUsed + a.albInternal.cursor
		}

		xpubBranchExt := a.albExternal.branchXpub
		xpubBranchInt := a.albInternal.branchXpub

		addrs := make([]dcrutil.Address, 0, deriveExt+deriveInt)
		for i := uint32(0); i < deriveExt; i, childExt = i+1, childExt+1 {
			// Only derive non-hardened keys.
			if childExt >= hdkeychain.HardenedKeyStart {
				break
			}
			childXpub, err := xpubBranchExt.Child(childExt)
			switch err {
			case nil:
			case hdkeychain.ErrInvalidChild:
				// Skip to the next child while still generating the same number
				// of addresses
				i--
				continue
			default:
				return err
			}
			addr, err := childXpub.Address(w.chainParams)
			if err != nil {
				return err
			}
			addrs = append(addrs, addr)
		}
		for i := uint32(0); i < deriveInt; i, childInt = i+1, childInt+1 {
			// As above but derive for the internal branch.
			if childInt >= hdkeychain.HardenedKeyStart {
				break
			}
			childXpub, err := xpubBranchInt.Child(childInt)
			switch err {
			case nil:
			case hdkeychain.ErrInvalidChild:
				i--
				continue
			default:
				return err
			}
			addr, err := childXpub.Address(w.chainParams)
			if err != nil {
				return err
			}
			addrs = append(addrs, addr)
		}

		go func() {
			loadFilterErrs <- client.LoadTxFilter(false, addrs, nil)
		}()
	}

	for i := 0; i < cap(loadFilterErrs); i++ {
		err := <-loadFilterErrs
		if err != nil {
			return err
		}
	}
	return nil
}

// NewExternalAddress returns an unused external address.
func (w *Wallet) NewExternalAddress(account uint32) (dcrutil.Address, error) {
	return w.nextAddress(account, udb.ExternalBranch)
}

// NewInternalAddress returns an unused internal address.
func (w *Wallet) NewInternalAddress(account uint32) (dcrutil.Address, error) {
	return w.nextAddress(account, udb.InternalBranch)
}

// BIP0044BranchIndexes returns the current external and internal branch child
// indexes of an account.
func (w *Wallet) BIP0044BranchIndexes(account uint32) (extChild, intChild uint32, err error) {
	defer w.addressBuffersMu.Unlock()
	w.addressBuffersMu.Lock()

	acctData, ok := w.addressBuffers[account]
	if !ok {
		const str = "account not found"
		return 0, 0, apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
	}
	extChild = acctData.albExternal.lastUsed + acctData.albExternal.cursor
	intChild = acctData.albInternal.lastUsed + acctData.albInternal.cursor
	return extChild, intChild, nil
}

// ExtendWatchedAddresses derives and watches additional addresses for an
// account branch they have not yet been derived.  This does not modify the next
// generated address for the branch.
func (w *Wallet) ExtendWatchedAddresses(account, branch, child uint32) error {
	var (
		branchXpub *hdkeychain.ExtendedKey
		lastUsed   uint32
	)
	err := walletdb.Update(w.db, func(tx walletdb.ReadWriteTx) error {
		defer w.addressBuffersMu.Unlock()
		w.addressBuffersMu.Lock()

		acctData, ok := w.addressBuffers[account]
		if !ok {
			const str = "account not found"
			return apperrors.E{ErrorCode: apperrors.ErrAccountNotFound, Description: str, Err: nil}
		}
		var alb *addressBuffer
		switch branch {
		case udb.ExternalBranch:
			alb = &acctData.albInternal
		case udb.InternalBranch:
			alb = &acctData.albInternal
		default:
			const str = "branch must be external or internal"
			return apperrors.E{ErrorCode: apperrors.ErrBranch, Description: str, Err: nil}
		}

		branchXpub = alb.branchXpub
		lastUsed = alb.lastUsed

		if child < lastUsed+uint32(w.gapLimit) {
			return nil
		}
		ns := tx.ReadWriteBucket(waddrmgrNamespaceKey)
		return w.Manager.SyncAccountToAddrIndex(ns, account, child, branch)
	})
	if err != nil {
		return err
	}

	if client := w.ChainClient(); client != nil {
		gapLimit := uint32(w.gapLimit)
		lastWatched := lastUsed + gapLimit - 1
		additionalAddrs := child - lastWatched
		addrs, err := deriveChildAddresses(branchXpub, lastUsed+gapLimit,
			additionalAddrs, w.chainParams)
		if err != nil {
			return err
		}
		err = client.LoadTxFilter(false, addrs, nil)
		if err != nil {
			return err
		}
	}

	return nil
}

func (w *Wallet) changeSource(account uint32) txauthor.ChangeSource {
	return func() ([]byte, uint16, error) {
		changeAddress, err := w.changeAddress(account)
		if err != nil {
			return nil, 0, err
		}
		script, err := txscript.PayToAddrScript(changeAddress)
		return script, txscript.DefaultScriptVersion, err
	}
}

func (w *Wallet) changeAddress(account uint32) (dcrutil.Address, error) {
	// Addresses can not be generated for the default account, so as a
	// workaround, change is sent to the first account.
	//
	// Yep, our accounts are broken.
	if account == udb.ImportedAddrAccount {
		account = udb.DefaultAccountNum
	}
	return w.NewInternalAddress(account)
}

func deriveChildren(key *hdkeychain.ExtendedKey, startIndex, count uint32) ([]*hdkeychain.ExtendedKey, error) {
	children := make([]*hdkeychain.ExtendedKey, 0, count)
	for i := uint32(0); i < count; i++ {
		child, err := key.Child(i)
		if err == hdkeychain.ErrInvalidChild {
			continue
		}
		if err != nil {
			return nil, err
		}
		children = append(children, child)
	}
	return children, nil
}

func deriveChildAddresses(key *hdkeychain.ExtendedKey, startIndex, count uint32, params *chaincfg.Params) ([]dcrutil.Address, error) {
	addresses := make([]dcrutil.Address, 0, count)
	for i := uint32(0); i < count; i++ {
		child, err := key.Child(startIndex + i)
		if err == hdkeychain.ErrInvalidChild {
			continue
		}
		if err != nil {
			return nil, err
		}
		addr, err := child.Address(params)
		if err != nil {
			return nil, err
		}
		addresses = append(addresses, addr)
	}
	return addresses, nil
}

func deriveChildAddress(key *hdkeychain.ExtendedKey, child uint32, params *chaincfg.Params) (dcrutil.Address, error) {
	childKey, err := key.Child(child)
	if err != nil {
		return nil, err
	}
	return childKey.Address(params)
}

func deriveBranches(acctXpub *hdkeychain.ExtendedKey) (extKey, intKey *hdkeychain.ExtendedKey, err error) {
	extKey, err = acctXpub.Child(udb.ExternalBranch)
	if err != nil {
		return
	}
	intKey, err = acctXpub.Child(udb.InternalBranch)
	return
}
<|endoftext|>


<commit_before>package cpf

import (
	"errors"
	"fmt"
	"strconv"
)

func Valid(digits interface{}) bool {
	ret, _ := Check(digits)
	return ret
}

func Check(digits interface{}) (bool, error) {
	cpf, err := fixType(digits)
	if err != nil {
		return false, err
	}

	if len(cpf) != 11 {
		return false, errors.New("Length exceeded")
	}

	if fmt.Sprintf("%v", cpf) == fmt.Sprintf("%v", []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0}) {
		return false, errors.New("Invalid value")
	}

	return !checkEqual(cpf) && checkEach(cpf, 9) && checkEach(cpf, 10), nil
}

func fixType(digits interface{}) ([]int, error) {
	switch v := digits.(type) {
	case string:
		return fixType([]byte(v))
	case []byte:
		var slice = []int{}
		for i, _ := range v {
			fix, _ := strconv.Atoi(string(v[i]))
			slice = append(slice, fix)
		}
		return fixType(slice)
	case []int:
		return v, nil
	default:
		return nil, errors.New("Type not supported")
	}
}

func checkEqual(cpf []int) (res bool) {
	var (
		i int
		j = 1
	)

	for ; i < len(cpf); i++ {
		if i == len(cpf)-1 {
			j = 0
		}

		if res || i == 0 {
			res = cpf[i] == cpf[i+j]
		}
	}

	return
}

func checkEach(cpf []int, n int) bool {
	var (
		i     int
		sum   int
		final int
	)

	for ; i < n; i++ {
		sum += cpf[i] * (n + 1 - i)
	}

	final = sum % 11
	if final < 2 {
		final = 0
	} else {
		final = 11 - final
	}

	return final == cpf[n]
}
<commit_msg>black list verification and errors fix<commit_after>package cpf

import (
	"errors"
	"strconv"
	"strings"
)

func Valid(digits interface{}) bool {
	ret, _ := Check(digits)
	return ret
}

func Check(digits interface{}) (bool, error) {
	cpf, err := fixType(digits)
	if err != nil {
		return false, err
	}
	return check(cpf)
}

func check(cpf []int) (bool, error) {
	if len(cpf) != 11 {
		return false, errors.New("Invalid length")
	}

	var (
		digits []byte
		i      int
	)

	for ; i < len(cpf); i++ {
		digits = strconv.AppendInt(digits, int64(cpf[i]), 10)
	}

	if blackListed(digits) || !checkEach(cpf, 9) || !checkEach(cpf, 10) {
		return false, errors.New("Invalid value")
	}

	return true, nil
}

func fixType(digits interface{}) ([]int, error) {
	switch v := digits.(type) {
	case string:
		return fixType([]byte(v))
	case []byte:
		var slice = []int{}
		for i, _ := range v {
			fix, _ := strconv.Atoi(string(v[i]))
			slice = append(slice, fix)
		}
		return fixType(slice)
	case []int:
		return v, nil
	default:
		return nil, errors.New("Type not supported")
	}
}

var blackList = []string{"123456789", "0000",
	"1111", "2222", "3333", "4444", "5555",
	"6666", "7777", "8888", "9999"}

func blackListed(cpf []byte) (res bool) {
	for i := 0; i < len(blackList); i++ {
		if strings.Contains(string(cpf), blackList[i]) {
			res = true
			break
		}
	}
	return
}

func checkEach(cpf []int, n int) bool {
	var (
		i     int
		sum   int
		final int
	)

	for ; i < n; i++ {
		sum += cpf[i] * (n + 1 - i)
	}

	final = sum % 11
	if final < 2 {
		final = 0
	} else {
		final = 11 - final
	}

	return final == cpf[n]
}
<|endoftext|>


<commit_before>package main

import (
    "fmt"
)

const (
    FLAG_C = uint8(4)
    FLAG_H = uint8(5)
    FLAG_N = uint8(6)
    FLAG_Z = uint8(7)
)

type Cpu struct {
    aReg, bReg, cReg, dReg, eReg, fReg, hReg, lReg uint8
    spReg, pcReg uint16
    ram *Ram
}

func (cpu *Cpu) Init(ram *Ram) {
    cpu.spReg = 0xFFFE
    cpu.pcReg = 0x0100
    cpu.ram = ram
}

func (cpu *Cpu) GetFlag(flag uint8) (result bool) {
    if (cpu.fReg & (1 << flag) == 1) {
        result = true
    } else {
        result = false
    }

    return
}

func (cpu *Cpu) SetFlag(flag uint8, set bool) {
    if (set) {
        cpu.fReg |= 1 << flag
    } else {
        cpu.fReg &^= 1 << flag
    }
}

func (cpu *Cpu) AND_A(val byte) {
    cpu.aReg &= val

    if (cpu.aReg == 0) {
        cpu.SetFlag(FLAG_Z, true)
    } else {
        cpu.SetFlag(FLAG_Z, false)
    }

    cpu.SetFlag(FLAG_N, false)
    cpu.SetFlag(FLAG_H, true)
    cpu.SetFlag(FLAG_C, false)
}

func (cpu *Cpu) OR_A(val byte) {
    cpu.aReg |= val

    if (cpu.aReg == 0) {
        cpu.SetFlag(FLAG_Z, true)
    } else {
        cpu.SetFlag(FLAG_Z, false)
    }

    cpu.SetFlag(FLAG_N, false)
    cpu.SetFlag(FLAG_H, false)
    cpu.SetFlag(FLAG_C, false)
}

func (cpu *Cpu) XOR_A(val byte) {
    cpu.aReg ^= val

    if (cpu.aReg == 0) {
        cpu.SetFlag(FLAG_Z, true)
    } else {
        cpu.SetFlag(FLAG_Z, false)
    }

    cpu.SetFlag(FLAG_N, false)
    cpu.SetFlag(FLAG_H, false)
    cpu.SetFlag(FLAG_C, false)
}

func (cpu *Cpu) Step() (cycleCount int) {
    opCode := cpu.ram.Read(cpu.pcReg)
    cpu.pcReg++
    fmt.Printf("OP: 0x%.2X\n", opCode)

    switch opCode {
        // START 3.3.3.5 AND n
        case 0xA7:
            cycleCount = 4
            cpu.AND_A(cpu.aReg)

        case 0xA0:
            cycleCount = 4
            cpu.AND_A(cpu.bReg)

        case 0xA1:
            cycleCount = 4
            cpu.AND_A(cpu.cReg)

        case 0xA2:
            cycleCount = 4
            cpu.AND_A(cpu.dReg)

        case 0xA3:
            cycleCount = 4
            cpu.AND_A(cpu.eReg)

        case 0xA4:
            cycleCount = 4
            cpu.AND_A(cpu.hReg)

        case 0xA5:
            cycleCount = 4
            cpu.AND_A(cpu.lReg)
        // END 3.3.3.5 AND n

        // START 3.3.3.6 OR n
        case 0xB7:
            cycleCount = 4
            cpu.OR_A(cpu.aReg)

        case 0xB0:
            cycleCount = 4
            cpu.OR_A(cpu.bReg)

        case 0xB1:
            cycleCount = 4
            cpu.OR_A(cpu.cReg)

        case 0xB2:
            cycleCount = 4
            cpu.OR_A(cpu.dReg)

        case 0xB3:
            cycleCount = 4
            cpu.OR_A(cpu.eReg)

        case 0xB4:
            cycleCount = 4
            cpu.OR_A(cpu.hReg)

        case 0xB5:
            cycleCount = 4
            cpu.OR_A(cpu.lReg)
        // END 3.3.3.6 OR n

        // START 3.3.3.7 XOR n
        case 0xAF:
            cycleCount = 4
            cpu.XOR_A(cpu.aReg)

        case 0xA8:
            cycleCount = 4
            cpu.XOR_A(cpu.bReg)

        case 0xA9:
            cycleCount = 4
            cpu.XOR_A(cpu.cReg)

        case 0xAA:
            cycleCount = 4
            cpu.XOR_A(cpu.dReg)

        case 0xAB:
            cycleCount = 4
            cpu.XOR_A(cpu.eReg)

        case 0xAC:
            cycleCount = 4
            cpu.XOR_A(cpu.hReg)

        case 0xAD:
            cycleCount = 4
            cpu.XOR_A(cpu.lReg)
        // END 3.3.3.7 XOR n

        // START 3.3.5.3 CPL
        case 0x2F:
            cycleCount = 4
            cpu.aReg = ^cpu.aReg
            cpu.SetFlag(FLAG_N, true)
            cpu.SetFlag(FLAG_H, true)
        // END 3.3.5.3 CPL

        // START 3.3.5.4 CCF
        case 0x3F:
            cycleCount = 4
            cpu.SetFlag(FLAG_N, false)
            cpu.SetFlag(FLAG_H, false)
            cpu.SetFlag(FLAG_C, !cpu.GetFlag(FLAG_C))
        // END 3.3.5.4 CCF

        // START 3.3.5.5 SCF
        case 0x37:
            cycleCount = 4
            cpu.SetFlag(FLAG_N, false)
            cpu.SetFlag(FLAG_H, false)
            cpu.SetFlag(FLAG_C, true)
        // END 3.3.5.5 SCF

        // START 3.3.5.6 NOP
        case 0x00:
            cycleCount = 4
        // END 3.3.5.6 NOP

        // START 3.3.8.1 JP nn
        case 0xC3:
            cycleCount = 16
            least := cpu.ram.Read(cpu.pcReg)
            cpu.pcReg++
            most := cpu.ram.Read(cpu.pcReg)
            cpu.pcReg = bytesToUint16(least, most)
        // END 3.3.8.1 JP nn

        default:
            cycleCount = 0
            fmt.Printf("Unknown OP: 0x%.2X\n", opCode)
    }

    return
}

func bytesToUint16(least byte, most byte) (uint16) {
    return uint16(most)<<8 + uint16(least)
}
<commit_msg>opCodeCycles table<commit_after>package main

import (
    "fmt"
)

const (
    FLAG_C = uint8(4)
    FLAG_H = uint8(5)
    FLAG_N = uint8(6)
    FLAG_Z = uint8(7)
)

var (
    opCodeCycles map[byte]int
)

type Cpu struct {
    aReg, bReg, cReg, dReg, eReg, fReg, hReg, lReg uint8
    spReg, pcReg uint16
    ram *Ram
}

func (cpu *Cpu) Init(ram *Ram) {
    cpu.spReg = 0xFFFE
    cpu.pcReg = 0x0100
    cpu.ram = ram

    opCodeCycles = map[byte]int {
        0xA7: 4,
        0xA0: 4,
        0xA1: 4,
        0xA2: 4,
        0xA3: 4,
        0xA4: 4,
        0xA5: 4,
        0xB7: 4,
        0xB0: 4,
        0xB1: 4,
        0xB2: 4,
        0xB3: 4,
        0xB4: 4,
        0xB5: 4,
        0xAF: 4,
        0xA8: 4,
        0xA9: 4,
        0xAA: 4,
        0xAB: 4,
        0xAC: 4,
        0xAD: 4,
        0x2F: 4,
        0x3F: 4,
        0x37: 4,
        0x00: 4,
        0xC3: 16,
    }
}

func (cpu *Cpu) GetFlag(flag uint8) (result bool) {
    if (cpu.fReg & (1 << flag) == 1) {
        result = true
    } else {
        result = false
    }

    return
}

func (cpu *Cpu) SetFlag(flag uint8, set bool) {
    if (set) {
        cpu.fReg |= 1 << flag
    } else {
        cpu.fReg &^= 1 << flag
    }
}

func (cpu *Cpu) AND_A(val byte) {
    cpu.aReg &= val

    if (cpu.aReg == 0) {
        cpu.SetFlag(FLAG_Z, true)
    } else {
        cpu.SetFlag(FLAG_Z, false)
    }

    cpu.SetFlag(FLAG_N, false)
    cpu.SetFlag(FLAG_H, true)
    cpu.SetFlag(FLAG_C, false)
}

func (cpu *Cpu) OR_A(val byte) {
    cpu.aReg |= val

    if (cpu.aReg == 0) {
        cpu.SetFlag(FLAG_Z, true)
    } else {
        cpu.SetFlag(FLAG_Z, false)
    }

    cpu.SetFlag(FLAG_N, false)
    cpu.SetFlag(FLAG_H, false)
    cpu.SetFlag(FLAG_C, false)
}

func (cpu *Cpu) XOR_A(val byte) {
    cpu.aReg ^= val

    if (cpu.aReg == 0) {
        cpu.SetFlag(FLAG_Z, true)
    } else {
        cpu.SetFlag(FLAG_Z, false)
    }

    cpu.SetFlag(FLAG_N, false)
    cpu.SetFlag(FLAG_H, false)
    cpu.SetFlag(FLAG_C, false)
}

func (cpu *Cpu) Step() (cycleCount int) {
    opCode := cpu.ram.Read(cpu.pcReg)
    cpu.pcReg++
    fmt.Printf("OP: 0x%.2X\n", opCode)

    switch opCode {
        // START 3.3.3.5 AND n
        case 0xA7:
            cpu.AND_A(cpu.aReg)

        case 0xA0:
            cpu.AND_A(cpu.bReg)

        case 0xA1:
            cpu.AND_A(cpu.cReg)

        case 0xA2:
            cpu.AND_A(cpu.dReg)

        case 0xA3:
            cpu.AND_A(cpu.eReg)

        case 0xA4:
            cpu.AND_A(cpu.hReg)

        case 0xA5:
            cpu.AND_A(cpu.lReg)
        // END 3.3.3.5 AND n

        // START 3.3.3.6 OR n
        case 0xB7:
            cpu.OR_A(cpu.aReg)

        case 0xB0:
            cpu.OR_A(cpu.bReg)

        case 0xB1:
            cpu.OR_A(cpu.cReg)

        case 0xB2:
            cpu.OR_A(cpu.dReg)

        case 0xB3:
            cpu.OR_A(cpu.eReg)

        case 0xB4:
            cpu.OR_A(cpu.hReg)

        case 0xB5:
            cpu.OR_A(cpu.lReg)
        // END 3.3.3.6 OR n

        // START 3.3.3.7 XOR n
        case 0xAF:
            cpu.XOR_A(cpu.aReg)

        case 0xA8:
            cpu.XOR_A(cpu.bReg)

        case 0xA9:
            cpu.XOR_A(cpu.cReg)

        case 0xAA:
            cpu.XOR_A(cpu.dReg)

        case 0xAB:
            cpu.XOR_A(cpu.eReg)

        case 0xAC:
            cpu.XOR_A(cpu.hReg)

        case 0xAD:
            cpu.XOR_A(cpu.lReg)
        // END 3.3.3.7 XOR n

        // START 3.3.5.3 CPL
        case 0x2F:
            cpu.aReg = ^cpu.aReg
            cpu.SetFlag(FLAG_N, true)
            cpu.SetFlag(FLAG_H, true)
        // END 3.3.5.3 CPL

        // START 3.3.5.4 CCF
        case 0x3F:
            cpu.SetFlag(FLAG_N, false)
            cpu.SetFlag(FLAG_H, false)
            cpu.SetFlag(FLAG_C, !cpu.GetFlag(FLAG_C))
        // END 3.3.5.4 CCF

        // START 3.3.5.5 SCF
        case 0x37:
            cpu.SetFlag(FLAG_N, false)
            cpu.SetFlag(FLAG_H, false)
            cpu.SetFlag(FLAG_C, true)
        // END 3.3.5.5 SCF

        // START 3.3.5.6 NOP
        case 0x00:
        // END 3.3.5.6 NOP

        // START 3.3.8.1 JP nn
        case 0xC3:
            least := cpu.ram.Read(cpu.pcReg)
            cpu.pcReg++
            most := cpu.ram.Read(cpu.pcReg)
            cpu.pcReg = bytesToUint16(least, most)
        // END 3.3.8.1 JP nn

        default:
            fmt.Printf("Unknown OP: 0x%.2X\n", opCode)
    }

    cycleCount = opCodeCycles[opCode]

    return
}

func bytesToUint16(least byte, most byte) (uint16) {
    return uint16(most)<<8 + uint16(least)
}
<|endoftext|>


<commit_before>// This package implements a provisioner for Packer that executes
// shell scripts within the remote machine.
package shell

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"
)

const DefaultRemotePath = "/tmp/script.sh"

type config struct {
	common.PackerConfig `mapstructure:",squash"`

	// If true, the script contains binary and line endings will not be
	// converted from Windows to Unix-style.
	Binary bool

	// An inline script to execute. Multiple strings are all executed
	// in the context of a single shell.
	Inline []string

	// The shebang value used when running inline scripts.
	InlineShebang string `mapstructure:"inline_shebang"`

	// The local path of the shell script to upload and execute.
	Script string

	// An array of multiple scripts to run.
	Scripts []string

	// An array of environment variables that will be injected before
	// your command(s) are executed.
	Vars []string `mapstructure:"environment_vars"`

	// The remote path where the local shell script will be uploaded to.
	// This should be set to a writable file that is in a pre-existing directory.
	RemotePath string `mapstructure:"remote_path"`

	// The command used to execute the script. The '{{ .Path }}' variable
	// should be used to specify where the script goes, {{ .Vars }}
	// can be used to inject the environment_vars into the environment.
	ExecuteCommand string `mapstructure:"execute_command"`

	// The timeout for retrying to start the process. Until this timeout
	// is reached, if the provisioner can't start a process, it retries.
	// This can be set high to allow for reboots.
	RawStartRetryTimeout string `mapstructure:"start_retry_timeout"`

	startRetryTimeout time.Duration
	tpl               *packer.ConfigTemplate
}

type Provisioner struct {
	config config
}

type ExecuteCommandTemplate struct {
	Vars string
	Path string
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	p.config.tpl.UserVars = p.config.PackerUserVars

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	if p.config.ExecuteCommand == "" {
		p.config.ExecuteCommand = "chmod +x {{.Path}}; {{.Vars}} {{.Path}}"
	}

	if p.config.Inline != nil && len(p.config.Inline) == 0 {
		p.config.Inline = nil
	}

	if p.config.InlineShebang == "" {
		p.config.InlineShebang = "/bin/sh"
	}

	if p.config.RawStartRetryTimeout == "" {
		p.config.RawStartRetryTimeout = "5m"
	}

	if p.config.RemotePath == "" {
		p.config.RemotePath = DefaultRemotePath
	}

	if p.config.Scripts == nil {
		p.config.Scripts = make([]string, 0)
	}

	if p.config.Vars == nil {
		p.config.Vars = make([]string, 0)
	}

	if p.config.Script != "" && len(p.config.Scripts) > 0 {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Only one of script or scripts can be specified."))
	}

	if p.config.Script != "" {
		p.config.Scripts = []string{p.config.Script}
	}

	templates := map[string]*string{
		"inline_shebang":      &p.config.InlineShebang,
		"script":              &p.config.Script,
		"start_retry_timeout": &p.config.RawStartRetryTimeout,
		"remote_path":         &p.config.RemotePath,
	}

	for n, ptr := range templates {
		var err error
		*ptr, err = p.config.tpl.Process(*ptr, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing %s: %s", n, err))
		}
	}

	sliceTemplates := map[string][]string{
		"inline":           p.config.Inline,
		"scripts":          p.config.Scripts,
		"environment_vars": p.config.Vars,
	}

	for n, slice := range sliceTemplates {
		for i, elem := range slice {
			var err error
			slice[i], err = p.config.tpl.Process(elem, nil)
			if err != nil {
				errs = packer.MultiErrorAppend(
					errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err))
			}
		}
	}

	if len(p.config.Scripts) == 0 && p.config.Inline == nil {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Either a script file or inline script must be specified."))
	} else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Only a script file or an inline script can be specified, not both."))
	}

	for _, path := range p.config.Scripts {
		if _, err := os.Stat(path); err != nil {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("Bad script '%s': %s", path, err))
		}
	}

	// Do a check for bad environment variables, such as '=foo', 'foobar'
	for idx, kv := range p.config.Vars {
		vs := strings.SplitN(kv, "=", 2)
		if len(vs) != 2 || vs[0] == "" {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
		} else {
			// Single quote env var values
			p.config.Vars[idx] = fmt.Sprintf("%s='%s'", vs[0], vs[1])
		}
	}

	if p.config.RawStartRetryTimeout != "" {
		p.config.startRetryTimeout, err = time.ParseDuration(p.config.RawStartRetryTimeout)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Failed parsing start_retry_timeout: %s", err))
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	scripts := make([]string, len(p.config.Scripts))
	copy(scripts, p.config.Scripts)

	// If we have an inline script, then turn that into a temporary
	// shell script and use that.
	if p.config.Inline != nil {
		tf, err := ioutil.TempFile("", "packer-shell")
		if err != nil {
			return fmt.Errorf("Error preparing shell script: %s", err)
		}
		defer os.Remove(tf.Name())

		// Set the path to the temporary file
		scripts = append(scripts, tf.Name())

		// Write our contents to it
		writer := bufio.NewWriter(tf)
		writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang))
		for _, command := range p.config.Inline {
			if _, err := writer.WriteString(command + "\n"); err != nil {
				return fmt.Errorf("Error preparing shell script: %s", err)
			}
		}

		if err := writer.Flush(); err != nil {
			return fmt.Errorf("Error preparing shell script: %s", err)
		}

		tf.Close()
	}

	// Build our variables up by adding in the build name and builder type
	envVars := make([]string, len(p.config.Vars)+2)
	envVars[0] = "PACKER_BUILD_NAME=" + p.config.PackerBuildName
	envVars[1] = "PACKER_BUILDER_TYPE=" + p.config.PackerBuilderType
	copy(envVars[2:], p.config.Vars)

	for _, path := range scripts {
		ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path))

		log.Printf("Opening %s for reading", path)
		f, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening shell script: %s", err)
		}
		defer f.Close()

		// Flatten the environment variables
		flattendVars := strings.Join(envVars, " ")

		// Compile the command
		command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteCommandTemplate{
			Vars: flattendVars,
			Path: p.config.RemotePath,
		})
		if err != nil {
			return fmt.Errorf("Error processing command: %s", err)
		}

		// Upload the file and run the command. Do this in the context of
		// a single retryable function so that we don't end up with
		// the case that the upload succeeded, a restart is initiated,
		// and then the command is executed but the file doesn't exist
		// any longer.
		var cmd *packer.RemoteCmd
		err = p.retryable(func() error {
			if _, err := f.Seek(0, 0); err != nil {
				return err
			}

			var r io.Reader = f
			if !p.config.Binary {
				r = &UnixReader{Reader: r}
			}

			if err := comm.Upload(p.config.RemotePath, r, nil); err != nil {
				return fmt.Errorf("Error uploading script: %s", err)
			}

			cmd = &packer.RemoteCmd{
				Command: fmt.Sprintf("chmod 0777 %s", p.config.RemotePath),
			}
			if err := comm.Start(cmd); err != nil {
				return fmt.Errorf(
					"Error chmodding script file to 0777 in remote "+
						"machine: %s", err)
			}
			cmd.Wait()

			cmd = &packer.RemoteCmd{Command: command}
			return cmd.StartWithUi(comm, ui)
		})
		if err != nil {
			return err
		}

		// Close the original file since we copied it
		f.Close()

		if cmd.ExitStatus != 0 {
			return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
		}
	}

	return nil
}

func (p *Provisioner) Cancel() {
	// Just hard quit. It isn't a big deal if what we're doing keeps
	// running on the other side.
	os.Exit(0)
}

// retryable will retry the given function over and over until a
// non-error is returned.
func (p *Provisioner) retryable(f func() error) error {
	startTimeout := time.After(p.config.startRetryTimeout)
	for {
		var err error
		if err = f(); err == nil {
			return nil
		}

		// Create an error and log it
		err = fmt.Errorf("Retryable error: %s", err)
		log.Printf(err.Error())

		// Check if we timed out, otherwise we retry. It is safe to
		// retry since the only error case above is if the command
		// failed to START.
		select {
		case <-startTimeout:
			return err
		default:
			time.Sleep(2 * time.Second)
		}
	}
}
<commit_msg>provisioner/shell: quote PACKER env vars [GH-1565]<commit_after>// This package implements a provisioner for Packer that executes
// shell scripts within the remote machine.
package shell

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/mitchellh/packer/common"
	"github.com/mitchellh/packer/packer"
	"io"
	"io/ioutil"
	"log"
	"os"
	"strings"
	"time"
)

const DefaultRemotePath = "/tmp/script.sh"

type config struct {
	common.PackerConfig `mapstructure:",squash"`

	// If true, the script contains binary and line endings will not be
	// converted from Windows to Unix-style.
	Binary bool

	// An inline script to execute. Multiple strings are all executed
	// in the context of a single shell.
	Inline []string

	// The shebang value used when running inline scripts.
	InlineShebang string `mapstructure:"inline_shebang"`

	// The local path of the shell script to upload and execute.
	Script string

	// An array of multiple scripts to run.
	Scripts []string

	// An array of environment variables that will be injected before
	// your command(s) are executed.
	Vars []string `mapstructure:"environment_vars"`

	// The remote path where the local shell script will be uploaded to.
	// This should be set to a writable file that is in a pre-existing directory.
	RemotePath string `mapstructure:"remote_path"`

	// The command used to execute the script. The '{{ .Path }}' variable
	// should be used to specify where the script goes, {{ .Vars }}
	// can be used to inject the environment_vars into the environment.
	ExecuteCommand string `mapstructure:"execute_command"`

	// The timeout for retrying to start the process. Until this timeout
	// is reached, if the provisioner can't start a process, it retries.
	// This can be set high to allow for reboots.
	RawStartRetryTimeout string `mapstructure:"start_retry_timeout"`

	startRetryTimeout time.Duration
	tpl               *packer.ConfigTemplate
}

type Provisioner struct {
	config config
}

type ExecuteCommandTemplate struct {
	Vars string
	Path string
}

func (p *Provisioner) Prepare(raws ...interface{}) error {
	md, err := common.DecodeConfig(&p.config, raws...)
	if err != nil {
		return err
	}

	p.config.tpl, err = packer.NewConfigTemplate()
	if err != nil {
		return err
	}
	p.config.tpl.UserVars = p.config.PackerUserVars

	// Accumulate any errors
	errs := common.CheckUnusedConfig(md)

	if p.config.ExecuteCommand == "" {
		p.config.ExecuteCommand = "chmod +x {{.Path}}; {{.Vars}} {{.Path}}"
	}

	if p.config.Inline != nil && len(p.config.Inline) == 0 {
		p.config.Inline = nil
	}

	if p.config.InlineShebang == "" {
		p.config.InlineShebang = "/bin/sh"
	}

	if p.config.RawStartRetryTimeout == "" {
		p.config.RawStartRetryTimeout = "5m"
	}

	if p.config.RemotePath == "" {
		p.config.RemotePath = DefaultRemotePath
	}

	if p.config.Scripts == nil {
		p.config.Scripts = make([]string, 0)
	}

	if p.config.Vars == nil {
		p.config.Vars = make([]string, 0)
	}

	if p.config.Script != "" && len(p.config.Scripts) > 0 {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Only one of script or scripts can be specified."))
	}

	if p.config.Script != "" {
		p.config.Scripts = []string{p.config.Script}
	}

	templates := map[string]*string{
		"inline_shebang":      &p.config.InlineShebang,
		"script":              &p.config.Script,
		"start_retry_timeout": &p.config.RawStartRetryTimeout,
		"remote_path":         &p.config.RemotePath,
	}

	for n, ptr := range templates {
		var err error
		*ptr, err = p.config.tpl.Process(*ptr, nil)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Error processing %s: %s", n, err))
		}
	}

	sliceTemplates := map[string][]string{
		"inline":           p.config.Inline,
		"scripts":          p.config.Scripts,
		"environment_vars": p.config.Vars,
	}

	for n, slice := range sliceTemplates {
		for i, elem := range slice {
			var err error
			slice[i], err = p.config.tpl.Process(elem, nil)
			if err != nil {
				errs = packer.MultiErrorAppend(
					errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err))
			}
		}
	}

	if len(p.config.Scripts) == 0 && p.config.Inline == nil {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Either a script file or inline script must be specified."))
	} else if len(p.config.Scripts) > 0 && p.config.Inline != nil {
		errs = packer.MultiErrorAppend(errs,
			errors.New("Only a script file or an inline script can be specified, not both."))
	}

	for _, path := range p.config.Scripts {
		if _, err := os.Stat(path); err != nil {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("Bad script '%s': %s", path, err))
		}
	}

	// Do a check for bad environment variables, such as '=foo', 'foobar'
	for idx, kv := range p.config.Vars {
		vs := strings.SplitN(kv, "=", 2)
		if len(vs) != 2 || vs[0] == "" {
			errs = packer.MultiErrorAppend(errs,
				fmt.Errorf("Environment variable not in format 'key=value': %s", kv))
		} else {
			// Single quote env var values
			p.config.Vars[idx] = fmt.Sprintf("%s='%s'", vs[0], vs[1])
		}
	}

	if p.config.RawStartRetryTimeout != "" {
		p.config.startRetryTimeout, err = time.ParseDuration(p.config.RawStartRetryTimeout)
		if err != nil {
			errs = packer.MultiErrorAppend(
				errs, fmt.Errorf("Failed parsing start_retry_timeout: %s", err))
		}
	}

	if errs != nil && len(errs.Errors) > 0 {
		return errs
	}

	return nil
}

func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
	scripts := make([]string, len(p.config.Scripts))
	copy(scripts, p.config.Scripts)

	// If we have an inline script, then turn that into a temporary
	// shell script and use that.
	if p.config.Inline != nil {
		tf, err := ioutil.TempFile("", "packer-shell")
		if err != nil {
			return fmt.Errorf("Error preparing shell script: %s", err)
		}
		defer os.Remove(tf.Name())

		// Set the path to the temporary file
		scripts = append(scripts, tf.Name())

		// Write our contents to it
		writer := bufio.NewWriter(tf)
		writer.WriteString(fmt.Sprintf("#!%s\n", p.config.InlineShebang))
		for _, command := range p.config.Inline {
			if _, err := writer.WriteString(command + "\n"); err != nil {
				return fmt.Errorf("Error preparing shell script: %s", err)
			}
		}

		if err := writer.Flush(); err != nil {
			return fmt.Errorf("Error preparing shell script: %s", err)
		}

		tf.Close()
	}

	// Build our variables up by adding in the build name and builder type
	envVars := make([]string, len(p.config.Vars)+2)
	envVars[0] = fmt.Sprintf("PACKER_BUILD_NAME='%s'", p.config.PackerBuildName)
	envVars[1] = fmt.Sprintf("PACKER_BUILDER_TYPE='%s'", p.config.PackerBuilderType)
	copy(envVars[2:], p.config.Vars)

	for _, path := range scripts {
		ui.Say(fmt.Sprintf("Provisioning with shell script: %s", path))

		log.Printf("Opening %s for reading", path)
		f, err := os.Open(path)
		if err != nil {
			return fmt.Errorf("Error opening shell script: %s", err)
		}
		defer f.Close()

		// Flatten the environment variables
		flattendVars := strings.Join(envVars, " ")

		// Compile the command
		command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteCommandTemplate{
			Vars: flattendVars,
			Path: p.config.RemotePath,
		})
		if err != nil {
			return fmt.Errorf("Error processing command: %s", err)
		}

		// Upload the file and run the command. Do this in the context of
		// a single retryable function so that we don't end up with
		// the case that the upload succeeded, a restart is initiated,
		// and then the command is executed but the file doesn't exist
		// any longer.
		var cmd *packer.RemoteCmd
		err = p.retryable(func() error {
			if _, err := f.Seek(0, 0); err != nil {
				return err
			}

			var r io.Reader = f
			if !p.config.Binary {
				r = &UnixReader{Reader: r}
			}

			if err := comm.Upload(p.config.RemotePath, r, nil); err != nil {
				return fmt.Errorf("Error uploading script: %s", err)
			}

			cmd = &packer.RemoteCmd{
				Command: fmt.Sprintf("chmod 0777 %s", p.config.RemotePath),
			}
			if err := comm.Start(cmd); err != nil {
				return fmt.Errorf(
					"Error chmodding script file to 0777 in remote "+
						"machine: %s", err)
			}
			cmd.Wait()

			cmd = &packer.RemoteCmd{Command: command}
			return cmd.StartWithUi(comm, ui)
		})
		if err != nil {
			return err
		}

		// Close the original file since we copied it
		f.Close()

		if cmd.ExitStatus != 0 {
			return fmt.Errorf("Script exited with non-zero exit status: %d", cmd.ExitStatus)
		}
	}

	return nil
}

func (p *Provisioner) Cancel() {
	// Just hard quit. It isn't a big deal if what we're doing keeps
	// running on the other side.
	os.Exit(0)
}

// retryable will retry the given function over and over until a
// non-error is returned.
func (p *Provisioner) retryable(f func() error) error {
	startTimeout := time.After(p.config.startRetryTimeout)
	for {
		var err error
		if err = f(); err == nil {
			return nil
		}

		// Create an error and log it
		err = fmt.Errorf("Retryable error: %s", err)
		log.Printf(err.Error())

		// Check if we timed out, otherwise we retry. It is safe to
		// retry since the only error case above is if the command
		// failed to START.
		select {
		case <-startTimeout:
			return err
		default:
			time.Sleep(2 * time.Second)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/alecaivazis/probe"
)

var qs = []*probe.Question{
	{
		Name:   "name",
		Prompt: &probe.Input{"What is your name?"},
	},
	{
		Name: "color",
		Prompt: &probe.Choice{
			Question: "Choose a color:",
			Choices:  []string{"red", "blue", "green"},
		},
	},
}

func main() {
	answers := probe.Ask(qs)
	fmt.Println(answers)
}
<commit_msg>example now shows how to access answers<commit_after>package main

import (
	"fmt"
	"github.com/alecaivazis/probe"
)

var qs = []*probe.Question{
	{
		Name:   "name",
		Prompt: &probe.Input{"What is your name?"},
	},
	{
		Name: "color",
		Prompt: &probe.Choice{
			Question: "Choose a color:",
			Choices:  []string{"red", "blue", "green"},
		},
	},
}

func main() {
	answers := probe.Ask(qs)
	fmt.Printf("%s chose %s.\n", answers["name"], answers["color"])
}
<|endoftext|>


<commit_before>package resolvable

import (
	"context"
	"fmt"
	"reflect"
	"strings"

	"github.com/neelance/graphql-go/internal/common"
	"github.com/neelance/graphql-go/internal/schema"
)

type Schema struct {
	schema.Schema
	Query    Resolvable
	Mutation Resolvable
	Resolver reflect.Value
}

type Resolvable interface {
	isResolvable()
}

type Object struct {
	Name           string
	Fields         map[string]*Field
	TypeAssertions map[string]*TypeAssertion
}

type Field struct {
	schema.Field
	TypeName    string
	MethodIndex int
	HasContext  bool
	ArgsPacker  *StructPacker
	HasError    bool
	ValueExec   Resolvable
	TraceLabel  string
}

type TypeAssertion struct {
	MethodIndex int
	TypeExec    Resolvable
}

type List struct {
	Elem Resolvable
}

type Scalar struct{}

func (*Object) isResolvable() {}
func (*List) isResolvable()   {}
func (*Scalar) isResolvable() {}

func ApplyResolver(s *schema.Schema, resolver interface{}) (*Schema, error) {
	b := newBuilder(s)

	var query, mutation Resolvable

	if t, ok := s.EntryPoints["query"]; ok {
		if err := b.assignExec(&query, t, reflect.TypeOf(resolver)); err != nil {
			return nil, err
		}
	}

	if t, ok := s.EntryPoints["mutation"]; ok {
		if err := b.assignExec(&mutation, t, reflect.TypeOf(resolver)); err != nil {
			return nil, err
		}
	}

	if err := b.finish(); err != nil {
		return nil, err
	}

	return &Schema{
		Schema:   *s,
		Resolver: reflect.ValueOf(resolver),
		Query:    query,
		Mutation: mutation,
	}, nil
}

type execBuilder struct {
	schema        *schema.Schema
	resMap        map[typePair]*resMapEntry
	packerMap     map[typePair]*packerMapEntry
	structPackers []*StructPacker
}

type typePair struct {
	graphQLType  common.Type
	resolverType reflect.Type
}

type resMapEntry struct {
	exec    Resolvable
	targets []*Resolvable
}

type packerMapEntry struct {
	packer  packer
	targets []*packer
}

func newBuilder(s *schema.Schema) *execBuilder {
	return &execBuilder{
		schema:    s,
		resMap:    make(map[typePair]*resMapEntry),
		packerMap: make(map[typePair]*packerMapEntry),
	}
}

func (b *execBuilder) finish() error {
	for _, entry := range b.resMap {
		for _, target := range entry.targets {
			*target = entry.exec
		}
	}

	for _, entry := range b.packerMap {
		for _, target := range entry.targets {
			*target = entry.packer
		}
	}

	for _, p := range b.structPackers {
		p.defaultStruct = reflect.New(p.structType).Elem()
		for _, f := range p.fields {
			if defaultVal := f.field.Default; defaultVal != nil {
				v, err := f.fieldPacker.Pack(nil, defaultVal.Value)
				if err != nil {
					return err
				}
				p.defaultStruct.FieldByIndex(f.fieldIndex).Set(v)
			}
		}
	}

	return nil
}

func (b *execBuilder) assignExec(target *Resolvable, t common.Type, resolverType reflect.Type) error {
	k := typePair{t, resolverType}
	ref, ok := b.resMap[k]
	if !ok {
		ref = &resMapEntry{}
		b.resMap[k] = ref
		var err error
		ref.exec, err = b.makeExec(t, resolverType)
		if err != nil {
			return err
		}
	}
	ref.targets = append(ref.targets, target)
	return nil
}

func (b *execBuilder) makeExec(t common.Type, resolverType reflect.Type) (Resolvable, error) {
	var nonNull bool
	t, nonNull = unwrapNonNull(t)

	switch t := t.(type) {
	case *schema.Object:
		return b.makeObjectExec(t.Name, t.Fields, nil, nonNull, resolverType)

	case *schema.Interface:
		return b.makeObjectExec(t.Name, t.Fields, t.PossibleTypes, nonNull, resolverType)

	case *schema.Union:
		return b.makeObjectExec(t.Name, nil, t.PossibleTypes, nonNull, resolverType)
	}

	if !nonNull {
		if resolverType.Kind() != reflect.Ptr {
			return nil, fmt.Errorf("%s is not a pointer", resolverType)
		}
		resolverType = resolverType.Elem()
	}

	switch t := t.(type) {
	case *schema.Scalar:
		return makeScalarExec(t, resolverType)

	case *schema.Enum:
		return &Scalar{}, nil

	case *common.List:
		if resolverType.Kind() != reflect.Slice {
			return nil, fmt.Errorf("%s is not a slice", resolverType)
		}
		e := &List{}
		if err := b.assignExec(&e.Elem, t.OfType, resolverType.Elem()); err != nil {
			return nil, err
		}
		return e, nil

	default:
		panic("invalid type")
	}
}

func makeScalarExec(t *schema.Scalar, resolverType reflect.Type) (Resolvable, error) {
	implementsType := false
	switch r := reflect.New(resolverType).Interface().(type) {
	case *int32:
		implementsType = (t.Name == "Int")
	case *float64:
		implementsType = (t.Name == "Float")
	case *string:
		implementsType = (t.Name == "String")
	case *bool:
		implementsType = (t.Name == "Boolean")
	case Unmarshaler:
		implementsType = r.ImplementsGraphQLType(t.Name)
	}
	if !implementsType {
		return nil, fmt.Errorf("can not use %s as %s", resolverType, t.Name)
	}
	return &Scalar{}, nil
}

func (b *execBuilder) makeObjectExec(typeName string, fields schema.FieldList, possibleTypes []*schema.Object, nonNull bool, resolverType reflect.Type) (*Object, error) {
	if !nonNull {
		if resolverType.Kind() != reflect.Ptr && resolverType.Kind() != reflect.Interface {
			return nil, fmt.Errorf("%s is not a pointer or interface", resolverType)
		}
	}

	methodHasReceiver := resolverType.Kind() != reflect.Interface

	Fields := make(map[string]*Field)
	for _, f := range fields {
		methodIndex := findMethod(resolverType, f.Name)
		if methodIndex == -1 {
			hint := ""
			if findMethod(reflect.PtrTo(resolverType), f.Name) != -1 {
				hint = " (hint: the method exists on the pointer type)"
			}
			return nil, fmt.Errorf("%s does not resolve %q: missing method for field %q%s", resolverType, typeName, f.Name, hint)
		}

		m := resolverType.Method(methodIndex)
		fe, err := b.makeFieldExec(typeName, f, m, methodIndex, methodHasReceiver)
		if err != nil {
			return nil, fmt.Errorf("%s\n\treturned by (%s).%s", err, resolverType, m.Name)
		}
		Fields[f.Name] = fe
	}

	typeAssertions := make(map[string]*TypeAssertion)
	for _, impl := range possibleTypes {
		methodIndex := findMethod(resolverType, "to"+impl.Name)
		if methodIndex == -1 {
			return nil, fmt.Errorf("%s does not resolve %q: missing method %q to convert to %q", resolverType, typeName, "to"+impl.Name, impl.Name)
		}
		a := &TypeAssertion{
			MethodIndex: methodIndex,
		}
		if err := b.assignExec(&a.TypeExec, impl, resolverType.Method(methodIndex).Type.Out(0)); err != nil {
			return nil, err
		}
		typeAssertions[impl.Name] = a
	}

	return &Object{
		Name:           typeName,
		Fields:         Fields,
		TypeAssertions: typeAssertions,
	}, nil
}

var contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
var errorType = reflect.TypeOf((*error)(nil)).Elem()

func (b *execBuilder) makeFieldExec(typeName string, f *schema.Field, m reflect.Method, methodIndex int, methodHasReceiver bool) (*Field, error) {
	in := make([]reflect.Type, m.Type.NumIn())
	for i := range in {
		in[i] = m.Type.In(i)
	}
	if methodHasReceiver {
		in = in[1:] // first parameter is receiver
	}

	hasContext := len(in) > 0 && in[0] == contextType
	if hasContext {
		in = in[1:]
	}

	var argsPacker *StructPacker
	if len(f.Args) > 0 {
		if len(in) == 0 {
			return nil, fmt.Errorf("must have parameter for field arguments")
		}
		var err error
		argsPacker, err = b.makeStructPacker(f.Args, in[0])
		if err != nil {
			return nil, err
		}
		in = in[1:]
	}

	if len(in) > 0 {
		return nil, fmt.Errorf("too many parameters")
	}

	if m.Type.NumOut() > 2 {
		return nil, fmt.Errorf("too many return values")
	}

	hasError := m.Type.NumOut() == 2
	if hasError {
		if m.Type.Out(1) != errorType {
			return nil, fmt.Errorf(`must have "error" as its second return value`)
		}
	}

	fe := &Field{
		Field:       *f,
		TypeName:    typeName,
		MethodIndex: methodIndex,
		HasContext:  hasContext,
		ArgsPacker:  argsPacker,
		HasError:    hasError,
		TraceLabel:  fmt.Sprintf("GraphQL field: %s.%s", typeName, f.Name),
	}
	if err := b.assignExec(&fe.ValueExec, f.Type, m.Type.Out(0)); err != nil {
		return nil, err
	}
	return fe, nil
}

func findMethod(t reflect.Type, name string) int {
	for i := 0; i < t.NumMethod(); i++ {
		if strings.EqualFold(stripUnderscore(name), stripUnderscore(t.Method(i).Name)) {
			return i
		}
	}
	return -1
}

func unwrapNonNull(t common.Type) (common.Type, bool) {
	if nn, ok := t.(*common.NonNull); ok {
		return nn.OfType, true
	}
	return t, false
}

func stripUnderscore(s string) string {
	return strings.Replace(s, "_", "", -1)
}
<commit_msg>Warn if an interface's resolver has a ToTYPE implementation that does not return two values.<commit_after>package resolvable

import (
	"context"
	"fmt"
	"reflect"
	"strings"

	"github.com/neelance/graphql-go/internal/common"
	"github.com/neelance/graphql-go/internal/schema"
)

type Schema struct {
	schema.Schema
	Query    Resolvable
	Mutation Resolvable
	Resolver reflect.Value
}

type Resolvable interface {
	isResolvable()
}

type Object struct {
	Name           string
	Fields         map[string]*Field
	TypeAssertions map[string]*TypeAssertion
}

type Field struct {
	schema.Field
	TypeName    string
	MethodIndex int
	HasContext  bool
	ArgsPacker  *StructPacker
	HasError    bool
	ValueExec   Resolvable
	TraceLabel  string
}

type TypeAssertion struct {
	MethodIndex int
	TypeExec    Resolvable
}

type List struct {
	Elem Resolvable
}

type Scalar struct{}

func (*Object) isResolvable() {}
func (*List) isResolvable()   {}
func (*Scalar) isResolvable() {}

func ApplyResolver(s *schema.Schema, resolver interface{}) (*Schema, error) {
	b := newBuilder(s)

	var query, mutation Resolvable

	if t, ok := s.EntryPoints["query"]; ok {
		if err := b.assignExec(&query, t, reflect.TypeOf(resolver)); err != nil {
			return nil, err
		}
	}

	if t, ok := s.EntryPoints["mutation"]; ok {
		if err := b.assignExec(&mutation, t, reflect.TypeOf(resolver)); err != nil {
			return nil, err
		}
	}

	if err := b.finish(); err != nil {
		return nil, err
	}

	return &Schema{
		Schema:   *s,
		Resolver: reflect.ValueOf(resolver),
		Query:    query,
		Mutation: mutation,
	}, nil
}

type execBuilder struct {
	schema        *schema.Schema
	resMap        map[typePair]*resMapEntry
	packerMap     map[typePair]*packerMapEntry
	structPackers []*StructPacker
}

type typePair struct {
	graphQLType  common.Type
	resolverType reflect.Type
}

type resMapEntry struct {
	exec    Resolvable
	targets []*Resolvable
}

type packerMapEntry struct {
	packer  packer
	targets []*packer
}

func newBuilder(s *schema.Schema) *execBuilder {
	return &execBuilder{
		schema:    s,
		resMap:    make(map[typePair]*resMapEntry),
		packerMap: make(map[typePair]*packerMapEntry),
	}
}

func (b *execBuilder) finish() error {
	for _, entry := range b.resMap {
		for _, target := range entry.targets {
			*target = entry.exec
		}
	}

	for _, entry := range b.packerMap {
		for _, target := range entry.targets {
			*target = entry.packer
		}
	}

	for _, p := range b.structPackers {
		p.defaultStruct = reflect.New(p.structType).Elem()
		for _, f := range p.fields {
			if defaultVal := f.field.Default; defaultVal != nil {
				v, err := f.fieldPacker.Pack(nil, defaultVal.Value)
				if err != nil {
					return err
				}
				p.defaultStruct.FieldByIndex(f.fieldIndex).Set(v)
			}
		}
	}

	return nil
}

func (b *execBuilder) assignExec(target *Resolvable, t common.Type, resolverType reflect.Type) error {
	k := typePair{t, resolverType}
	ref, ok := b.resMap[k]
	if !ok {
		ref = &resMapEntry{}
		b.resMap[k] = ref
		var err error
		ref.exec, err = b.makeExec(t, resolverType)
		if err != nil {
			return err
		}
	}
	ref.targets = append(ref.targets, target)
	return nil
}

func (b *execBuilder) makeExec(t common.Type, resolverType reflect.Type) (Resolvable, error) {
	var nonNull bool
	t, nonNull = unwrapNonNull(t)

	switch t := t.(type) {
	case *schema.Object:
		return b.makeObjectExec(t.Name, t.Fields, nil, nonNull, resolverType)

	case *schema.Interface:
		return b.makeObjectExec(t.Name, t.Fields, t.PossibleTypes, nonNull, resolverType)

	case *schema.Union:
		return b.makeObjectExec(t.Name, nil, t.PossibleTypes, nonNull, resolverType)
	}

	if !nonNull {
		if resolverType.Kind() != reflect.Ptr {
			return nil, fmt.Errorf("%s is not a pointer", resolverType)
		}
		resolverType = resolverType.Elem()
	}

	switch t := t.(type) {
	case *schema.Scalar:
		return makeScalarExec(t, resolverType)

	case *schema.Enum:
		return &Scalar{}, nil

	case *common.List:
		if resolverType.Kind() != reflect.Slice {
			return nil, fmt.Errorf("%s is not a slice", resolverType)
		}
		e := &List{}
		if err := b.assignExec(&e.Elem, t.OfType, resolverType.Elem()); err != nil {
			return nil, err
		}
		return e, nil

	default:
		panic("invalid type")
	}
}

func makeScalarExec(t *schema.Scalar, resolverType reflect.Type) (Resolvable, error) {
	implementsType := false
	switch r := reflect.New(resolverType).Interface().(type) {
	case *int32:
		implementsType = (t.Name == "Int")
	case *float64:
		implementsType = (t.Name == "Float")
	case *string:
		implementsType = (t.Name == "String")
	case *bool:
		implementsType = (t.Name == "Boolean")
	case Unmarshaler:
		implementsType = r.ImplementsGraphQLType(t.Name)
	}
	if !implementsType {
		return nil, fmt.Errorf("can not use %s as %s", resolverType, t.Name)
	}
	return &Scalar{}, nil
}

func (b *execBuilder) makeObjectExec(typeName string, fields schema.FieldList, possibleTypes []*schema.Object, nonNull bool, resolverType reflect.Type) (*Object, error) {
	if !nonNull {
		if resolverType.Kind() != reflect.Ptr && resolverType.Kind() != reflect.Interface {
			return nil, fmt.Errorf("%s is not a pointer or interface", resolverType)
		}
	}

	methodHasReceiver := resolverType.Kind() != reflect.Interface

	Fields := make(map[string]*Field)
	for _, f := range fields {
		methodIndex := findMethod(resolverType, f.Name)
		if methodIndex == -1 {
			hint := ""
			if findMethod(reflect.PtrTo(resolverType), f.Name) != -1 {
				hint = " (hint: the method exists on the pointer type)"
			}
			return nil, fmt.Errorf("%s does not resolve %q: missing method for field %q%s", resolverType, typeName, f.Name, hint)
		}

		m := resolverType.Method(methodIndex)
		fe, err := b.makeFieldExec(typeName, f, m, methodIndex, methodHasReceiver)
		if err != nil {
			return nil, fmt.Errorf("%s\n\treturned by (%s).%s", err, resolverType, m.Name)
		}
		Fields[f.Name] = fe
	}

	typeAssertions := make(map[string]*TypeAssertion)
	for _, impl := range possibleTypes {
		methodIndex := findMethod(resolverType, "to"+impl.Name)
		if methodIndex == -1 {
			return nil, fmt.Errorf("%s does not resolve %q: missing method %q to convert to %q", resolverType, typeName, "to"+impl.Name, impl.Name)
		}
		if resolverType.Method(methodIndex).Type.NumOut() != 2 {
			return nil, fmt.Errorf("%s does not resolve %q: method %q should return a value and a bool indicating success", resolverType, typeName, "to"+impl.Name)
		}
		a := &TypeAssertion{
			MethodIndex: methodIndex,
		}
		if err := b.assignExec(&a.TypeExec, impl, resolverType.Method(methodIndex).Type.Out(0)); err != nil {
			return nil, err
		}
		typeAssertions[impl.Name] = a
	}

	return &Object{
		Name:           typeName,
		Fields:         Fields,
		TypeAssertions: typeAssertions,
	}, nil
}

var contextType = reflect.TypeOf((*context.Context)(nil)).Elem()
var errorType = reflect.TypeOf((*error)(nil)).Elem()

func (b *execBuilder) makeFieldExec(typeName string, f *schema.Field, m reflect.Method, methodIndex int, methodHasReceiver bool) (*Field, error) {
	in := make([]reflect.Type, m.Type.NumIn())
	for i := range in {
		in[i] = m.Type.In(i)
	}
	if methodHasReceiver {
		in = in[1:] // first parameter is receiver
	}

	hasContext := len(in) > 0 && in[0] == contextType
	if hasContext {
		in = in[1:]
	}

	var argsPacker *StructPacker
	if len(f.Args) > 0 {
		if len(in) == 0 {
			return nil, fmt.Errorf("must have parameter for field arguments")
		}
		var err error
		argsPacker, err = b.makeStructPacker(f.Args, in[0])
		if err != nil {
			return nil, err
		}
		in = in[1:]
	}

	if len(in) > 0 {
		return nil, fmt.Errorf("too many parameters")
	}

	if m.Type.NumOut() > 2 {
		return nil, fmt.Errorf("too many return values")
	}

	hasError := m.Type.NumOut() == 2
	if hasError {
		if m.Type.Out(1) != errorType {
			return nil, fmt.Errorf(`must have "error" as its second return value`)
		}
	}

	fe := &Field{
		Field:       *f,
		TypeName:    typeName,
		MethodIndex: methodIndex,
		HasContext:  hasContext,
		ArgsPacker:  argsPacker,
		HasError:    hasError,
		TraceLabel:  fmt.Sprintf("GraphQL field: %s.%s", typeName, f.Name),
	}
	if err := b.assignExec(&fe.ValueExec, f.Type, m.Type.Out(0)); err != nil {
		return nil, err
	}
	return fe, nil
}

func findMethod(t reflect.Type, name string) int {
	for i := 0; i < t.NumMethod(); i++ {
		if strings.EqualFold(stripUnderscore(name), stripUnderscore(t.Method(i).Name)) {
			return i
		}
	}
	return -1
}

func unwrapNonNull(t common.Type) (common.Type, bool) {
	if nn, ok := t.(*common.NonNull); ok {
		return nn.OfType, true
	}
	return t, false
}

func stripUnderscore(s string) string {
	return strings.Replace(s, "_", "", -1)
}
<|endoftext|>


<commit_before>package lfqueue

import (
	"log"
	"runtime"
	"sync"
	"testing"
	"time"
)

func TestLfQueueConsistency(t *testing.T) {
	max := 100000000
	c := 10
	var wg sync.WaitGroup
	q := NewLockfreeQueue()
	go func() {
		i := 0
		for {
			r := q.Pop()
			if r == nil {
				runtime.Gosched()
			}
			i++
			if i == max {
				wg.Done()
				return
			}
		}
	}()

	for j := 0; j < c; j++ {
		cmax := max / c
		go func() {
			for i := 0; i < cmax; i++ {
				q.Push("abc")
			}
		}()
	}

	wg.Wait()
	time.Sleep(500 * time.Millisecond)
	//queue should be empty
	for i := 0; i < 100; i++ {
		r := q.Pop()
		if r != nil {
			log.Printf("unexpected result %+v", r)
			t.FailNow()
		}
	}
}
<commit_msg>lfqueue is safe<commit_after>package lfqueue

import (
	"fmt"
	"log"
	"runtime"
	"sync"
	"testing"
	"time"
)

func TestLfQueueConsistency(t *testing.T) {
	max := 1000000
	c := 10
	var wg sync.WaitGroup
	wg.Add(1)
	q := NewLockfreeQueue()
	go func() {
		i := 0
		for {
			r := q.Pop()
			if r == nil {
				runtime.Gosched()

				continue
			}
			i++
			if i == max {
				wg.Done()
				return
			}
		}
	}()

	for j := 0; j < c; j++ {
		cmax := max / c
		go func() {
			for i := 0; i < cmax; i++ {
				q.Push(fmt.Sprintf("%v %v", j, i))
			}
		}()
	}

	wg.Wait()
	time.Sleep(500 * time.Millisecond)
	//queue should be empty
	for i := 0; i < 100; i++ {
		r := q.Pop()
		if r != nil {
			log.Printf("unexpected result %+v", r)
			t.FailNow()
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2022 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	"context"
	"fmt"
	"testing"

	"github.com/fsouza/fake-gcs-server/fakestorage"
	"github.com/jacobsa/gcloud/gcs"
	. "github.com/jacobsa/ogletest"
)

const missingObjectName string = "test/foo"

func TestBucketHandle(t *testing.T) { RunTests(t) }

type BucketHandleTest struct {
	fakeStorageServer *fakestorage.Server
	bucketHandle      *bucketHandle
}

var _ SetUpInterface = &BucketHandleTest{}
var _ TearDownInterface = &BucketHandleTest{}

func init() { RegisterTestSuite(&BucketHandleTest{}) }

func (t *BucketHandleTest) SetUp(_ *TestInfo) {
	var err error
	t.fakeStorageServer, err = CreateFakeStorageServer([]fakestorage.Object{GetTestFakeStorageObject()})
	AssertEq(nil, err)

	storageClient := &storageClient{client: t.fakeStorageServer.Client()}
	t.bucketHandle, err = storageClient.BucketHandle(TestBucketName)
	AssertEq(nil, err)
	AssertNe(nil, t.bucketHandle)
}

func (t *BucketHandleTest) TearDown() {
	t.fakeStorageServer.Stop()
}

func (t *BucketHandleTest) TestNewReaderMethodWithCompleteRead() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithRangeRead() {
	start := uint64(2)
	limit := uint64(8)

	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: start,
				Limit: limit,
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, limit-start)
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject[start:limit])
}

func (t *BucketHandleTest) TestNewReaderMethodWithInValidObject() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: missingObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestNewReaderMethodWithValidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: TestObjectGeneration,
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithInvalidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: 222, // other than TestObjectGeneration, doesn't exist.
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestDeleteObjectMethodWithValidObject() {
	error := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       TestObjectName,
			Generation:                 0,
			MetaGenerationPrecondition: nil,
		})

	AssertEq(nil, error)
}

func (t *BucketHandleTest) TestDeleteObjectMethodWithMissingObject() {
	error := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       missingObjectName,
			Generation:                 0,
			MetaGenerationPrecondition: nil,
		})

	err_expected := fmt.Errorf("storage: object doesn't exist")
	AssertEq(err_expected.Error(), error.Error())
}
<commit_msg>delete object method and unit test<commit_after>// Copyright 2022 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package storage

import (
	"context"
	"fmt"
	"testing"

	"github.com/fsouza/fake-gcs-server/fakestorage"
	"github.com/jacobsa/gcloud/gcs"
	. "github.com/jacobsa/ogletest"
)

const missingObjectName string = "test/foo"

func TestBucketHandle(t *testing.T) { RunTests(t) }

type BucketHandleTest struct {
	fakeStorageServer *fakestorage.Server
	bucketHandle      *bucketHandle
}

var _ SetUpInterface = &BucketHandleTest{}
var _ TearDownInterface = &BucketHandleTest{}

func init() { RegisterTestSuite(&BucketHandleTest{}) }

func (t *BucketHandleTest) SetUp(_ *TestInfo) {
	var err error
	t.fakeStorageServer, err = CreateFakeStorageServer([]fakestorage.Object{GetTestFakeStorageObject()})
	AssertEq(nil, err)

	storageClient := &storageClient{client: t.fakeStorageServer.Client()}
	t.bucketHandle, err = storageClient.BucketHandle(TestBucketName)
	AssertEq(nil, err)
	AssertNe(nil, t.bucketHandle)
}

func (t *BucketHandleTest) TearDown() {
	t.fakeStorageServer.Stop()
}

func (t *BucketHandleTest) TestNewReaderMethodWithCompleteRead() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithRangeRead() {
	start := uint64(2)
	limit := uint64(8)

	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: start,
				Limit: limit,
			},
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, limit-start)
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject[start:limit])
}

func (t *BucketHandleTest) TestNewReaderMethodWithInValidObject() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: missingObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestNewReaderMethodWithValidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: TestObjectGeneration,
		})

	AssertEq(nil, err)
	defer rc.Close()
	buf := make([]byte, len(ContentInTestObject))
	_, err = rc.Read(buf)
	AssertEq(nil, err)
	ExpectEq(string(buf[:]), ContentInTestObject)
}

func (t *BucketHandleTest) TestNewReaderMethodWithInvalidGeneration() {
	rc, err := t.bucketHandle.NewReader(context.Background(),
		&gcs.ReadObjectRequest{
			Name: TestObjectName,
			Range: &gcs.ByteRange{
				Start: uint64(0),
				Limit: uint64(len(ContentInTestObject)),
			},
			Generation: 222, // other than TestObjectGeneration, doesn't exist.
		})

	AssertNe(nil, err)
	AssertEq(nil, rc)
}

func (t *BucketHandleTest) TestDeleteObjectMethodWithValidObject() {
	error := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       TestObjectName,
			Generation:                 0,
			MetaGenerationPrecondition: nil,
		})

	AssertEq(nil, error)
}

func (t *BucketHandleTest) TestDeleteObjectMethodWithMissingObject() {
	error := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       missingObjectName,
			Generation:                 0,
			MetaGenerationPrecondition: nil,
		})

	err_expected := fmt.Errorf("storage: object doesn't exist")
	AssertEq(err_expected.Error(), error.Error())
}
func (t *BucketHandleTest) TestDeleteObjectMethodWithValidGeneration() {
	error := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       TestObjectName,
			Generation:                 0,
			MetaGenerationPrecondition: nil,
		})

	AssertEq(nil, error)
}
func (t *BucketHandleTest) TestDeleteObjectMethodWithInValidGeneration() {
	error := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       TestObjectName,
			Generation:                 222, // other than TestObjectGeneration, doesn't exist.
			MetaGenerationPrecondition: nil,
		})

	AssertEq(nil, error)
}
func (t *BucketHandleTest) TestDeleteObjectMethodWithValidMetaGeneration() {
	error := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       TestObjectName,
			Generation:                 0,
			MetaGenerationPrecondition: nil,
		})

	AssertEq(nil, error)
}
func (t *BucketHandleTest) TestDeleteObjectMethodWithInValidMetaGeneration() {
	var metagenration int64 = 222

	error := t.bucketHandle.DeleteObject(context.Background(),
		&gcs.DeleteObjectRequest{
			Name:                       TestObjectName,
			Generation:                 0,
			MetaGenerationPrecondition: &metagenration,
		})

	AssertEq(nil, error)
}
<|endoftext|>


<commit_before>// Copyright 2013 com 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 com

import (
	"errors"
	"os"
	"path"
	"strings"
)

// IsDir checks whether the path is a directory.
// It returns false when it's a file or does not exist.
func IsDir(dir string) bool {
	f, e := os.Stat(dir)
	if e != nil {
		return false
	}
	return f.IsDir()
}

func statDir(dirPath, recPath string, includeDir bool) ([]string, error) {
	dir, err := os.Open(dirPath)
	if err != nil {
		return nil, err
	}
	defer dir.Close()

	fis, err := dir.Readdir(0)
	if err != nil {
		return nil, err
	}

	statList := make([]string, 0)
	for _, fi := range fis {
		relPath := path.Join(recPath, fi.Name())
		curPath := path.Join(dirPath, fi.Name())
		if fi.IsDir() {
			if includeDir {
				statList = append(statList, relPath+"/")
			}
			s, err := statDir(curPath, relPath, includeDir)
			if err != nil {
				return nil, err
			}
			statList = append(statList, s...)
		} else {
			statList = append(statList, relPath)
		}
	}
	return statList, nil
}

// StatDir gathers information of given directory by depth-first.
// It returns slice of file list and includes subdirectories if enabled;
// it returns error and nil slice when error occurs in underlying functions,
// or given path is not a directory or does not exist.
//
// Slice does not include given path itself.
// If subdirectories is enabled, they will have suffix '/'.
func StatDir(dirPath string, includeDir ...bool) ([]string, error) {
	if !IsDir(dirPath) {
		return nil, errors.New("not a directory or does not exist: " + dirPath)
	}

	isIncludeDir := false
	if len(includeDir) >= 1 {
		isIncludeDir = includeDir[0]
	}

	return statDir(dirPath, "", isIncludeDir)
}

// CopyDir copy files recursively from source to target directory.
//
// The filter accepts a function that process the path info.
// and should return true for need to filter.
//
// It returns error when error occurs in underlying functions.
func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error {
	// Check if target directory exists.
	if IsExist(destPath) {
		return errors.New("file or directory alreay exists: " + destPath)
	}

	err := os.MkdirAll(destPath, os.ModePerm)
	if err != nil {
		return err
	}

	// Gather directory info.
	infos, err := StatDir(srcPath, true)
	if err != nil {
		return err
	}

	var filter func(filePath string) bool
	if len(filters) > 0 {
		filter = filters[0]
	}

	for _, info := range infos {
		if filter != nil && filter(info) {
			continue
		}

		curPath := path.Join(destPath, info)
		if strings.HasSuffix(info, "/") {
			err = os.MkdirAll(curPath, os.ModePerm)
		} else {
			_, err = Copy(path.Join(srcPath, info), curPath)
		}
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>add func StatDir ignored “.DS_Store”<commit_after>// Copyright 2013 com 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 com

import (
	"errors"
	"os"
	"path"
	"strings"
)

// IsDir checks whether the path is a directory.
// It returns false when it's a file or does not exist.
func IsDir(dir string) bool {
	f, e := os.Stat(dir)
	if e != nil {
		return false
	}
	return f.IsDir()
}

func statDir(dirPath, recPath string, includeDir bool) ([]string, error) {
	dir, err := os.Open(dirPath)
	if err != nil {
		return nil, err
	}
	defer dir.Close()

	fis, err := dir.Readdir(0)
	if err != nil {
		return nil, err
	}

	statList := make([]string, 0)
	for _, fi := range fis {
		if strings.Contains(fi.Name(), ".DS_Store") {
			continue
		}

		relPath := path.Join(recPath, fi.Name())
		curPath := path.Join(dirPath, fi.Name())
		if fi.IsDir() {
			if includeDir {
				statList = append(statList, relPath+"/")
			}
			s, err := statDir(curPath, relPath, includeDir)
			if err != nil {
				return nil, err
			}
			statList = append(statList, s...)
		} else {
			statList = append(statList, relPath)
		}
	}
	return statList, nil
}

// StatDir gathers information of given directory by depth-first.
// It returns slice of file list and includes subdirectories if enabled;
// it returns error and nil slice when error occurs in underlying functions,
// or given path is not a directory or does not exist.
//
// Slice does not include given path itself.
// If subdirectories is enabled, they will have suffix '/'.
func StatDir(dirPath string, includeDir ...bool) ([]string, error) {
	if !IsDir(dirPath) {
		return nil, errors.New("not a directory or does not exist: " + dirPath)
	}

	isIncludeDir := false
	if len(includeDir) >= 1 {
		isIncludeDir = includeDir[0]
	}

	return statDir(dirPath, "", isIncludeDir)
}

// CopyDir copy files recursively from source to target directory.
//
// The filter accepts a function that process the path info.
// and should return true for need to filter.
//
// It returns error when error occurs in underlying functions.
func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error {
	// Check if target directory exists.
	if IsExist(destPath) {
		return errors.New("file or directory alreay exists: " + destPath)
	}

	err := os.MkdirAll(destPath, os.ModePerm)
	if err != nil {
		return err
	}

	// Gather directory info.
	infos, err := StatDir(srcPath, true)
	if err != nil {
		return err
	}

	var filter func(filePath string) bool
	if len(filters) > 0 {
		filter = filters[0]
	}

	for _, info := range infos {
		if filter != nil && filter(info) {
			continue
		}

		curPath := path.Join(destPath, info)
		if strings.HasSuffix(info, "/") {
			err = os.MkdirAll(curPath, os.ModePerm)
		} else {
			_, err = Copy(path.Join(srcPath, info), curPath)
		}
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>/*
Package bolthold is an indexing and querying layer on top of a Bolt DB.  The goal is to allow easy, persistant storage
and retrieval of Go types.  BoltDB is an embedded key-value store, and bolthold servers a similar use case however with
a higher level interface for common uses of BoltDB.

Go Types

BoltHold deals directly with Go Types.  When inserting data, you pass in your stucture directly.  When querying data you
pass in a pointer to a slice of the type you want to return.  By default Gob encoding is used. You can put multiple
different types into the same DB file and they (and their indexes) will be stored separately.

	err := store.Insert(1234, Item{
		Name:    "Test Name",
		Created: time.Now(),
	})

	var result []Item

	err := store.Find(&result, query)

Indexes

BoltHold will automatically create an index for any struct fields tags with "boldholdIndex"

	type Item struct {
		ID       int
		Name     string
		Category string `boltholdIndex:"Category"`
		Created  time.Time
	}

The first field specified in query will be used as the index (if one exists).

Queries are chained together criteria that applies to a set of fields:

	bolthold.Where("Name").Eq("John Doe").And("DOB").Lt(time.Now())

*/
package bolthold
<commit_msg>Fixed typo<commit_after>/*
Package bolthold is an indexing and querying layer on top of a Bolt DB.  The goal is to allow easy, persistent storage
and retrieval of Go types.  BoltDB is an embedded key-value store, and bolthold servers a similar use case however with
a higher level interface for common uses of BoltDB.

Go Types

BoltHold deals directly with Go Types.  When inserting data, you pass in your structure directly.  When querying data you
pass in a pointer to a slice of the type you want to return.  By default Gob encoding is used. You can put multiple
different types into the same DB file and they (and their indexes) will be stored separately.

	err := store.Insert(1234, Item{
		Name:    "Test Name",
		Created: time.Now(),
	})

	var result []Item

	err := store.Find(&result, query)

Indexes

BoltHold will automatically create an index for any struct fields tags with "boldholdIndex"

	type Item struct {
		ID       int
		Name     string
		Category string `boltholdIndex:"Category"`
		Created  time.Time
	}

The first field specified in query will be used as the index (if one exists).

Queries are chained together criteria that applies to a set of fields:

	bolthold.Where("Name").Eq("John Doe").And("DOB").Lt(time.Now())

*/
package bolthold
<|endoftext|>


<commit_before>// Copyright (c) 2015, Benjamin Borbe <bborbe@rocketnews.de>.
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package provide http-server helpers

Simple Web-Server:

	package main

	import (
		"github.com/bborbe/server"
		"github.com/bborbe/server/handler/static"
	)

	func main() {
		srv := server.NewServerPort(8080, static.NewHandlerStaticContent("Hello World"))
		srv.Run()
	}

*/
package server
<commit_msg>2015 -> 2016<commit_after>// Copyright (c) 2016, Benjamin Borbe <bborbe@rocketnews.de>.
// All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package provide http-server helpers

Simple Web-Server:

	package main

	import (
		"github.com/bborbe/server"
		"github.com/bborbe/server/handler/static"
	)

	func main() {
		srv := server.NewServerPort(8080, static.NewHandlerStaticContent("Hello World"))
		srv.Run()
	}

*/
package server
<|endoftext|>