<commit_before>// Package ware is a powerful package for easily create middleware layer in Golang.
//
// For a full guide visit https://github.com/futurespaceio/ware
//
// package main
//
// import (
//   "log"
//   "github.com/futurespaceio/ware"
// )
//
// func main() {
//   w := ware.New()
//
//   w.Use(func(c ware.Context, log *log.Logger) {
//     log.Println("before")
//     c.Next()
//     log.Println("after")
//   })
//
//   w.Run()
// }
package ware

import (
  "log"
  "os"
  "reflect"

  "github.com/codegangsta/inject"
)

// Middleware inject.Injector methods can be invoked to map services on a global level.
type Ware struct {
  inject.Injector
  handlers []Handler
  action   Handler
  logger   *log.Logger
}

// New creates a base bones Ware instance. Use this method if you want to have full control over the middleware that is used.
func New() *Ware {
  w := &Ware{Injector: inject.New(), action: func() {}, logger: log.New(os.Stdout, "[ware] ", 0)}
  w.Map(w.logger)
  w.Map(defaultReturnHandler())
  return w
}

// Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers.
// Will panic if any of the handlers is not a callable function
func (w *Ware) Handlers(handlers ...Handler) {
  w.handlers = make([]Handler, 0)
  for _, handler := range handlers {
    w.Use(handler)
  }
}

// Action sets the handler that will be called after all the middleware has been invoked. This is set to other Ware in a Ware.
func (w *Ware) Action(handler Handler) {
  validateHandler(handler)
  w.action = handler
}

// Use adds a middleware Handler to the stack. Will panic if the handler is not a callable func. Middleware Handlers are invoked in the order that they are added
func (w *Ware) Use(handler Handler) {
  validateHandler(handler)

  w.handlers = append(w.handlers, handler)
}

// Run the ware.
func (w *Ware) Run() {
  w.createContext().run()
}

// Creates a context.
func (w *Ware) createContext() *context {
  c := &context{inject.New(), w.handlers, w.action, nil, 0}
  c.SetParent(w)
  c.MapTo(c, (*Context)(nil))
  return c
}

// Handler can be any callable function. Martini attempts to inject services into the handler's argument list.
// Martini will panic if an argument could not be fullfilled via dependency injection.
type Handler interface{}

func validateHandler(handler Handler) {
  if reflect.TypeOf(handler).Kind() != reflect.Func {
    panic("ware handler must be a callable func")
  }
}

// Context represents a request context. Services can be mapped on the request level from this interface.
type Context interface {
  inject.Injector
  // Next is an optional function that Middleware Handlers can call to yield the until after
  // the other Handlers have been executed. This works really well for any operations that must
  // happen after a request
  Next()
  // Written returns whether or not the response for this context has been written.
  Written() bool
  // The response instance.
  Out(interface{})
}

type context struct {
  inject.Injector
  handlers []Handler
  action   Handler
  out      interface{}
  index    int
}

func (c *context) Out(o interface{}) {
  c.out = o
}

func (c *context) handler() Handler {
  if c.index < len(c.handlers) {
    return c.handlers[c.index]
  }
  if c.index == len(c.handlers) {
    return c.action
  }
  panic("invalid index for context handler")
}

func (c *context) Next() {
  c.index += 1
  c.run()
}

func (c *context) Written() bool {
  out := reflect.ValueOf(c.out)
  if out.IsValid() {
    // Currently, defaults only mapping Written method.
    f := out.MethodByName("Written")
    if f.IsValid() && f.Kind() == reflect.Func {
      res := f.Call(nil)
      return res[0].Interface().(bool)
    }
  }
  return false
}

func (c *context) run() {
  for c.index <= len(c.handlers) {
    _, err := c.Invoke(c.handler())
    if err != nil {
      panic(err)
    }
    c.index += 1

    // if the handler returned something, write it to the http response
    // TODO
    // if len(vals) > 0 {
    //   ev := c.Get(reflect.TypeOf(ReturnHandler(nil)))
    //   handleReturn := ev.Interface().(ReturnHandler)
    //   handleReturn(c, vals)
    // }

    if c.Written() {
      return
    }
  }
}

<commit_msg>add comments<commit_after>// Package ware is a powerful package for easily create middleware layer in Golang.
//
// For a full guide visit https://github.com/futurespaceio/ware
//
// package main
//
// import (
//   "log"
//   "github.com/futurespaceio/ware"
// )
//
// func main() {
//   w := ware.New()
//
//   w.Use(func(c ware.Context, log *log.Logger) {
//     log.Println("before")
//     c.Next()
//     log.Println("after")
//   })
//
//   w.Run()
// }
package ware

import (
  "log"
  "os"
  "reflect"

  "github.com/codegangsta/inject"
)

// Middleware inject.Injector methods can be invoked to map services on a global level.
type Ware struct {
  inject.Injector
  handlers []Handler
  action   Handler
  logger   *log.Logger
}

// New creates a base bones Ware instance. Use this method if you want to have full control over the middleware that is used.
func New() *Ware {
  w := &Ware{Injector: inject.New(), action: func() {}, logger: log.New(os.Stdout, "[ware] ", 0)}
  w.Map(w.logger)
  w.Map(defaultReturnHandler())
  return w
}

// Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers.
// Will panic if any of the handlers is not a callable function
func (w *Ware) Handlers(handlers ...Handler) {
  w.handlers = make([]Handler, 0)
  for _, handler := range handlers {
    w.Use(handler)
  }
}

// Action sets the handler that will be called after all the middleware has been invoked. This is set to other Ware in a Ware.
func (w *Ware) Action(handler Handler) {
  validateHandler(handler)
  w.action = handler
}

// Use adds a middleware Handler to the stack. Will panic if the handler is not a callable func. Middleware Handlers are invoked in the order that they are added
func (w *Ware) Use(handler Handler) {
  validateHandler(handler)

  w.handlers = append(w.handlers, handler)
}

// Run the ware.
func (w *Ware) Run() {
  w.createContext().run()
}

// Creates a context.
func (w *Ware) createContext() *context {
  c := &context{inject.New(), w.handlers, w.action, nil, 0}
  c.SetParent(w)
  c.MapTo(c, (*Context)(nil))
  return c
}

// Handler can be any callable function. Martini attempts to inject services into the handler's argument list.
// Martini will panic if an argument could not be fullfilled via dependency injection.
type Handler interface{}

func validateHandler(handler Handler) {
  if reflect.TypeOf(handler).Kind() != reflect.Func {
    panic("ware handler must be a callable func")
  }
}

// Context represents a request context. Services can be mapped on the request level from this interface.
type Context interface {
  inject.Injector
  // Next is an optional function that Middleware Handlers can call to yield the until after
  // the other Handlers have been executed. This works really well for any operations that must
  // happen after a request
  Next()
  // Written returns whether or not the response for this context has been written.
  Written() bool
  // The response instance.
  Out(interface{})
}

type context struct {
  inject.Injector
  handlers []Handler
  action   Handler
  out      interface{}
  index    int
}

// Changes the response instance.
func (c *context) Out(o interface{}) {
  c.out = o
}

func (c *context) handler() Handler {
  if c.index < len(c.handlers) {
    return c.handlers[c.index]
  }
  if c.index == len(c.handlers) {
    return c.action
  }
  panic("invalid index for context handler")
}

func (c *context) Next() {
  c.index += 1
  c.run()
}

func (c *context) Written() bool {
  out := reflect.ValueOf(c.out)
  if out.IsValid() {
    // Currently, defaults only mapping Written method.
    f := out.MethodByName("Written")
    if f.IsValid() && f.Kind() == reflect.Func {
      res := f.Call(nil)
      return res[0].Interface().(bool)
    }
  }
  return false
}

func (c *context) run() {
  for c.index <= len(c.handlers) {
    _, err := c.Invoke(c.handler())
    if err != nil {
      panic(err)
    }
    c.index += 1

    // if the handler returned something, write it to the http response
    // TODO
    // if len(vals) > 0 {
    //   ev := c.Get(reflect.TypeOf(ReturnHandler(nil)))
    //   handleReturn := ev.Interface().(ReturnHandler)
    //   handleReturn(c, vals)
    // }

    if c.Written() {
      return
    }
  }
}

<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"log"
	"os"
	"sync"
)

func main() {
	file, err := os.Open("./puzzle-input.txt")
	if err != nil {
		log.Fatalf("Error reading puzzle file: %s", err.Error())
	}

	defer file.Close()

	reader := bufio.NewScanner(file)
	reader.Split(bufio.ScanLines)

	stringChannel := make(chan string, 100)
	statusChannel := make(chan StringStatus, 100)
	waitGroup := &sync.WaitGroup{}
	done := make(chan bool)

	niceCount := 0
	naughtyCount := 0

	go func() {
		for {
			select {
			case <-done:
				break

			case status := <-statusChannel:
				if status == NAUGHTY {
					naughtyCount++
				}

				if status == NICE {
					niceCount++
				}

				waitGroup.Done()
			}
		}
	}()

	go func() {
		for {
			select {
			case <-done:
				break

			case stringToParse := <-stringChannel:
				stringParser := NewStringParser()
				status := stringParser.DetermineStatus(stringToParse)
				statusChannel <- status
			}
		}
	}()

	for reader.Scan() {
		waitGroup.Add(1)
		stringToParse := reader.Text()
		stringChannel <- stringToParse
	}

	waitGroup.Wait()
	done <- true

	log.Printf("%d are nice, %d are naughty\n", niceCount, naughtyCount)
}
<commit_msg>Forgot the comment with the puzzle, and the announcement log<commit_after>/*
--- Day 5: Doesn't He Have Intern-Elves For This? ---

Santa needs help figuring out which strings in his text file are naughty or nice.

A nice string is one with all of the following properties:

It contains at least three vowels (aeiou only), like aei, xazegov, or aeiouaeiouaeiou.
It contains at least one letter that appears twice in a row, like xx, abcdde (dd), or aabbccdd (aa, bb, cc, or dd).
It does not contain the strings ab, cd, pq, or xy, even if they are part of one of the other requirements.
For example:

* ugknbfddgicrmopn is nice because it has at least three vowels (u...i...o...), a double letter (...dd...), and none of the disallowed substrings.
* aaa is nice because it has at least three vowels and a double letter, even though the letters used by different rules overlap.
* jchzalrnumimnmhp is naughty because it has no double letter.
* haegwjzuvuyypxyu is naughty because it contains the string xy.
* dvszwmarrgswjxmb is naughty because it contains only one vowel.
How many strings are nice?
*/

package main

import (
	"bufio"
	"log"
	"os"
	"sync"
)

func main() {
	log.Println("AdventOfCode.com - Day 5 - Puzzle 1")

	file, err := os.Open("./puzzle-input.txt")
	if err != nil {
		log.Fatalf("Error reading puzzle file: %s", err.Error())
	}

	defer file.Close()

	reader := bufio.NewScanner(file)
	reader.Split(bufio.ScanLines)

	stringChannel := make(chan string, 100)
	statusChannel := make(chan StringStatus, 100)
	waitGroup := &sync.WaitGroup{}
	done := make(chan bool)

	niceCount := 0
	naughtyCount := 0

	go func() {
		for {
			select {
			case <-done:
				break

			case status := <-statusChannel:
				if status == NAUGHTY {
					naughtyCount++
				}

				if status == NICE {
					niceCount++
				}

				waitGroup.Done()
			}
		}
	}()

	go func() {
		for {
			select {
			case <-done:
				break

			case stringToParse := <-stringChannel:
				stringParser := NewStringParser()
				status := stringParser.DetermineStatus(stringToParse)
				statusChannel <- status
			}
		}
	}()

	for reader.Scan() {
		waitGroup.Add(1)
		stringToParse := reader.Text()
		stringChannel <- stringToParse
	}

	waitGroup.Wait()
	done <- true

	log.Printf("%d are nice, %d are naughty\n", niceCount, naughtyCount)
}
<|endoftext|>


