<commit_before>package tnt

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestSelect(t *testing.T) {
	assert := assert.New(t)

	tarantoolConfig := `
    s = box.schema.space.create('tester', {id = 42})
    s:create_index('primary', {
        type = 'hash',
        parts = {1, 'NUM'}
    })
    t = s:insert({1})
    t = s:insert({2, 'Music'})
    t = s:insert({3, 'Length', 93})
    `

	box, err := NewBox(tarantoolConfig, nil)
	if !assert.NoError(err) {
		return
	}
	defer box.Close()

	// unkwnown user
	conn, err := box.Connect(nil)
	assert.NoError(err)
	assert.NotNil(conn)

	data, err := conn.Execute(&Select{
		Space: 42,
		Key:   3,
	})

	assert.NoError(err)
	assert.Equal([]interface{}{
		[]interface{}{
			uint32(0x3),
			"Length",
			uint32(0x5d),
		},
	}, data)

}

func BenchmarkSelectNoPack(b *testing.B) {
	cache := &packCache{}

	for i := 0; i < b.N; i += 1 {
		(&Select{
			Key: 3,
		}).Pack(0, 42, cache)
	}
}
<commit_msg>checkpoint<commit_after>package tnt

import (
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestSelect(t *testing.T) {
	assert := assert.New(t)

	tarantoolConfig := `
    s = box.schema.space.create('tester', {id = 42})
    s:create_index('primary', {
        type = 'hash',
        parts = {1, 'NUM'}
    })
    t = s:insert({1})
    t = s:insert({2, 'Music'})
    t = s:insert({3, 'Length', 93})
    `

	box, err := NewBox(tarantoolConfig, nil)
	if !assert.NoError(err) {
		return
	}
	defer box.Close()

	// unkwnown user
	conn, err := box.Connect(nil)
	assert.NoError(err)
	assert.NotNil(conn)

	data, err := conn.Execute(&Select{
		Space: 42,
		Key:   3,
	})

	assert.NoError(err)
	assert.Equal([]interface{}{
		[]interface{}{
			uint32(0x3),
			"Length",
			uint32(0x5d),
		},
	}, data)

}

func BenchmarkSelectPack(b *testing.B) {
	cache := &packCache{}

	for i := 0; i < b.N; i += 1 {
		(&Select{
			Key: 3,
		}).Pack(0, 42, cache)
	}
}
<|endoftext|>


<commit_before>package shell

import (
	"flag"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/util"
	"io"
	"math"
	"time"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
)

func init() {
	Commands = append(Commands, &commandS3CleanUploads{})
}

type commandS3CleanUploads struct {
}

func (c *commandS3CleanUploads) Name() string {
	return "s3.clean.uploads"
}

func (c *commandS3CleanUploads) Help() string {
	return `clean up stale multipart uploads

	Example:
		s3.clean.uploads -timeAgo 1.5h

`
}

func (c *commandS3CleanUploads) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {

	bucketCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	uploadedTimeAgo := bucketCommand.Duration("timeAgo", 24*time.Hour, "created time before now. \"1.5h\" or \"2h45m\". Valid time units are \"m\", \"h\"")
	if err = bucketCommand.Parse(args); err != nil {
		return nil
	}

	var filerBucketsPath string
	filerBucketsPath, err = readFilerBucketsPath(commandEnv)
	if err != nil {
		return fmt.Errorf("read buckets: %v", err)
	}

	var buckets []string
	err = filer_pb.List(commandEnv, filerBucketsPath, "", func(entry *filer_pb.Entry, isLast bool) error {
		buckets = append(buckets, entry.Name)
		return nil
	}, "", false, math.MaxUint32)
	if err != nil {
		return fmt.Errorf("list buckets under %v: %v", filerBucketsPath, err)
	}

	for _, bucket := range buckets {
		c.cleanupUploads(commandEnv, writer, filerBucketsPath, bucket, *uploadedTimeAgo)
	}

	return err

}

func (c *commandS3CleanUploads) cleanupUploads(commandEnv *CommandEnv, writer io.Writer, filerBucketsPath string, bucket string, timeAgo time.Duration) error {
	uploadsDir := filerBucketsPath + "/" + bucket + "/.uploads"
	var staleUploads []string
	now := time.Now()
	err := filer_pb.List(commandEnv, uploadsDir, "", func(entry *filer_pb.Entry, isLast bool) error {
		ctime := time.Unix(entry.Attributes.Crtime, 0)
		if ctime.Add(timeAgo).Before(now) {
			staleUploads = append(staleUploads, entry.Name)
		}
		return nil
	}, "", false, math.MaxUint32)
	if err != nil {
		return fmt.Errorf("list uploads under %v: %v", uploadsDir, err)
	}

	for _, staleUpload := range staleUploads {
		deleteUrl := fmt.Sprintf("http://%s%s/%s?recursive=true&ignoreRecursiveError=true", commandEnv.option.FilerAddress.ToHttpAddress(), uploadsDir, staleUpload)
		fmt.Fprintf(writer, "purge %s\n", deleteUrl)

		err = util.Delete(deleteUrl, "")
		if err != nil {
			return fmt.Errorf("purge %s/%s: %v", uploadsDir, staleUpload, err)
		}
	}

	return nil

}
<commit_msg>avoid breaking loop in cleanupUploads if error is empty<commit_after>package shell

import (
	"flag"
	"fmt"
	"github.com/chrislusf/seaweedfs/weed/util"
	"io"
	"math"
	"time"

	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
)

func init() {
	Commands = append(Commands, &commandS3CleanUploads{})
}

type commandS3CleanUploads struct {
}

func (c *commandS3CleanUploads) Name() string {
	return "s3.clean.uploads"
}

func (c *commandS3CleanUploads) Help() string {
	return `clean up stale multipart uploads

	Example:
		s3.clean.uploads -timeAgo 1.5h

`
}

func (c *commandS3CleanUploads) Do(args []string, commandEnv *CommandEnv, writer io.Writer) (err error) {

	bucketCommand := flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	uploadedTimeAgo := bucketCommand.Duration("timeAgo", 24*time.Hour, "created time before now. \"1.5h\" or \"2h45m\". Valid time units are \"m\", \"h\"")
	if err = bucketCommand.Parse(args); err != nil {
		return nil
	}

	var filerBucketsPath string
	filerBucketsPath, err = readFilerBucketsPath(commandEnv)
	if err != nil {
		return fmt.Errorf("read buckets: %v", err)
	}

	var buckets []string
	err = filer_pb.List(commandEnv, filerBucketsPath, "", func(entry *filer_pb.Entry, isLast bool) error {
		buckets = append(buckets, entry.Name)
		return nil
	}, "", false, math.MaxUint32)
	if err != nil {
		return fmt.Errorf("list buckets under %v: %v", filerBucketsPath, err)
	}

	for _, bucket := range buckets {
		if err := c.cleanupUploads(commandEnv, writer, filerBucketsPath, bucket, *uploadedTimeAgo); err != nil {
			fmt.Fprintf(writer, fmt.Sprintf("failed cleanup uploads for backet %s: %v", bucket, err))
		}
	}

	return err

}

func (c *commandS3CleanUploads) cleanupUploads(commandEnv *CommandEnv, writer io.Writer, filerBucketsPath string, bucket string, timeAgo time.Duration) error {
	uploadsDir := filerBucketsPath + "/" + bucket + "/.uploads"
	var staleUploads []string
	now := time.Now()
	err := filer_pb.List(commandEnv, uploadsDir, "", func(entry *filer_pb.Entry, isLast bool) error {
		ctime := time.Unix(entry.Attributes.Crtime, 0)
		if ctime.Add(timeAgo).Before(now) {
			staleUploads = append(staleUploads, entry.Name)
		}
		return nil
	}, "", false, math.MaxUint32)
	if err != nil {
		return fmt.Errorf("list uploads under %v: %v", uploadsDir, err)
	}

	for _, staleUpload := range staleUploads {
		deleteUrl := fmt.Sprintf("http://%s%s/%s?recursive=true&ignoreRecursiveError=true", commandEnv.option.FilerAddress.ToHttpAddress(), uploadsDir, staleUpload)
		fmt.Fprintf(writer, "purge %s\n", deleteUrl)

		err = util.Delete(deleteUrl, "")
		if err != nil && err.Error() != "" {
			return fmt.Errorf("purge %s/%s: %v", uploadsDir, staleUpload, err)
		}
	}

	return nil

}
<|endoftext|>


<commit_before>/*
** Copyright [2012-2014] [Megam Systems]
**
** 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 action

import (
	"errors"
	"fmt"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/megamsys/libgo/cmd"
)

// Result is the value returned by Forward. It is used in the call of the next
// action, and also when rolling back the actions.
type Result interface{}

// Forward is the function called by the pipeline executor in the forward
// phase.  It receives a FWContext instance, that contains the list of
// parameters given to the pipeline executor and the result of the previous
// action in the pipeline (which will be nil for the first action in the
// pipeline).
type Forward func(context FWContext) (Result, error)

// Backward is the function called by the pipeline executor when in the
// backward phase. It receives the context instance, that contains the list of
// parameters given to the pipeline executor and the result of the forward
// phase.
type Backward func(context BWContext)

type OnErrorFunc func(FWContext, error)

// FWContext is the context used in calls to Forward functions (forward phase).
type FWContext struct {
	// Result of the previous action.
	Previous Result

	// List of parameters given to the executor.
	Params []interface{}
}

// BWContext is the context used in calls to Backward functions (backward
// phase).
type BWContext struct {
	// Result of the forward phase (for the current action).
	FWResult Result

	// List of parameters given to the executor.
	Params []interface{}
}

// Action defines actions that should be . It is composed of two functions:
// Forward and Backward.
//
// Each action should do only one thing, and do it well. All information that
// is needed to undo the action should be returned by the Forward function.
type Action struct {
	// Name is the action name. Used by the log.
	Name string

	// Function that will be invoked in the forward phase. This value
	// cannot be nil.
	Forward Forward

	// Function that will be invoked in the backward phase. For actions
	// that are not undoable, this attribute should be nil.
	Backward Backward

	// Minimum number of parameters that this action requires to run.
	MinParams int

	// Function taht will be invoked after some failure occurured in the
	// Forward phase of this same action.
	OnError OnErrorFunc

	// Result of the action. Stored for use in the backward phase.
	result Result

	// mutex for the result
	rMutex sync.Mutex
}

// Pipeline is a list of actions. Each pipeline is atomic: either all actions
// are successfully executed, or none of them are. For that, it's fundamental
// that all actions are really small and atomic.
type Pipeline struct {
	actions []*Action
}

// NewPipeline creates a new pipeline instance with the given list of actions.
func NewPipeline(actions ...*Action) *Pipeline {
	return &Pipeline{actions: actions}
}

func (p *Pipeline) Result() Result {
	action := p.actions[len(p.actions)-1]
	action.rMutex.Lock()
	defer action.rMutex.Unlock()
	return action.result
}

// Execute executes the pipeline.
//
// The execution starts in the forward phase, calling the Forward function of
// all actions. If none of the Forward calls return error, the pipeline
// execution ends in the forward phase and is "committed".
//
// If any of the Forward calls fails, the executor switches to the backward phase
// (roll back) and call the Backward function for each action completed. It
// does not call the Backward function of the action that has failed.
//
// After rolling back all completed actions, it returns the original error
// returned by the action that failed.
func (p *Pipeline) Execute(params ...interface{}) error {
	var (
		r   Result
		err error
	)
	if len(p.actions) == 0 {
		return errors.New("No actions to execute.")
	}

	log.Debugf(cmd.Colorfy(fmt.Sprintf("==> pipeline [%d]", len(p.actions)), "gren", "", "bold"))

	fwCtx := FWContext{Params: params}
	for i, a := range p.actions {
		log.Debugf(cmd.Colorfy(fmt.Sprintf("  ==> step %d: %s action", i, a.Name), "blue", "", "bold"))
		if a.Forward == nil {
			err = errors.New("All actions must define the forward function.")
		} else if len(fwCtx.Params) < a.MinParams {
			err = errors.New("Not enough parameters to call Action.Forward.")
		} else {
			r, err = a.Forward(fwCtx)
			a.rMutex.Lock()
			a.result = r
			a.rMutex.Unlock()
			fwCtx.Previous = r
		}
		if err != nil {
			log.Debugf(cmd.Colorfy(fmt.Sprintf("  ==> step %d: %s action error - %s", i, a.Name, err), "yellow", "", ""))
			if a.OnError != nil {
				a.OnError(fwCtx, err)
			}
			p.rollback(i-1, params)
			return err
		}
	}
	log.Debugf(cmd.Colorfy("==> pipeline /-end-/", "green", "", "bold"))
	return nil
}

func (p *Pipeline) rollback(index int, params []interface{}) {
	bwCtx := BWContext{Params: params}
	for i := index; i >= 0; i-- {
		log.Debugf(cmd.Colorfy(fmt.Sprintf("  ==> step %d: %s action", i, p.actions[i].Name), "red", "", "bold"))
		if p.actions[i].Backward != nil {
			bwCtx.FWResult = p.actions[i].result
			p.actions[i].Backward(bwCtx)
		}
	}
}
<commit_msg>log color change<commit_after>/*
** Copyright [2012-2014] [Megam Systems]
**
** 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 action

import (
	"errors"
	"fmt"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/megamsys/libgo/cmd"
)

// Result is the value returned by Forward. It is used in the call of the next
// action, and also when rolling back the actions.
type Result interface{}

// Forward is the function called by the pipeline executor in the forward
// phase.  It receives a FWContext instance, that contains the list of
// parameters given to the pipeline executor and the result of the previous
// action in the pipeline (which will be nil for the first action in the
// pipeline).
type Forward func(context FWContext) (Result, error)

// Backward is the function called by the pipeline executor when in the
// backward phase. It receives the context instance, that contains the list of
// parameters given to the pipeline executor and the result of the forward
// phase.
type Backward func(context BWContext)

type OnErrorFunc func(FWContext, error)

// FWContext is the context used in calls to Forward functions (forward phase).
type FWContext struct {
	// Result of the previous action.
	Previous Result

	// List of parameters given to the executor.
	Params []interface{}
}

// BWContext is the context used in calls to Backward functions (backward
// phase).
type BWContext struct {
	// Result of the forward phase (for the current action).
	FWResult Result

	// List of parameters given to the executor.
	Params []interface{}
}

// Action defines actions that should be . It is composed of two functions:
// Forward and Backward.
//
// Each action should do only one thing, and do it well. All information that
// is needed to undo the action should be returned by the Forward function.
type Action struct {
	// Name is the action name. Used by the log.
	Name string

	// Function that will be invoked in the forward phase. This value
	// cannot be nil.
	Forward Forward

	// Function that will be invoked in the backward phase. For actions
	// that are not undoable, this attribute should be nil.
	Backward Backward

	// Minimum number of parameters that this action requires to run.
	MinParams int

	// Function taht will be invoked after some failure occurured in the
	// Forward phase of this same action.
	OnError OnErrorFunc

	// Result of the action. Stored for use in the backward phase.
	result Result

	// mutex for the result
	rMutex sync.Mutex
}

// Pipeline is a list of actions. Each pipeline is atomic: either all actions
// are successfully executed, or none of them are. For that, it's fundamental
// that all actions are really small and atomic.
type Pipeline struct {
	actions []*Action
}

// NewPipeline creates a new pipeline instance with the given list of actions.
func NewPipeline(actions ...*Action) *Pipeline {
	return &Pipeline{actions: actions}
}

func (p *Pipeline) Result() Result {
	action := p.actions[len(p.actions)-1]
	action.rMutex.Lock()
	defer action.rMutex.Unlock()
	return action.result
}

// Execute executes the pipeline.
//
// The execution starts in the forward phase, calling the Forward function of
// all actions. If none of the Forward calls return error, the pipeline
// execution ends in the forward phase and is "committed".
//
// If any of the Forward calls fails, the executor switches to the backward phase
// (roll back) and call the Backward function for each action completed. It
// does not call the Backward function of the action that has failed.
//
// After rolling back all completed actions, it returns the original error
// returned by the action that failed.
func (p *Pipeline) Execute(params ...interface{}) error {
	var (
		r   Result
		err error
	)
	if len(p.actions) == 0 {
		return errors.New("No actions to execute.")
	}

	log.Debugf(cmd.Colorfy(fmt.Sprintf("==> pipeline [%d]", len(p.actions)), "light gray", "", "bold"))

	fwCtx := FWContext{Params: params}
	for i, a := range p.actions {
		log.Debugf(cmd.Colorfy(fmt.Sprintf("  ==> step %d: %s action", i, a.Name), "green", "", "bold"))
		if a.Forward == nil {
			err = errors.New("All actions must define the forward function.")
		} else if len(fwCtx.Params) < a.MinParams {
			err = errors.New("Not enough parameters to call Action.Forward.")
		} else {
			r, err = a.Forward(fwCtx)
			a.rMutex.Lock()
			a.result = r
			a.rMutex.Unlock()
			fwCtx.Previous = r
		}
		if err != nil {
			log.Debugf(cmd.Colorfy(fmt.Sprintf("  ==> step %d: %s action error - %s", i, a.Name, err), "yellow", "", ""))
			if a.OnError != nil {
				a.OnError(fwCtx, err)
			}
			p.rollback(i-1, params)
			return err
		}
	}
	log.Debugf(cmd.Colorfy("==> pipeline /-end-/", "light gray", "", "bold"))
	return nil
}

func (p *Pipeline) rollback(index int, params []interface{}) {
	bwCtx := BWContext{Params: params}
	for i := index; i >= 0; i-- {
		log.Debugf(cmd.Colorfy(fmt.Sprintf("  ==> step %d: %s action", i, p.actions[i].Name), "red", "", "bold"))
		if p.actions[i].Backward != nil {
			bwCtx.FWResult = p.actions[i].result
			p.actions[i].Backward(bwCtx)
		}
	}
}
<|endoftext|>


<commit_before>package actor

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

	"github.com/emirpasic/gods/stacks/linkedliststack"
)

type Request struct {
	Message interface{}
	Sender  *PID
}

type MessageInvoker interface {
	InvokeSystemMessage(SystemMessage)
	InvokeUserMessage(interface{})
}

type Context interface {
	// Watch registers the actor as a monitor for the specified PID
	Watch(*PID)

	// Unwatch unregisters the actor as a monitor for the specified PID
	Unwatch(*PID)

	// Message returns the current message to be processed
	Message() interface{}

	// SetReceiveTimeout sets the inactivity timeout, after which a ReceiveTimeout message will be sent to the actor.
	// A duration of less than 1ms will disable the inactivity timer.
	SetReceiveTimeout(d time.Duration)

	// ReceiveTimeout returns the current timeout
	ReceiveTimeout() time.Duration

	// Sender returns the PID of actor that sent currently processed message
	Sender() *PID

	// Become replaces the actors current Receive handler with a new handler
	Become(Receive)

	// BecomeStacked pushes a new Receive handler on the current handler stack
	BecomeStacked(Receive)

	// UnbecomeStacked reverts to the previous Receive handler
	UnbecomeStacked()

	// Self returns the PID for the current actor
	Self() *PID

	// Parent returns the PID for the current actors parent
	Parent() *PID

	// Spawn spawns a child actor using the given Props
	Spawn(Props) *PID

	// SpawnNamed spawns a named child actor using the given Props
	SpawnNamed(Props, string) *PID

	// Returns a slice of the current actors children
	Children() []*PID

	// Next performs the next middleware or base Receive handler
	Next()

	// Receive processes a custom user message synchronously
	Receive(interface{})

	// Stash stashes the current message on a stack for reprocessing when the actor restarts
	Stash()

	// Respond sends a response to the to the current `Sender`
	Respond(response interface{})

	// Actor returns the actor associated with this context
	Actor() Actor
}

func (cell *actorCell) Actor() Actor {
	return cell.actor
}

func (cell *actorCell) Message() interface{} {
	userMessage, ok := cell.message.(*Request)
	if ok {
		return userMessage.Message
	}
	return cell.message
}

func (cell *actorCell) Sender() *PID {
	userMessage, ok := cell.message.(*Request)
	if ok {
		return userMessage.Sender
	}
	return nil
}

func (cell *actorCell) Stash() {
	if cell.stash == nil {
		cell.stash = linkedliststack.New()
	}

	cell.stash.Push(cell.message)
}

func (cell *actorCell) cancelTimer() {
	if cell.t != nil {
		cell.t.Stop()
		cell.t = nil
	}
}

func (cell *actorCell) receiveTimeoutHandler() {
	cell.self.Request(receiveTimeoutMessage, nil)
}

func (cell *actorCell) SetReceiveTimeout(d time.Duration) {
	if d == cell.receiveTimeout {
		return
	}
	if cell.t != nil {
		cell.t.Stop()
	}

	if d < time.Millisecond {
		// anything less than than 1 millisecond is set to zero
		d = 0
	}

	cell.receiveTimeout = d
	if d > 0 {
		if cell.t == nil {
			cell.t = time.AfterFunc(d, cell.receiveTimeoutHandler)
		} else {
			cell.t.Reset(d)
		}
	}
}

func (cell *actorCell) ReceiveTimeout() time.Duration {
	return cell.receiveTimeout
}

type actorCell struct {
	message        interface{}
	parent         *PID
	self           *PID
	actor          Actor
	props          Props
	behavior       behaviorStack
	receive        Receive
	children       PIDSet
	watchers       PIDSet
	watching       PIDSet
	stash          *linkedliststack.Stack
	receiveIndex   int
	stopping       bool
	restarting     bool
	receiveTimeout time.Duration
	t              *time.Timer
}

func (cell *actorCell) Children() []*PID {
	r := make([]*PID, cell.children.Len())
	cell.children.ForEach(func(i int, p PID) {
		r[i] = &p
	})
	return r
}

func (cell *actorCell) Self() *PID {
	return cell.self
}

func (cell *actorCell) Parent() *PID {
	return cell.parent
}

func NewActorCell(props Props, parent *PID) *actorCell {
	cell := &actorCell{
		parent: parent,
		props:  props,
	}
	cell.incarnateActor()
	return cell
}

func (cell *actorCell) Receive(message interface{}) {
	i := cell.receiveIndex
	m := cell.message

	cell.receiveIndex = 0
	cell.message = message
	cell.Next()

	cell.receiveIndex = i
	cell.message = m
}

func (cell *actorCell) Next() {
	if cell.receiveIndex < len(cell.props.receivePlugins) {
		receive := cell.props.receivePlugins[cell.receiveIndex]
		cell.receiveIndex++
		receive(cell)
	} else {
		cell.AutoReceiveOrUser()
	}
}
func (cell *actorCell) incarnateActor() {
	actor := cell.props.ProduceActor()
	cell.restarting = false
	cell.stopping = false
	cell.actor = actor
	cell.Become(actor.Receive)
}

func (cell *actorCell) InvokeSystemMessage(message SystemMessage) {
	switch msg := message.(interface{}).(type) {
	case *SuspendMailbox:
		//pass
	case *ResumeMailbox:
		//pass
	case *Stop:
		cell.handleStop(msg)
	case *Terminated:
		cell.handleTerminated(msg)
	case *Watch:
		cell.watchers.Add(msg.Watcher)
	case *Unwatch:
		cell.watchers.Remove(msg.Watcher)
	case *Failure:
		cell.handleFailure(msg)
	case *Restart:
		cell.handleRestart(msg)
	default:
		log.Printf("Unknown system message %T", msg)
	}
}

func (cell *actorCell) handleRestart(msg *Restart) {
	cell.stopping = false
	cell.restarting = true
	cell.InvokeUserMessage(restartingMessage)
	cell.children.ForEach(func(_ int, pid PID) {
		pid.Stop()
	})
	cell.tryRestartOrTerminate()
}

//I am stopping
func (cell *actorCell) handleStop(msg *Stop) {
	cell.stopping = true
	cell.restarting = false
	cell.InvokeUserMessage(stoppingMessage)
	cell.children.ForEach(func(_ int, pid PID) {
		pid.Stop()
	})
	cell.tryRestartOrTerminate()
}

//child stopped, check if we can stop or restart (if needed)
func (cell *actorCell) handleTerminated(msg *Terminated) {
	cell.children.Remove(msg.Who)
	cell.watching.Remove(msg.Who)

	cell.InvokeUserMessage(msg)
	cell.tryRestartOrTerminate()
}

//offload the supervision completely to the supervisor strategy
func (cell *actorCell) handleFailure(msg *Failure) {
	if strategy, ok := cell.actor.(SupervisorStrategy); ok {
		strategy.HandleFailure(cell, msg.Who, msg.Reason)
		return
	}
	cell.props.Supervisor().HandleFailure(cell, msg.Who, msg.Reason)
}

func (cell *actorCell) EscalateFailure(who *PID, reason interface{}) {
	//suspend self
	cell.Self().sendSystemMessage(suspendMailboxMessage)
	//send failure to parent
	cell.Parent().sendSystemMessage(&Failure{Reason: reason, Who: who})
}

func (cell *actorCell) tryRestartOrTerminate() {
	if cell.t != nil {
		cell.t.Stop()
		cell.t = nil
		cell.receiveTimeout = 0
	}

	if !cell.children.Empty() {
		return
	}

	if cell.restarting {
		cell.restart()
		return
	}

	if cell.stopping {
		cell.stopped()
	}
}

func (cell *actorCell) restart() {
	cell.incarnateActor()
	cell.InvokeUserMessage(&Started{})
	if cell.stash != nil {
		for !cell.stash.Empty() {
			msg, _ := cell.stash.Pop()
			cell.InvokeUserMessage(msg)
		}
	}
	cell.self.sendSystemMessage(resumeMailboxMessage)
}

func (cell *actorCell) stopped() {
	ProcessRegistry.remove(cell.self)
	cell.InvokeUserMessage(stoppedMessage)
	otherStopped := &Terminated{Who: cell.self}
	cell.watchers.ForEach(func(i int, pid PID) {
		pid.sendSystemMessage(otherStopped)
	})
}

func identifyPanic() string {
	var name, file string
	var line int
	var pc [16]uintptr

	n := runtime.Callers(3, pc[:])
	for _, pc := range pc[:n] {
		log.Printf("%s", pc)
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			continue
		}
		file, line = fn.FileLine(pc)
		fmt.Printf(file, line, pc)
		name = fn.Name()
		if !strings.HasPrefix(name, "runtime.") {
			break
		}
	}

	switch {
	case name != "":
		return fmt.Sprintf("%v:%v", name, line)
	case file != "":
		return fmt.Sprintf("%v:%v", file, line)
	}

	return fmt.Sprintf("pc:%x", pc)
}

func (cell *actorCell) InvokeUserMessage(md interface{}) {
	defer func() {
		if r := recover(); r != nil {
			log.Printf("[ACTOR] '%v' Recovering from: %v. Detailed stack: %v", cell.debugString(), r, identifyPanic())
			failure := &Failure{Reason: r, Who: cell.self}
			if cell.parent == nil {
				handleRootFailure(failure)
			} else {
				//TODO: Akka recursively suspends all children also on failure
				//Not sure if I think this is the right way to go, why do children need to wait for their parents failed state to recover?
				cell.self.sendSystemMessage(suspendMailboxMessage)
				cell.parent.sendSystemMessage(failure)
			}
		}
	}()
	cell.receiveIndex = 0
	cell.message = md

	influenceTimeout := true
	if cell.receiveTimeout > 0 {
		_, influenceTimeout = md.(NotInfluenceReceiveTimeout)
		influenceTimeout = !influenceTimeout
		if influenceTimeout {
			cell.t.Stop()
		}
	}

	//optimize fast path, remove next from profiler flow
	if cell.props.receivePlugins == nil {
		cell.AutoReceiveOrUser()
	} else {
		cell.Next()
	}

	if cell.receiveTimeout > 0 && influenceTimeout {
		cell.t.Reset(cell.receiveTimeout)
	}
}

func (cell *actorCell) AutoReceiveOrUser() {
	switch cell.Message().(type) {
	case *PoisonPill:
		cell.self.Stop()
	default:
		cell.receive(cell)
	}
}

func (cell *actorCell) Become(behavior Receive) {
	cell.behavior.Clear()
	cell.receive = behavior
}

func (cell *actorCell) BecomeStacked(behavior Receive) {
	cell.behavior.Push(cell.receive)
	cell.receive = behavior
}

func (cell *actorCell) UnbecomeStacked() {
	if cell.behavior.Len() == 0 {
		panic("Can not unbecome actor base behavior")
	}
	cell.receive, _ = cell.behavior.Pop()
}

func (cell *actorCell) Watch(who *PID) {
	who.sendSystemMessage(&Watch{
		Watcher: cell.self,
	})
	cell.watching.Add(who)
}

func (cell *actorCell) Unwatch(who *PID) {
	who.sendSystemMessage(&Unwatch{
		Watcher: cell.self,
	})
	cell.watching.Remove(who)
}

func (cell *actorCell) Respond(response interface{}) {
	if cell.Sender() == nil {
		log.Fatal("[ACTOR] No sender")
	}
	cell.Sender().Tell(response)
}

func (cell *actorCell) Spawn(props Props) *PID {
	id := ProcessRegistry.getAutoId()
	return cell.SpawnNamed(props, id)
}

func (cell *actorCell) SpawnNamed(props Props, name string) *PID {
	var fullName string
	if cell.parent != nil {
		fullName = cell.parent.Id + "/" + name
	} else {
		fullName = name
	}

	pid := spawn(fullName, props, cell.self)
	cell.children.Add(pid)
	cell.Watch(pid)
	return pid
}

func (cell *actorCell) debugString() string {
	return fmt.Sprintf("%v/%v:%v", cell.self.Host, cell.self.Id, reflect.TypeOf(cell.actor))
}

func handleRootFailure(msg *Failure) {
	defaultSupervisionStrategy.HandleFailure(nil, msg.Who, msg.Reason)
}
<commit_msg>simplify<commit_after>package actor

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

	"github.com/emirpasic/gods/stacks/linkedliststack"
)

type Request struct {
	Message interface{}
	Sender  *PID
}

type MessageInvoker interface {
	InvokeSystemMessage(SystemMessage)
	InvokeUserMessage(interface{})
}

type Context interface {
	// Watch registers the actor as a monitor for the specified PID
	Watch(*PID)

	// Unwatch unregisters the actor as a monitor for the specified PID
	Unwatch(*PID)

	// Message returns the current message to be processed
	Message() interface{}

	// SetReceiveTimeout sets the inactivity timeout, after which a ReceiveTimeout message will be sent to the actor.
	// A duration of less than 1ms will disable the inactivity timer.
	SetReceiveTimeout(d time.Duration)

	// ReceiveTimeout returns the current timeout
	ReceiveTimeout() time.Duration

	// Sender returns the PID of actor that sent currently processed message
	Sender() *PID

	// Become replaces the actors current Receive handler with a new handler
	Become(Receive)

	// BecomeStacked pushes a new Receive handler on the current handler stack
	BecomeStacked(Receive)

	// UnbecomeStacked reverts to the previous Receive handler
	UnbecomeStacked()

	// Self returns the PID for the current actor
	Self() *PID

	// Parent returns the PID for the current actors parent
	Parent() *PID

	// Spawn spawns a child actor using the given Props
	Spawn(Props) *PID

	// SpawnNamed spawns a named child actor using the given Props
	SpawnNamed(Props, string) *PID

	// Returns a slice of the current actors children
	Children() []*PID

	// Next performs the next middleware or base Receive handler
	Next()

	// Receive processes a custom user message synchronously
	Receive(interface{})

	// Stash stashes the current message on a stack for reprocessing when the actor restarts
	Stash()

	// Respond sends a response to the to the current `Sender`
	Respond(response interface{})

	// Actor returns the actor associated with this context
	Actor() Actor
}

func (cell *actorCell) Actor() Actor {
	return cell.actor
}

func (cell *actorCell) Message() interface{} {
	userMessage, ok := cell.message.(*Request)
	if ok {
		return userMessage.Message
	}
	return cell.message
}

func (cell *actorCell) Sender() *PID {
	userMessage, ok := cell.message.(*Request)
	if ok {
		return userMessage.Sender
	}
	return nil
}

func (cell *actorCell) Stash() {
	if cell.stash == nil {
		cell.stash = linkedliststack.New()
	}

	cell.stash.Push(cell.message)
}

func (cell *actorCell) cancelTimer() {
	if cell.t != nil {
		cell.t.Stop()
		cell.t = nil
	}
}

func (cell *actorCell) receiveTimeoutHandler() {
	cell.self.Request(receiveTimeoutMessage, nil)
}

func (cell *actorCell) SetReceiveTimeout(d time.Duration) {
	if d == cell.receiveTimeout {
		return
	}
	if cell.t != nil {
		cell.t.Stop()
	}

	if d < time.Millisecond {
		// anything less than than 1 millisecond is set to zero
		d = 0
	}

	cell.receiveTimeout = d
	if d > 0 {
		if cell.t == nil {
			cell.t = time.AfterFunc(d, cell.receiveTimeoutHandler)
		} else {
			cell.t.Reset(d)
		}
	}
}

func (cell *actorCell) ReceiveTimeout() time.Duration {
	return cell.receiveTimeout
}

type actorCell struct {
	message        interface{}
	parent         *PID
	self           *PID
	actor          Actor
	props          Props
	behavior       behaviorStack
	receive        Receive
	children       PIDSet
	watchers       PIDSet
	watching       PIDSet
	stash          *linkedliststack.Stack
	receiveIndex   int
	stopping       bool
	restarting     bool
	receiveTimeout time.Duration
	t              *time.Timer
}

func (cell *actorCell) Children() []*PID {
	r := make([]*PID, cell.children.Len())
	cell.children.ForEach(func(i int, p PID) {
		r[i] = &p
	})
	return r
}

func (cell *actorCell) Self() *PID {
	return cell.self
}

func (cell *actorCell) Parent() *PID {
	return cell.parent
}

func NewActorCell(props Props, parent *PID) *actorCell {
	cell := &actorCell{
		parent: parent,
		props:  props,
	}
	cell.incarnateActor()
	return cell
}

func (cell *actorCell) Receive(message interface{}) {
	i := cell.receiveIndex
	m := cell.message

	cell.receiveIndex = 0
	cell.message = message
	cell.Next()

	cell.receiveIndex = i
	cell.message = m
}

func (cell *actorCell) Next() {
	if cell.receiveIndex < len(cell.props.receivePlugins) {
		receive := cell.props.receivePlugins[cell.receiveIndex]
		cell.receiveIndex++
		receive(cell)
	} else {
		cell.AutoReceiveOrUser()
	}
}
func (cell *actorCell) incarnateActor() {
	actor := cell.props.ProduceActor()
	cell.restarting = false
	cell.stopping = false
	cell.actor = actor
	cell.receive = actor.Receive
}

func (cell *actorCell) InvokeSystemMessage(message SystemMessage) {
	switch msg := message.(interface{}).(type) {
	case *SuspendMailbox:
		//pass
	case *ResumeMailbox:
		//pass
	case *Stop:
		cell.handleStop(msg)
	case *Terminated:
		cell.handleTerminated(msg)
	case *Watch:
		cell.watchers.Add(msg.Watcher)
	case *Unwatch:
		cell.watchers.Remove(msg.Watcher)
	case *Failure:
		cell.handleFailure(msg)
	case *Restart:
		cell.handleRestart(msg)
	default:
		log.Printf("Unknown system message %T", msg)
	}
}

func (cell *actorCell) handleRestart(msg *Restart) {
	cell.stopping = false
	cell.restarting = true
	cell.InvokeUserMessage(restartingMessage)
	cell.children.ForEach(func(_ int, pid PID) {
		pid.Stop()
	})
	cell.tryRestartOrTerminate()
}

//I am stopping
func (cell *actorCell) handleStop(msg *Stop) {
	cell.stopping = true
	cell.restarting = false
	cell.InvokeUserMessage(stoppingMessage)
	cell.children.ForEach(func(_ int, pid PID) {
		pid.Stop()
	})
	cell.tryRestartOrTerminate()
}

//child stopped, check if we can stop or restart (if needed)
func (cell *actorCell) handleTerminated(msg *Terminated) {
	cell.children.Remove(msg.Who)
	cell.watching.Remove(msg.Who)

	cell.InvokeUserMessage(msg)
	cell.tryRestartOrTerminate()
}

//offload the supervision completely to the supervisor strategy
func (cell *actorCell) handleFailure(msg *Failure) {
	if strategy, ok := cell.actor.(SupervisorStrategy); ok {
		strategy.HandleFailure(cell, msg.Who, msg.Reason)
		return
	}
	cell.props.Supervisor().HandleFailure(cell, msg.Who, msg.Reason)
}

func (cell *actorCell) EscalateFailure(who *PID, reason interface{}) {
	//suspend self
	cell.Self().sendSystemMessage(suspendMailboxMessage)
	//send failure to parent
	cell.Parent().sendSystemMessage(&Failure{Reason: reason, Who: who})
}

func (cell *actorCell) tryRestartOrTerminate() {
	if cell.t != nil {
		cell.t.Stop()
		cell.t = nil
		cell.receiveTimeout = 0
	}

	if !cell.children.Empty() {
		return
	}

	if cell.restarting {
		cell.restart()
		return
	}

	if cell.stopping {
		cell.stopped()
	}
}

func (cell *actorCell) restart() {
	cell.incarnateActor()
	cell.InvokeUserMessage(&Started{})
	if cell.stash != nil {
		for !cell.stash.Empty() {
			msg, _ := cell.stash.Pop()
			cell.InvokeUserMessage(msg)
		}
	}
	cell.self.sendSystemMessage(resumeMailboxMessage)
}

func (cell *actorCell) stopped() {
	ProcessRegistry.remove(cell.self)
	cell.InvokeUserMessage(stoppedMessage)
	otherStopped := &Terminated{Who: cell.self}
	cell.watchers.ForEach(func(i int, pid PID) {
		pid.sendSystemMessage(otherStopped)
	})
}

func identifyPanic() string {
	var name, file string
	var line int
	var pc [16]uintptr

	n := runtime.Callers(3, pc[:])
	for _, pc := range pc[:n] {
		log.Printf("%s", pc)
		fn := runtime.FuncForPC(pc)
		if fn == nil {
			continue
		}
		file, line = fn.FileLine(pc)
		fmt.Printf(file, line, pc)
		name = fn.Name()
		if !strings.HasPrefix(name, "runtime.") {
			break
		}
	}

	switch {
	case name != "":
		return fmt.Sprintf("%v:%v", name, line)
	case file != "":
		return fmt.Sprintf("%v:%v", file, line)
	}

	return fmt.Sprintf("pc:%x", pc)
}

func (cell *actorCell) InvokeUserMessage(md interface{}) {
	defer func() {
		if r := recover(); r != nil {
			log.Printf("[ACTOR] '%v' Recovering from: %v. Detailed stack: %v", cell.debugString(), r, identifyPanic())
			failure := &Failure{Reason: r, Who: cell.self}
			if cell.parent == nil {
				handleRootFailure(failure)
			} else {
				//TODO: Akka recursively suspends all children also on failure
				//Not sure if I think this is the right way to go, why do children need to wait for their parents failed state to recover?
				cell.self.sendSystemMessage(suspendMailboxMessage)
				cell.parent.sendSystemMessage(failure)
			}
		}
	}()
	cell.receiveIndex = 0
	cell.message = md

	influenceTimeout := true
	if cell.receiveTimeout > 0 {
		_, influenceTimeout = md.(NotInfluenceReceiveTimeout)
		influenceTimeout = !influenceTimeout
		if influenceTimeout {
			cell.t.Stop()
		}
	}

	//optimize fast path, remove next from profiler flow
	if cell.props.receivePlugins == nil {
		cell.AutoReceiveOrUser()
	} else {
		cell.Next()
	}

	if cell.receiveTimeout > 0 && influenceTimeout {
		cell.t.Reset(cell.receiveTimeout)
	}
}

func (cell *actorCell) AutoReceiveOrUser() {
	switch cell.Message().(type) {
	case *PoisonPill:
		cell.self.Stop()
	default:
		cell.receive(cell)
	}
}

func (cell *actorCell) Become(behavior Receive) {
	cell.behavior.Clear()
	cell.receive = behavior
}

func (cell *actorCell) BecomeStacked(behavior Receive) {
	cell.behavior.Push(cell.receive)
	cell.receive = behavior
}

func (cell *actorCell) UnbecomeStacked() {
	if cell.behavior.Len() == 0 {
		panic("Can not unbecome actor base behavior")
	}
	cell.receive, _ = cell.behavior.Pop()
}

func (cell *actorCell) Watch(who *PID) {
	who.sendSystemMessage(&Watch{
		Watcher: cell.self,
	})
	cell.watching.Add(who)
}

func (cell *actorCell) Unwatch(who *PID) {
	who.sendSystemMessage(&Unwatch{
		Watcher: cell.self,
	})
	cell.watching.Remove(who)
}

func (cell *actorCell) Respond(response interface{}) {
	if cell.Sender() == nil {
		log.Fatal("[ACTOR] No sender")
	}
	cell.Sender().Tell(response)
}

func (cell *actorCell) Spawn(props Props) *PID {
	id := ProcessRegistry.getAutoId()
	return cell.SpawnNamed(props, id)
}

func (cell *actorCell) SpawnNamed(props Props, name string) *PID {
	var fullName string
	if cell.parent != nil {
		fullName = cell.parent.Id + "/" + name
	} else {
		fullName = name
	}

	pid := spawn(fullName, props, cell.self)
	cell.children.Add(pid)
	cell.Watch(pid)
	return pid
}

func (cell *actorCell) debugString() string {
	return fmt.Sprintf("%v/%v:%v", cell.self.Host, cell.self.Id, reflect.TypeOf(cell.actor))
}

func handleRootFailure(msg *Failure) {
	defaultSupervisionStrategy.HandleFailure(nil, msg.Who, msg.Reason)
}
<|endoftext|>


<commit_before>// Copyright 2016 Philippe Beaudoin
//
// 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 dynstory

import (
    "io/ioutil"
    "net/http"
)

var (
  mainTemplate []byte
)

func init() {
  content, err := ioutil.ReadFile("dynamic-story/mainTemplate.html")
  if err != nil {
    panic(err)
  }
  mainTemplate = content

  http.HandleFunc("/", root)
}

func root(w http.ResponseWriter, r *http.Request) {
  w.Write(mainTemplate)
}<commit_msg>Added basic authentication.<commit_after>// Copyright 2016 Philippe Beaudoin
//
// 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 dynstory

import (
    "io/ioutil"
    "net/http"

    "appengine"
    "appengine/user"
)

var (
  mainTemplate []byte
)

func init() {
  content, err := ioutil.ReadFile("dynamic-story/mainTemplate.html")
  if err != nil {
    panic(err)
  }
  mainTemplate = content

  http.HandleFunc("/", root)
}

func root(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-type", "text/html; charset=utf-8")
  ctx := appengine.NewContext(r)
  u := user.Current(ctx)
  if u == nil {
    url, err := user.LoginURL(ctx, r.URL.String())
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    w.Header().Set("Location", url)
    w.WriteHeader(http.StatusFound)
    return
  }

  if !user.IsAdmin(ctx) {
    http.Error(w, "Unauthorized user.", http.StatusUnauthorized)
    return
  }

  w.Write(mainTemplate)
}<|endoftext|>


<commit_before>package dynamicDrivers

import (
	"encoding/json"
	"errors"
	"strings"
)

func uploadMachineSchema(drivers []string) error {
	err := uploadMachineServiceJSON(drivers)
	err2 := uploadMachineProjectJSON(drivers)
	err3 := uploadMachineUserJSON(drivers)
	if err != nil || err2 != nil || err3 != nil {
		return errors.New("Failed to upload one of the machine jsons.")
	}
	return nil
}

func genFieldSchema(resourceFieldStruct ResourceFieldConfigs, field, fieldType, auth string) {
	resourceFieldStruct[field] = ResourceFieldConfig{
		Nullable: true,
		Type:     fieldType,
		Create:   strings.Contains(auth, "c"),
		Update:   strings.Contains(auth, "u"),
	}
}
func nameField(resourceFieldStruct ResourceFieldConfigs) {
	resourceFieldStruct["name"] = ResourceFieldConfig{
		Type:     "string",
		Create:   true,
		Update:   false,
		Required: true,
		Nullable: false,
	}
}

func uploadMachineServiceJSON(drivers []string) error {
	resourceFieldStruct := make(map[string]interface{})
	resourceFieldMap := make(ResourceFieldConfigs)
	resourceFieldStruct["collectionMethods"] = []string{"GET", "POST", "PUT", "DELETE"}
	resourceFieldStruct["resourceMethods"] = []string{"GET", "PUT", "DELETE"}
	resourceFieldStruct["resourceFields"] = resourceFieldMap
	for _, driver := range drivers {
		genFieldSchema(resourceFieldMap, driver+"Config", driver+"Config", "c")
	}
	genFieldSchema(resourceFieldMap, "authCertificateAuthority", "string", "c")
	genFieldSchema(resourceFieldMap, "authKey", "string", "c")
	genFieldSchema(resourceFieldMap, "dockerVersion", "string", "c")
	genFieldSchema(resourceFieldMap, "engineEnv", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineInsecureRegistry", "array[string]", "c")
	genFieldSchema(resourceFieldMap, "engineInstallUrl", "string", "c")
	genFieldSchema(resourceFieldMap, "engineLabel", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineOpt", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineRegistryMirror", "array[string]", "c")
	genFieldSchema(resourceFieldMap, "engineStorageDriver", "string", "c")
	genFieldSchema(resourceFieldMap, "extractedConfig", "string", "u")
	genFieldSchema(resourceFieldMap, "labels", "map[string]", "cu")
	nameField(resourceFieldMap)

	jsonData, err := json.MarshalIndent(resourceFieldStruct, "", "    ")
	if err != nil {
		return err
	}
	return uploadDynamicSchema("machine", string(jsonData), "physicalHost", []string{"service"}, true)
}

func uploadMachineProjectJSON(drivers []string) error {
	resourceFieldStruct := make(map[string]interface{})
	resourceFieldMap := make(ResourceFieldConfigs)
	resourceFieldStruct["collectionMethods"] = []string{"GET", "POST", "DELETE"}
	resourceFieldStruct["resourceMethods"] = []string{"GET", "DELETE"}
	resourceFieldStruct["resourceFields"] = resourceFieldMap
	for _, driver := range drivers {
		genFieldSchema(resourceFieldMap, driver+"Config", driver+"Config", "c")
	}
	genFieldSchema(resourceFieldMap, "authCertificateAuthority", "string", "c")
	genFieldSchema(resourceFieldMap, "authKey", "string", "c")
	genFieldSchema(resourceFieldMap, "dockerVersion", "string", "c")
	genFieldSchema(resourceFieldMap, "engineEnv", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineInsecureRegistry", "array[string]", "c")
	genFieldSchema(resourceFieldMap, "engineInstallUrl", "string", "c")
	genFieldSchema(resourceFieldMap, "engineLabel", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineOpt", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineRegistryMirror", "array[string]", "c")
	genFieldSchema(resourceFieldMap, "engineStorageDriver", "string", "c")
	genFieldSchema(resourceFieldMap, "labels", "map[string]", "c")
	nameField(resourceFieldMap)

	jsonData, err := json.MarshalIndent(resourceFieldStruct, "", "    ")
	if err != nil {
		return err
	}
	return uploadDynamicSchema("machine", string(jsonData), "physicalHost",
		[]string{"project", "member", "owner"}, false)
}

func uploadMachineUserJSON(drivers []string) error {
	resourceFieldStruct := make(map[string]interface{})
	resourceFieldMap := make(ResourceFieldConfigs)
	resourceFieldStruct["collectionMethods"] = []string{"GET"}
	resourceFieldStruct["resourceMethods"] = []string{"GET"}
	resourceFieldStruct["resourceFields"] = resourceFieldMap
	for _, driver := range drivers {
		genFieldSchema(resourceFieldMap, driver+"Config", driver+"Config", "")
	}
	genFieldSchema(resourceFieldMap, "authCertificateAuthority", "string", "")
	genFieldSchema(resourceFieldMap, "authKey", "string", "")
	genFieldSchema(resourceFieldMap, "dockerVersion", "string", "")
	genFieldSchema(resourceFieldMap, "driver", "string", "")
	genFieldSchema(resourceFieldMap, "engineEnv", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineInsecureRegistry", "array[string]", "")
	genFieldSchema(resourceFieldMap, "engineInstallUrl", "string", "")
	genFieldSchema(resourceFieldMap, "engineLabel", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineOpt", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineRegistryMirror", "array[string]", "")
	genFieldSchema(resourceFieldMap, "engineStorageDriver", "string", "")
	genFieldSchema(resourceFieldMap, "labels", "map[string]", "")
	nameField(resourceFieldMap)

	jsonData, err := json.MarshalIndent(resourceFieldStruct, "", "    ")
	if err != nil {
		return err
	}
	return uploadDynamicSchema("machine", string(jsonData), "physicalHost", []string{"admin", "user", "readAdmin"},
		false)
}
<commit_msg>Add readonly role<commit_after>package dynamicDrivers

import (
	"encoding/json"
	"errors"
	"strings"
)

func uploadMachineSchema(drivers []string) error {
	err := uploadMachineServiceJSON(drivers)
	err2 := uploadMachineProjectJSON(drivers)
	err3 := uploadMachineUserJSON(drivers)
	err4 := uploadMachineReadOnlyJSON(drivers)
	if err != nil || err2 != nil || err3 != nil || err4 != nil {
		return errors.New("Failed to upload one of the machine jsons.")
	}
	return nil
}

func genFieldSchema(resourceFieldStruct ResourceFieldConfigs, field, fieldType, auth string) {
	resourceFieldStruct[field] = ResourceFieldConfig{
		Nullable: true,
		Type:     fieldType,
		Create:   strings.Contains(auth, "c"),
		Update:   strings.Contains(auth, "u"),
	}
}
func nameField(resourceFieldStruct ResourceFieldConfigs) {
	resourceFieldStruct["name"] = ResourceFieldConfig{
		Type:     "string",
		Create:   true,
		Update:   false,
		Required: true,
		Nullable: false,
	}
}

func uploadMachineServiceJSON(drivers []string) error {
	resourceFieldStruct := make(map[string]interface{})
	resourceFieldMap := make(ResourceFieldConfigs)
	resourceFieldStruct["collectionMethods"] = []string{"GET", "POST", "PUT", "DELETE"}
	resourceFieldStruct["resourceMethods"] = []string{"GET", "PUT", "DELETE"}
	resourceFieldStruct["resourceFields"] = resourceFieldMap
	for _, driver := range drivers {
		genFieldSchema(resourceFieldMap, driver+"Config", driver+"Config", "c")
	}
	genFieldSchema(resourceFieldMap, "authCertificateAuthority", "string", "c")
	genFieldSchema(resourceFieldMap, "authKey", "string", "c")
	genFieldSchema(resourceFieldMap, "dockerVersion", "string", "c")
	genFieldSchema(resourceFieldMap, "engineEnv", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineInsecureRegistry", "array[string]", "c")
	genFieldSchema(resourceFieldMap, "engineInstallUrl", "string", "c")
	genFieldSchema(resourceFieldMap, "engineLabel", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineOpt", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineRegistryMirror", "array[string]", "c")
	genFieldSchema(resourceFieldMap, "engineStorageDriver", "string", "c")
	genFieldSchema(resourceFieldMap, "extractedConfig", "string", "u")
	genFieldSchema(resourceFieldMap, "labels", "map[string]", "cu")
	nameField(resourceFieldMap)

	jsonData, err := json.MarshalIndent(resourceFieldStruct, "", "    ")
	if err != nil {
		return err
	}
	return uploadDynamicSchema("machine", string(jsonData), "physicalHost", []string{"service"}, true)
}

func uploadMachineProjectJSON(drivers []string) error {
	resourceFieldStruct := make(map[string]interface{})
	resourceFieldMap := make(ResourceFieldConfigs)
	resourceFieldStruct["collectionMethods"] = []string{"GET", "POST", "DELETE"}
	resourceFieldStruct["resourceMethods"] = []string{"GET", "DELETE"}
	resourceFieldStruct["resourceFields"] = resourceFieldMap
	for _, driver := range drivers {
		genFieldSchema(resourceFieldMap, driver+"Config", driver+"Config", "c")
	}
	genFieldSchema(resourceFieldMap, "authCertificateAuthority", "string", "c")
	genFieldSchema(resourceFieldMap, "authKey", "string", "c")
	genFieldSchema(resourceFieldMap, "dockerVersion", "string", "c")
	genFieldSchema(resourceFieldMap, "engineEnv", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineInsecureRegistry", "array[string]", "c")
	genFieldSchema(resourceFieldMap, "engineInstallUrl", "string", "c")
	genFieldSchema(resourceFieldMap, "engineLabel", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineOpt", "map[string]", "c")
	genFieldSchema(resourceFieldMap, "engineRegistryMirror", "array[string]", "c")
	genFieldSchema(resourceFieldMap, "engineStorageDriver", "string", "c")
	genFieldSchema(resourceFieldMap, "labels", "map[string]", "c")
	nameField(resourceFieldMap)

	jsonData, err := json.MarshalIndent(resourceFieldStruct, "", "    ")
	if err != nil {
		return err
	}
	return uploadDynamicSchema("machine", string(jsonData), "physicalHost",
		[]string{"project", "member", "owner"}, false)
}

func uploadMachineUserJSON(drivers []string) error {
	resourceFieldStruct := make(map[string]interface{})
	resourceFieldMap := make(ResourceFieldConfigs)
	resourceFieldStruct["collectionMethods"] = []string{"GET"}
	resourceFieldStruct["resourceMethods"] = []string{"GET"}
	resourceFieldStruct["resourceFields"] = resourceFieldMap
	for _, driver := range drivers {
		genFieldSchema(resourceFieldMap, driver+"Config", driver+"Config", "")
	}
	genFieldSchema(resourceFieldMap, "authCertificateAuthority", "string", "")
	genFieldSchema(resourceFieldMap, "authKey", "string", "")
	genFieldSchema(resourceFieldMap, "dockerVersion", "string", "")
	genFieldSchema(resourceFieldMap, "driver", "string", "")
	genFieldSchema(resourceFieldMap, "engineEnv", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineInsecureRegistry", "array[string]", "")
	genFieldSchema(resourceFieldMap, "engineInstallUrl", "string", "")
	genFieldSchema(resourceFieldMap, "engineLabel", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineOpt", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineRegistryMirror", "array[string]", "")
	genFieldSchema(resourceFieldMap, "engineStorageDriver", "string", "")
	genFieldSchema(resourceFieldMap, "labels", "map[string]", "")
	nameField(resourceFieldMap)

	jsonData, err := json.MarshalIndent(resourceFieldStruct, "", "    ")
	if err != nil {
		return err
	}
	return uploadDynamicSchema("machine", string(jsonData), "physicalHost", []string{"admin", "user", "readAdmin"},
		false)
}

func uploadMachineReadOnlyJSON(drivers []string) error {
	resourceFieldStruct := make(map[string]interface{})
	resourceFieldMap := make(ResourceFieldConfigs)
	resourceFieldStruct["collectionMethods"] = []string{"GET"}
	resourceFieldStruct["resourceMethods"] = []string{"GET"}
	resourceFieldStruct["resourceFields"] = resourceFieldMap
	genFieldSchema(resourceFieldMap, "authCertificateAuthority", "string", "")
	genFieldSchema(resourceFieldMap, "authKey", "string", "")
	genFieldSchema(resourceFieldMap, "dockerVersion", "string", "")
	genFieldSchema(resourceFieldMap, "driver", "string", "")
	genFieldSchema(resourceFieldMap, "engineEnv", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineInsecureRegistry", "array[string]", "")
	genFieldSchema(resourceFieldMap, "engineInstallUrl", "string", "")
	genFieldSchema(resourceFieldMap, "engineLabel", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineOpt", "map[string]", "")
	genFieldSchema(resourceFieldMap, "engineRegistryMirror", "array[string]", "")
	genFieldSchema(resourceFieldMap, "engineStorageDriver", "string", "")
	genFieldSchema(resourceFieldMap, "labels", "map[string]", "")
	nameField(resourceFieldMap)

	jsonData, err := json.MarshalIndent(resourceFieldStruct, "", "    ")
	if err != nil {
		return err
	}
	return uploadDynamicSchema("machine", string(jsonData), "physicalHost", []string{"readonly"},
		false)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net"
	"time"

	"github.com/gortc/stun"
)

func main() {
	var (
		addr *net.UDPAddr
		err  error
	)

	fmt.Println("START")
	for i := 0; i < 10; i++ {
		addr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("stun-server:%d", stun.DefaultPort))
		if err == nil {
			break
		}
		time.Sleep(time.Millisecond * 300 * time.Duration(i))
	}
	if err != nil {
		log.Fatalln("too many attempts to resolve:", err)
	}

	fmt.Println("DIALING", addr)
	conn, err := net.DialUDP("udp", nil, addr)
	if err != nil {
		log.Fatalln("failed to dial:", err)
	}
	client, err := stun.NewClient(stun.ClientOptions{
		Connection: conn,
	})
	if err != nil {
		log.Fatal(err)
	}
	laddr := conn.LocalAddr()
	fmt.Println("LISTEN ON", laddr)

	request, err := stun.Build(stun.BindingRequest, stun.TransactionID)
	if err != nil {
		log.Fatalln("failed to build:", err)
	}
	timeout := time.Second
	deadline := time.Now().Add(timeout)
	if err := client.Do(request, deadline, func(event stun.Event) {
		if event.Error != nil {
			log.Fatalln("got event with error:", event.Error)
		}
		response := event.Message
		if response.Type != stun.BindingSuccess {
			log.Fatalln("bad message", response)
		}
		var xorMapped stun.XORMappedAddress
		if err = response.Parse(&xorMapped); err != nil {
			log.Fatalln("failed to parse xor mapped address:", err)
		}
		if laddr.String() != xorMapped.String() {
			log.Fatalln(laddr, "!=", xorMapped)
		}
		fmt.Println("OK", response, "GOT", xorMapped)
	}); err != nil {
		log.Fatalln("failed to Do:", err)
	}
	if err := client.Close(); err != nil {
		log.Fatalln("failed to close client:", err)
	}
}
<commit_msg>e2e: fix lint warning<commit_after>package main

import (
	"fmt"
	"log"
	"net"
	"time"

	"github.com/gortc/stun"
)

func main() {
	var (
		addr *net.UDPAddr
		err  error
	)

	fmt.Println("START")
	for i := 0; i < 10; i++ {
		addr, err = net.ResolveUDPAddr("udp", fmt.Sprintf("stun-server:%d", stun.DefaultPort))
		if err == nil {
			break
		}
		time.Sleep(time.Millisecond * 300 * time.Duration(i))
	}
	if err != nil {
		log.Fatalln("too many attempts to resolve:", err)
	}

	fmt.Println("DIALING", addr)
	conn, err := net.DialUDP("udp", nil, addr)
	if err != nil {
		log.Fatalln("failed to dial:", err)
	}
	client, err := stun.NewClient(stun.ClientOptions{
		Connection: conn,
	})
	if err != nil {
		log.Fatal(err)
	}
	laddr := conn.LocalAddr()
	fmt.Println("LISTEN ON", laddr)

	request, err := stun.Build(stun.BindingRequest, stun.TransactionID)
	if err != nil {
		log.Fatalln("failed to build:", err)
	}
	timeout := time.Second
	deadline := time.Now().Add(timeout)
	if err = client.Do(request, deadline, func(event stun.Event) {
		if event.Error != nil {
			log.Fatalln("got event with error:", event.Error)
		}
		response := event.Message
		if response.Type != stun.BindingSuccess {
			log.Fatalln("bad message", response)
		}
		var xorMapped stun.XORMappedAddress
		if err = response.Parse(&xorMapped); err != nil {
			log.Fatalln("failed to parse xor mapped address:", err)
		}
		if laddr.String() != xorMapped.String() {
			log.Fatalln(laddr, "!=", xorMapped)
		}
		fmt.Println("OK", response, "GOT", xorMapped)
	}); err != nil {
		log.Fatalln("failed to Do:", err)
	}
	if err := client.Close(); err != nil {
		log.Fatalln("failed to close client:", err)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Skaffold 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 integration

import (
	"context"
	"io/ioutil"
	"os"
	"os/exec"
	"testing"
	"time"

	"github.com/GoogleContainerTools/skaffold/integration/skaffold"
	"github.com/GoogleContainerTools/skaffold/proto"
	"github.com/GoogleContainerTools/skaffold/testutil"
	"k8s.io/apimachinery/pkg/util/wait"
)

func TestDevSync(t *testing.T) {
	tests := []struct {
		description string
		trigger     string
		config      string
	}{
		{
			description: "manual sync with polling trigger",
			trigger:     "polling",
			config:      "skaffold-manual.yaml",
		},
		{
			description: "manual sync with notify trigger",
			trigger:     "notify",
			config:      "skaffold-manual.yaml",
		},
		{
			description: "inferred sync with notify trigger",
			trigger:     "notify",
			config:      "skaffold-infer.yaml",
		},
	}
	for _, test := range tests {
		t.Run(test.description, func(t *testing.T) {
			if testing.Short() {
				t.Skip("skipping integration test")
			}
			if ShouldRunGCPOnlyTests() {
				t.Skip("skipping test that is not gcp only")
			}

			// Run skaffold build first to fail quickly on a build failure
			skaffold.Build().InDir("testdata/file-sync").WithConfig(test.config).RunOrFail(t)

			ns, client, deleteNs := SetupNamespace(t)
			defer deleteNs()

			stop := skaffold.Dev("--trigger", test.trigger).InDir("testdata/file-sync").WithConfig(test.config).InNs(ns.Name).RunBackground(t)
			defer stop()

			client.WaitForPodsReady("test-file-sync")

			ioutil.WriteFile("testdata/file-sync/foo", []byte("foo"), 0644)
			defer func() { os.Truncate("testdata/file-sync/foo", 0) }()

			err := wait.PollImmediate(time.Millisecond*500, 1*time.Minute, func() (bool, error) {
				out, _ := exec.Command("kubectl", "exec", "test-file-sync", "-n", ns.Name, "--", "cat", "foo").Output()
				return string(out) == "foo", nil
			})
			testutil.CheckError(t, false, err)
		})
	}
}

func TestDevSyncAPITrigger(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping integration test")
	}
	if ShouldRunGCPOnlyTests() {
		t.Skip("skipping test that is not gcp only")
	}

	ns, k8sclient, deleteNs := SetupNamespace(t)
	defer deleteNs()

	skaffold.Build().InDir("testdata/file-sync").WithConfig("skaffold-manual.yaml").InNs(ns.Name).RunOrFail(t)

	rpcAddr := randomPort()
	client, shutdown := setupRPCClient(t, rpcAddr)
	defer shutdown()

	stop := skaffold.Dev("--auto-sync=false", "--rpc-port", rpcAddr).InDir("testdata/file-sync").WithConfig("skaffold-manual.yaml").InNs(ns.Name).RunBackground(t)
	defer stop()

	k8sclient.WaitForPodsReady("test-file-sync")

	Run(t, "testdata/file-sync", "mkdir", "-p", "test")
	Run(t, "testdata/file-sync", "touch", "test/foobar")
	defer Run(t, "testdata/file-sync", "rm", "-rf", "test")

	client.Execute(context.Background(), &proto.UserIntentRequest{
		Intent: &proto.Intent{
			Sync: true,
		},
	})

	err := wait.PollImmediate(time.Millisecond*500, 1*time.Minute, func() (bool, error) {
		_, err := exec.Command("kubectl", "exec", "test-file-sync", "-n", ns.Name, "--", "ls", "/test").Output()
		return err == nil, nil
	})
	testutil.CheckError(t, false, err)
}
<commit_msg>Adapt TestDevSyncAPITrigger to improved test protocol<commit_after>/*
Copyright 2019 The Skaffold 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 integration

import (
	"context"
	"io/ioutil"
	"os"
	"os/exec"
	"testing"
	"time"

	"github.com/GoogleContainerTools/skaffold/integration/skaffold"
	"github.com/GoogleContainerTools/skaffold/proto"
	"github.com/GoogleContainerTools/skaffold/testutil"
	"k8s.io/apimachinery/pkg/util/wait"
)

func TestDevSync(t *testing.T) {
	tests := []struct {
		description string
		trigger     string
		config      string
	}{
		{
			description: "manual sync with polling trigger",
			trigger:     "polling",
			config:      "skaffold-manual.yaml",
		},
		{
			description: "manual sync with notify trigger",
			trigger:     "notify",
			config:      "skaffold-manual.yaml",
		},
		{
			description: "inferred sync with notify trigger",
			trigger:     "notify",
			config:      "skaffold-infer.yaml",
		},
	}
	for _, test := range tests {
		t.Run(test.description, func(t *testing.T) {
			if testing.Short() {
				t.Skip("skipping integration test")
			}
			if ShouldRunGCPOnlyTests() {
				t.Skip("skipping test that is not gcp only")
			}

			// Run skaffold build first to fail quickly on a build failure
			skaffold.Build().InDir("testdata/file-sync").WithConfig(test.config).RunOrFail(t)

			ns, client, deleteNs := SetupNamespace(t)
			defer deleteNs()

			stop := skaffold.Dev("--trigger", test.trigger).InDir("testdata/file-sync").WithConfig(test.config).InNs(ns.Name).RunBackground(t)
			defer stop()

			client.WaitForPodsReady("test-file-sync")

			ioutil.WriteFile("testdata/file-sync/foo", []byte("foo"), 0644)
			defer func() { os.Truncate("testdata/file-sync/foo", 0) }()

			err := wait.PollImmediate(time.Millisecond*500, 1*time.Minute, func() (bool, error) {
				out, _ := exec.Command("kubectl", "exec", "test-file-sync", "-n", ns.Name, "--", "cat", "foo").Output()
				return string(out) == "foo", nil
			})
			testutil.CheckError(t, false, err)
		})
	}
}

func TestDevSyncAPITrigger(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping integration test")
	}
	if ShouldRunGCPOnlyTests() {
		t.Skip("skipping test that is not gcp only")
	}

	ns, k8sclient, deleteNs := SetupNamespace(t)
	defer deleteNs()

	skaffold.Build().InDir("testdata/file-sync").WithConfig("skaffold-manual.yaml").InNs(ns.Name).RunOrFail(t)

	rpcAddr := randomPort()
	client, shutdown := setupRPCClient(t, rpcAddr)
	defer shutdown()

	stop := skaffold.Dev("--auto-sync=false", "--rpc-port", rpcAddr).InDir("testdata/file-sync").WithConfig("skaffold-manual.yaml").InNs(ns.Name).RunBackground(t)
	defer stop()

	k8sclient.WaitForPodsReady("test-file-sync")

	ioutil.WriteFile("testdata/file-sync/foo", []byte("foo"), 0644)
	defer func() { os.Truncate("testdata/file-sync/foo", 0) }()

	client.Execute(context.Background(), &proto.UserIntentRequest{
		Intent: &proto.Intent{
			Sync: true,
		},
	})

	err := wait.PollImmediate(time.Millisecond*500, 1*time.Minute, func() (bool, error) {
		out, _ := exec.Command("kubectl", "exec", "test-file-sync", "-n", ns.Name, "--", "cat", "foo").Output()
		return string(out) == "foo", nil
	})
	testutil.CheckError(t, false, err)
}
<|endoftext|>


<commit_before>package gitignore

import (
	"os"
	"os/user"
	"strconv"

	"github.com/go-git/go-billy/v5"
	"github.com/go-git/go-billy/v5/memfs"
	. "gopkg.in/check.v1"
)

type MatcherSuite struct {
	GFS  billy.Filesystem // git repository root
	RFS  billy.Filesystem // root that contains user home
	MCFS billy.Filesystem // root that contains user home, but missing ~/.gitconfig
	MEFS billy.Filesystem // root that contains user home, but missing excludesfile entry
	MIFS billy.Filesystem // root that contains user home, but missing .gitnignore

	SFS billy.Filesystem // root that contains /etc/gitconfig
}

var _ = Suite(&MatcherSuite{})

func (s *MatcherSuite) SetUpTest(c *C) {
	// setup generic git repository root
	fs := memfs.New()
	f, err := fs.Create(".gitignore")
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("vendor/g*/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("ignore.crlf\r\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	err = fs.MkdirAll("vendor", os.ModePerm)
	c.Assert(err, IsNil)
	f, err = fs.Create("vendor/.gitignore")
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("!github.com/\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	err = fs.MkdirAll("another", os.ModePerm)
	c.Assert(err, IsNil)
	err = fs.MkdirAll("ignore.crlf", os.ModePerm)
	c.Assert(err, IsNil)
	err = fs.MkdirAll("vendor/github.com", os.ModePerm)
	c.Assert(err, IsNil)
	err = fs.MkdirAll("vendor/gopkg.in", os.ModePerm)
	c.Assert(err, IsNil)

	s.GFS = fs

	// setup root that contains user home
	usr, err := user.Current()
	c.Assert(err, IsNil)

	fs = memfs.New()
	err = fs.MkdirAll(usr.HomeDir, os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, gitconfigFile))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("[core]\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("	excludesfile = " + strconv.Quote(fs.Join(usr.HomeDir, ".gitignore_global")) + "\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, ".gitignore_global"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("# IntelliJ\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte(".idea/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("*.iml\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.RFS = fs

	// root that contains user home, but missing ~/.gitconfig
	fs = memfs.New()
	err = fs.MkdirAll(usr.HomeDir, os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, ".gitignore_global"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("# IntelliJ\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte(".idea/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("*.iml\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.MCFS = fs

	// setup root that contains user home, but missing excludesfile entry
	fs = memfs.New()
	err = fs.MkdirAll(usr.HomeDir, os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, gitconfigFile))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("[core]\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, ".gitignore_global"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("# IntelliJ\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte(".idea/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("*.iml\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.MEFS = fs

	// setup root that contains user home, but missing .gitnignore
	fs = memfs.New()
	err = fs.MkdirAll(usr.HomeDir, os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, gitconfigFile))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("[core]\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("	excludesfile = " + strconv.Quote(fs.Join(usr.HomeDir, ".gitignore_global")) + "\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.MIFS = fs

	// setup root that contains user home
	fs = memfs.New()
	err = fs.MkdirAll("etc", os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(systemFile)
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("[core]\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("	excludesfile = /etc/gitignore_global\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	f, err = fs.Create("/etc/gitignore_global")
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("# IntelliJ\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte(".idea/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("*.iml\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.SFS = fs
}

func (s *MatcherSuite) TestDir_ReadPatterns(c *C) {
	ps, err := ReadPatterns(s.GFS, nil)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 3)

	m := NewMatcher(ps)
	c.Assert(m.Match([]string{"ignore.crlf"}, true), Equals, true)
	c.Assert(m.Match([]string{"vendor", "gopkg.in"}, true), Equals, true)
	c.Assert(m.Match([]string{"vendor", "github.com"}, true), Equals, false)
}

func (s *MatcherSuite) TestDir_LoadGlobalPatterns(c *C) {
	ps, err := LoadGlobalPatterns(s.RFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 2)

	m := NewMatcher(ps)
	c.Assert(m.Match([]string{"go-git.v4.iml"}, true), Equals, true)
	c.Assert(m.Match([]string{".idea"}, true), Equals, true)
}

func (s *MatcherSuite) TestDir_LoadGlobalPatternsMissingGitconfig(c *C) {
	ps, err := LoadGlobalPatterns(s.MCFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 0)
}

func (s *MatcherSuite) TestDir_LoadGlobalPatternsMissingExcludesfile(c *C) {
	ps, err := LoadGlobalPatterns(s.MEFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 0)
}

func (s *MatcherSuite) TestDir_LoadGlobalPatternsMissingGitignore(c *C) {
	ps, err := LoadGlobalPatterns(s.MIFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 0)
}

func (s *MatcherSuite) TestDir_LoadSystemPatterns(c *C) {
	ps, err := LoadSystemPatterns(s.SFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 2)

	m := NewMatcher(ps)
	c.Assert(m.Match([]string{"go-git.v4.iml"}, true), Equals, true)
	c.Assert(m.Match([]string{".idea"}, true), Equals, true)
}
<commit_msg>fix typo<commit_after>package gitignore

import (
	"os"
	"os/user"
	"strconv"

	"github.com/go-git/go-billy/v5"
	"github.com/go-git/go-billy/v5/memfs"
	. "gopkg.in/check.v1"
)

type MatcherSuite struct {
	GFS  billy.Filesystem // git repository root
	RFS  billy.Filesystem // root that contains user home
	MCFS billy.Filesystem // root that contains user home, but missing ~/.gitconfig
	MEFS billy.Filesystem // root that contains user home, but missing excludesfile entry
	MIFS billy.Filesystem // root that contains user home, but missing .gitignore

	SFS billy.Filesystem // root that contains /etc/gitconfig
}

var _ = Suite(&MatcherSuite{})

func (s *MatcherSuite) SetUpTest(c *C) {
	// setup generic git repository root
	fs := memfs.New()
	f, err := fs.Create(".gitignore")
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("vendor/g*/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("ignore.crlf\r\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	err = fs.MkdirAll("vendor", os.ModePerm)
	c.Assert(err, IsNil)
	f, err = fs.Create("vendor/.gitignore")
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("!github.com/\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	err = fs.MkdirAll("another", os.ModePerm)
	c.Assert(err, IsNil)
	err = fs.MkdirAll("ignore.crlf", os.ModePerm)
	c.Assert(err, IsNil)
	err = fs.MkdirAll("vendor/github.com", os.ModePerm)
	c.Assert(err, IsNil)
	err = fs.MkdirAll("vendor/gopkg.in", os.ModePerm)
	c.Assert(err, IsNil)

	s.GFS = fs

	// setup root that contains user home
	usr, err := user.Current()
	c.Assert(err, IsNil)

	fs = memfs.New()
	err = fs.MkdirAll(usr.HomeDir, os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, gitconfigFile))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("[core]\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("	excludesfile = " + strconv.Quote(fs.Join(usr.HomeDir, ".gitignore_global")) + "\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, ".gitignore_global"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("# IntelliJ\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte(".idea/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("*.iml\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.RFS = fs

	// root that contains user home, but missing ~/.gitconfig
	fs = memfs.New()
	err = fs.MkdirAll(usr.HomeDir, os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, ".gitignore_global"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("# IntelliJ\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte(".idea/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("*.iml\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.MCFS = fs

	// setup root that contains user home, but missing excludesfile entry
	fs = memfs.New()
	err = fs.MkdirAll(usr.HomeDir, os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, gitconfigFile))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("[core]\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, ".gitignore_global"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("# IntelliJ\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte(".idea/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("*.iml\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.MEFS = fs

	// setup root that contains user home, but missing .gitnignore
	fs = memfs.New()
	err = fs.MkdirAll(usr.HomeDir, os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(fs.Join(usr.HomeDir, gitconfigFile))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("[core]\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("	excludesfile = " + strconv.Quote(fs.Join(usr.HomeDir, ".gitignore_global")) + "\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.MIFS = fs

	// setup root that contains user home
	fs = memfs.New()
	err = fs.MkdirAll("etc", os.ModePerm)
	c.Assert(err, IsNil)

	f, err = fs.Create(systemFile)
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("[core]\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("	excludesfile = /etc/gitignore_global\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	f, err = fs.Create("/etc/gitignore_global")
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("# IntelliJ\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte(".idea/\n"))
	c.Assert(err, IsNil)
	_, err = f.Write([]byte("*.iml\n"))
	c.Assert(err, IsNil)
	err = f.Close()
	c.Assert(err, IsNil)

	s.SFS = fs
}

func (s *MatcherSuite) TestDir_ReadPatterns(c *C) {
	ps, err := ReadPatterns(s.GFS, nil)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 3)

	m := NewMatcher(ps)
	c.Assert(m.Match([]string{"ignore.crlf"}, true), Equals, true)
	c.Assert(m.Match([]string{"vendor", "gopkg.in"}, true), Equals, true)
	c.Assert(m.Match([]string{"vendor", "github.com"}, true), Equals, false)
}

func (s *MatcherSuite) TestDir_LoadGlobalPatterns(c *C) {
	ps, err := LoadGlobalPatterns(s.RFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 2)

	m := NewMatcher(ps)
	c.Assert(m.Match([]string{"go-git.v4.iml"}, true), Equals, true)
	c.Assert(m.Match([]string{".idea"}, true), Equals, true)
}

func (s *MatcherSuite) TestDir_LoadGlobalPatternsMissingGitconfig(c *C) {
	ps, err := LoadGlobalPatterns(s.MCFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 0)
}

func (s *MatcherSuite) TestDir_LoadGlobalPatternsMissingExcludesfile(c *C) {
	ps, err := LoadGlobalPatterns(s.MEFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 0)
}

func (s *MatcherSuite) TestDir_LoadGlobalPatternsMissingGitignore(c *C) {
	ps, err := LoadGlobalPatterns(s.MIFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 0)
}

func (s *MatcherSuite) TestDir_LoadSystemPatterns(c *C) {
	ps, err := LoadSystemPatterns(s.SFS)
	c.Assert(err, IsNil)
	c.Assert(ps, HasLen, 2)

	m := NewMatcher(ps)
	c.Assert(m.Match([]string{"go-git.v4.iml"}, true), Equals, true)
	c.Assert(m.Match([]string{".idea"}, true), Equals, true)
}
<|endoftext|>


<commit_before>package cli_test

import (
	"time"

	. "github.com/jwaldrip/odin/cli"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("CLI Start", func() {

	var cli *CLI
	var cmd Command
	var didRun bool

	BeforeEach(func() {
		didRun = false
		runFn := func(c Command) {
			cmd = c
			didRun = true
		}
		cli = NewCLI("v1.0.0", "sample description", runFn)
		cli.ErrorHandling = PanicOnError
		cli.Mute()
	})

	Describe("flag definitions", func() {
		Describe("BoolFlag", func() {

			It("should set and parse", func() {
				cli.DefineBoolFlag("boolflag", false, "desc")
				cli.Start("cmd", "--boolflag")
				Expect(cmd.Flag("boolflag").Get()).To(Equal(true))
			})

			It("should set and parse from var", func() {
				var val bool
				cli.DefineBoolFlagVar(&val, "boolflag", false, "desc")
				cli.DefineBoolFlagVar(&val, "boolflag2", false, "desc")
				cli.Start("cmd", "--boolflag")
				Expect(cmd.Flag("boolflag2").Get()).To(Equal(true))
			})
		})

		Describe("DurationFlag", func() {

			It("should set and parse", func() {
				cli.DefineDurationFlag("durflag", time.Duration(60)*time.Second, "desc")
				cli.Start("cmd", "--durflag=30s")
				Expect(cmd.Flag("durflag").Get()).To(Equal(time.Duration(30) * time.Second))
			})

			It("should set and parse from var", func() {
				var val time.Duration
				cli.DefineDurationFlagVar(&val, "durflag", time.Duration(60)*time.Second, "desc")
				cli.DefineDurationFlagVar(&val, "durflag2", time.Duration(45)*time.Second, "desc")
				cli.Start("cmd", "--durflag=100s")
				Expect(cmd.Flag("durflag2").Get()).To(Equal(time.Duration(100) * time.Second))
			})
		})

	})

})
<commit_msg>float64 flag test<commit_after>package cli_test

import (
	"time"

	. "github.com/jwaldrip/odin/cli"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("CLI Start", func() {

	var cli *CLI
	var cmd Command
	var didRun bool

	BeforeEach(func() {
		didRun = false
		runFn := func(c Command) {
			cmd = c
			didRun = true
		}
		cli = NewCLI("v1.0.0", "sample description", runFn)
		cli.ErrorHandling = PanicOnError
		cli.Mute()
	})

	Describe("flag definitions", func() {
		Describe("BoolFlag", func() {

			It("should set and parse", func() {
				cli.DefineBoolFlag("boolflag", false, "desc")
				cli.Start("cmd", "--boolflag")
				Expect(cmd.Flag("boolflag").Get()).To(Equal(true))
			})

			It("should set and parse from var", func() {
				var val bool
				cli.DefineBoolFlagVar(&val, "boolflag", false, "desc")
				cli.DefineBoolFlagVar(&val, "boolflag2", false, "desc")
				cli.Start("cmd", "--boolflag")
				Expect(cmd.Flag("boolflag2").Get()).To(Equal(true))
			})
		})

		Describe("DurationFlag", func() {

			It("should set and parse", func() {
				cli.DefineDurationFlag("durflag", time.Duration(60)*time.Second, "desc")
				cli.Start("cmd", "--durflag=30s")
				Expect(cmd.Flag("durflag").Get()).To(Equal(time.Duration(30) * time.Second))
			})

			It("should set and parse from var", func() {
				var val time.Duration
				cli.DefineDurationFlagVar(&val, "durflag", time.Duration(60)*time.Second, "desc")
				cli.DefineDurationFlagVar(&val, "durflag2", time.Duration(45)*time.Second, "desc")
				cli.Start("cmd", "--durflag=100s")
				Expect(cmd.Flag("durflag2").Get()).To(Equal(time.Duration(100) * time.Second))
			})
		})

		Describe("Float64Flag", func() {

			It("should set and parse", func() {
				cli.DefineFloat64Flag("float64flag", 10.1, "desc")
				cli.Start("cmd", "--float64flag=9.9")
				Expect(cmd.Flag("float64flag").Get()).To(Equal(9.9))
			})

			It("should set and parse from var", func() {
				var val float64
				cli.DefineFloat64FlagVar(&val, "float64flag", 10.10, "desc")
				cli.DefineFloat64FlagVar(&val, "float64flag2", 9.9, "desc")
				cli.Start("cmd", "--float64flag=8.8")
				Expect(cmd.Flag("float64flag2").Get()).To(Equal(8.8))
			})
		})

	})

})
<|endoftext|>


<commit_before>package storage

import (
	"strings"
	"time"

	"github.com/mailslurper/libmailslurper/model/search"
)

func getMailAndAttachmentsQuery(whereClause string) string {
	sqlQuery := `
		SELECT
			  mailitem.dateSent
			, mailitem.fromAddress
			, mailitem.toAddressList
			, mailitem.subject
			, mailitem.xmailer
			, mailitem.body
			, mailitem.contentType
			, mailitem.boundary
			, attachment.id AS attachmentID
			, attachment.fileName
			, attachment.contentType

		FROM mailitem
			LEFT JOIN attachment ON attachment.mailItemID=mailitem.id

		WHERE 1=1 `

	sqlQuery = sqlQuery + whereClause
	sqlQuery = sqlQuery + ` ORDER BY mailitem.dateSent DESC `

	return sqlQuery
}

func getMailCountQuery(mailSearch *search.MailSearch) (string, []interface{}) {
	sqlQuery := `
		SELECT COUNT(id) AS mailItemCount FROM mailitem WHERE 1=1
	`

	var parameters []interface{}
	return addSearchCriteria(sqlQuery, parameters, mailSearch)
}

func getDeleteMailQuery(startDate string) string {
	where := ""

	if len(startDate) > 0 {
		where = where + " AND dateSent <= ? "
	}

	sqlQuery := "DELETE FROM mailitem WHERE 1=1" + where
	return sqlQuery
}

func getInsertMailQuery() string {
	sqlQuery := `
		INSERT INTO mailitem (
			  id
			, dateSent
			, fromAddress
			, toAddressList
			, subject
			, xmailer
			, body
			, contentType
			, boundary
		) VALUES (
			  ?
			, ?
			, ?
			, ?
			, ?
			, ?
			, ?
			, ?
			, ?
		)
	`

	return sqlQuery
}

func getInsertAttachmentQuery() string {
	sqlQuery := `
		INSERT INTO attachment (
			  id
			, mailItemId
			, fileName
			, contentType
			, content
		) VALUES (
			  ?
			, ?
			, ?
			, ?
			, ?
		)
	`

	return sqlQuery
}

func addSearchCriteria(sqlQuery string, parameters []interface{}, mailSearch *search.MailSearch) (string, []interface{}) {
	var date time.Time
	var err error

	if len(strings.TrimSpace(mailSearch.Message)) > 0 {
		sqlQuery += `
			AND (
				mailitem.body LIKE ?
				OR mailitem.subject LIKE ?
			)
		`

		parameters = append(parameters, "%"+mailSearch.Message+"%")
		parameters = append(parameters, "%"+mailSearch.Message+"%")
	}

	if len(strings.TrimSpace(mailSearch.From)) > 0 {
		sqlQuery += `
			AND mailitem.subject LIKE ?
		`

		parameters = append(parameters, "%"+mailSearch.From+"%")
	}

	if len(strings.TrimSpace(mailSearch.To)) > 0 {
		sqlQuery += `
			AND mailitem.toAddressList LIKE ?
		`

		parameters = append(parameters, "%"+mailSearch.To+"%")
	}

	if len(strings.TrimSpace(mailSearch.Start)) > 0 {
		if date, err = time.Parse("2006-01-02", mailSearch.Start); err == nil {
			sqlQuery += `
				AND mailitem.dateSent >= ?
			`

			parameters = append(parameters, date)
		}
	}

	if len(strings.TrimSpace(mailSearch.End)) > 0 {
		if date, err = time.Parse("2006-01-02", mailSearch.End); err == nil {
			sqlQuery += `
				AND mailitem.dateSent <= ?
			`

			parameters = append(parameters, date)
		}
	}

	return sqlQuery, parameters
}
<commit_msg>Moved storing attachments here<commit_after>package storage

import (
	"database/sql"
	"fmt"
	"strings"
	"time"

	"github.com/mailslurper/libmailslurper/model/attachment"
	"github.com/mailslurper/libmailslurper/model/mailitem"
	"github.com/mailslurper/libmailslurper/model/search"
)

func getMailAndAttachmentsQuery(whereClause string) string {
	sqlQuery := `
		SELECT
			  mailitem.dateSent
			, mailitem.fromAddress
			, mailitem.toAddressList
			, mailitem.subject
			, mailitem.xmailer
			, mailitem.body
			, mailitem.contentType
			, mailitem.boundary
			, attachment.id AS attachmentID
			, attachment.fileName
			, attachment.contentType

		FROM mailitem
			LEFT JOIN attachment ON attachment.mailItemID=mailitem.id

		WHERE 1=1 `

	sqlQuery = sqlQuery + whereClause
	sqlQuery = sqlQuery + ` ORDER BY mailitem.dateSent DESC `

	return sqlQuery
}

func getMailCountQuery(mailSearch *search.MailSearch) (string, []interface{}) {
	sqlQuery := `
		SELECT COUNT(id) AS mailItemCount FROM mailitem WHERE 1=1
	`

	var parameters []interface{}
	return addSearchCriteria(sqlQuery, parameters, mailSearch)
}

func getDeleteMailQuery(startDate string) string {
	where := ""

	if len(startDate) > 0 {
		where = where + " AND dateSent <= ? "
	}

	sqlQuery := "DELETE FROM mailitem WHERE 1=1" + where
	return sqlQuery
}

func getInsertMailQuery() string {
	sqlQuery := `
		INSERT INTO mailitem (
			  id
			, dateSent
			, fromAddress
			, toAddressList
			, subject
			, xmailer
			, body
			, contentType
			, boundary
		) VALUES (
			  ?
			, ?
			, ?
			, ?
			, ?
			, ?
			, ?
			, ?
			, ?
		)
	`

	return sqlQuery
}

func getInsertAttachmentQuery() string {
	sqlQuery := `
		INSERT INTO attachment (
			  id
			, mailItemId
			, fileName
			, contentType
			, content
		) VALUES (
			  ?
			, ?
			, ?
			, ?
			, ?
		)
	`

	return sqlQuery
}

func addSearchCriteria(sqlQuery string, parameters []interface{}, mailSearch *search.MailSearch) (string, []interface{}) {
	var date time.Time
	var err error

	if len(strings.TrimSpace(mailSearch.Message)) > 0 {
		sqlQuery += `
			AND (
				mailitem.body LIKE ?
				OR mailitem.subject LIKE ?
			)
		`

		parameters = append(parameters, "%"+mailSearch.Message+"%")
		parameters = append(parameters, "%"+mailSearch.Message+"%")
	}

	if len(strings.TrimSpace(mailSearch.From)) > 0 {
		sqlQuery += `
			AND mailitem.subject LIKE ?
		`

		parameters = append(parameters, "%"+mailSearch.From+"%")
	}

	if len(strings.TrimSpace(mailSearch.To)) > 0 {
		sqlQuery += `
			AND mailitem.toAddressList LIKE ?
		`

		parameters = append(parameters, "%"+mailSearch.To+"%")
	}

	if len(strings.TrimSpace(mailSearch.Start)) > 0 {
		if date, err = time.Parse("2006-01-02", mailSearch.Start); err == nil {
			sqlQuery += `
				AND mailitem.dateSent >= ?
			`

			parameters = append(parameters, date)
		}
	}

	if len(strings.TrimSpace(mailSearch.End)) > 0 {
		if date, err = time.Parse("2006-01-02", mailSearch.End); err == nil {
			sqlQuery += `
				AND mailitem.dateSent <= ?
			`

			parameters = append(parameters, date)
		}
	}

	return sqlQuery, parameters
}

func storeAttachments(mailItemID string, transaction *sql.Tx, attachments []*attachment.Attachment) error {
	var err error
	var attachmentID string

	for _, currentAttachment := range attachments {
		if attachmentID, err = mailitem.GenerateId(); err != nil {
			return fmt.Errorf("Error generating ID for attachment: %s", err.Error())
		}

		statement, err := transaction.Prepare(getInsertAttachmentQuery())
		if err != nil {
			return fmt.Errorf("Error preparing insert attachment statement: %s", err.Error())
		}

		_, err = statement.Exec(
			attachmentID,
			mailItemID,
			currentAttachment.Headers.FileName,
			currentAttachment.Headers.ContentType,
			currentAttachment.Contents,
		)

		if err != nil {
			return fmt.Errorf("Error executing insert attachment in StoreMail: %s", err.Error())
		}

		statement.Close()
		currentAttachment.Id = attachmentID
	}

	return nil
}
<|endoftext|>


<commit_before>package storage

import (
	"encoding/json"
	"time"

	"github.com/RangelReale/osin"
	"github.com/Wikia/go-commons/logger"
	"github.com/Wikia/helios/config"
	"github.com/garyburd/redigo/redis"
)

const (
	CLIENT_PREFIX    = "client."
	AUTHORIZE_PREFIX = "authorization."
	ACCESS_PREFIX    = "access."
	REFRESH_PREFIX   = "refresh."
)

type RedisStorage struct {
	pool   *redis.Pool
	prefix string
}

func NewRedisStorage(config *config.RedisConfig) *RedisStorage {
	pool := newPool(config)
	return &RedisStorage{pool: pool, prefix: config.Prefix}
}

func newPool(config *config.RedisConfig) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     config.MaxIdleConn,
		IdleTimeout: config.IdleTimeoutSec * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", config.Address)
			if err != nil {
				logger.GetLogger().ErrorErr(err)
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}

func (storage *RedisStorage) Close() {}

func (storage *RedisStorage) Clone() osin.Storage {
	return storage
}

func (storage *RedisStorage) GetClient(id string) (osin.Client, error) {
	key := createClientKey(id)
	clientJSON, err := storage.GetKey(key)
	if err != nil {
		return nil, err
	}

	client := new(osin.DefaultClient)
	if err := json.Unmarshal(clientJSON, &client); err != nil {
		logger.GetLogger().ErrorErr(err)
		return nil, err
	}

	return client, nil
}

func (storage *RedisStorage) SetClient(id string, client osin.Client) error {
	key := createClientKey(id)
	clientJSON, err := json.Marshal(client)
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		return err
	}

	return storage.SetKey(key, clientJSON)
}

func (storage *RedisStorage) SaveAuthorize(data *osin.AuthorizeData) error {
	key := createAuthorizeKey(data.Code)
	dataJSON, err := json.Marshal(data)
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		return err
	}

	return storage.SetKey(key, dataJSON)
}

func (storage *RedisStorage) LoadAuthorize(code string) (*osin.AuthorizeData, error) {
	key := createAuthorizeKey(code)
	authJSON, err := storage.GetKey(key)
	if err != nil {
		return nil, err
	}

	auth := new(osin.AuthorizeData)
	err = json.Unmarshal(authJSON, &auth)
	logger.GetLogger().ErrorErr(err)
	return auth, err
}

func (storage *RedisStorage) RemoveAuthorize(code string) error {
	key := createAuthorizeKey(code)
	return storage.DeleteKey(key)
}

func (storage *RedisStorage) SaveAccess(data *osin.AccessData) error {
	key := createAccessKey(data.AccessToken)
	dataJSON, err := json.Marshal(data)
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		return err
	}

	err = storage.SetKey(key, dataJSON)
	if data.RefreshToken != "" {
		key_refresh := createRefreshKey(data.RefreshToken)
		err = storage.SetKey(key_refresh, dataJSON)
	}
	return err
}

func (storage *RedisStorage) LoadAccess(token string) (*osin.AccessData, error) {
	key := createAccessKey(token)
	accessJSON, err := storage.GetKey(key)
	if err != nil {
		return nil, err
	}

	return unmarshallAccess(accessJSON)
}

func (storage *RedisStorage) RemoveAccess(token string) error {
	key := createAccessKey(token)
	return storage.DeleteKey(key)
}

func (storage *RedisStorage) LoadRefresh(token string) (*osin.AccessData, error) {
	key := createRefreshKey(token)
	refreshJSON, storeErr := storage.GetKey(key)
	if storeErr != nil {
		return nil, storeErr
	}

	access, err := unmarshallAccess(refreshJSON)
	if err != nil {
		return nil, err
	}

	// Clear old access data
	if access.AccessData != nil {
		access.AccessData = nil
	}
	return access, nil
}

func (storage *RedisStorage) RemoveRefresh(token string) error {
	key := createRefreshKey(token)
	return storage.DeleteKey(key)
}

func (storage *RedisStorage) GetKey(keyName string) ([]byte, error) {
	db := storage.pool.Get()
	defer db.Close()
	value, err := redis.String(db.Do("GET", keyName))
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		return nil, err
	}
	return []byte(value), nil
}

func (storage *RedisStorage) SetKey(key string, value []byte) error {
	db := storage.pool.Get()
	defer db.Close()
	_, err := db.Do("SET", key, string(value))
	logger.GetLogger().ErrorErr(err)
	return err
}

func (storage *RedisStorage) DeleteKey(keyName string) error {
	db := storage.pool.Get()
	defer db.Close()
	_, err := db.Do("DEL", keyName)
	logger.GetLogger().ErrorErr(err)
	return err
}

func createClientKey(id string) string {
	return CLIENT_PREFIX + id
}

func createAuthorizeKey(code string) string {
	return AUTHORIZE_PREFIX + code
}

func createAccessKey(token string) string {
	return ACCESS_PREFIX + token
}

func createRefreshKey(token string) string {
	return REFRESH_PREFIX + token
}

func unmarshallAccess(JSON []byte) (*osin.AccessData, error) {
	access := new(osin.AccessData)
	access.Client = new(osin.DefaultClient)
	access.AccessData = new(osin.AccessData)
	access.AccessData.Client = new(osin.DefaultClient)
	err := json.Unmarshal(JSON, &access)
	logger.GetLogger().ErrorErr(err)
	return access, err
}
<commit_msg>Fixed returning of object when error occurs<commit_after>package storage

import (
	"encoding/json"
	"time"

	"github.com/RangelReale/osin"
	"github.com/Wikia/go-commons/logger"
	"github.com/Wikia/helios/config"
	"github.com/garyburd/redigo/redis"
)

const (
	CLIENT_PREFIX    = "client."
	AUTHORIZE_PREFIX = "authorization."
	ACCESS_PREFIX    = "access."
	REFRESH_PREFIX   = "refresh."
)

type RedisStorage struct {
	pool   *redis.Pool
	prefix string
}

func NewRedisStorage(config *config.RedisConfig) *RedisStorage {
	pool := newPool(config)
	return &RedisStorage{pool: pool, prefix: config.Prefix}
}

func newPool(config *config.RedisConfig) *redis.Pool {
	return &redis.Pool{
		MaxIdle:     config.MaxIdleConn,
		IdleTimeout: config.IdleTimeoutSec * time.Second,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", config.Address)
			if err != nil {
				logger.GetLogger().ErrorErr(err)
				return nil, err
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}
}

func (storage *RedisStorage) Close() {}

func (storage *RedisStorage) Clone() osin.Storage {
	return storage
}

func (storage *RedisStorage) GetClient(id string) (osin.Client, error) {
	key := createClientKey(id)
	clientJSON, err := storage.GetKey(key)
	if err != nil {
		return nil, err
	}

	client := new(osin.DefaultClient)
	if err := json.Unmarshal(clientJSON, &client); err != nil {
		logger.GetLogger().ErrorErr(err)
		return nil, err
	}

	return client, nil
}

func (storage *RedisStorage) SetClient(id string, client osin.Client) error {
	key := createClientKey(id)
	clientJSON, err := json.Marshal(client)
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		return err
	}

	return storage.SetKey(key, clientJSON)
}

func (storage *RedisStorage) SaveAuthorize(data *osin.AuthorizeData) error {
	key := createAuthorizeKey(data.Code)
	dataJSON, err := json.Marshal(data)
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		return err
	}

	return storage.SetKey(key, dataJSON)
}

func (storage *RedisStorage) LoadAuthorize(code string) (*osin.AuthorizeData, error) {
	key := createAuthorizeKey(code)
	authJSON, err := storage.GetKey(key)
	if err != nil {
		return nil, err
	}

	auth := new(osin.AuthorizeData)
	err = json.Unmarshal(authJSON, &auth)
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		auth = nil
	}
	return auth, err
}

func (storage *RedisStorage) RemoveAuthorize(code string) error {
	key := createAuthorizeKey(code)
	return storage.DeleteKey(key)
}

func (storage *RedisStorage) SaveAccess(data *osin.AccessData) error {
	key := createAccessKey(data.AccessToken)
	dataJSON, err := json.Marshal(data)
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		return err
	}

	err = storage.SetKey(key, dataJSON)
	if data.RefreshToken != "" {
		key_refresh := createRefreshKey(data.RefreshToken)
		err = storage.SetKey(key_refresh, dataJSON)
	}
	return err
}

func (storage *RedisStorage) LoadAccess(token string) (*osin.AccessData, error) {
	key := createAccessKey(token)
	accessJSON, err := storage.GetKey(key)
	if err != nil {
		return nil, err
	}

	return unmarshallAccess(accessJSON)
}

func (storage *RedisStorage) RemoveAccess(token string) error {
	key := createAccessKey(token)
	return storage.DeleteKey(key)
}

func (storage *RedisStorage) LoadRefresh(token string) (*osin.AccessData, error) {
	key := createRefreshKey(token)
	refreshJSON, storeErr := storage.GetKey(key)
	if storeErr != nil {
		return nil, storeErr
	}

	access, err := unmarshallAccess(refreshJSON)
	if err != nil {
		return nil, err
	}

	// Clear old access data
	if access.AccessData != nil {
		access.AccessData = nil
	}
	return access, nil
}

func (storage *RedisStorage) RemoveRefresh(token string) error {
	key := createRefreshKey(token)
	return storage.DeleteKey(key)
}

func (storage *RedisStorage) GetKey(keyName string) ([]byte, error) {
	db := storage.pool.Get()
	defer db.Close()
	value, err := redis.String(db.Do("GET", keyName))
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		return nil, err
	}
	return []byte(value), nil
}

func (storage *RedisStorage) SetKey(key string, value []byte) error {
	db := storage.pool.Get()
	defer db.Close()
	_, err := db.Do("SET", key, string(value))
	logger.GetLogger().ErrorErr(err)
	return err
}

func (storage *RedisStorage) DeleteKey(keyName string) error {
	db := storage.pool.Get()
	defer db.Close()
	_, err := db.Do("DEL", keyName)
	logger.GetLogger().ErrorErr(err)
	return err
}

func createClientKey(id string) string {
	return CLIENT_PREFIX + id
}

func createAuthorizeKey(code string) string {
	return AUTHORIZE_PREFIX + code
}

func createAccessKey(token string) string {
	return ACCESS_PREFIX + token
}

func createRefreshKey(token string) string {
	return REFRESH_PREFIX + token
}

func unmarshallAccess(JSON []byte) (*osin.AccessData, error) {
	access := new(osin.AccessData)
	access.Client = new(osin.DefaultClient)
	access.AccessData = new(osin.AccessData)
	access.AccessData.Client = new(osin.DefaultClient)
	err := json.Unmarshal(JSON, &access)
	if err != nil {
		logger.GetLogger().ErrorErr(err)
		access = nil
	}
	return access, err
}
<|endoftext|>