<commit_before>package wdte

import (
	"fmt"
	"io"

	"github.com/DeedleFake/wdte/ast"
)

// A Module is the result of parsing a WDTE script. It is the main
// type of this entire library.
type Module struct {
	// Imports maps IDs to other modules. WDTE import statements create
	// these when parsed.
	Imports map[ID]*Module

	// Funcs maps IDs to functions. WDTE function declarations create
	// these when parsed.
	Funcs map[ID]Func
}

// Parse parses an AST from r and then translates it into a module. im
// is used to handle import statements. If im is nil, a no-op importer
// is used.
func Parse(r io.Reader, im Importer) (*Module, error) {
	root, err := ast.Parse(r)
	if err != nil {
		return nil, err
	}

	return FromAST(root, im)
}

// FromAST translates an AST into a module. im is used to handle
// import statements. If im is nil, a no-op importer is used.
func FromAST(root ast.Node, im Importer) (*Module, error) {
	return fromScript(root.(*ast.NTerm), im)
}

// An Importer creates modules from strings. When parsing a WDTE script, an importer is used to import modules.
//
// When the WDTE import statement
//
//    'example' => e;
//
// is parsed, the associated Importer will be invoked as follows:
//
//    im.Import(example)
//
// The return value will then be added to the module's Imports map.
type Importer interface {
	Import(from string) (*Module, error)
}

// ImportFunc is a wrapper around simple functions to allow them to be
// used as Importers.
type ImportFunc func(from string) (*Module, error)

func (f ImportFunc) Import(from string) (*Module, error) {
	return f(from)
}

// ID represents a WDTE ID, such as a function or imported module
// name.
type ID string

// Func is the base type through which all data is handled by WDTE. It
// represents everything that can be passed around in the language.
// This includes functions, of course, expressions, strings, numbers,
// Go functions, and anything else the client wants to pass into WDTE.
type Func interface {
	// Call calls the function with the given arguments, returning its
	// return value. frame represents the current call frame. This is
	// used to keep track of function arguments during the evaluation of
	// expressions, and can largely be ignored by clients.
	Call(frame []Func, args ...Func) Func

	// Equals returns true if one function equals another one. This is
	// meaningless for the majority of implementations, and should
	// largely be ignored by clients. When implementing custom
	// functions, if you're not sure what to do for this, you probably
	// won't have any issues. This is only used, by default, by switches
	// as a way of checking if the condition matches one of the cases.
	Equals(other Func) bool
}

// A GoFunc is an implementation of Func that calls a Go function.
// This is the easiest way to implement lower-level systems for WDTE
// scripts to make use of.
//
// For example, to implement a simple, non-type-safe addition
// function:
//
//    module.Funcs["+"] = GoFunc(func(frame []wdte.Func, args ...wdte.Func) wdte.Func {
//      var sum wdte.Number
//      for _, arg := range(args) {
//        sum += arg.Call(frame).(wdte.Number)
//      }
//      return sum
//    })
//
// This can then be called from WDTE as follows:
//
//    + 3 6 9
//
// As shown, it is recommended that arguments be passed the given
// frame when evaluating them. Failing to do so without knowing what
// you're doing can cause unexpected behavior, including sending the
// evaluation system into infinite loops or causing panics.
type GoFunc func(frame []Func, args ...Func) Func

func (f GoFunc) Call(frame []Func, args ...Func) (r Func) {
	defer func() {
		if err, ok := recover().(error); ok {
			r = Error{err}
		}
	}()

	return f(frame, args...)
}

func (f GoFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// A DeclFunc is a function that was declared in a WDTE function
// declaration. This is the primary source of the frame argument that
// is passed around everywhere.
type DeclFunc struct {
	// ID is the name that the function was declared with. This is
	// primarily for debugging.
	ID ID

	// Expr is the expression that the function maps to.
	Expr Func

	// Args is the number of arguments the function expects.
	Args int

	// Stored is the arguments that have already been passed to a
	// function if it was given less arguments than it was declared
	// with.
	Stored []Func
}

func (f DeclFunc) Call(frame []Func, args ...Func) Func {
	if len(args) < f.Args {
		return &DeclFunc{
			Expr:   f,
			Args:   f.Args - len(args),
			Stored: args,
		}
	}

	next := make([]Func, 0, len(f.Stored)+len(args))
	for _, arg := range f.Stored {
		next = append(next, &FramedFunc{
			Func:  arg,
			Frame: frame,
		})
	}
	for _, arg := range args {
		next = append(next, &FramedFunc{
			Func:  arg,
			Frame: frame,
		})
	}
	return f.Expr.Call(next, next...)
}

func (f DeclFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// An Expr is an unevaluated expression. This is usually the
// right-hand side of a function declaration, but could also be any of
// various pieces of switches, compounds, or arrays.
type Expr struct {
	// Func is the underlying function.
	Func Func

	// Args are the arguments to pass to Func.
	Args []Func
}

func (f Expr) Call(frame []Func, args ...Func) Func {
	return f.Func.Call(frame, f.Args...)
}

func (f Expr) Equals(other Func) bool {
	panic("Not implemented.")
}

// Chain is an unevaluated chain expression.
type Chain struct {
	// Func is the expression at the current part of the chain.
	Func Func

	// Args is the arguments to Func.
	Args []Func

	// Prev is the previous part of the chain.
	Prev Func
}

func (f Chain) Call(frame []Func, args ...Func) Func {
	return f.Func.Call(frame, f.Args...).Call(frame, f.Prev.Call(frame))
}

func (f Chain) Equals(other Func) bool {
	panic("Not implemented.")
}

// A String is a string, as parsed from a string literal. That's about
// it. Like everything else, it's a function. It simply returns itself
// when called.
type String string

func (s String) Call(frame []Func, args ...Func) Func {
	// TODO: Use the arguments for something. Probably concatenation.
	return s
}

func (s String) Equals(other Func) bool {
	o, ok := other.(String)
	return ok && (s == o)
}

// A Number is a number, as parsed from a number literal. That's about
// it. Like everything else, it's a function. It simply returns itself
// when called.
type Number float64

func (n Number) Call(frame []Func, args ...Func) Func {
	// TODO: Use the arguments for something, perhaps.
	return n
}

func (n Number) Equals(other Func) bool {
	o, ok := other.(Number)
	return ok && (n == o)
}

// External represents a function from an imported module. It looks
// the function up when called, so it is safe to pass Externals around
// before importing, so long as they are not evaluated until after
// importing.
type External struct {
	// Module is the module that the function was called from. This is
	// *not* the module that the function was declared in. Unless, for
	// some reason, the module has itself as an import.
	Module *Module

	// Import is the import ID of the module that the function was
	// declared in.
	Import ID

	// Func is the ID of the function in the module it was declared in.
	Func ID
}

func (e External) Call(frame []Func, args ...Func) Func {
	i, ok := e.Module.Imports[e.Import]
	if !ok {
		return Error{fmt.Errorf("Import %q does not exist", e.Import)}
	}
	f, ok := i.Funcs[e.Func]
	if !ok {
		return Error{fmt.Errorf("Function %q does not exist in import %q", e.Func, e.Import)}
	}

	return f.Call(frame, args...)
}

func (e External) Equals(other Func) bool {
	o, ok := other.(External)
	return ok && (e.Import == o.Import) && (e.Func == o.Func)
}

// Local represents a function from a module, usually the current one.
// It looks the function up when called, so it is safe to pass Locals
// around before importing, so long as they are not evaluated until
// after importing.
type Local struct {
	// Module is the module that the function was declared in.
	Module *Module

	// Func is the ID of the function in the module.
	Func ID
}

func (local Local) Call(frame []Func, args ...Func) Func {
	f, ok := local.Module.Funcs[local.Func]
	if !ok {
		return Error{fmt.Errorf("Function %q does not exist", local.Func)}
	}

	return f.Call(frame, args...)
}

func (local Local) Equals(other Func) bool {
	o, ok := other.(Local)
	return ok && (local.Func == o.Func)
}

// A Compound represents a compound expression. Calling it calls each
// of the expressions in the compound, returning the value of the last
// one. If the compound is empty, nil is returned.
type Compound []Func

func (c Compound) Call(frame []Func, args ...Func) Func {
	var last Func
	for _, f := range c {
		last = f.Call(frame)
		if last, ok := last.(Error); ok {
			return last
		}
	}

	return last
}

func (c Compound) Equals(other Func) bool {
	panic("Not implemented.")
}

// Switch represents a switch expression.
type Switch struct {
	// Check is the condition at the front of the switch.
	Check Func

	// Cases is the switch's cases. Each contains two functions. The
	// first index is the left-hand side, while the second is the
	// right-hand side. When the switch is evaluated, the cases are run
	// in order. If any matches, the right-hand side is evaluated and
	// its return value is returned.
	//
	// A default case is represented by a nil in the first index. It is
	// possible to have cases after a default, but pointless, as a
	// default is always run when it is encountered.
	Cases [][2]Func
}

func (s Switch) Call(frame []Func, args ...Func) Func {
	check := s.Check.Call(frame)
	if check, ok := check.(Error); ok {
		return check
	}

	for _, c := range s.Cases {
		if c[0] == nil {
			return c[1].Call(frame)
		}

		lhs := c[0].Call(frame)
		if lhs, ok := lhs.(Error); ok {
			return lhs
		}

		if check.Equals(lhs) {
			return c[1].Call(frame)
		}
	}

	return nil
}

func (s Switch) Equals(other Func) bool {
	panic("Not implemented.")
}

// Arg represents an argument in the current frame. It is the opposite
// end from DeclFunc of the frame argument that gets passed around all
// over the place.
type Arg int

func (a Arg) Call(frame []Func, args ...Func) Func {
	if int(a) >= len(frame) {
		return Error{fmt.Errorf("Attempted to access %vth argument in a frame containing %v", a, len(frame))}
	}

	return frame[a].Call(frame, args...)
}

func (a Arg) Equals(other Func) bool {
	panic("Not implemented.")
}

// A FramedFunc is a function which keeps track of its own calling
// frame.
type FramedFunc struct {
	// Func is the actual function.
	Func Func

	// Frame is the function to call Func with.
	Frame []Func
}

func (f FramedFunc) Call(frame []Func, args ...Func) Func {
	return f.Func.Call(f.Frame, args...)
}

func (f FramedFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// An Array represents a WDTE array type. It's similar to a Compound,
// but doesn't evaluate its own members. Instead, evaluation simply
// returns itself, much like strings and numbers.
type Array []Func

func (a Array) Call(frame []Func, args ...Func) Func {
	return a
}

func (a Array) Equals(other Func) bool {
	o, ok := other.(Array)
	if !ok || (len(a) != len(o)) {
		return false
	}

	for i := range a {
		if !a[i].Equals(o[i]) {
			return false
		}
	}

	return true
}

// An Error is returned by any of the built-in functions when they run
// into an error.
type Error struct {
	// Cause is the cause of the error.
	Cause error
}

func (e Error) Call(frame []Func, args ...Func) Func {
	return e
}

func (e Error) Equals(other Func) bool {
	panic("Not implemented.")
}

func (e Error) Error() string {
	return fmt.Sprintf("WDTE error: %v", e.Cause)
}
<commit_msg>wdte: Slight clarification in array comment.<commit_after>package wdte

import (
	"fmt"
	"io"

	"github.com/DeedleFake/wdte/ast"
)

// A Module is the result of parsing a WDTE script. It is the main
// type of this entire library.
type Module struct {
	// Imports maps IDs to other modules. WDTE import statements create
	// these when parsed.
	Imports map[ID]*Module

	// Funcs maps IDs to functions. WDTE function declarations create
	// these when parsed.
	Funcs map[ID]Func
}

// Parse parses an AST from r and then translates it into a module. im
// is used to handle import statements. If im is nil, a no-op importer
// is used.
func Parse(r io.Reader, im Importer) (*Module, error) {
	root, err := ast.Parse(r)
	if err != nil {
		return nil, err
	}

	return FromAST(root, im)
}

// FromAST translates an AST into a module. im is used to handle
// import statements. If im is nil, a no-op importer is used.
func FromAST(root ast.Node, im Importer) (*Module, error) {
	return fromScript(root.(*ast.NTerm), im)
}

// An Importer creates modules from strings. When parsing a WDTE script, an importer is used to import modules.
//
// When the WDTE import statement
//
//    'example' => e;
//
// is parsed, the associated Importer will be invoked as follows:
//
//    im.Import(example)
//
// The return value will then be added to the module's Imports map.
type Importer interface {
	Import(from string) (*Module, error)
}

// ImportFunc is a wrapper around simple functions to allow them to be
// used as Importers.
type ImportFunc func(from string) (*Module, error)

func (f ImportFunc) Import(from string) (*Module, error) {
	return f(from)
}

// ID represents a WDTE ID, such as a function or imported module
// name.
type ID string

// Func is the base type through which all data is handled by WDTE. It
// represents everything that can be passed around in the language.
// This includes functions, of course, expressions, strings, numbers,
// Go functions, and anything else the client wants to pass into WDTE.
type Func interface {
	// Call calls the function with the given arguments, returning its
	// return value. frame represents the current call frame. This is
	// used to keep track of function arguments during the evaluation of
	// expressions, and can largely be ignored by clients.
	Call(frame []Func, args ...Func) Func

	// Equals returns true if one function equals another one. This is
	// meaningless for the majority of implementations, and should
	// largely be ignored by clients. When implementing custom
	// functions, if you're not sure what to do for this, you probably
	// won't have any issues. This is only used, by default, by switches
	// as a way of checking if the condition matches one of the cases.
	Equals(other Func) bool
}

// A GoFunc is an implementation of Func that calls a Go function.
// This is the easiest way to implement lower-level systems for WDTE
// scripts to make use of.
//
// For example, to implement a simple, non-type-safe addition
// function:
//
//    module.Funcs["+"] = GoFunc(func(frame []wdte.Func, args ...wdte.Func) wdte.Func {
//      var sum wdte.Number
//      for _, arg := range(args) {
//        sum += arg.Call(frame).(wdte.Number)
//      }
//      return sum
//    })
//
// This can then be called from WDTE as follows:
//
//    + 3 6 9
//
// As shown, it is recommended that arguments be passed the given
// frame when evaluating them. Failing to do so without knowing what
// you're doing can cause unexpected behavior, including sending the
// evaluation system into infinite loops or causing panics.
type GoFunc func(frame []Func, args ...Func) Func

func (f GoFunc) Call(frame []Func, args ...Func) (r Func) {
	defer func() {
		if err, ok := recover().(error); ok {
			r = Error{err}
		}
	}()

	return f(frame, args...)
}

func (f GoFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// A DeclFunc is a function that was declared in a WDTE function
// declaration. This is the primary source of the frame argument that
// is passed around everywhere.
type DeclFunc struct {
	// ID is the name that the function was declared with. This is
	// primarily for debugging.
	ID ID

	// Expr is the expression that the function maps to.
	Expr Func

	// Args is the number of arguments the function expects.
	Args int

	// Stored is the arguments that have already been passed to a
	// function if it was given less arguments than it was declared
	// with.
	Stored []Func
}

func (f DeclFunc) Call(frame []Func, args ...Func) Func {
	if len(args) < f.Args {
		return &DeclFunc{
			Expr:   f,
			Args:   f.Args - len(args),
			Stored: args,
		}
	}

	next := make([]Func, 0, len(f.Stored)+len(args))
	for _, arg := range f.Stored {
		next = append(next, &FramedFunc{
			Func:  arg,
			Frame: frame,
		})
	}
	for _, arg := range args {
		next = append(next, &FramedFunc{
			Func:  arg,
			Frame: frame,
		})
	}
	return f.Expr.Call(next, next...)
}

func (f DeclFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// An Expr is an unevaluated expression. This is usually the
// right-hand side of a function declaration, but could also be any of
// various pieces of switches, compounds, or arrays.
type Expr struct {
	// Func is the underlying function.
	Func Func

	// Args are the arguments to pass to Func.
	Args []Func
}

func (f Expr) Call(frame []Func, args ...Func) Func {
	return f.Func.Call(frame, f.Args...)
}

func (f Expr) Equals(other Func) bool {
	panic("Not implemented.")
}

// Chain is an unevaluated chain expression.
type Chain struct {
	// Func is the expression at the current part of the chain.
	Func Func

	// Args is the arguments to Func.
	Args []Func

	// Prev is the previous part of the chain.
	Prev Func
}

func (f Chain) Call(frame []Func, args ...Func) Func {
	return f.Func.Call(frame, f.Args...).Call(frame, f.Prev.Call(frame))
}

func (f Chain) Equals(other Func) bool {
	panic("Not implemented.")
}

// A String is a string, as parsed from a string literal. That's about
// it. Like everything else, it's a function. It simply returns itself
// when called.
type String string

func (s String) Call(frame []Func, args ...Func) Func {
	// TODO: Use the arguments for something. Probably concatenation.
	return s
}

func (s String) Equals(other Func) bool {
	o, ok := other.(String)
	return ok && (s == o)
}

// A Number is a number, as parsed from a number literal. That's about
// it. Like everything else, it's a function. It simply returns itself
// when called.
type Number float64

func (n Number) Call(frame []Func, args ...Func) Func {
	// TODO: Use the arguments for something, perhaps.
	return n
}

func (n Number) Equals(other Func) bool {
	o, ok := other.(Number)
	return ok && (n == o)
}

// External represents a function from an imported module. It looks
// the function up when called, so it is safe to pass Externals around
// before importing, so long as they are not evaluated until after
// importing.
type External struct {
	// Module is the module that the function was called from. This is
	// *not* the module that the function was declared in. Unless, for
	// some reason, the module has itself as an import.
	Module *Module

	// Import is the import ID of the module that the function was
	// declared in.
	Import ID

	// Func is the ID of the function in the module it was declared in.
	Func ID
}

func (e External) Call(frame []Func, args ...Func) Func {
	i, ok := e.Module.Imports[e.Import]
	if !ok {
		return Error{fmt.Errorf("Import %q does not exist", e.Import)}
	}
	f, ok := i.Funcs[e.Func]
	if !ok {
		return Error{fmt.Errorf("Function %q does not exist in import %q", e.Func, e.Import)}
	}

	return f.Call(frame, args...)
}

func (e External) Equals(other Func) bool {
	o, ok := other.(External)
	return ok && (e.Import == o.Import) && (e.Func == o.Func)
}

// Local represents a function from a module, usually the current one.
// It looks the function up when called, so it is safe to pass Locals
// around before importing, so long as they are not evaluated until
// after importing.
type Local struct {
	// Module is the module that the function was declared in.
	Module *Module

	// Func is the ID of the function in the module.
	Func ID
}

func (local Local) Call(frame []Func, args ...Func) Func {
	f, ok := local.Module.Funcs[local.Func]
	if !ok {
		return Error{fmt.Errorf("Function %q does not exist", local.Func)}
	}

	return f.Call(frame, args...)
}

func (local Local) Equals(other Func) bool {
	o, ok := other.(Local)
	return ok && (local.Func == o.Func)
}

// A Compound represents a compound expression. Calling it calls each
// of the expressions in the compound, returning the value of the last
// one. If the compound is empty, nil is returned.
type Compound []Func

func (c Compound) Call(frame []Func, args ...Func) Func {
	var last Func
	for _, f := range c {
		last = f.Call(frame)
		if last, ok := last.(Error); ok {
			return last
		}
	}

	return last
}

func (c Compound) Equals(other Func) bool {
	panic("Not implemented.")
}

// Switch represents a switch expression.
type Switch struct {
	// Check is the condition at the front of the switch.
	Check Func

	// Cases is the switch's cases. Each contains two functions. The
	// first index is the left-hand side, while the second is the
	// right-hand side. When the switch is evaluated, the cases are run
	// in order. If any matches, the right-hand side is evaluated and
	// its return value is returned.
	//
	// A default case is represented by a nil in the first index. It is
	// possible to have cases after a default, but pointless, as a
	// default is always run when it is encountered.
	Cases [][2]Func
}

func (s Switch) Call(frame []Func, args ...Func) Func {
	check := s.Check.Call(frame)
	if check, ok := check.(Error); ok {
		return check
	}

	for _, c := range s.Cases {
		if c[0] == nil {
			return c[1].Call(frame)
		}

		lhs := c[0].Call(frame)
		if lhs, ok := lhs.(Error); ok {
			return lhs
		}

		if check.Equals(lhs) {
			return c[1].Call(frame)
		}
	}

	return nil
}

func (s Switch) Equals(other Func) bool {
	panic("Not implemented.")
}

// Arg represents an argument in the current frame. It is the opposite
// end from DeclFunc of the frame argument that gets passed around all
// over the place.
type Arg int

func (a Arg) Call(frame []Func, args ...Func) Func {
	if int(a) >= len(frame) {
		return Error{fmt.Errorf("Attempted to access %vth argument in a frame containing %v", a, len(frame))}
	}

	return frame[a].Call(frame, args...)
}

func (a Arg) Equals(other Func) bool {
	panic("Not implemented.")
}

// A FramedFunc is a function which keeps track of its own calling
// frame.
type FramedFunc struct {
	// Func is the actual function.
	Func Func

	// Frame is the function to call Func with.
	Frame []Func
}

func (f FramedFunc) Call(frame []Func, args ...Func) Func {
	return f.Func.Call(f.Frame, args...)
}

func (f FramedFunc) Equals(other Func) bool {
	panic("Not implemented.")
}

// An Array represents a WDTE array type. It's similar to a Compound,
// but doesn't evaluate its own members. Instead, evaluation simply
// yields the array, much like how strings and numbers work.
type Array []Func

func (a Array) Call(frame []Func, args ...Func) Func {
	return a
}

func (a Array) Equals(other Func) bool {
	o, ok := other.(Array)
	if !ok || (len(a) != len(o)) {
		return false
	}

	for i := range a {
		if !a[i].Equals(o[i]) {
			return false
		}
	}

	return true
}

// An Error is returned by any of the built-in functions when they run
// into an error.
type Error struct {
	// Cause is the cause of the error.
	Cause error
}

func (e Error) Call(frame []Func, args ...Func) Func {
	return e
}

func (e Error) Equals(other Func) bool {
	panic("Not implemented.")
}

func (e Error) Error() string {
	return fmt.Sprintf("WDTE error: %v", e.Cause)
}
<|endoftext|>


<commit_before>package couchbase

import (
	"errors"
	"time"

	"github.com/dustin/gomemcached/client"
)

type connectionPool struct {
	host, name  string
	mkConn      func(host, name string) (*memcached.Client, error)
	connections chan *memcached.Client
}

func newConnectionPool(host, name string, poolSize int) *connectionPool {
	return &connectionPool{
		host:        host,
		name:        name,
		connections: make(chan *memcached.Client, poolSize),
		mkConn:      defaultMkConn,
	}
}

func defaultMkConn(host, name string) (*memcached.Client, error) {
	conn, err := memcached.Connect("tcp", host)
	if err != nil {
		return nil, err
	}
	if name != "default" {
		conn.Auth(name, "") // error checking?
	}
	return conn, nil
}

func (cp *connectionPool) Close() (err error) {
	defer func() { err, _ = recover().(error) }()
	close(cp.connections)
	for c := range cp.connections {
		c.Close()
	}
	return
}

func (cp *connectionPool) Get() (*memcached.Client, error) {
	if cp == nil {
		return nil, errors.New("no pool")
	}

	select {
	case rv := <-cp.connections:
		return rv, nil
	case <-time.After(time.Millisecond):
		// Build a connection if we can't get a real one.
		// This can potentially be an overflow connection, or
		// a pooled connection.
		return cp.mkConn(cp.host, cp.name)
	}
}

func (cp *connectionPool) Return(c *memcached.Client) {
	if cp == nil {
		return
	}

	if c != nil {
		if c.IsHealthy() {
			select {
			case cp.connections <- c:
			default:
				// Overflow connection.
				c.Close()
			}
		} else {
			c.Close()
		}
	}
}

func (cp *connectionPool) StartTapFeed(args *memcached.TapArguments) (*memcached.TapFeed, error) {
	if cp == nil {
		return nil, errors.New("no pool")
	}
	mc, err := cp.Get()
	if err != nil {
		return nil, err
	}
	return mc.StartTapFeed(*args)
}
<commit_msg>Limit the maximum number of concurrent connections<commit_after>package couchbase

import (
	"errors"
	"time"

	"github.com/dustin/gomemcached/client"
)

var TimeoutError = errors.New("timeout waiting to build connection")

type connectionPool struct {
	host, name  string
	mkConn      func(host, name string) (*memcached.Client, error)
	connections chan *memcached.Client
	createsem   chan bool
}

func newConnectionPool(host, name string, poolSize int) *connectionPool {
	return &connectionPool{
		host:        host,
		name:        name,
		connections: make(chan *memcached.Client, poolSize),
		createsem:   make(chan bool, 2*poolSize),
		mkConn:      defaultMkConn,
	}
}

func defaultMkConn(host, name string) (*memcached.Client, error) {
	conn, err := memcached.Connect("tcp", host)
	if err != nil {
		return nil, err
	}
	if name != "default" {
		conn.Auth(name, "") // error checking?
	}
	return conn, nil
}

func (cp *connectionPool) Close() (err error) {
	defer func() { err, _ = recover().(error) }()
	close(cp.connections)
	for c := range cp.connections {
		c.Close()
	}
	return
}

func (cp *connectionPool) GetWithTimeout(d time.Duration) (*memcached.Client, error) {
	if cp == nil {
		return nil, errors.New("no pool")
	}

	select {
	case rv := <-cp.connections:
		return rv, nil
	case <-time.After(time.Millisecond):
		select {
		case rv := <-cp.connections:
			return rv, nil
		case cp.createsem <- true:
			// Build a connection if we can't get a real one.
			// This can potentially be an overflow connection, or
			// a pooled connection.
			return cp.mkConn(cp.host, cp.name)
		case <-time.After(d):
			return nil, TimeoutError
		}
	}
}

func (cp *connectionPool) Get() (*memcached.Client, error) {
	return cp.GetWithTimeout(time.Hour * 24 * 30)
}

func (cp *connectionPool) Return(c *memcached.Client) {
	if cp == nil {
		return
	}

	if c != nil {
		if c.IsHealthy() {
			select {
			case cp.connections <- c:
			default:
				// Overflow connection.
				<-cp.createsem
				c.Close()
			}
		} else {
			<-cp.createsem
			c.Close()
		}
	}
}

func (cp *connectionPool) StartTapFeed(args *memcached.TapArguments) (*memcached.TapFeed, error) {
	if cp == nil {
		return nil, errors.New("no pool")
	}
	mc, err := cp.Get()
	if err != nil {
		return nil, err
	}
	return mc.StartTapFeed(*args)
}
<|endoftext|>


<commit_before>package validation

// When returns a validation rule that executes the given list of rules when the condition is true.
func When(condition bool, rules ...Rule) WhenRule {
	return WhenRule{
		condition: condition,
		rules:     rules,
		elseRules: []Rule{},
	}
}

// WhenRule is a validation rule that executes the given list of rules when the condition is true.
type WhenRule struct {
	condition bool
	rules     []Rule
	elseRules []Rule
}

// Validate checks if the condition is true and if so, it validates the value using the specified rules.
func (r WhenRule) Validate(value interface{}) error {
	if r.condition {
		return Validate(value, r.rules...)
	}

	return Validate(value, r.elseRules...)
}

// When returns a validation rule that executes the given list of rules when the condition is false.
func (r WhenRule) Else(rules ...Rule) WhenRule {
	r.elseRules = rules
	return r
}
<commit_msg>fixed doc<commit_after>package validation

// When returns a validation rule that executes the given list of rules when the condition is true.
func When(condition bool, rules ...Rule) WhenRule {
	return WhenRule{
		condition: condition,
		rules:     rules,
		elseRules: []Rule{},
	}
}

// WhenRule is a validation rule that executes the given list of rules when the condition is true.
type WhenRule struct {
	condition bool
	rules     []Rule
	elseRules []Rule
}

// Validate checks if the condition is true and if so, it validates the value using the specified rules.
func (r WhenRule) Validate(value interface{}) error {
	if r.condition {
		return Validate(value, r.rules...)
	}

	return Validate(value, r.elseRules...)
}

// Else returns a validation rule that executes the given list of rules when the condition is false.
func (r WhenRule) Else(rules ...Rule) WhenRule {
	r.elseRules = rules
	return r
}
<|endoftext|>


<commit_before>package main

import (
	"time"
)

// Version is the current application version
const Version = "0.1"

// DefaultPort is the default server port
const DefaultPort = 3001

// DatabaseURL is the full url to download the maxmind database
const DatabaseURL = "http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz"

// UpdateInterval is the default time to update the database
const UpdateInterval = 24 * time.Hour

// RetryInterval is the default retry time to retry the update
const RetryInterval = time.Hour
<commit_msg>Bump version<commit_after>package main

import (
	"time"
)

// Version is the current application version
const Version = "0.2"

// DefaultPort is the default server port
const DefaultPort = 3001

// DatabaseURL is the full url to download the maxmind database
const DatabaseURL = "http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz"

// UpdateInterval is the default time to update the database
const UpdateInterval = 24 * time.Hour

// RetryInterval is the default retry time to retry the update
const RetryInterval = time.Hour
<|endoftext|>


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

package custom

import (
	"fmt"

	"github.com/blevesearch/bleve/analysis"
	"github.com/blevesearch/bleve/registry"
)

const Name = "custom"

func AnalyzerConstructor(config map[string]interface{}, cache *registry.Cache) (*analysis.Analyzer, error) {

	var err error
	var charFilters []analysis.CharFilter
	charFiltersNames, ok := config["char_filters"].([]string)
	if ok {
		charFilters, err = getCharFilters(charFiltersNames, cache)
		if err != nil {
			return nil, err
		}
	} else {
		charFiltersNamesInterfaceSlice, ok := config["char_filters"].([]interface{})
		if ok {
			charFiltersNames, err := convertInterfaceSliceToStringSlice(charFiltersNamesInterfaceSlice, "char filter")
			if err != nil {
				return nil, err
			}
			charFilters, err = getCharFilters(charFiltersNames, cache)
			if err != nil {
				return nil, err
			}
		}
	}

	tokenizerName, ok := config["tokenizer"].(string)
	if !ok {
		return nil, fmt.Errorf("must specify tokenizer")
	}

	tokenizer, err := cache.TokenizerNamed(tokenizerName)
	if err != nil {
		return nil, err
	}

	var tokenFilters []analysis.TokenFilter
	tokenFiltersNames, ok := config["token_filters"].([]string)
	if ok {
		tokenFilters, err = getTokenFilters(tokenFiltersNames, cache)
		if err != nil {
			return nil, err
		}
	} else {
		tokenFiltersNamesInterfaceSlice, ok := config["token_filters"].([]interface{})
		if ok {
			tokenFiltersNames, err := convertInterfaceSliceToStringSlice(tokenFiltersNamesInterfaceSlice, "token filter")
			if err != nil {
				return nil, err
			}
			tokenFilters, err = getTokenFilters(tokenFiltersNames, cache)
			if err != nil {
				return nil, err
			}
		}
	}

	rv := analysis.Analyzer{
		Tokenizer: tokenizer,
	}
	if charFilters != nil {
		rv.CharFilters = charFilters
	}
	if tokenFilters != nil {
		rv.TokenFilters = tokenFilters
	}
	return &rv, nil
}

func init() {
	registry.RegisterAnalyzer(Name, AnalyzerConstructor)
}

func getCharFilters(charFilterNames []string, cache *registry.Cache) ([]analysis.CharFilter, error) {
	charFilters := make([]analysis.CharFilter, len(charFilterNames))
	for i, charFilterName := range charFilterNames {
		charFilter, err := cache.CharFilterNamed(charFilterName)
		if err != nil {
			return nil, err
		}
		charFilters[i] = charFilter
	}

	return charFilters, nil
}

func getTokenFilters(tokenFilterNames []string, cache *registry.Cache) ([]analysis.TokenFilter, error) {
	tokenFilters := make([]analysis.TokenFilter, len(tokenFilterNames))
	for i, tokenFilterName := range tokenFilterNames {
		tokenFilter, err := cache.TokenFilterNamed(tokenFilterName)
		if err != nil {
			return nil, err
		}
		tokenFilters[i] = tokenFilter
	}

	return tokenFilters, nil
}

func convertInterfaceSliceToStringSlice(interfaceSlice []interface{}, objType string) ([]string, error) {
	stringSlice := make([]string, len(interfaceSlice))
	for i, interfaceObj := range interfaceSlice {
		stringObj, ok := interfaceObj.(string)
		if ok {
			stringSlice[i] = stringObj
		} else {
			return nil, fmt.Errorf(objType + " name must be a string")
		}
	}

	return stringSlice, nil
}
<commit_msg>add validtion which checks the type of char/token filters when specified in the custom type of analyzer<commit_after>//  Copyright (c) 2014 Couchbase, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 		http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package custom

import (
	"fmt"

	"github.com/blevesearch/bleve/analysis"
	"github.com/blevesearch/bleve/registry"
)

const Name = "custom"

func AnalyzerConstructor(config map[string]interface{}, cache *registry.Cache) (*analysis.Analyzer, error) {

	var err error
	var charFilters []analysis.CharFilter
	charFiltersValue, ok := config["char_filters"]
	if ok {
		switch charFiltersValue := charFiltersValue.(type) {
		case []string:
			charFilters, err = getCharFilters(charFiltersValue, cache)
			if err != nil {
				return nil, err
			}
		case []interface{}:
			charFiltersNames, err := convertInterfaceSliceToStringSlice(charFiltersValue, "char filter")
			if err != nil {
				return nil, err
			}
			charFilters, err = getCharFilters(charFiltersNames, cache)
			if err != nil {
				return nil, err
			}
		default:
			return nil, fmt.Errorf("unsupported type for char_filters, must be slice")
		}
	}

	var tokenizerName string
	tokenizerValue, ok := config["tokenizer"]
	if ok {
		tokenizerName, ok = tokenizerValue.(string)
		if !ok {
			return nil, fmt.Errorf("must specify tokenizer as string")
		}
	} else {
		return nil, fmt.Errorf("must specify tokenizer")
	}

	tokenizer, err := cache.TokenizerNamed(tokenizerName)
	if err != nil {
		return nil, err
	}

	var tokenFilters []analysis.TokenFilter
	tokenFiltersValue, ok := config["token_filters"]
	if ok {
		switch tokenFiltersValue := tokenFiltersValue.(type) {
		case []string:
			tokenFilters, err = getTokenFilters(tokenFiltersValue, cache)
			if err != nil {
				return nil, err
			}
		case []interface{}:
			tokenFiltersNames, err := convertInterfaceSliceToStringSlice(tokenFiltersValue, "token filter")
			if err != nil {
				return nil, err
			}
			tokenFilters, err = getTokenFilters(tokenFiltersNames, cache)
			if err != nil {
				return nil, err
			}
		default:
			return nil, fmt.Errorf("unsupported type for token_filters, must be slice")
		}
	}

	rv := analysis.Analyzer{
		Tokenizer: tokenizer,
	}
	if charFilters != nil {
		rv.CharFilters = charFilters
	}
	if tokenFilters != nil {
		rv.TokenFilters = tokenFilters
	}
	return &rv, nil
}

func init() {
	registry.RegisterAnalyzer(Name, AnalyzerConstructor)
}

func getCharFilters(charFilterNames []string, cache *registry.Cache) ([]analysis.CharFilter, error) {
	charFilters := make([]analysis.CharFilter, len(charFilterNames))
	for i, charFilterName := range charFilterNames {
		charFilter, err := cache.CharFilterNamed(charFilterName)
		if err != nil {
			return nil, err
		}
		charFilters[i] = charFilter
	}

	return charFilters, nil
}

func getTokenFilters(tokenFilterNames []string, cache *registry.Cache) ([]analysis.TokenFilter, error) {
	tokenFilters := make([]analysis.TokenFilter, len(tokenFilterNames))
	for i, tokenFilterName := range tokenFilterNames {
		tokenFilter, err := cache.TokenFilterNamed(tokenFilterName)
		if err != nil {
			return nil, err
		}
		tokenFilters[i] = tokenFilter
	}

	return tokenFilters, nil
}

func convertInterfaceSliceToStringSlice(interfaceSlice []interface{}, objType string) ([]string, error) {
	stringSlice := make([]string, len(interfaceSlice))
	for i, interfaceObj := range interfaceSlice {
		stringObj, ok := interfaceObj.(string)
		if ok {
			stringSlice[i] = stringObj
		} else {
			return nil, fmt.Errorf(objType + " name must be a string")
		}
	}

	return stringSlice, nil
}
<|endoftext|>


<commit_before>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package kio

import (
	"fmt"
	"os"
	"path/filepath"

	"sigs.k8s.io/kustomize/kyaml/errors"
	"sigs.k8s.io/kustomize/kyaml/filesys"
	"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
	"sigs.k8s.io/kustomize/kyaml/sets"
	"sigs.k8s.io/kustomize/kyaml/yaml"
)

// requiredResourcePackageAnnotations are annotations that are required to write resources back to
// files.
var requiredResourcePackageAnnotations = []string{kioutil.IndexAnnotation, kioutil.PathAnnotation}

// PackageBuffer implements Reader and Writer, storing Resources in a local field.
type PackageBuffer struct {
	Nodes []*yaml.RNode
}

func (r *PackageBuffer) Read() ([]*yaml.RNode, error) {
	return r.Nodes, nil
}

func (r *PackageBuffer) Write(nodes []*yaml.RNode) error {
	r.Nodes = nodes
	return nil
}

// LocalPackageReadWriter reads and writes Resources from / to a local directory.
// When writing, LocalPackageReadWriter will delete files if all of the Resources from
// that file have been removed from the output.
type LocalPackageReadWriter struct {
	Kind string `yaml:"kind,omitempty"`

	KeepReaderAnnotations bool `yaml:"keepReaderAnnotations,omitempty"`

	// PreserveSeqIndent if true adds kioutil.SeqIndentAnnotation to each resource
	PreserveSeqIndent bool

	// PackagePath is the path to the package directory.
	PackagePath string `yaml:"path,omitempty"`

	// PackageFileName is the name of file containing package metadata.
	// It will be used to identify package.
	PackageFileName string `yaml:"packageFileName,omitempty"`

	// MatchFilesGlob configures Read to only read Resources from files matching any of the
	// provided patterns.
	// Defaults to ["*.yaml", "*.yml"] if empty.  To match all files specify ["*"].
	MatchFilesGlob []string `yaml:"matchFilesGlob,omitempty"`

	// IncludeSubpackages will configure Read to read Resources from subpackages.
	// Subpackages are identified by presence of PackageFileName.
	IncludeSubpackages bool `yaml:"includeSubpackages,omitempty"`

	// ErrorIfNonResources will configure Read to throw an error if yaml missing missing
	// apiVersion or kind is read.
	ErrorIfNonResources bool `yaml:"errorIfNonResources,omitempty"`

	// OmitReaderAnnotations will cause the reader to skip annotating Resources with the file
	// path and mode.
	OmitReaderAnnotations bool `yaml:"omitReaderAnnotations,omitempty"`

	// SetAnnotations are annotations to set on the Resources as they are read.
	SetAnnotations map[string]string `yaml:"setAnnotations,omitempty"`

	// NoDeleteFiles if set to true, LocalPackageReadWriter won't delete any files
	NoDeleteFiles bool `yaml:"noDeleteFiles,omitempty"`

	files sets.String

	// FileSkipFunc is a function which returns true if reader should ignore
	// the file
	FileSkipFunc LocalPackageSkipFileFunc
}

func (r *LocalPackageReadWriter) Read() ([]*yaml.RNode, error) {
	nodes, err := LocalPackageReader{
		PackagePath:         r.PackagePath,
		MatchFilesGlob:      r.MatchFilesGlob,
		IncludeSubpackages:  r.IncludeSubpackages,
		ErrorIfNonResources: r.ErrorIfNonResources,
		SetAnnotations:      r.SetAnnotations,
		PackageFileName:     r.PackageFileName,
		FileSkipFunc:        r.FileSkipFunc,
		PreserveSeqIndent:   r.PreserveSeqIndent,
	}.Read()
	if err != nil {
		return nil, errors.Wrap(err)
	}
	// keep track of all the files
	if !r.NoDeleteFiles {
		r.files, err = r.getFiles(nodes)
		if err != nil {
			return nil, errors.Wrap(err)
		}
	}
	return nodes, nil
}

func (r *LocalPackageReadWriter) Write(nodes []*yaml.RNode) error {
	newFiles, err := r.getFiles(nodes)
	if err != nil {
		return errors.Wrap(err)
	}
	var clear []string
	for k := range r.SetAnnotations {
		clear = append(clear, k)
	}
	err = LocalPackageWriter{
		PackagePath:           r.PackagePath,
		ClearAnnotations:      clear,
		KeepReaderAnnotations: r.KeepReaderAnnotations,
	}.Write(nodes)
	if err != nil {
		return errors.Wrap(err)
	}
	deleteFiles := r.files.Difference(newFiles)
	for f := range deleteFiles {
		if err = os.Remove(filepath.Join(r.PackagePath, f)); err != nil {
			return errors.Wrap(err)
		}
	}
	return nil
}

func (r *LocalPackageReadWriter) getFiles(nodes []*yaml.RNode) (sets.String, error) {
	val := sets.String{}
	for _, n := range nodes {
		path, _, err := kioutil.GetFileAnnotations(n)
		if err != nil {
			return nil, errors.Wrap(err)
		}
		val.Insert(path)
	}
	return val, nil
}

// LocalPackageSkipFileFunc is a function which returns true if the file
// in the package should be ignored by reader.
// relPath is an OS specific relative path
type LocalPackageSkipFileFunc func(relPath string) bool

// LocalPackageReader reads ResourceNodes from a local package.
type LocalPackageReader struct {
	Kind string `yaml:"kind,omitempty"`

	// PackagePath is the path to the package directory.
	PackagePath string `yaml:"path,omitempty"`

	// PackageFileName is the name of file containing package metadata.
	// It will be used to identify package.
	PackageFileName string `yaml:"packageFileName,omitempty"`

	// MatchFilesGlob configures Read to only read Resources from files matching any of the
	// provided patterns.
	// Defaults to ["*.yaml", "*.yml"] if empty.  To match all files specify ["*"].
	MatchFilesGlob []string `yaml:"matchFilesGlob,omitempty"`

	// IncludeSubpackages will configure Read to read Resources from subpackages.
	// Subpackages are identified by presence of PackageFileName.
	IncludeSubpackages bool `yaml:"includeSubpackages,omitempty"`

	// ErrorIfNonResources will configure Read to throw an error if yaml missing missing
	// apiVersion or kind is read.
	ErrorIfNonResources bool `yaml:"errorIfNonResources,omitempty"`

	// OmitReaderAnnotations will cause the reader to skip annotating Resources with the file
	// path and mode.
	OmitReaderAnnotations bool `yaml:"omitReaderAnnotations,omitempty"`

	// SetAnnotations are annotations to set on the Resources as they are read.
	SetAnnotations map[string]string `yaml:"setAnnotations,omitempty"`

	// FileSkipFunc is a function which returns true if reader should ignore
	// the file
	FileSkipFunc LocalPackageSkipFileFunc

	// PreserveSeqIndent if true adds kioutil.SeqIndentAnnotation to each resource
	PreserveSeqIndent bool

	// FileSystem can be used to mock the disk file system.
	FileSystem filesys.FileSystemOrOnDisk
}

var _ Reader = LocalPackageReader{}

var DefaultMatch = []string{"*.yaml", "*.yml"}
var JSONMatch = []string{"*.json"}
var MatchAll = append(DefaultMatch, JSONMatch...)

// Read reads the Resources.
func (r LocalPackageReader) Read() ([]*yaml.RNode, error) {
	if r.PackagePath == "" {
		return nil, fmt.Errorf("must specify package path")
	}

	// use slash for path
	r.PackagePath = filepath.ToSlash(r.PackagePath)
	if len(r.MatchFilesGlob) == 0 {
		r.MatchFilesGlob = DefaultMatch
	}

	var operand ResourceNodeSlice
	var pathRelativeTo string
	var err error
	ignoreFilesMatcher := &ignoreFilesMatcher{
		fs: r.FileSystem,
	}
	dir, file, err := r.FileSystem.CleanedAbs(r.PackagePath)
	if err != nil {
		return nil, errors.Wrap(err)
	}
	r.PackagePath = filepath.Join(string(dir), file)
	err = r.FileSystem.Walk(r.PackagePath, func(
		path string, info os.FileInfo, err error) error {
		if err != nil {
			return errors.Wrap(err)
		}

		// is this the user specified path?
		if path == r.PackagePath {
			if info.IsDir() {
				// skip the root package directory, but check for a
				// .krmignore file first.
				pathRelativeTo = r.PackagePath
				return ignoreFilesMatcher.readIgnoreFile(path)
			}

			// user specified path is a file rather than a directory.
			// make its path relative to its parent so it can be written to another file.
			pathRelativeTo = filepath.Dir(r.PackagePath)
		}

		// check if we should skip the directory or file
		if info.IsDir() {
			return r.shouldSkipDir(path, ignoreFilesMatcher)
		}

		// get the relative path to file within the package so we can write the files back out
		// to another location.
		relPath, err := filepath.Rel(pathRelativeTo, path)
		if err != nil {
			return errors.WrapPrefixf(err, pathRelativeTo)
		}
		if match, err := r.shouldSkipFile(path, relPath, ignoreFilesMatcher); err != nil {
			return err
		} else if match {
			// skip this file
			return nil
		}

		r.initReaderAnnotations(relPath, info)
		nodes, err := r.readFile(path, info)
		if err != nil {
			return errors.WrapPrefixf(err, path)
		}
		operand = append(operand, nodes...)
		return nil
	})
	return operand, err
}

// readFile reads the ResourceNodes from a file
func (r *LocalPackageReader) readFile(path string, _ os.FileInfo) ([]*yaml.RNode, error) {
	f, err := r.FileSystem.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	rr := &ByteReader{
		DisableUnwrapping:     true,
		Reader:                f,
		OmitReaderAnnotations: r.OmitReaderAnnotations,
		SetAnnotations:        r.SetAnnotations,
		PreserveSeqIndent:     r.PreserveSeqIndent,
	}
	return rr.Read()
}

// shouldSkipFile returns true if the file should be skipped
func (r *LocalPackageReader) shouldSkipFile(path, relPath string, matcher *ignoreFilesMatcher) (bool, error) {
	// check if the file is covered by a .krmignore file.
	if matcher.matchFile(path) {
		return true, nil
	}

	if r.FileSkipFunc != nil && r.FileSkipFunc(relPath) {
		return true, nil
	}

	// check if the files are in scope
	for _, g := range r.MatchFilesGlob {
		if match, err := filepath.Match(g, filepath.Base(path)); err != nil {
			return true, errors.Wrap(err)
		} else if match {
			return false, nil
		}
	}
	return true, nil
}

// initReaderAnnotations adds the LocalPackageReader Annotations to r.SetAnnotations
func (r *LocalPackageReader) initReaderAnnotations(path string, _ os.FileInfo) {
	if r.SetAnnotations == nil {
		r.SetAnnotations = map[string]string{}
	}
	if !r.OmitReaderAnnotations {
		r.SetAnnotations[kioutil.PathAnnotation] = path
	}
}

// shouldSkipDir returns a filepath.SkipDir if the directory should be skipped
func (r *LocalPackageReader) shouldSkipDir(path string, matcher *ignoreFilesMatcher) error {
	if matcher.matchDir(path) {
		return filepath.SkipDir
	}

	if r.PackageFileName == "" {
		return nil
	}
	// check if this is a subpackage
	if !r.FileSystem.Exists(filepath.Join(path, r.PackageFileName)) {
		return nil
	}
	if !r.IncludeSubpackages {
		return filepath.SkipDir
	}
	return matcher.readIgnoreFile(path)
}
<commit_msg>Add FileSystem interface to LocalPackageReadWriter and hook to LocalPackageReader<commit_after>// Copyright 2019 The Kubernetes Authors.
// SPDX-License-Identifier: Apache-2.0

package kio

import (
	"fmt"
	"os"
	"path/filepath"

	"sigs.k8s.io/kustomize/kyaml/errors"
	"sigs.k8s.io/kustomize/kyaml/filesys"
	"sigs.k8s.io/kustomize/kyaml/kio/kioutil"
	"sigs.k8s.io/kustomize/kyaml/sets"
	"sigs.k8s.io/kustomize/kyaml/yaml"
)

// requiredResourcePackageAnnotations are annotations that are required to write resources back to
// files.
var requiredResourcePackageAnnotations = []string{kioutil.IndexAnnotation, kioutil.PathAnnotation}

// PackageBuffer implements Reader and Writer, storing Resources in a local field.
type PackageBuffer struct {
	Nodes []*yaml.RNode
}

func (r *PackageBuffer) Read() ([]*yaml.RNode, error) {
	return r.Nodes, nil
}

func (r *PackageBuffer) Write(nodes []*yaml.RNode) error {
	r.Nodes = nodes
	return nil
}

// LocalPackageReadWriter reads and writes Resources from / to a local directory.
// When writing, LocalPackageReadWriter will delete files if all of the Resources from
// that file have been removed from the output.
type LocalPackageReadWriter struct {
	Kind string `yaml:"kind,omitempty"`

	KeepReaderAnnotations bool `yaml:"keepReaderAnnotations,omitempty"`

	// PreserveSeqIndent if true adds kioutil.SeqIndentAnnotation to each resource
	PreserveSeqIndent bool

	// PackagePath is the path to the package directory.
	PackagePath string `yaml:"path,omitempty"`

	// PackageFileName is the name of file containing package metadata.
	// It will be used to identify package.
	PackageFileName string `yaml:"packageFileName,omitempty"`

	// MatchFilesGlob configures Read to only read Resources from files matching any of the
	// provided patterns.
	// Defaults to ["*.yaml", "*.yml"] if empty.  To match all files specify ["*"].
	MatchFilesGlob []string `yaml:"matchFilesGlob,omitempty"`

	// IncludeSubpackages will configure Read to read Resources from subpackages.
	// Subpackages are identified by presence of PackageFileName.
	IncludeSubpackages bool `yaml:"includeSubpackages,omitempty"`

	// ErrorIfNonResources will configure Read to throw an error if yaml missing missing
	// apiVersion or kind is read.
	ErrorIfNonResources bool `yaml:"errorIfNonResources,omitempty"`

	// OmitReaderAnnotations will cause the reader to skip annotating Resources with the file
	// path and mode.
	OmitReaderAnnotations bool `yaml:"omitReaderAnnotations,omitempty"`

	// SetAnnotations are annotations to set on the Resources as they are read.
	SetAnnotations map[string]string `yaml:"setAnnotations,omitempty"`

	// NoDeleteFiles if set to true, LocalPackageReadWriter won't delete any files
	NoDeleteFiles bool `yaml:"noDeleteFiles,omitempty"`

	files sets.String

	// FileSkipFunc is a function which returns true if reader should ignore
	// the file
	FileSkipFunc LocalPackageSkipFileFunc

	// FileSystem can be used to mock the disk file system.
	FileSystem filesys.FileSystemOrOnDisk
}

func (r *LocalPackageReadWriter) Read() ([]*yaml.RNode, error) {
	nodes, err := LocalPackageReader{
		PackagePath:         r.PackagePath,
		MatchFilesGlob:      r.MatchFilesGlob,
		IncludeSubpackages:  r.IncludeSubpackages,
		ErrorIfNonResources: r.ErrorIfNonResources,
		SetAnnotations:      r.SetAnnotations,
		PackageFileName:     r.PackageFileName,
		FileSkipFunc:        r.FileSkipFunc,
		PreserveSeqIndent:   r.PreserveSeqIndent,
		FileSystem:          r.FileSystem,
	}.Read()
	if err != nil {
		return nil, errors.Wrap(err)
	}
	// keep track of all the files
	if !r.NoDeleteFiles {
		r.files, err = r.getFiles(nodes)
		if err != nil {
			return nil, errors.Wrap(err)
		}
	}
	return nodes, nil
}

func (r *LocalPackageReadWriter) Write(nodes []*yaml.RNode) error {
	newFiles, err := r.getFiles(nodes)
	if err != nil {
		return errors.Wrap(err)
	}
	var clear []string
	for k := range r.SetAnnotations {
		clear = append(clear, k)
	}
	err = LocalPackageWriter{
		PackagePath:           r.PackagePath,
		ClearAnnotations:      clear,
		KeepReaderAnnotations: r.KeepReaderAnnotations,
	}.Write(nodes)
	if err != nil {
		return errors.Wrap(err)
	}
	deleteFiles := r.files.Difference(newFiles)
	for f := range deleteFiles {
		if err = os.Remove(filepath.Join(r.PackagePath, f)); err != nil {
			return errors.Wrap(err)
		}
	}
	return nil
}

func (r *LocalPackageReadWriter) getFiles(nodes []*yaml.RNode) (sets.String, error) {
	val := sets.String{}
	for _, n := range nodes {
		path, _, err := kioutil.GetFileAnnotations(n)
		if err != nil {
			return nil, errors.Wrap(err)
		}
		val.Insert(path)
	}
	return val, nil
}

// LocalPackageSkipFileFunc is a function which returns true if the file
// in the package should be ignored by reader.
// relPath is an OS specific relative path
type LocalPackageSkipFileFunc func(relPath string) bool

// LocalPackageReader reads ResourceNodes from a local package.
type LocalPackageReader struct {
	Kind string `yaml:"kind,omitempty"`

	// PackagePath is the path to the package directory.
	PackagePath string `yaml:"path,omitempty"`

	// PackageFileName is the name of file containing package metadata.
	// It will be used to identify package.
	PackageFileName string `yaml:"packageFileName,omitempty"`

	// MatchFilesGlob configures Read to only read Resources from files matching any of the
	// provided patterns.
	// Defaults to ["*.yaml", "*.yml"] if empty.  To match all files specify ["*"].
	MatchFilesGlob []string `yaml:"matchFilesGlob,omitempty"`

	// IncludeSubpackages will configure Read to read Resources from subpackages.
	// Subpackages are identified by presence of PackageFileName.
	IncludeSubpackages bool `yaml:"includeSubpackages,omitempty"`

	// ErrorIfNonResources will configure Read to throw an error if yaml missing missing
	// apiVersion or kind is read.
	ErrorIfNonResources bool `yaml:"errorIfNonResources,omitempty"`

	// OmitReaderAnnotations will cause the reader to skip annotating Resources with the file
	// path and mode.
	OmitReaderAnnotations bool `yaml:"omitReaderAnnotations,omitempty"`

	// SetAnnotations are annotations to set on the Resources as they are read.
	SetAnnotations map[string]string `yaml:"setAnnotations,omitempty"`

	// FileSkipFunc is a function which returns true if reader should ignore
	// the file
	FileSkipFunc LocalPackageSkipFileFunc

	// PreserveSeqIndent if true adds kioutil.SeqIndentAnnotation to each resource
	PreserveSeqIndent bool

	// FileSystem can be used to mock the disk file system.
	FileSystem filesys.FileSystemOrOnDisk
}

var _ Reader = LocalPackageReader{}

var DefaultMatch = []string{"*.yaml", "*.yml"}
var JSONMatch = []string{"*.json"}
var MatchAll = append(DefaultMatch, JSONMatch...)

// Read reads the Resources.
func (r LocalPackageReader) Read() ([]*yaml.RNode, error) {
	if r.PackagePath == "" {
		return nil, fmt.Errorf("must specify package path")
	}

	// use slash for path
	r.PackagePath = filepath.ToSlash(r.PackagePath)
	if len(r.MatchFilesGlob) == 0 {
		r.MatchFilesGlob = DefaultMatch
	}

	var operand ResourceNodeSlice
	var pathRelativeTo string
	var err error
	ignoreFilesMatcher := &ignoreFilesMatcher{
		fs: r.FileSystem,
	}
	dir, file, err := r.FileSystem.CleanedAbs(r.PackagePath)
	if err != nil {
		return nil, errors.Wrap(err)
	}
	r.PackagePath = filepath.Join(string(dir), file)
	err = r.FileSystem.Walk(r.PackagePath, func(
		path string, info os.FileInfo, err error) error {
		if err != nil {
			return errors.Wrap(err)
		}

		// is this the user specified path?
		if path == r.PackagePath {
			if info.IsDir() {
				// skip the root package directory, but check for a
				// .krmignore file first.
				pathRelativeTo = r.PackagePath
				return ignoreFilesMatcher.readIgnoreFile(path)
			}

			// user specified path is a file rather than a directory.
			// make its path relative to its parent so it can be written to another file.
			pathRelativeTo = filepath.Dir(r.PackagePath)
		}

		// check if we should skip the directory or file
		if info.IsDir() {
			return r.shouldSkipDir(path, ignoreFilesMatcher)
		}

		// get the relative path to file within the package so we can write the files back out
		// to another location.
		relPath, err := filepath.Rel(pathRelativeTo, path)
		if err != nil {
			return errors.WrapPrefixf(err, pathRelativeTo)
		}
		if match, err := r.shouldSkipFile(path, relPath, ignoreFilesMatcher); err != nil {
			return err
		} else if match {
			// skip this file
			return nil
		}

		r.initReaderAnnotations(relPath, info)
		nodes, err := r.readFile(path, info)
		if err != nil {
			return errors.WrapPrefixf(err, path)
		}
		operand = append(operand, nodes...)
		return nil
	})
	return operand, err
}

// readFile reads the ResourceNodes from a file
func (r *LocalPackageReader) readFile(path string, _ os.FileInfo) ([]*yaml.RNode, error) {
	f, err := r.FileSystem.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	rr := &ByteReader{
		DisableUnwrapping:     true,
		Reader:                f,
		OmitReaderAnnotations: r.OmitReaderAnnotations,
		SetAnnotations:        r.SetAnnotations,
		PreserveSeqIndent:     r.PreserveSeqIndent,
	}
	return rr.Read()
}

// shouldSkipFile returns true if the file should be skipped
func (r *LocalPackageReader) shouldSkipFile(path, relPath string, matcher *ignoreFilesMatcher) (bool, error) {
	// check if the file is covered by a .krmignore file.
	if matcher.matchFile(path) {
		return true, nil
	}

	if r.FileSkipFunc != nil && r.FileSkipFunc(relPath) {
		return true, nil
	}

	// check if the files are in scope
	for _, g := range r.MatchFilesGlob {
		if match, err := filepath.Match(g, filepath.Base(path)); err != nil {
			return true, errors.Wrap(err)
		} else if match {
			return false, nil
		}
	}
	return true, nil
}

// initReaderAnnotations adds the LocalPackageReader Annotations to r.SetAnnotations
func (r *LocalPackageReader) initReaderAnnotations(path string, _ os.FileInfo) {
	if r.SetAnnotations == nil {
		r.SetAnnotations = map[string]string{}
	}
	if !r.OmitReaderAnnotations {
		r.SetAnnotations[kioutil.PathAnnotation] = path
	}
}

// shouldSkipDir returns a filepath.SkipDir if the directory should be skipped
func (r *LocalPackageReader) shouldSkipDir(path string, matcher *ignoreFilesMatcher) error {
	if matcher.matchDir(path) {
		return filepath.SkipDir
	}

	if r.PackageFileName == "" {
		return nil
	}
	// check if this is a subpackage
	if !r.FileSystem.Exists(filepath.Join(path, r.PackageFileName)) {
		return nil
	}
	if !r.IncludeSubpackages {
		return filepath.SkipDir
	}
	return matcher.readIgnoreFile(path)
}
<|endoftext|>


<commit_before>package memcache

import (
	"fmt"
	memcache_impl "github.com/bradfitz/gomemcache/memcache"
	"github.com/pierrre/imageproxy"
)

type MemcacheCache struct {
	Prefix   string
	Memcache *memcache_impl.Client
}

func (cache *MemcacheCache) Get(key string) (image *imageproxy.Image, err error) {
	hashedKey := imageproxy.HashCacheKey(key)
	item, err := cache.Memcache.Get(cache.Prefix + hashedKey)
	if err != nil {
		fmt.Println(err)
		return
	}
	image = &imageproxy.Image{}
	err = image.Unserialize(item.Value)
	if err != nil {
		image = nil
	}
	return
}

func (cache *MemcacheCache) Set(key string, image *imageproxy.Image) (err error) {
	serialized, err := image.Serialize()
	if err != nil {
		return
	}
	hashedKey := imageproxy.HashCacheKey(key)
	item := &memcache_impl.Item{
		Key:   cache.Prefix + hashedKey,
		Value: serialized,
	}
	err = cache.Memcache.Set(item)
	return
}
<commit_msg>Remove debug<commit_after>package memcache

import (
	memcache_impl "github.com/bradfitz/gomemcache/memcache"
	"github.com/pierrre/imageproxy"
)

type MemcacheCache struct {
	Prefix   string
	Memcache *memcache_impl.Client
}

func (cache *MemcacheCache) Get(key string) (image *imageproxy.Image, err error) {
	hashedKey := imageproxy.HashCacheKey(key)
	item, err := cache.Memcache.Get(cache.Prefix + hashedKey)
	if err != nil {
		return
	}
	image = &imageproxy.Image{}
	err = image.Unserialize(item.Value)
	if err != nil {
		image = nil
	}
	return
}

func (cache *MemcacheCache) Set(key string, image *imageproxy.Image) (err error) {
	serialized, err := image.Serialize()
	if err != nil {
		return
	}
	hashedKey := imageproxy.HashCacheKey(key)
	item := &memcache_impl.Item{
		Key:   cache.Prefix + hashedKey,
		Value: serialized,
	}
	err = cache.Memcache.Set(item)
	return
}
<|endoftext|>


<commit_before><commit_msg>Helper message<commit_after><|endoftext|>


<commit_before>package wats

import (
	"fmt"
	"io"
	"os"
	"time"

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

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
)

var _ = Describe("Application Lifecycle", func() {
	reportedComputerNames := func(instances int) map[string]bool {
		timer := time.NewTimer(time.Second * 120)
		defer timer.Stop()
		run := true
		go func() {
			<-timer.C
			run = false
		}()

		seenComputerNames := map[string]bool{}
		for len(seenComputerNames) != instances && run == true {
			seenComputerNames[helpers.CurlApp(config, appName, "/ENV/CF_INSTANCE_IP")] = true
		}

		return seenComputerNames
	}

	BeforeEach(func() {
		if config.GetStack() == "windows2016" {
			Skip("this test may not pass on windows2016")
		}

		memLimit := config.GetNumWindowsCells() * 2 * 4
		if memLimit < 10 {
			memLimit = 10
		}
		setTotalMemoryLimit(fmt.Sprintf("%dG", memLimit))
	})

	AfterEach(func() {
		setTotalMemoryLimit("10G")
	})

	Describe("An app staged on Diego and running on Diego", func() {
		It("attempts to forkbomb the environment", func() {
			src, err := os.Open("../../assets/greenhouse-security-fixtures/bin/BreakoutBomb.exe")
			Expect(err).NotTo(HaveOccurred())
			defer src.Close()
			dst, err := os.Create("../../assets/nora/NoraPublished/bin/breakoutbomb.exe")
			Expect(err).NotTo(HaveOccurred())
			defer dst.Close()
			_, err = io.Copy(dst, src)
			Expect(err).NotTo(HaveOccurred())
			dst.Close()

			By("pushing it", func() {
				Expect(pushNoraWithOptions(appName, config.GetNumWindowsCells()*2, "2G").Wait(CF_PUSH_TIMEOUT)).To(gexec.Exit(0))
			})

			By("staging and running it on Diego", func() {
				Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(gexec.Exit(0))
			})

			By("verifying it's up", func() {
				Eventually(appRunning(appName, config.GetNumWindowsCells()*2, CF_PUSH_TIMEOUT), CF_PUSH_TIMEOUT).Should(Succeed())
				Eventually(helpers.CurlingAppRoot(config, appName)).Should(ContainSubstring("hello i am nora"))
			})

			By("storing the current computer names")
			computerNames := reportedComputerNames(config.GetNumWindowsCells())
			Expect(len(computerNames)).To(Equal(config.GetNumWindowsCells()))

			By("Running fork bomb", func() {
				helpers.CurlApp(config, appName, "/run", "-f", "-X", "POST", "-d", "bin/breakoutbomb.exe")
			})

			time.Sleep(3 * time.Second)

			By("Making sure the bomb did not take down the machine", func() {
				newComputerNames := reportedComputerNames(config.GetNumWindowsCells())
				Expect(newComputerNames).To(Equal(computerNames))
			})
		})
	})
})
<commit_msg>Don't skip forkbomb test on windows2016<commit_after>package wats

import (
	"fmt"
	"io"
	"os"
	"time"

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

	"github.com/cloudfoundry-incubator/cf-test-helpers/cf"
	"github.com/cloudfoundry-incubator/cf-test-helpers/helpers"
)

var _ = Describe("Application Lifecycle", func() {
	reportedComputerNames := func(instances int) map[string]bool {
		timer := time.NewTimer(time.Second * 120)
		defer timer.Stop()
		run := true
		go func() {
			<-timer.C
			run = false
		}()

		seenComputerNames := map[string]bool{}
		for len(seenComputerNames) != instances && run == true {
			seenComputerNames[helpers.CurlApp(config, appName, "/ENV/CF_INSTANCE_IP")] = true
		}

		return seenComputerNames
	}

	BeforeEach(func() {
		memLimit := config.GetNumWindowsCells() * 2 * 4
		if memLimit < 10 {
			memLimit = 10
		}
		setTotalMemoryLimit(fmt.Sprintf("%dG", memLimit))
	})

	AfterEach(func() {
		setTotalMemoryLimit("10G")
	})

	Describe("An app staged on Diego and running on Diego", func() {
		It("attempts to forkbomb the environment", func() {
			src, err := os.Open("../../assets/greenhouse-security-fixtures/bin/BreakoutBomb.exe")
			Expect(err).NotTo(HaveOccurred())
			defer src.Close()
			dst, err := os.Create("../../assets/nora/NoraPublished/bin/breakoutbomb.exe")
			Expect(err).NotTo(HaveOccurred())
			defer dst.Close()
			_, err = io.Copy(dst, src)
			Expect(err).NotTo(HaveOccurred())
			dst.Close()

			By("pushing it", func() {
				Expect(pushNoraWithOptions(appName, config.GetNumWindowsCells()*2, "2G").Wait(CF_PUSH_TIMEOUT)).To(gexec.Exit(0))
			})

			By("staging and running it on Diego", func() {
				Expect(cf.Cf("start", appName).Wait(CF_PUSH_TIMEOUT)).To(gexec.Exit(0))
			})

			By("verifying it's up", func() {
				Eventually(appRunning(appName, config.GetNumWindowsCells()*2, CF_PUSH_TIMEOUT), CF_PUSH_TIMEOUT).Should(Succeed())
				Eventually(helpers.CurlingAppRoot(config, appName)).Should(ContainSubstring("hello i am nora"))
			})

			By("storing the current computer names")
			computerNames := reportedComputerNames(config.GetNumWindowsCells())
			Expect(len(computerNames)).To(Equal(config.GetNumWindowsCells()))

			By("Running fork bomb", func() {
				helpers.CurlApp(config, appName, "/run", "-f", "-X", "POST", "-d", "bin/breakoutbomb.exe")
			})

			time.Sleep(3 * time.Second)

			By("Making sure the bomb did not take down the machine", func() {
				newComputerNames := reportedComputerNames(config.GetNumWindowsCells())
				Expect(newComputerNames).To(Equal(computerNames))
			})
		})
	})
})
<|endoftext|>


<commit_before>/*
Copyright 2021 The Kubernetes Authors All rights reserved.

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

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

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

package main

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"text/template"
	"time"

	"github.com/google/go-github/v43/github"
	"golang.org/x/mod/semver"
	"k8s.io/klog/v2"
	"k8s.io/minikube/hack/update"
	"k8s.io/minikube/pkg/minikube/constants"
)

const (
	// default context timeout
	cxTimeout                 = 5 * time.Minute
	kubeadmReleaseURL         = "https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubeadm"
	kubeadmBinaryName         = "kubeadm-linux-amd64-%s"
	minikubeConstantsFilePath = "pkg/minikube/constants/constants_kubeadm_images.go"
	kubeadmImagesTemplate     = `
		{{- range $version, $element := .}}
		"{{$version}}": {
			{{- range $image, $tag := $element}}
			"{{$image}}": "{{$tag}}",
			{{- end}}
		},{{- end}}`
)

// Data contains kubeadm Images map
type Data struct {
	ImageMap string
}

func main() {
	minver := constants.OldestKubernetesVersion

	releases := []string{}

	ghc := github.NewClient(nil)

	opts := &github.ListOptions{PerPage: 100}
	for {
		rls, resp, err := ghc.Repositories.ListReleases(context.Background(), "kubernetes", "kubernetes", opts)
		if err != nil {
			klog.Fatal(err)
		}
		for _, rl := range rls {
			ver := rl.GetTagName()
			if !semver.IsValid(ver) {
				continue
			}
			// skip out-of-range versions
			if (minver != "" && semver.Compare(minver, ver) == 1) {
				continue
			}
			releases = append([]string{ver}, releases...)
		}
		if resp.NextPage == 0 {
			break
		}
		opts.Page = resp.NextPage
	}

	for _, imageVersion := range releases {
		if _, ok := constants.KubeadmImages[imageVersion]; ok {
			continue
		}
		imageMapString, err := getKubeadmImagesMapString(imageVersion)
		if err != nil {
			klog.Fatalln(err)
		}

		var data Data
		schema := map[string]update.Item{
			minikubeConstantsFilePath: {
				Replace: map[string]string{},
			},
		}

		data = Data{ImageMap: imageMapString}
		schema[minikubeConstantsFilePath].Replace[`KubeadmImages = .*`] =
			`KubeadmImages = map[string]map[string]string{ {{.ImageMap}}`
		update.Apply(schema, data)
	}
}

func getKubeadmImagesMapString(version string) (string, error) {
	url := fmt.Sprintf(kubeadmReleaseURL, version)
	fileName := fmt.Sprintf(kubeadmBinaryName, version)
	if err := downloadFile(url, fileName); err != nil {
		klog.Errorf("failed to download kubeadm binary %s", err.Error())
		return "", err
	}

	kubeadmCommand := fmt.Sprintf("./%s", fileName)
	args := []string{"config", "images", "list"}
	imageListString, err := executeCommand(kubeadmCommand, args...)
	if err != nil {
		klog.Errorf("failed to execute kubeadm command %s", kubeadmCommand)
		return "", err
	}

	if err := os.Remove(fileName); err != nil {
		klog.Errorf("failed to remove binary %s", fileName)
	}

	return formatKubeadmImageList(version, imageListString)
}

func formatKubeadmImageList(version, data string) (string, error) {
	templateData := make(map[string]map[string]string)
	templateData[version] = make(map[string]string)
	lines := strings.Split(data, "\n")
	for _, line := range lines {
		imageTag := strings.Split(line, ":")
		if len(imageTag) != 2 {
			continue
		}
		// removing the repo from image name
		imageName := strings.Split(imageTag[0], "/")
		imageTag[0] = strings.Join(imageName[1:], "/")
		if !isKubeImage(imageTag[0]) {
			templateData[version][imageTag[0]] = imageTag[1]
		}
	}

	imageTemplate := template.New("kubeadmImage")
	t, err := imageTemplate.Parse(kubeadmImagesTemplate)
	if err != nil {
		klog.Errorf("failed to create kubeadm image map template %s", err.Error())
		return "", err
	}

	var bytesBuffer bytes.Buffer
	if err := t.Execute(&bytesBuffer, &templateData); err != nil {
		return "", err
	}

	return bytesBuffer.String(), nil
}

func isKubeImage(name string) bool {
	kubeImages := map[string]bool{
		"kube-apiserver":          true,
		"kube-controller-manager": true,
		"kube-proxy":              true,
		"kube-scheduler":          true,
	}
	return kubeImages[name]
}

func downloadFile(url, fileName string) error {
	file, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer file.Close()

	response, err := http.Get(url)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return fmt.Errorf("non success status code, while downloading file: %s from: %s", fileName, url)
	}

	if _, err := io.Copy(file, response.Body); err != nil {
		return err
	}

	return os.Chmod(fileName, os.ModePerm)
}

func executeCommand(command string, args ...string) (string, error) {
	output, err := exec.Command(command, args...).Output()
	if err != nil {
		return "", err
	}
	return string(output), nil
}
<commit_msg>gofmt<commit_after>/*
Copyright 2021 The Kubernetes Authors All rights reserved.

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

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

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

package main

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"os"
	"os/exec"
	"strings"
	"text/template"
	"time"

	"github.com/google/go-github/v43/github"
	"golang.org/x/mod/semver"
	"k8s.io/klog/v2"
	"k8s.io/minikube/hack/update"
	"k8s.io/minikube/pkg/minikube/constants"
)

const (
	// default context timeout
	cxTimeout                 = 5 * time.Minute
	kubeadmReleaseURL         = "https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64/kubeadm"
	kubeadmBinaryName         = "kubeadm-linux-amd64-%s"
	minikubeConstantsFilePath = "pkg/minikube/constants/constants_kubeadm_images.go"
	kubeadmImagesTemplate     = `
		{{- range $version, $element := .}}
		"{{$version}}": {
			{{- range $image, $tag := $element}}
			"{{$image}}": "{{$tag}}",
			{{- end}}
		},{{- end}}`
)

// Data contains kubeadm Images map
type Data struct {
	ImageMap string
}

func main() {
	minver := constants.OldestKubernetesVersion

	releases := []string{}

	ghc := github.NewClient(nil)

	opts := &github.ListOptions{PerPage: 100}
	for {
		rls, resp, err := ghc.Repositories.ListReleases(context.Background(), "kubernetes", "kubernetes", opts)
		if err != nil {
			klog.Fatal(err)
		}
		for _, rl := range rls {
			ver := rl.GetTagName()
			if !semver.IsValid(ver) {
				continue
			}
			// skip out-of-range versions
			if minver != "" && semver.Compare(minver, ver) == 1 {
				continue
			}
			releases = append([]string{ver}, releases...)
		}
		if resp.NextPage == 0 {
			break
		}
		opts.Page = resp.NextPage
	}

	for _, imageVersion := range releases {
		if _, ok := constants.KubeadmImages[imageVersion]; ok {
			continue
		}
		imageMapString, err := getKubeadmImagesMapString(imageVersion)
		if err != nil {
			klog.Fatalln(err)
		}

		var data Data
		schema := map[string]update.Item{
			minikubeConstantsFilePath: {
				Replace: map[string]string{},
			},
		}

		data = Data{ImageMap: imageMapString}
		schema[minikubeConstantsFilePath].Replace[`KubeadmImages = .*`] =
			`KubeadmImages = map[string]map[string]string{ {{.ImageMap}}`
		update.Apply(schema, data)
	}
}

func getKubeadmImagesMapString(version string) (string, error) {
	url := fmt.Sprintf(kubeadmReleaseURL, version)
	fileName := fmt.Sprintf(kubeadmBinaryName, version)
	if err := downloadFile(url, fileName); err != nil {
		klog.Errorf("failed to download kubeadm binary %s", err.Error())
		return "", err
	}

	kubeadmCommand := fmt.Sprintf("./%s", fileName)
	args := []string{"config", "images", "list"}
	imageListString, err := executeCommand(kubeadmCommand, args...)
	if err != nil {
		klog.Errorf("failed to execute kubeadm command %s", kubeadmCommand)
		return "", err
	}

	if err := os.Remove(fileName); err != nil {
		klog.Errorf("failed to remove binary %s", fileName)
	}

	return formatKubeadmImageList(version, imageListString)
}

func formatKubeadmImageList(version, data string) (string, error) {
	templateData := make(map[string]map[string]string)
	templateData[version] = make(map[string]string)
	lines := strings.Split(data, "\n")
	for _, line := range lines {
		imageTag := strings.Split(line, ":")
		if len(imageTag) != 2 {
			continue
		}
		// removing the repo from image name
		imageName := strings.Split(imageTag[0], "/")
		imageTag[0] = strings.Join(imageName[1:], "/")
		if !isKubeImage(imageTag[0]) {
			templateData[version][imageTag[0]] = imageTag[1]
		}
	}

	imageTemplate := template.New("kubeadmImage")
	t, err := imageTemplate.Parse(kubeadmImagesTemplate)
	if err != nil {
		klog.Errorf("failed to create kubeadm image map template %s", err.Error())
		return "", err
	}

	var bytesBuffer bytes.Buffer
	if err := t.Execute(&bytesBuffer, &templateData); err != nil {
		return "", err
	}

	return bytesBuffer.String(), nil
}

func isKubeImage(name string) bool {
	kubeImages := map[string]bool{
		"kube-apiserver":          true,
		"kube-controller-manager": true,
		"kube-proxy":              true,
		"kube-scheduler":          true,
	}
	return kubeImages[name]
}

func downloadFile(url, fileName string) error {
	file, err := os.Create(fileName)
	if err != nil {
		return err
	}
	defer file.Close()

	response, err := http.Get(url)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.StatusCode != http.StatusOK {
		return fmt.Errorf("non success status code, while downloading file: %s from: %s", fileName, url)
	}

	if _, err := io.Copy(file, response.Body); err != nil {
		return err
	}

	return os.Chmod(fileName, os.ModePerm)
}

func executeCommand(command string, args ...string) (string, error) {
	output, err := exec.Command(command, args...).Output()
	if err != nil {
		return "", err
	}
	return string(output), nil
}
<|endoftext|>