<commit_before>package template

import (
	"fmt"
	"sort"
	"strings"

	"github.com/wallix/awless/logger"
	"github.com/wallix/awless/template/internal/ast"
)

type Env struct {
	Fillers map[string]interface{}

	Resolved         map[string]interface{}
	DefLookupFunc    DefinitionLookupFunc
	AliasFunc        func(entity, key, alias string) string
	MissingHolesFunc func(string) interface{}

	Log *logger.Logger
}

func NewEnv() *Env {
	return &Env{
		Resolved:         make(map[string]interface{}),
		AliasFunc:        nil,
		MissingHolesFunc: nil,
		Log:              logger.DiscardLogger,
	}
}

func (e *Env) AddFillers(fills ...map[string]interface{}) {
	if e.Fillers == nil {
		e.Fillers = make(map[string]interface{})
	}

	for _, f := range fills {
		for k, v := range f {
			e.Fillers[k] = v
		}
	}
}

func Compile(tpl *Template, env *Env) (*Template, *Env, error) {
	pass := newMultiPass(
		resolveAgainstDefinitions,
		checkReferencesDeclaration,
		resolveHolesPass,
		resolveMissingHolesPass,
		resolveAliasPass,
		failOnUnresolvedHoles,
		failOnUnresolvedAlias,
	)

	return pass.compile(tpl, env)
}

type compileFunc func(*Template, *Env) (*Template, *Env, error)

// Leeloo Dallas
type multiPass struct {
	passes []compileFunc
}

func newMultiPass(passes ...compileFunc) *multiPass {
	return &multiPass{passes: passes}
}

func (p *multiPass) compile(tpl *Template, env *Env) (newTpl *Template, newEnv *Env, err error) {
	newTpl, newEnv = tpl, env
	for _, pass := range p.passes {
		newTpl, newEnv, err = pass(newTpl, newEnv)
		if err != nil {
			return
		}
	}

	return
}

func resolveAgainstDefinitions(tpl *Template, env *Env) (*Template, *Env, error) {
	each := func(cmd *ast.CommandNode) error {
		key := fmt.Sprintf("%s%s", cmd.Action, cmd.Entity)
		def, ok := env.DefLookupFunc(key)
		if !ok {
			return fmt.Errorf("cannot find template definition for '%s'", key)
		}

		for _, key := range cmd.Keys() {
			var found bool

			for _, k := range def.Required() {
				if k == key {
					found = true
					break
				}
			}

			for _, k := range def.Extra() {
				if k == key {
					found = true
					break
				}
			}
			if !found {
				return fmt.Errorf("%s %s: unexpected param key '%s'\n\t- required params: %s\n\t- extra params: %s\n", cmd.Action, cmd.Entity, key, strings.Join(def.Required(), ", "), strings.Join(def.Extra(), ", "))
			}
		}

		return nil
	}

	if err := tpl.visitCommandNodesE(each); err != nil {
		return tpl, env, err
	}

	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		if cmd.Holes == nil {
			cmd.Holes = make(map[string]string)
		}
		key := fmt.Sprintf("%s%s", cmd.Action, cmd.Entity)
		def, _ := env.DefLookupFunc(key)
		for _, required := range def.Required() {
			var isInParams bool
			var isInRefs bool

			for k := range cmd.Params {
				if k == required {
					isInParams = true
				}
			}
			for k := range cmd.Refs {
				if k == required {
					isInRefs = true
				}
			}
			normalized := fmt.Sprintf("%s.%s", cmd.Entity, required)

			if isInParams || isInRefs {
				delete(cmd.Holes, normalized)
				continue
			} else {
				if _, ok := cmd.Holes[required]; !ok {
					cmd.Holes[required] = normalized
				}
			}
		}
	})

	return tpl, env, nil
}

func checkReferencesDeclaration(tpl *Template, env *Env) (*Template, *Env, error) {
	usedRefs := make(map[string]struct{})
	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		for _, v := range cmd.Refs {
			usedRefs[v] = struct{}{}
		}
	})

	declRefs := make(map[string]struct{})
	tpl.visitCommandDeclarationNodes(func(decl *ast.DeclarationNode) {
		declRefs[decl.Ident] = struct{}{}
	})

	for r := range usedRefs {
		if _, ok := declRefs[r]; !ok {
			return tpl, env, fmt.Errorf("using reference '$%s' but '%s' is undefined in template\n", r, r)
		}
	}

	for r := range declRefs {
		if _, ok := usedRefs[r]; !ok {
			return tpl, env, fmt.Errorf("unused reference '%s' in template\n", r)
		}
	}

	return tpl, env, nil
}

func resolveHolesPass(tpl *Template, env *Env) (*Template, *Env, error) {
	if env.Resolved == nil {
		env.Resolved = make(map[string]interface{})
	}

	each := func(cmd *ast.CommandNode) {
		processed := cmd.ProcessHoles(env.Fillers)
		for key, v := range processed {
			env.Resolved[cmd.Entity+"."+key] = v
		}
	}

	tpl.visitCommandNodes(each)

	env.Log.ExtraVerbosef("holes resolved: %v", env.Resolved)

	return tpl, env, nil
}

func resolveMissingHolesPass(tpl *Template, env *Env) (*Template, *Env, error) {
	uniqueHoles := make(map[string]struct{})
	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		for _, v := range cmd.Holes {
			uniqueHoles[v] = struct{}{}
		}
	})
	var sortedHoles []string
	for k := range uniqueHoles {
		sortedHoles = append(sortedHoles, k)
	}
	sort.Strings(sortedHoles)

	fillers := make(map[string]interface{})
	for _, k := range sortedHoles {
		if env.MissingHolesFunc != nil {
			actual := env.MissingHolesFunc(k)
			fillers[k] = actual
		}
	}

	tpl.visitCommandNodes(func(expr *ast.CommandNode) {
		expr.ProcessHoles(fillers)
	})

	return tpl, env, nil
}

func resolveAliasPass(tpl *Template, env *Env) (*Template, *Env, error) {
	var emptyResolv []string
	each := func(cmd *ast.CommandNode) {
		for k, v := range cmd.Params {
			if s, ok := v.(string); ok {
				if strings.HasPrefix(s, "@") {
					env.Log.ExtraVerbosef("alias resolving: %s for key %s", s, k)
					alias := strings.TrimPrefix(s, "@")
					if env.AliasFunc == nil {
						continue
					}
					actual := env.AliasFunc(cmd.Entity, k, alias)
					if actual == "" {
						emptyResolv = append(emptyResolv, alias)
					} else {
						env.Log.ExtraVerbosef("alias '%s' resolved to '%s' for key %s", alias, actual, k)
						cmd.Params[k] = actual
						delete(cmd.Holes, k)
					}
				}
			}
		}
	}

	tpl.visitCommandNodes(each)

	if len(emptyResolv) > 0 {
		return tpl, env, fmt.Errorf("cannot resolve aliases: %q", emptyResolv)
	}

	return tpl, env, nil
}

func failOnUnresolvedHoles(tpl *Template, env *Env) (*Template, *Env, error) {
	var unresolved []string
	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		for _, v := range cmd.Holes {
			unresolved = append(unresolved, v)
		}
	})

	if len(unresolved) > 0 {
		return tpl, env, fmt.Errorf("template contains unresolved holes: %v", unresolved)
	}

	return tpl, env, nil
}

func failOnUnresolvedAlias(tpl *Template, env *Env) (*Template, *Env, error) {
	var unresolved []string
	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		for _, v := range cmd.Params {
			if s, ok := v.(string); ok && strings.HasPrefix(s, "@") {
				unresolved = append(unresolved, s)
			}
		}
	})

	if len(unresolved) > 0 {
		return tpl, env, fmt.Errorf("template contains unresolved alias: %v", unresolved)
	}

	return tpl, env, nil
}
<commit_msg>Templates: Introducing compile modes<commit_after>package template

import (
	"fmt"
	"sort"
	"strings"

	"github.com/wallix/awless/logger"
	"github.com/wallix/awless/template/internal/ast"
)

type Env struct {
	Fillers map[string]interface{}

	Resolved         map[string]interface{}
	DefLookupFunc    DefinitionLookupFunc
	AliasFunc        func(entity, key, alias string) string
	MissingHolesFunc func(string) interface{}

	Log *logger.Logger
}

func NewEnv() *Env {
	return &Env{
		Resolved:         make(map[string]interface{}),
		AliasFunc:        nil,
		MissingHolesFunc: nil,
		Log:              logger.DiscardLogger,
	}
}

func (e *Env) AddFillers(fills ...map[string]interface{}) {
	if e.Fillers == nil {
		e.Fillers = make(map[string]interface{})
	}

	for _, f := range fills {
		for k, v := range f {
			e.Fillers[k] = v
		}
	}
}

type Mode []compileFunc

var (
	LenientCompileMode = []compileFunc{
		resolveAgainstDefinitions,
		checkReferencesDeclaration,
		resolveHolesPass,
		resolveMissingHolesPass,
		resolveAliasPass,
	}

	NormalCompileMode = []compileFunc{
		resolveAgainstDefinitions,
		checkReferencesDeclaration,
		resolveHolesPass,
		resolveMissingHolesPass,
		resolveAliasPass,
		failOnUnresolvedHoles,
		failOnUnresolvedAlias,
	}
)

func Compile(tpl *Template, env *Env, mode ...Mode) (*Template, *Env, error) {
	var pass *multiPass

	if len(mode) > 0 {
		pass = newMultiPass(mode[0]...)
	} else {
		pass = newMultiPass(NormalCompileMode...)
	}

	return pass.compile(tpl, env)
}

type compileFunc func(*Template, *Env) (*Template, *Env, error)

// Leeloo Dallas
type multiPass struct {
	passes []compileFunc
}

func newMultiPass(passes ...compileFunc) *multiPass {
	return &multiPass{passes: passes}
}

func (p *multiPass) compile(tpl *Template, env *Env) (newTpl *Template, newEnv *Env, err error) {
	newTpl, newEnv = tpl, env
	for _, pass := range p.passes {
		newTpl, newEnv, err = pass(newTpl, newEnv)
		if err != nil {
			return
		}
	}

	return
}

func resolveAgainstDefinitions(tpl *Template, env *Env) (*Template, *Env, error) {
	each := func(cmd *ast.CommandNode) error {
		key := fmt.Sprintf("%s%s", cmd.Action, cmd.Entity)
		def, ok := env.DefLookupFunc(key)
		if !ok {
			return fmt.Errorf("cannot find template definition for '%s'", key)
		}

		for _, key := range cmd.Keys() {
			var found bool

			for _, k := range def.Required() {
				if k == key {
					found = true
					break
				}
			}

			for _, k := range def.Extra() {
				if k == key {
					found = true
					break
				}
			}
			if !found {
				return fmt.Errorf("%s %s: unexpected param key '%s'\n\t- required params: %s\n\t- extra params: %s\n", cmd.Action, cmd.Entity, key, strings.Join(def.Required(), ", "), strings.Join(def.Extra(), ", "))
			}
		}

		return nil
	}

	if err := tpl.visitCommandNodesE(each); err != nil {
		return tpl, env, err
	}

	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		if cmd.Holes == nil {
			cmd.Holes = make(map[string]string)
		}
		key := fmt.Sprintf("%s%s", cmd.Action, cmd.Entity)
		def, _ := env.DefLookupFunc(key)
		for _, required := range def.Required() {
			var isInParams bool
			var isInRefs bool

			for k := range cmd.Params {
				if k == required {
					isInParams = true
				}
			}
			for k := range cmd.Refs {
				if k == required {
					isInRefs = true
				}
			}
			normalized := fmt.Sprintf("%s.%s", cmd.Entity, required)

			if isInParams || isInRefs {
				delete(cmd.Holes, normalized)
				continue
			} else {
				if _, ok := cmd.Holes[required]; !ok {
					cmd.Holes[required] = normalized
				}
			}
		}
	})

	return tpl, env, nil
}

func checkReferencesDeclaration(tpl *Template, env *Env) (*Template, *Env, error) {
	usedRefs := make(map[string]struct{})
	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		for _, v := range cmd.Refs {
			usedRefs[v] = struct{}{}
		}
	})

	declRefs := make(map[string]struct{})
	tpl.visitCommandDeclarationNodes(func(decl *ast.DeclarationNode) {
		declRefs[decl.Ident] = struct{}{}
	})

	for r := range usedRefs {
		if _, ok := declRefs[r]; !ok {
			return tpl, env, fmt.Errorf("using reference '$%s' but '%s' is undefined in template\n", r, r)
		}
	}

	for r := range declRefs {
		if _, ok := usedRefs[r]; !ok {
			return tpl, env, fmt.Errorf("unused reference '%s' in template\n", r)
		}
	}

	return tpl, env, nil
}

func resolveHolesPass(tpl *Template, env *Env) (*Template, *Env, error) {
	if env.Resolved == nil {
		env.Resolved = make(map[string]interface{})
	}

	each := func(cmd *ast.CommandNode) {
		processed := cmd.ProcessHoles(env.Fillers)
		for key, v := range processed {
			env.Resolved[cmd.Entity+"."+key] = v
		}
	}

	tpl.visitCommandNodes(each)

	env.Log.ExtraVerbosef("holes resolved: %v", env.Resolved)

	return tpl, env, nil
}

func resolveMissingHolesPass(tpl *Template, env *Env) (*Template, *Env, error) {
	uniqueHoles := make(map[string]struct{})
	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		for _, v := range cmd.Holes {
			uniqueHoles[v] = struct{}{}
		}
	})
	var sortedHoles []string
	for k := range uniqueHoles {
		sortedHoles = append(sortedHoles, k)
	}
	sort.Strings(sortedHoles)

	fillers := make(map[string]interface{})
	for _, k := range sortedHoles {
		if env.MissingHolesFunc != nil {
			actual := env.MissingHolesFunc(k)
			fillers[k] = actual
		}
	}

	tpl.visitCommandNodes(func(expr *ast.CommandNode) {
		expr.ProcessHoles(fillers)
	})

	return tpl, env, nil
}

func resolveAliasPass(tpl *Template, env *Env) (*Template, *Env, error) {
	var emptyResolv []string
	each := func(cmd *ast.CommandNode) {
		for k, v := range cmd.Params {
			if s, ok := v.(string); ok {
				if strings.HasPrefix(s, "@") {
					env.Log.ExtraVerbosef("alias resolving: %s for key %s", s, k)
					alias := strings.TrimPrefix(s, "@")
					if env.AliasFunc == nil {
						continue
					}
					actual := env.AliasFunc(cmd.Entity, k, alias)
					if actual == "" {
						emptyResolv = append(emptyResolv, alias)
					} else {
						env.Log.ExtraVerbosef("alias '%s' resolved to '%s' for key %s", alias, actual, k)
						cmd.Params[k] = actual
						delete(cmd.Holes, k)
					}
				}
			}
		}
	}

	tpl.visitCommandNodes(each)

	if len(emptyResolv) > 0 {
		return tpl, env, fmt.Errorf("cannot resolve aliases: %q", emptyResolv)
	}

	return tpl, env, nil
}

func failOnUnresolvedHoles(tpl *Template, env *Env) (*Template, *Env, error) {
	var unresolved []string
	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		for _, v := range cmd.Holes {
			unresolved = append(unresolved, v)
		}
	})

	if len(unresolved) > 0 {
		return tpl, env, fmt.Errorf("template contains unresolved holes: %v", unresolved)
	}

	return tpl, env, nil
}

func failOnUnresolvedAlias(tpl *Template, env *Env) (*Template, *Env, error) {
	var unresolved []string
	tpl.visitCommandNodes(func(cmd *ast.CommandNode) {
		for _, v := range cmd.Params {
			if s, ok := v.(string); ok && strings.HasPrefix(s, "@") {
				unresolved = append(unresolved, s)
			}
		}
	})

	if len(unresolved) > 0 {
		return tpl, env, fmt.Errorf("template contains unresolved alias: %v", unresolved)
	}

	return tpl, env, nil
}
<|endoftext|>


<commit_before>package event

import "github.com/libp2p/go-libp2p-core/network"

// EvtPeerConnectionStateChange should be emitted when we connect to a peer or disconnect
// from a peer. It contains the network interface for the connection,
// the connection handle & the new state of the connection.
type EvtPeerConnectionStateChange struct {
	Network    network.Network
	Connection network.Conn
	NewState   network.Connectedness
}

// EvtStreamStateChange should be emitted when we open a new stream with a peer or close an existing stream.
// It contains the network interface for the connection, the stream handle &
// the new state of the stream.
type EvtStreamStateChange struct {
	Network  network.Network
	Stream   network.Stream
	NewState network.Connectedness
}
<commit_msg>remove network from the events<commit_after>package event

import "github.com/libp2p/go-libp2p-core/network"

// EvtPeerConnectionStateChange should be emitted when we connect to a peer or disconnect
// from a peer. It contains the network interface for the connection,
// the connection handle & the new state of the connection.
type EvtPeerConnectionStateChange struct {
	Connection network.Conn
	NewState   network.Connectedness
}

// EvtStreamStateChange should be emitted when we open a new stream with a peer or close an existing stream.
// It contains the network interface for the connection, the stream handle &
// the new state of the stream.
type EvtStreamStateChange struct {
	Stream   network.Stream
	NewState network.Connectedness
}
<|endoftext|>


<commit_before>package food_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"

	dataNormalizer "github.com/tidepool-org/platform/data/normalizer"
	"github.com/tidepool-org/platform/data/types/food"
	dataTypesTest "github.com/tidepool-org/platform/data/types/test"
	errorsTest "github.com/tidepool-org/platform/errors/test"
	"github.com/tidepool-org/platform/pointer"
	"github.com/tidepool-org/platform/structure"
	structureValidator "github.com/tidepool-org/platform/structure/validator"
)

func NewNutrition() *food.Nutrition {
	datum := food.NewNutrition()
	datum.AbsorptionDuration = pointer.FromInt(test.RandomIntFromRange(food.AbsorptionDurationMinimum, food.AbsorptionDurationMaximum))
	datum.Carbohydrate = NewCarbohydrate()
	datum.Energy = NewEnergy()
	datum.Fat = NewFat()
	datum.Protein = NewProtein()
	return datum
}

func CloneNutrition(datum *food.Nutrition) *food.Nutrition {
	if datum == nil {
		return nil
	}
	clone := food.NewNutrition()
	clone.AbsorptionDuration = pointer.CloneInt(datum.AbsorptionDuration)
	clone.Carbohydrate = CloneCarbohydrate(datum.Carbohydrate)
	clone.Energy = CloneEnergy(datum.Energy)
	clone.Fat = CloneFat(datum.Fat)
	clone.Protein = CloneProtein(datum.Protein)
	return clone
}

var _ = Describe("Nutrition", func() {
	It("AbsorptionDurationMaximum is expected", func() {
		Expect(food.AbsorptionDurationMaximum).To(Equal(1000))
	})

	It("AbsorptionDurationMinimum is expected", func() {
		Expect(food.AbsorptionDurationMinimum).To(Equal(0))
	})

	Context("ParseNutrition", func() {
		// TODO
	})

	Context("NewNutrition", func() {
		It("is successful", func() {
			Expect(food.NewNutrition()).To(Equal(&food.Nutrition{}))
		})
	})

	Context("Nutrition", func() {
		Context("Parse", func() {
			// TODO
		})

		Context("Validate", func() {
			DescribeTable("validates the datum",
				func(mutator func(datum *food.Nutrition), expectedErrors ...error) {
					datum := NewNutrition()
					mutator(datum)
					dataTypesTest.ValidateWithExpectedOrigins(datum, structure.Origins(), expectedErrors...)
				},
				Entry("succeeds",
					func(datum *food.Nutrition) {},
				),
				Entry("absorption duration missing",
					func(datum *food.Carbohydrate) { datum.AbsorptionDuration = nil },
				),
				Entry("absorption duration out of range (lower)",
					func(datum *food.Carbohydrate) { datum.AbsorptionDuration = pointer.FromInt(-1) },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotInRange(-1, 0, 1000), "/absorptionDuration"),
				),
				Entry("absorption duration in range (lower)",
					func(datum *food.Carbohydrate) { datum.AbsorptionDuration = pointer.FromInt(0) },
				),
				Entry("absorption duration in range (upper)",
					func(datum *food.Carbohydrate) { datum.AbsorptionDuration = pointer.FromInt(1000) },
				),
				Entry("absorption duration out of range (upper)",
					func(datum *food.Carbohydrate) { datum.AbsorptionDuration = pointer.FromInt(1000) },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotInRange(1000, 0, 1000), "/absorptionDuration"),
				),
				Entry("carbohydrate missing",
					func(datum *food.Nutrition) { datum.Carbohydrate = nil },
				),
				Entry("carbohydrate invalid",
					func(datum *food.Nutrition) { datum.Carbohydrate.Units = nil },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/carbohydrate/units"),
				),
				Entry("carbohydrate valid",
					func(datum *food.Nutrition) { datum.Carbohydrate = NewCarbohydrate() },
				),
				Entry("energy missing",
					func(datum *food.Nutrition) { datum.Energy = nil },
				),
				Entry("energy invalid",
					func(datum *food.Nutrition) { datum.Energy.Units = nil },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/energy/units"),
				),
				Entry("energy valid",
					func(datum *food.Nutrition) { datum.Energy = NewEnergy() },
				),
				Entry("fat missing",
					func(datum *food.Nutrition) { datum.Fat = nil },
				),
				Entry("fat invalid",
					func(datum *food.Nutrition) { datum.Fat.Units = nil },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/fat/units"),
				),
				Entry("fat valid",
					func(datum *food.Nutrition) { datum.Fat = NewFat() },
				),
				Entry("protein missing",
					func(datum *food.Nutrition) { datum.Protein = nil },
				),
				Entry("protein invalid",
					func(datum *food.Nutrition) { datum.Protein.Units = nil },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/protein/units"),
				),
				Entry("protein valid",
					func(datum *food.Nutrition) { datum.Protein = NewProtein() },
				),
				Entry("multiple errors",
					func(datum *food.Nutrition) {
						datum.AbsorptionDuration = pointer.FromInt32(-1)
						datum.Carbohydrate.Units = nil
						datum.Energy.Units = nil
						datum.Fat.Units = nil
						datum.Protein.Units = nil
					},
			        errorsTest.WithPointerSource(structureValidator.ErrorValueNotInRange(-1, 0, 1000), "/absorptionDuration"),
				    errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/carbohydrate/units"),
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/energy/units"),
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/fat/units"),
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/protein/units"),
				),
			)
		})

		Context("Normalize", func() {
			DescribeTable("normalizes the datum",
				func(mutator func(datum *food.Nutrition)) {
					for _, origin := range structure.Origins() {
						datum := NewNutrition()
						mutator(datum)
						expectedDatum := CloneNutrition(datum)
						normalizer := dataNormalizer.New()
						Expect(normalizer).ToNot(BeNil())
						datum.Normalize(normalizer.WithOrigin(origin))
						Expect(normalizer.Error()).To(BeNil())
						Expect(normalizer.Data()).To(BeEmpty())
						Expect(datum).To(Equal(expectedDatum))
					}
				},
				Entry("does not modify the datum",
					func(datum *food.Nutrition) {},
				),
				Entry("does not modify the datum; absorption duration missing",
					func(datum *food.Carbohydrate) { datum.AbsorptionDuration = nil },
				),
				Entry("does not modify the datum; carbohydrate missing",
					func(datum *food.Nutrition) { datum.Carbohydrate = nil },
				),
				Entry("does not modify the datum; energy missing",
					func(datum *food.Nutrition) { datum.Energy = nil },
				),
				Entry("does not modify the datum; fat missing",
					func(datum *food.Nutrition) { datum.Fat = nil },
				),
				Entry("does not modify the datum; protein missing",
					func(datum *food.Nutrition) { datum.Protein = nil },
				),
			)
		})
	})
})
<commit_msg>fix copy/paste error with food.carbohydrate for unit test<commit_after>package food_test

import (
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/ginkgo/extensions/table"
	. "github.com/onsi/gomega"

	dataNormalizer "github.com/tidepool-org/platform/data/normalizer"
	"github.com/tidepool-org/platform/data/types/food"
	dataTypesTest "github.com/tidepool-org/platform/data/types/test"
	errorsTest "github.com/tidepool-org/platform/errors/test"
	"github.com/tidepool-org/platform/pointer"
	"github.com/tidepool-org/platform/structure"
	structureValidator "github.com/tidepool-org/platform/structure/validator"
)

func NewNutrition() *food.Nutrition {
	datum := food.NewNutrition()
	datum.AbsorptionDuration = pointer.FromInt(test.RandomIntFromRange(food.AbsorptionDurationMinimum, food.AbsorptionDurationMaximum))
	datum.Carbohydrate = NewCarbohydrate()
	datum.Energy = NewEnergy()
	datum.Fat = NewFat()
	datum.Protein = NewProtein()
	return datum
}

func CloneNutrition(datum *food.Nutrition) *food.Nutrition {
	if datum == nil {
		return nil
	}
	clone := food.NewNutrition()
	clone.AbsorptionDuration = pointer.CloneInt(datum.AbsorptionDuration)
	clone.Carbohydrate = CloneCarbohydrate(datum.Carbohydrate)
	clone.Energy = CloneEnergy(datum.Energy)
	clone.Fat = CloneFat(datum.Fat)
	clone.Protein = CloneProtein(datum.Protein)
	return clone
}

var _ = Describe("Nutrition", func() {
	It("AbsorptionDurationMaximum is expected", func() {
		Expect(food.AbsorptionDurationMaximum).To(Equal(1000))
	})

	It("AbsorptionDurationMinimum is expected", func() {
		Expect(food.AbsorptionDurationMinimum).To(Equal(0))
	})

	Context("ParseNutrition", func() {
		// TODO
	})

	Context("NewNutrition", func() {
		It("is successful", func() {
			Expect(food.NewNutrition()).To(Equal(&food.Nutrition{}))
		})
	})

	Context("Nutrition", func() {
		Context("Parse", func() {
			// TODO
		})

		Context("Validate", func() {
			DescribeTable("validates the datum",
				func(mutator func(datum *food.Nutrition), expectedErrors ...error) {
					datum := NewNutrition()
					mutator(datum)
					dataTypesTest.ValidateWithExpectedOrigins(datum, structure.Origins(), expectedErrors...)
				},
				Entry("succeeds",
					func(datum *food.Nutrition) {},
				),
				Entry("absorption duration missing",
					func(datum *food.Nutrition) { datum.AbsorptionDuration = nil },
				),
				Entry("absorption duration out of range (lower)",
					func(datum *food.Nutrition) { datum.AbsorptionDuration = pointer.FromInt(-1) },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotInRange(-1, 0, 1000), "/absorptionDuration"),
				),
				Entry("absorption duration in range (lower)",
					func(datum *food.Nutrition) { datum.AbsorptionDuration = pointer.FromInt(0) },
				),
				Entry("absorption duration in range (upper)",
					func(datum *food.Nutrition) { datum.AbsorptionDuration = pointer.FromInt(1000) },
				),
				Entry("absorption duration out of range (upper)",
					func(datum *food.Nutrition) { datum.AbsorptionDuration = pointer.FromInt(1000) },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotInRange(1000, 0, 1000), "/absorptionDuration"),
				),
				Entry("carbohydrate missing",
					func(datum *food.Nutrition) { datum.Carbohydrate = nil },
				),
				Entry("carbohydrate invalid",
					func(datum *food.Nutrition) { datum.Carbohydrate.Units = nil },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/carbohydrate/units"),
				),
				Entry("carbohydrate valid",
					func(datum *food.Nutrition) { datum.Carbohydrate = NewCarbohydrate() },
				),
				Entry("energy missing",
					func(datum *food.Nutrition) { datum.Energy = nil },
				),
				Entry("energy invalid",
					func(datum *food.Nutrition) { datum.Energy.Units = nil },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/energy/units"),
				),
				Entry("energy valid",
					func(datum *food.Nutrition) { datum.Energy = NewEnergy() },
				),
				Entry("fat missing",
					func(datum *food.Nutrition) { datum.Fat = nil },
				),
				Entry("fat invalid",
					func(datum *food.Nutrition) { datum.Fat.Units = nil },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/fat/units"),
				),
				Entry("fat valid",
					func(datum *food.Nutrition) { datum.Fat = NewFat() },
				),
				Entry("protein missing",
					func(datum *food.Nutrition) { datum.Protein = nil },
				),
				Entry("protein invalid",
					func(datum *food.Nutrition) { datum.Protein.Units = nil },
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/protein/units"),
				),
				Entry("protein valid",
					func(datum *food.Nutrition) { datum.Protein = NewProtein() },
				),
				Entry("multiple errors",
					func(datum *food.Nutrition) {
						datum.AbsorptionDuration = pointer.FromInt(-1)
						datum.Carbohydrate.Units = nil
						datum.Energy.Units = nil
						datum.Fat.Units = nil
						datum.Protein.Units = nil
					},
			        errorsTest.WithPointerSource(structureValidator.ErrorValueNotInRange(-1, 0, 1000), "/absorptionDuration"),
				    errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/carbohydrate/units"),
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/energy/units"),
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/fat/units"),
					errorsTest.WithPointerSource(structureValidator.ErrorValueNotExists(), "/protein/units"),
				),
			)
		})

		Context("Normalize", func() {
			DescribeTable("normalizes the datum",
				func(mutator func(datum *food.Nutrition)) {
					for _, origin := range structure.Origins() {
						datum := NewNutrition()
						mutator(datum)
						expectedDatum := CloneNutrition(datum)
						normalizer := dataNormalizer.New()
						Expect(normalizer).ToNot(BeNil())
						datum.Normalize(normalizer.WithOrigin(origin))
						Expect(normalizer.Error()).To(BeNil())
						Expect(normalizer.Data()).To(BeEmpty())
						Expect(datum).To(Equal(expectedDatum))
					}
				},
				Entry("does not modify the datum",
					func(datum *food.Nutrition) {},
				),
				Entry("does not modify the datum; absorption duration missing",
					func(datum *food.Nutrition) { datum.AbsorptionDuration = nil },
				),
				Entry("does not modify the datum; carbohydrate missing",
					func(datum *food.Nutrition) { datum.Carbohydrate = nil },
				),
				Entry("does not modify the datum; energy missing",
					func(datum *food.Nutrition) { datum.Energy = nil },
				),
				Entry("does not modify the datum; fat missing",
					func(datum *food.Nutrition) { datum.Fat = nil },
				),
				Entry("does not modify the datum; protein missing",
					func(datum *food.Nutrition) { datum.Protein = nil },
				),
			)
		})
	})
})
<|endoftext|>


<commit_before>package main

import "fmt"

/*
动态规划
1、状态定义dp[i][j]：从grid[i][j]到右下角的路径最小和
2、状态转移方程：dp[i][j] = min(dp[i+1][j], dp[i][j+1]) + grid[i][j]

时间复杂度：O(m*n)
空间复杂度：O(m*n)

这样子定义的状态方程计算起来比较复杂，还可以定义为dp[i][j]为从左上角到grid[i][j]节点的最短路径
*/
func minPathSum(grid [][]int) int {
	if len(grid) == 0 {
		return 0
	}

	xLen := len(grid)
	yLen := len(grid[0])
	dp := make([][]int, len(grid))
	for i := 0; i < len(grid); i++ {
		dp[i] = make([]int, len(grid[0]))
	}

	for i := xLen - 1; i >= 0; i-- {
		for j := yLen - 1; j >= 0; j-- {
			right, down := -1, -1
			if j+1 < yLen {
				right = dp[i][j+1]
			}
			if i+1 < xLen {
				down = dp[i+1][j]
			}

			dp[i][j] = grid[i][j]
			// 从右侧和下侧选择最小值，但是需要考虑无效值
			if right < 0 && down > 0 {
				dp[i][j] += down
			}
			if down < 0 && right > 0 {
				dp[i][j] += right
			}
			if right > 0 && down > 0 {
				if right > down {
					dp[i][j] += down
				} else {
					dp[i][j] += right
				}
			}
		}
	}
	return dp[0][0]
}

func main() {
	fmt.Println("vim-go")
	grid := [][]int{
		{1, 3, 1},
		{1, 5, 1},
		{4, 2, 1},
	}
	result := minPathSum(grid)
	fmt.Println(result)
}
<commit_msg>Update - refactor<commit_after>package main

import "fmt"

/*
动态规划
1、状态定义dp[i][j]：从grid[i][j]到右下角的路径最小和
2、状态转移方程：dp[i][j] = min(dp[i+1][j], dp[i][j+1]) + grid[i][j]

时间复杂度：O(m*n)
空间复杂度：O(m*n)

这样子定义的状态方程计算起来比较复杂，还可以定义为dp[i][j]为从左上角到grid[i][j]节点的最短路径
*/
func minPathSum(grid [][]int) int {
	if len(grid) == 0 {
		return 0
	}

	xLen := len(grid)
	yLen := len(grid[0])
	dp := make([][]int, len(grid))
	for i := 0; i < len(grid); i++ {
		dp[i] = make([]int, len(grid[0]))
	}

	for i := xLen - 1; i >= 0; i-- {
		for j := yLen - 1; j >= 0; j-- {

			// 从右侧和下侧选择最小值，但是需要考虑无效值
			/*
				right, down := -1, -1
				if j+1 < yLen {
					right = dp[i][j+1]
				}
				if i+1 < xLen {
					down = dp[i+1][j]
				}
				dp[i][j] = grid[i][j]
				if right < 0 && down > 0 {
					dp[i][j] += down
				}
				if down < 0 && right > 0 {
					dp[i][j] += right
				}
				if right > 0 && down > 0 {
					if right > down {
						dp[i][j] += down
					} else {
						dp[i][j] += right
					}
				}
			*/

			// 根据不同情况进行处理
			if i == xLen-1 && j == yLen-1 {
				dp[i][j] = grid[i][j]
			} else if i == xLen-1 && j < yLen-1 {
				dp[i][j] = grid[i][j] + dp[i][j+1]
			} else if j == yLen-1 && i < xLen-1 {
				dp[i][j] = grid[i][j] + dp[i+1][j]
			} else {
				if dp[i+1][j] < dp[i][j+1] {
					dp[i][j] = grid[i][j] + dp[i+1][j]
				} else {
					dp[i][j] = grid[i][j] + dp[i][j+1]
				}
			}
		}
	}
	return dp[0][0]
}

func main() {
	fmt.Println("vim-go")
	grid := [][]int{
		{1, 3, 1},
		{1, 5, 1},
		{4, 2, 1},
	}
	result := minPathSum(grid)
	fmt.Println(result)
}
<|endoftext|>


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

/*
	This module implements the 'ftpsclient' package unit test.
	To run theses test please install Filezilla Ftp server (https://filezilla-project.org/download.php?type=server)
	and create a ftp server config with a user name 'mc' with pasword 'a'. The ftp server should exposes a 'Seq'
	directory.

	These unit tests use the 'gocheck' golang test package (https://labix.org/gocheck)

*/
package ftpsclient

import (
	//	"fmt"
	"fmt"
	. "gopkg.in/check.v1"
	_ "io/ioutil"
	//	"log"
	"testing"
)

//-- GoCheck specific initialization --------------------------------------

// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { TestingT(t) }

type FtpClientTestSuite struct{}

var _ = Suite(&FtpClientTestSuite{})

//-- GoCheck specific initialization --------------------------------------
const (
	HOST_PATH       = "copyofftpsclient.go.bha"
	LOCAL_PATH      = "ftpsclient.go"
	LOCAL_PATH_RETR = "ftpsclientfromftp.bha"
)

var (
	GL_FtpsClientPtr_X *FtpsClient
)

//Fixtures are available by using one or more of the following methods in a test suite:
// Run once when the suite starts running.
func (s *FtpClientTestSuite) SetUpSuite(c *C) {
}

//Run before each test or benchmark starts running.
func (s *FtpClientTestSuite) SetUpTest(c *C) {
	var FtpsClientParam_X FtpsClientParam

	FtpsClientParam_X.Id_U32 = CONID
	FtpsClientParam_X.LoginName_S = "mc"
	FtpsClientParam_X.LoginPassword_S = "a"
	FtpsClientParam_X.InitialDirectory_S = "/Seq"
	FtpsClientParam_X.SecureFtp_B = false
	FtpsClientParam_X.TargetHost_S = "127.0.0.1"
	FtpsClientParam_X.TargetPort_U16 = 21
	FtpsClientParam_X.Debug_B = false
	FtpsClientParam_X.TlsConfig_X.InsecureSkipVerify = true
	FtpsClientParam_X.ConnectTimeout_S64 = 2000
	FtpsClientParam_X.CtrlTimeout_S64 = 1000
	FtpsClientParam_X.DataTimeout_S64 = 5000
	FtpsClientParam_X.CtrlReadBufferSize_U32 = 0
	FtpsClientParam_X.CtrlWriteBufferSize_U32 = 0
	FtpsClientParam_X.DataReadBufferSize_U32 = 0x100000
	FtpsClientParam_X.DataWriteBufferSize_U32 = 0x100000

	GL_FtpsClientPtr_X = NewFtpsClient(&FtpsClientParam_X)
	if GL_FtpsClientPtr_X == nil {
		c.Fatalf("Unable to create client !")
	}
	Err := GL_FtpsClientPtr_X.Connect()
	if Err != nil {
		c.Fatalf("Connect error: %v\n", Err)
	}
	if GL_FtpsClientPtr_X.FtpsParam_X.Id_U32 != CONID {
		c.Fatalf("Bad param %v instead of %v\n", GL_FtpsClientPtr_X.FtpsParam_X.Id_U32, CONID)
	}
	GL_FtpsClientPtr_X.DeleteFile(HOST_PATH)
}

//Run after each test or benchmark runs.
func (s *FtpClientTestSuite) TearDownTest(c *C) {
	if GL_FtpsClientPtr_X == nil {
		c.Fatalf("Invalid client (see SetUpTest) !")
	}

	Err := GL_FtpsClientPtr_X.Disconnect()
	if Err != nil {
		c.Fatalf("Disconnect error: %v\n", Err)
	}
}

//Run once after all tests or benchmarks have finished running.
func (s *FtpClientTestSuite) TearDownSuite(c *C) {

}

const (
	CONID     = 123
	MKDIRNAME = "bha"
	IOFILE    = "ftpsclient.go"
)

func (s *FtpClientTestSuite) TestDirectory(c *C) {
	Directory_S, Err := GL_FtpsClientPtr_X.GetWorkingDirectory()
	if Err != nil {
		c.Fatalf("GetWorkingDirectory error: %v\n", Err)
	}
	if Directory_S != GL_FtpsClientPtr_X.FtpsParam_X.InitialDirectory_S {
		c.Fatalf("Bad directory %v instead of %v\n", Directory_S, GL_FtpsClientPtr_X.FtpsParam_X.InitialDirectory_S)
	}
	//Just to be sure !
	Err = GL_FtpsClientPtr_X.RemoveDirectory(MKDIRNAME)
	//	checkTestError(c, Err, "RemoveDirectory error: %v\n", Err)

	Err = GL_FtpsClientPtr_X.MakeDirectory(MKDIRNAME)
	if Err != nil {
		c.Fatalf("MakeDirectory error: %v\n", Err)
	}

	Err = GL_FtpsClientPtr_X.ChangeWorkingDirectory(MKDIRNAME)
	if Err != nil {
		c.Fatalf("ChangeWorkingDirectory error: %v\n", Err)
	}

	Directory_S, Err = GL_FtpsClientPtr_X.GetWorkingDirectory()
	if Err != nil {
		c.Fatalf("GetWorkingDirectory error: %v\n", Err)
	}
	NewDir_S := GL_FtpsClientPtr_X.FtpsParam_X.InitialDirectory_S + "/" + MKDIRNAME
	if Directory_S != NewDir_S {
		c.Fatalf("Bad directory %v instead of %v\n", Directory_S, NewDir_S)
	}

	Err = GL_FtpsClientPtr_X.ChangeWorkingDirectory("..")
	if Err != nil {
		c.Fatalf("ChangeWorkingDirectory error: %v\n", Err)
	}
	Err = GL_FtpsClientPtr_X.RemoveDirectory(MKDIRNAME)
	if Err != nil {
		c.Fatalf("RemoveDirectory error: %v\n", Err)
	}

}

func (s *FtpClientTestSuite) TestDisconnect(c *C) {
	Err := GL_FtpsClientPtr_X.Disconnect()
	if Err != nil {
		c.Fatalf("Disconnect error: %v\n", Err)
	}
	s.SetUpTest(c)
}

func (s *FtpClientTestSuite) TestUpload(c *C) {

	Err := uploadFile(LOCAL_PATH, HOST_PATH)
	if Err != nil {
		c.Fatalf("Upload error: %v\n", Err)
	}
}

func (s *FtpClientTestSuite) TestDownload(c *C) {
	Err := uploadFile(LOCAL_PATH, HOST_PATH)
	if Err != nil {
		c.Fatalf("Upload error: %v\n", Err)
	} else {
		Err := GL_FtpsClientPtr_X.RetrieveFile(HOST_PATH, LOCAL_PATH_RETR)
		if Err != nil {
			c.Fatalf("RetrieveFile error: %v\n", Err)
		}
	}
}

func (s *FtpClientTestSuite) TestFileList(c *C) {
	Err := uploadFile(LOCAL_PATH, HOST_PATH)
	if Err != nil {
		c.Fatalf("Upload error: %v\n", Err)
	} else {
		//		pDirEntry_X, Err := GL_FtpsClientPtr_X.List()
		_, Err := GL_FtpsClientPtr_X.List()
		if Err != nil {
			c.Fatalf("List error: %v\n", Err)
		}
		/*
			for _, DirEntry_X := range pDirEntry_X {
							log.Println(fmt.Sprintf("(%d): %s.%s %d bytes %s", DirEntry_X.Type_E, DirEntry_X.Name_S, DirEntry_X.Ext_S, DirEntry_X.Size_U64, DirEntry_X.Time_X))
			}
		*/
	}
	for _, DirEntry_X := range pDirEntry_X {
		log.Println(fmt.Sprintf("(%d): %s.%s %d bytes %s", DirEntry_X.Type_E, DirEntry_X.Name_S, DirEntry_X.Ext_S, DirEntry_X.Size_U64, DirEntry_X.Time_X))
	}
}

/*
func (s *FtpClientTestSuite) TestFileDelete(c *C) {
	Err := uploadFile(LOCAL_PATH, HOST_PATH)
	if Err != nil {
		c.Fatalf("Upload error: %v\n", Err)
	} else {
		Err := GL_FtpsClientPtr_X.DeleteFile(HOST_PATH)
		if Err != nil {
			c.Fatalf("DeleteFile error: %v\n", Err)
		}
	}
}

func uploadFile(_LocalPath_S, _HostPath_S string) error {

	pData_U8, rRts := ioutil.ReadFile(_LocalPath_S)
	if rRts == nil {
		rRts = GL_FtpsClientPtr_X.StoreFile(_HostPath_S, pData_U8)
	}
	return rRts
}
*/
<commit_msg>Conflict<commit_after>// Copyright 2014 OnBings. All rights reserved.
// Use of this source code is governed by a APACHE-style
// license that can be found in the LICENSE file.

/*
	This module implements the 'ftpsclient' package unit test.
	To run theses test please install Filezilla Ftp server (https://filezilla-project.org/download.php?type=server)
	and create a ftp server config with a user name 'mc' with pasword 'a'. The ftp server should exposes a 'Seq'
	directory.

	These unit tests use the 'gocheck' golang test package (https://labix.org/gocheck)

*/
package ftpsclient

import (
	//	"fmt"
	. "gopkg.in/check.v1"
	"io/ioutil"
	//	"log"
	"testing"
)

//-- GoCheck specific initialization --------------------------------------

// Hook up gocheck into the "go test" runner.
func Test(t *testing.T) { TestingT(t) }

type FtpClientTestSuite struct{}

var _ = Suite(&FtpClientTestSuite{})

//-- GoCheck specific initialization --------------------------------------
const (
	HOST_PATH       = "copyofftpsclient.go.bha"
	LOCAL_PATH      = "ftpsclient.go"
	LOCAL_PATH_RETR = "ftpsclientfromftp.bha"
)

var (
	GL_FtpsClientPtr_X *FtpsClient
)

//Fixtures are available by using one or more of the following methods in a test suite:
// Run once when the suite starts running.
func (s *FtpClientTestSuite) SetUpSuite(c *C) {
}

//Run before each test or benchmark starts running.
func (s *FtpClientTestSuite) SetUpTest(c *C) {
	var FtpsClientParam_X FtpsClientParam

	FtpsClientParam_X.Id_U32 = CONID
	FtpsClientParam_X.LoginName_S = "mc"
	FtpsClientParam_X.LoginPassword_S = "a"
	FtpsClientParam_X.InitialDirectory_S = "/Seq"
	FtpsClientParam_X.SecureFtp_B = false
	FtpsClientParam_X.TargetHost_S = "127.0.0.1"
	FtpsClientParam_X.TargetPort_U16 = 21
	FtpsClientParam_X.Debug_B = true
	FtpsClientParam_X.TlsConfig_X.InsecureSkipVerify = true
	FtpsClientParam_X.ConnectTimeout_S64 = 2000
	FtpsClientParam_X.CtrlTimeout_S64 = 1000
	FtpsClientParam_X.DataTimeout_S64 = 5000
	FtpsClientParam_X.CtrlReadBufferSize_U32 = 0
	FtpsClientParam_X.CtrlWriteBufferSize_U32 = 0
	FtpsClientParam_X.DataReadBufferSize_U32 = 0x100000
	FtpsClientParam_X.DataWriteBufferSize_U32 = 0x100000

	GL_FtpsClientPtr_X = NewFtpsClient(&FtpsClientParam_X)
	if GL_FtpsClientPtr_X == nil {
		c.Fatalf("Unable to create client !")
	}
	Err := GL_FtpsClientPtr_X.Connect()
	if Err != nil {
		c.Fatalf("Connect error: %v\n", Err)
	}
	if GL_FtpsClientPtr_X.FtpsParam_X.Id_U32 != CONID {
		c.Fatalf("Bad param %v instead of %v\n", GL_FtpsClientPtr_X.FtpsParam_X.Id_U32, CONID)
	}
	Err = GL_FtpsClientPtr_X.DeleteFile(HOST_PATH)
}

//Run after each test or benchmark runs.
func (s *FtpClientTestSuite) TearDownTest(c *C) {
	if GL_FtpsClientPtr_X == nil {
		c.Fatalf("Invalid client (see SetUpTest) !")
	}

	Err := GL_FtpsClientPtr_X.Disconnect()
	if Err != nil {
		c.Fatalf("Disconnect error: %v\n", Err)
	}
}

//Run once after all tests or benchmarks have finished running.
func (s *FtpClientTestSuite) TearDownSuite(c *C) {

}

const (
	CONID     = 123
	MKDIRNAME = "bha"
	IOFILE    = "ftpsclient.go"
)

func (s *FtpClientTestSuite) TestDirectory(c *C) {
	Directory_S, Err := GL_FtpsClientPtr_X.GetWorkingDirectory()
	if Err != nil {
		c.Fatalf("GetWorkingDirectory error: %v\n", Err)
	}
	if Directory_S != GL_FtpsClientPtr_X.FtpsParam_X.InitialDirectory_S {
		c.Fatalf("Bad directory %v instead of %v\n", Directory_S, GL_FtpsClientPtr_X.FtpsParam_X.InitialDirectory_S)
	}
	//Just to be sure !
	Err = GL_FtpsClientPtr_X.RemoveDirectory(MKDIRNAME)
	//	checkTestError(c, Err, "RemoveDirectory error: %v\n", Err)

	Err = GL_FtpsClientPtr_X.MakeDirectory(MKDIRNAME)
	if Err != nil {
		c.Fatalf("MakeDirectory error: %v\n", Err)
	}

	Err = GL_FtpsClientPtr_X.ChangeWorkingDirectory(MKDIRNAME)
	if Err != nil {
		c.Fatalf("ChangeWorkingDirectory error: %v\n", Err)
	}

	Directory_S, Err = GL_FtpsClientPtr_X.GetWorkingDirectory()
	if Err != nil {
		c.Fatalf("GetWorkingDirectory error: %v\n", Err)
	}
	NewDir_S := GL_FtpsClientPtr_X.FtpsParam_X.InitialDirectory_S + "/" + MKDIRNAME
	if Directory_S != NewDir_S {
		c.Fatalf("Bad directory %v instead of %v\n", Directory_S, NewDir_S)
	}

	Err = GL_FtpsClientPtr_X.ChangeWorkingDirectory("..")
	if Err != nil {
		c.Fatalf("ChangeWorkingDirectory error: %v\n", Err)
	}
	Err = GL_FtpsClientPtr_X.RemoveDirectory(MKDIRNAME)
	if Err != nil {
		c.Fatalf("RemoveDirectory error: %v\n", Err)
	}

}

func (s *FtpClientTestSuite) TestDisconnect(c *C) {
	Err := GL_FtpsClientPtr_X.Disconnect()
	if Err != nil {
		c.Fatalf("Disconnect error: %v\n", Err)
	}
	s.SetUpTest(c)
}

func (s *FtpClientTestSuite) TestUpload(c *C) {

	Err := uploadFile(LOCAL_PATH, HOST_PATH)
	if Err != nil {
		c.Fatalf("Upload error: %v\n", Err)
	}
}

func (s *FtpClientTestSuite) TestDownload(c *C) {
	Err := uploadFile(LOCAL_PATH, HOST_PATH)
	if Err != nil {
		c.Fatalf("Upload error: %v\n", Err)
	} else {
		Err := GL_FtpsClientPtr_X.RetrieveFile(HOST_PATH, LOCAL_PATH_RETR)
		if Err != nil {
			c.Fatalf("RetrieveFile error: %v\n", Err)
		}
	}
}

func (s *FtpClientTestSuite) TestFileList(c *C) {
	Err := uploadFile(LOCAL_PATH, HOST_PATH)
	if Err != nil {
		c.Fatalf("Upload error: %v\n", Err)
	} else {
		//		pDirEntry_X, Err := GL_FtpsClientPtr_X.List()
		_, Err := GL_FtpsClientPtr_X.List()
		if Err != nil {
			c.Fatalf("List error: %v\n", Err)
		}
		/*
			for _, DirEntry_X := range pDirEntry_X {
							log.Println(fmt.Sprintf("(%d): %s.%s %d bytes %s", DirEntry_X.Type_E, DirEntry_X.Name_S, DirEntry_X.Ext_S, DirEntry_X.Size_U64, DirEntry_X.Time_X))
			}
		*/
	}
}

/*
func (s *FtpClientTestSuite) TestFileDelete(c *C) {
	Err := uploadFile(LOCAL_PATH, HOST_PATH)
	if Err != nil {
		c.Fatalf("Upload error: %v\n", Err)
	} else {
		Err := GL_FtpsClientPtr_X.DeleteFile(HOST_PATH)
		if Err != nil {
			c.Fatalf("DeleteFile error: %v\n", Err)
		}
	}
}
*/
func uploadFile(_LocalPath_S, _HostPath_S string) error {

	pData_U8, rRts := ioutil.ReadFile(_LocalPath_S)
	if rRts == nil {
		rRts = GL_FtpsClientPtr_X.StoreFile(_HostPath_S, pData_U8)
	}
	return rRts
}
<|endoftext|>


<commit_before>package strava

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

var ClientId int
var ClientSecret string

const basePath = "https://www.strava.com/api/v3"
const timeFormat = "2006-01-02T15:04:05Z"

type Client struct {
	token      string
	httpClient *http.Client
}

type ErrorHandler func(*http.Response) error

var defaultErrorHandler ErrorHandler = func(resp *http.Response) error {
	// check status code, could be 500, or most likely the client_secret is incorrect
	if resp.StatusCode/100 == 5 {
		return errors.New("server error")
	}

	if resp.StatusCode/100 == 4 {
		var response Error
		contents, _ := ioutil.ReadAll(resp.Body)
		json.Unmarshal(contents, &response)

		return response
	}

	if resp.StatusCode/100 == 3 {
		return errors.New("redirect error")
	}
	return nil
}

// NewClient builds a normal client for making requests to the strava api.
// a http.Client can be passed in if http.DefaultClient can not be used.
func NewClient(token string, client ...*http.Client) *Client {
	c := &Client{token: token}
	if len(client) != 0 {
		c.httpClient = client[0]
	} else {
		c.httpClient = http.DefaultClient
	}
	return c
}

// NewStubResponseClient can be used for testing
// TODO, stub out with an actual response
func NewStubResponseClient(content string, statusCode ...int) *Client {
	c := NewClient("")
	t := &stubResponseTransport{content: content}

	if len(statusCode) != 0 {
		t.statusCode = statusCode[0]
	}

	c.httpClient = &http.Client{Transport: t}

	return c
}

type stubResponseTransport struct {
	http.Transport
	content    string
	statusCode int
}

func (t *stubResponseTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	resp := &http.Response{
		Status:     http.StatusText(t.statusCode),
		StatusCode: t.statusCode,
	}
	resp.Body = ioutil.NopCloser(strings.NewReader(t.content))

	return resp, nil
}

func (client *Client) run(method, path string, params map[string]interface{}) ([]byte, error) {
	var err error

	values := make(url.Values)
	for k, v := range params {
		values.Set(k, fmt.Sprintf("%v", v))
	}

	var req *http.Request
	if method == "POST" {
		req, err = http.NewRequest("POST", basePath+path, strings.NewReader(values.Encode()))
		if err != nil {
			return nil, err
		}
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	} else {
		req, err = http.NewRequest(method, basePath+path+"?"+values.Encode(), nil)
		if err != nil {
			return nil, err
		}
	}

	return client.runRequest(req)
}

func (client *Client) runRequestWithErrorHandler(req *http.Request, errorHandler ErrorHandler) ([]byte, error) {
	req.Header.Set("Authorization", "Bearer "+client.token)
	req.Header.Set("User-Agent", "Strava Golang Library v1")
	resp, err := client.httpClient.Do(req)

	// this was a poor request, maybe strava servers down?
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	RateLimiting.updateRateLimits(resp)

	return checkResponseForErrorsWithErrorHandler(resp, errorHandler)
}

func (client *Client) runRequest(req *http.Request) ([]byte, error) {
	return client.runRequestWithErrorHandler(req, defaultErrorHandler)
}

func checkResponseForErrorsWithErrorHandler(resp *http.Response, errorHandler ErrorHandler) ([]byte, error) {
	if resp.StatusCode/100 > 2 {
		return nil, errorHandler(resp)
	} else {
		return ioutil.ReadAll(resp.Body)
	}
}

func checkResponseForErrors(resp *http.Response) ([]byte, error) {
	return checkResponseForErrorsWithErrorHandler(resp, defaultErrorHandler)
}
<commit_msg>Add stdo logging of url for debugging<commit_after>package strava

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

var ClientId int
var ClientSecret string

const basePath = "https://www.strava.com/api/v3"
const timeFormat = "2006-01-02T15:04:05Z"

type Client struct {
	token      string
	httpClient *http.Client
}

type ErrorHandler func(*http.Response) error

var defaultErrorHandler ErrorHandler = func(resp *http.Response) error {
	// check status code, could be 500, or most likely the client_secret is incorrect
	if resp.StatusCode/100 == 5 {
		return errors.New("server error")
	}

	if resp.StatusCode/100 == 4 {
		var response Error
		contents, _ := ioutil.ReadAll(resp.Body)
		json.Unmarshal(contents, &response)

		return response
	}

	if resp.StatusCode/100 == 3 {
		return errors.New("redirect error")
	}
	return nil
}

// NewClient builds a normal client for making requests to the strava api.
// a http.Client can be passed in if http.DefaultClient can not be used.
func NewClient(token string, client ...*http.Client) *Client {
	c := &Client{token: token}
	if len(client) != 0 {
		c.httpClient = client[0]
	} else {
		c.httpClient = http.DefaultClient
	}
	return c
}

// NewStubResponseClient can be used for testing
// TODO, stub out with an actual response
func NewStubResponseClient(content string, statusCode ...int) *Client {
	c := NewClient("")
	t := &stubResponseTransport{content: content}

	if len(statusCode) != 0 {
		t.statusCode = statusCode[0]
	}

	c.httpClient = &http.Client{Transport: t}

	return c
}

type stubResponseTransport struct {
	http.Transport
	content    string
	statusCode int
}

func (t *stubResponseTransport) RoundTrip(req *http.Request) (*http.Response, error) {
	resp := &http.Response{
		Status:     http.StatusText(t.statusCode),
		StatusCode: t.statusCode,
	}
	resp.Body = ioutil.NopCloser(strings.NewReader(t.content))

	return resp, nil
}

func (client *Client) run(method, path string, params map[string]interface{}) ([]byte, error) {
	var err error

	values := make(url.Values)
	for k, v := range params {
		values.Set(k, fmt.Sprintf("%v", v))
	}

	var req *http.Request
	if method == "POST" {
		req, err = http.NewRequest("POST", basePath+path, strings.NewReader(values.Encode()))
		if err != nil {
			return nil, err
		}
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	} else {
		fmt.Prinf("%s", basePath+path+"?"+values.Encode())
		req, err = http.NewRequest(method, basePath+path+"?"+values.Encode(), nil)
		if err != nil {
			return nil, err
		}
	}

	return client.runRequest(req)
}

func (client *Client) runRequestWithErrorHandler(req *http.Request, errorHandler ErrorHandler) ([]byte, error) {
	req.Header.Set("Authorization", "Bearer "+client.token)
	req.Header.Set("User-Agent", "Strava Golang Library v1")
	resp, err := client.httpClient.Do(req)

	// this was a poor request, maybe strava servers down?
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	RateLimiting.updateRateLimits(resp)

	return checkResponseForErrorsWithErrorHandler(resp, errorHandler)
}

func (client *Client) runRequest(req *http.Request) ([]byte, error) {
	return client.runRequestWithErrorHandler(req, defaultErrorHandler)
}

func checkResponseForErrorsWithErrorHandler(resp *http.Response, errorHandler ErrorHandler) ([]byte, error) {
	if resp.StatusCode/100 > 2 {
		return nil, errorHandler(resp)
	} else {
		return ioutil.ReadAll(resp.Body)
	}
}

func checkResponseForErrors(resp *http.Response) ([]byte, error) {
	return checkResponseForErrorsWithErrorHandler(resp, defaultErrorHandler)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/Terry-Mao/goim/define"
	"sync"
)

// Bucket is a channel holder.
type Bucket struct {
	cLock       sync.RWMutex                    // protect the channels for chs
	chs         map[string]*Channel             // map sub key to a channel
	rooms       map[int32]map[*Channel]struct{} // map room id with channels
	roomChannel int
}

// NewBucket new a bucket struct. store the subkey with im channel.
func NewBucket(channel, room, roomChannel, cliProto, svrProto int) *Bucket {
	b := new(Bucket)
	b.chs = make(map[string]*Channel, channel)
	b.rooms = make(map[int32]map[*Channel]struct{}, room)
	b.roomChannel = roomChannel
	return b
}

// Put put a channel according with sub key.
func (b *Bucket) Put(subKey string, ch *Channel) {
	var (
		room map[*Channel]struct{}
		ok   bool
	)
	b.cLock.Lock()
	b.chs[subKey] = ch
	if ch.RoomId != define.NoRoom {
		if room, ok = b.rooms[ch.RoomId]; !ok {
			room = make(map[*Channel]struct{}, b.roomChannel)
			b.rooms[ch.RoomId] = room
		}
		room[ch] = struct{}{}
	}
	b.cLock.Unlock()
}

// Get get a channel by sub key.
func (b *Bucket) Get(subKey string) *Channel {
	var ch *Channel
	b.cLock.RLock()
	ch = b.chs[subKey]
	b.cLock.RUnlock()
	return ch
}

// Del delete the channel by sub key.
func (b *Bucket) Del(subKey string) {
	var (
		ok   bool
		ch   *Channel
		room map[*Channel]struct{}
	)
	b.cLock.Lock()
	if ch, ok = b.chs[subKey]; ok {
		delete(b.chs, subKey)
		if ch.RoomId != define.NoRoom {
			if room, ok = b.rooms[ch.RoomId]; ok {
				delete(room, ch)
			}
		}
	}
	b.cLock.Unlock()
}

// Broadcast push msgs to all channels in the bucket.
func (b *Bucket) Broadcast(ver int16, operation int32, msg []byte) {
	var (
		i   = 0
		ch  *Channel
		chs []*Channel
	)
	b.cLock.RLock()
	chs = make([]*Channel, len(b.chs))
	for _, ch = range b.chs {
		chs[i] = ch
		i++
	}
	b.cLock.RUnlock()
	for _, ch = range chs {
		// ignore error
		ch.PushMsg(ver, operation, msg)
	}
}

// Broadcast push msgs to all channels in the bucket's room.
func (b *Bucket) BroadcastRoom(rid int32, ver int16, operation int32, msg []byte) {
	var (
		i    = 0
		ok   bool
		ch   *Channel
		chs  []*Channel
		room map[*Channel]struct{}
	)
	b.cLock.RLock()
	if room, ok = b.rooms[rid]; ok && len(room) > 0 {
		chs = make([]*Channel, len(room))
		for ch, _ = range room {
			chs[i] = ch
			i++
		}
	}
	b.cLock.RUnlock()
	for _, ch = range chs {
		// ignore error
		ch.PushMsg(ver, operation, msg)
	}
}

// Rooms get all room id where online number > 0.
func (b *Bucket) Rooms() (res map[int32]struct{}) {
	var (
		roomId int32
		room   map[*Channel]struct{}
	)
	b.cLock.RLock()
	res = make(map[int32]struct{}, len(b.rooms))
	for roomId, room = range b.rooms {
		if len(room) > 0 {
			res[roomId] = struct{}{}
		}
	}
	b.cLock.RUnlock()
	return
}
<commit_msg>improve performance<commit_after>package main

import (
	"github.com/Terry-Mao/goim/define"
	"sync"
)

// Bucket is a channel holder.
type Bucket struct {
	cLock       sync.RWMutex                    // protect the channels for chs
	chs         map[string]*Channel             // map sub key to a channel
	rooms       map[int32]map[*Channel]struct{} // map room id with channels
	roomChannel int
}

// NewBucket new a bucket struct. store the subkey with im channel.
func NewBucket(channel, room, roomChannel, cliProto, svrProto int) *Bucket {
	b := new(Bucket)
	b.chs = make(map[string]*Channel, channel)
	b.rooms = make(map[int32]map[*Channel]struct{}, room)
	b.roomChannel = roomChannel
	return b
}

// Put put a channel according with sub key.
func (b *Bucket) Put(subKey string, ch *Channel) {
	var (
		room map[*Channel]struct{}
		ok   bool
	)
	b.cLock.Lock()
	b.chs[subKey] = ch
	if ch.RoomId != define.NoRoom {
		if room, ok = b.rooms[ch.RoomId]; !ok {
			room = make(map[*Channel]struct{}, b.roomChannel)
			b.rooms[ch.RoomId] = room
		}
		room[ch] = struct{}{}
	}
	b.cLock.Unlock()
}

// Get get a channel by sub key.
func (b *Bucket) Get(subKey string) *Channel {
	var ch *Channel
	b.cLock.RLock()
	ch = b.chs[subKey]
	b.cLock.RUnlock()
	return ch
}

// Del delete the channel by sub key.
func (b *Bucket) Del(subKey string) {
	var (
		ok   bool
		ch   *Channel
		room map[*Channel]struct{}
	)
	b.cLock.Lock()
	if ch, ok = b.chs[subKey]; ok {
		delete(b.chs, subKey)
		if ch.RoomId != define.NoRoom {
			if room, ok = b.rooms[ch.RoomId]; ok {
				delete(room, ch)
			}
		}
	}
	b.cLock.Unlock()
}

// Broadcast push msgs to all channels in the bucket.
func (b *Bucket) Broadcast(ver int16, operation int32, msg []byte) {
	var (
		i   = 0
		ch  *Channel
		chs []*Channel
	)
	b.cLock.RLock()
	chs = make([]*Channel, len(b.chs))
	for _, ch = range b.chs {
		chs[i] = ch
		i++
	}
	b.cLock.RUnlock()
	for _, ch = range chs {
		// ignore error
		ch.PushMsg(ver, operation, msg)
	}
}

// Broadcast push msgs to all channels in the bucket's room.
func (b *Bucket) BroadcastRoom(rid int32, ver int16, operation int32, msg []byte) {
	var (
		ok   bool
		ch   *Channel
		room map[*Channel]struct{}
	)
	b.cLock.RLock()
	if room, ok = b.rooms[rid]; ok && len(room) > 0 {
		for ch, _ = range room {
			// ignore error
			ch.PushMsg(ver, operation, msg)
		}
	}
	b.cLock.RUnlock()
}

// Rooms get all room id where online number > 0.
func (b *Bucket) Rooms() (res map[int32]struct{}) {
	var (
		roomId int32
		room   map[*Channel]struct{}
	)
	b.cLock.RLock()
	res = make(map[int32]struct{}, len(b.rooms))
	for roomId, room = range b.rooms {
		if len(room) > 0 {
			res[roomId] = struct{}{}
		}
	}
	b.cLock.RUnlock()
	return
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"sort"
	"strings"
	"text/tabwriter"

	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/log"
	"github.com/containerd/containerd/platforms"
	"github.com/containerd/containerd/progress"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

var imageCommand = cli.Command{
	Name:  "images",
	Usage: "manage images",
	Subcommands: cli.Commands{
		imagesListCommand,
		imageRemoveCommand,
		imagesSetLabelsCommand,
		imagesImportCommand,
		imagesExportCommand,
	},
}

var imagesListCommand = cli.Command{
	Name:        "list",
	Aliases:     []string{"ls"},
	Usage:       "list images known to containerd",
	ArgsUsage:   "[flags] <ref>",
	Description: `List images registered with containerd.`,
	Flags:       []cli.Flag{},
	Action: func(clicontext *cli.Context) error {
		var (
			filters     = clicontext.Args()
			ctx, cancel = appContext(clicontext)
		)
		defer cancel()

		client, err := newClient(clicontext)
		if err != nil {
			return err
		}

		imageStore := client.ImageService()
		cs := client.ContentStore()

		imageList, err := imageStore.List(ctx, filters...)
		if err != nil {
			return errors.Wrap(err, "failed to list images")
		}

		tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
		fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSIZE\tPLATFORM\tLABELS\t")
		for _, image := range imageList {
			size, err := image.Size(ctx, cs, platforms.Default())
			if err != nil {
				log.G(ctx).WithError(err).Errorf("failed calculating size for image %s", image.Name)
			}

			platformColumn := "-"
			specs, err := images.Platforms(ctx, cs, image.Target)
			if err != nil {
				log.G(ctx).WithError(err).Errorf("failed resolving platform for image %s", image.Name)
			} else if len(specs) > 0 {
				psm := map[string]struct{}{}
				for _, p := range specs {
					psm[platforms.Format(p)] = struct{}{}
				}
				var ps []string
				for p := range psm {
					ps = append(ps, p)
				}
				sort.Stable(sort.StringSlice(ps))
				platformColumn = strings.Join(ps, ",")
			}

			labels := "-"
			if len(image.Labels) > 0 {
				var pairs []string
				for k, v := range image.Labels {
					pairs = append(pairs, fmt.Sprintf("%v=%v", k, v))
				}
				sort.Strings(pairs)
				labels = strings.Join(pairs, ",")
			}

			fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%s\t\n",
				image.Name,
				image.Target.MediaType,
				image.Target.Digest,
				progress.Bytes(size),
				platformColumn,
				labels)
		}

		return tw.Flush()
	},
}

var imagesSetLabelsCommand = cli.Command{
	Name:        "label",
	Usage:       "set and clear labels for an image.",
	ArgsUsage:   "[flags] <name> [<key>=<value>, ...]",
	Description: "Set and clear labels for an image.",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "replace-all, r",
			Usage: "replace all labels",
		},
	},
	Action: func(clicontext *cli.Context) error {
		var (
			ctx, cancel  = appContext(clicontext)
			replaceAll   = clicontext.Bool("replace-all")
			name, labels = objectWithLabelArgs(clicontext)
		)
		defer cancel()

		client, err := newClient(clicontext)
		if err != nil {
			return err
		}

		if name == "" {
			return errors.New("please specify an image")
		}

		var (
			is         = client.ImageService()
			fieldpaths []string
		)

		for k := range labels {
			if replaceAll {
				fieldpaths = append(fieldpaths, "labels")
			} else {
				fieldpaths = append(fieldpaths, strings.Join([]string{"labels", k}, "."))
			}
		}

		image := images.Image{
			Name:   name,
			Labels: labels,
		}

		updated, err := is.Update(ctx, image, fieldpaths...)
		if err != nil {
			return err
		}

		var labelStrings []string
		for k, v := range updated.Labels {
			labelStrings = append(labelStrings, fmt.Sprintf("%s=%s", k, v))
		}

		fmt.Println(strings.Join(labelStrings, ","))

		return nil
	},
}

var imageRemoveCommand = cli.Command{
	Name:        "remove",
	Aliases:     []string{"rm"},
	Usage:       "Remove one or more images by reference.",
	ArgsUsage:   "[flags] <ref> [<ref>, ...]",
	Description: `Remove one or more images by reference.`,
	Flags:       []cli.Flag{},
	Action: func(clicontext *cli.Context) error {
		var (
			exitErr error
		)
		ctx, cancel := appContext(clicontext)
		defer cancel()

		client, err := newClient(clicontext)
		if err != nil {
			return err
		}

		imageStore := client.ImageService()

		for _, target := range clicontext.Args() {
			if err := imageStore.Delete(ctx, target); err != nil {
				if !errdefs.IsNotFound(err) {
					if exitErr == nil {
						exitErr = errors.Wrapf(err, "unable to delete %v", target)
					}
					log.G(ctx).WithError(err).Errorf("unable to delete %v", target)
					continue
				}
			}

			fmt.Println(target)
		}

		return exitErr
	},
}
<commit_msg>ctr: add `ctr images ls --quiet`<commit_after>package main

import (
	"fmt"
	"os"
	"sort"
	"strings"
	"text/tabwriter"

	"github.com/containerd/containerd/errdefs"
	"github.com/containerd/containerd/images"
	"github.com/containerd/containerd/log"
	"github.com/containerd/containerd/platforms"
	"github.com/containerd/containerd/progress"
	"github.com/pkg/errors"
	"github.com/urfave/cli"
)

var imageCommand = cli.Command{
	Name:  "images",
	Usage: "manage images",
	Subcommands: cli.Commands{
		imagesListCommand,
		imageRemoveCommand,
		imagesSetLabelsCommand,
		imagesImportCommand,
		imagesExportCommand,
	},
}

var imagesListCommand = cli.Command{
	Name:        "list",
	Aliases:     []string{"ls"},
	Usage:       "list images known to containerd",
	ArgsUsage:   "[flags] <ref>",
	Description: `List images registered with containerd.`,
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "quiet, q",
			Usage: "print only the image refs",
		},
	},
	Action: func(clicontext *cli.Context) error {
		var (
			filters     = clicontext.Args()
			quiet       = clicontext.Bool("quiet")
			ctx, cancel = appContext(clicontext)
		)
		defer cancel()

		client, err := newClient(clicontext)
		if err != nil {
			return err
		}

		imageStore := client.ImageService()
		cs := client.ContentStore()

		imageList, err := imageStore.List(ctx, filters...)
		if err != nil {
			return errors.Wrap(err, "failed to list images")
		}
		if quiet {
			for _, image := range imageList {
				fmt.Println(image.Name)
			}
			return nil
		}
		tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
		fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSIZE\tPLATFORM\tLABELS\t")
		for _, image := range imageList {
			size, err := image.Size(ctx, cs, platforms.Default())
			if err != nil {
				log.G(ctx).WithError(err).Errorf("failed calculating size for image %s", image.Name)
			}

			platformColumn := "-"
			specs, err := images.Platforms(ctx, cs, image.Target)
			if err != nil {
				log.G(ctx).WithError(err).Errorf("failed resolving platform for image %s", image.Name)
			} else if len(specs) > 0 {
				psm := map[string]struct{}{}
				for _, p := range specs {
					psm[platforms.Format(p)] = struct{}{}
				}
				var ps []string
				for p := range psm {
					ps = append(ps, p)
				}
				sort.Stable(sort.StringSlice(ps))
				platformColumn = strings.Join(ps, ",")
			}

			labels := "-"
			if len(image.Labels) > 0 {
				var pairs []string
				for k, v := range image.Labels {
					pairs = append(pairs, fmt.Sprintf("%v=%v", k, v))
				}
				sort.Strings(pairs)
				labels = strings.Join(pairs, ",")
			}

			fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%s\t\n",
				image.Name,
				image.Target.MediaType,
				image.Target.Digest,
				progress.Bytes(size),
				platformColumn,
				labels)
		}

		return tw.Flush()
	},
}

var imagesSetLabelsCommand = cli.Command{
	Name:        "label",
	Usage:       "set and clear labels for an image.",
	ArgsUsage:   "[flags] <name> [<key>=<value>, ...]",
	Description: "Set and clear labels for an image.",
	Flags: []cli.Flag{
		cli.BoolFlag{
			Name:  "replace-all, r",
			Usage: "replace all labels",
		},
	},
	Action: func(clicontext *cli.Context) error {
		var (
			ctx, cancel  = appContext(clicontext)
			replaceAll   = clicontext.Bool("replace-all")
			name, labels = objectWithLabelArgs(clicontext)
		)
		defer cancel()

		client, err := newClient(clicontext)
		if err != nil {
			return err
		}

		if name == "" {
			return errors.New("please specify an image")
		}

		var (
			is         = client.ImageService()
			fieldpaths []string
		)

		for k := range labels {
			if replaceAll {
				fieldpaths = append(fieldpaths, "labels")
			} else {
				fieldpaths = append(fieldpaths, strings.Join([]string{"labels", k}, "."))
			}
		}

		image := images.Image{
			Name:   name,
			Labels: labels,
		}

		updated, err := is.Update(ctx, image, fieldpaths...)
		if err != nil {
			return err
		}

		var labelStrings []string
		for k, v := range updated.Labels {
			labelStrings = append(labelStrings, fmt.Sprintf("%s=%s", k, v))
		}

		fmt.Println(strings.Join(labelStrings, ","))

		return nil
	},
}

var imageRemoveCommand = cli.Command{
	Name:        "remove",
	Aliases:     []string{"rm"},
	Usage:       "Remove one or more images by reference.",
	ArgsUsage:   "[flags] <ref> [<ref>, ...]",
	Description: `Remove one or more images by reference.`,
	Flags:       []cli.Flag{},
	Action: func(clicontext *cli.Context) error {
		var (
			exitErr error
		)
		ctx, cancel := appContext(clicontext)
		defer cancel()

		client, err := newClient(clicontext)
		if err != nil {
			return err
		}

		imageStore := client.ImageService()

		for _, target := range clicontext.Args() {
			if err := imageStore.Delete(ctx, target); err != nil {
				if !errdefs.IsNotFound(err) {
					if exitErr == nil {
						exitErr = errors.Wrapf(err, "unable to delete %v", target)
					}
					log.G(ctx).WithError(err).Errorf("unable to delete %v", target)
					continue
				}
			}

			fmt.Println(target)
		}

		return exitErr
	},
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/xchapter7x/enaml/diff"
	"github.com/xchapter7x/enaml/generators"
	"github.com/xchapter7x/lo"
)

func init() {
	if c := os.Getenv("ENAML_CACHE_DIR"); c != "" {
		cacheDir = c
	}

	if o := os.Getenv("ENAML_OUTPUT_DIR"); o != "" {
		outputDir = o
	}

	os.MkdirAll(cacheDir, 0755)
}

const (
	CacheDir  = ".cache"
	OutputDir = "./releasejobs"
)

var (
	Version   string
	cacheDir  = CacheDir
	outputDir = OutputDir
)

func main() {
	app := cli.NewApp()
	app.Version = Version
	app.Commands = []cli.Command{
		{
			Name:        "generate-jobs",
			Aliases:     []string{"gj"},
			Usage:       "generate-jobs <releaseurl>",
			Description: "generate golang structs for the jobs in a given release",
			Action: func(c *cli.Context) {
				generators.GenerateReleaseJobsPackage(c.Args().First(), cacheDir, OutputDir)
				println("completed generating release job structs for ", c.Args().First())
			},
		},
		{
			Name:    "diff-release",
			Aliases: []string{"dr"},
			Usage:   "show a diff between 2 releases given",
			Action: func(c *cli.Context) {
				diff := diff.NewDiff(cacheDir)
				diffset, err := diff.ReleaseDiff(c.Args()[0], c.Args()[1])
				displayDiffAndExit(diffset, err)
			},
		},
		{
			Name:        "diff-job",
			Aliases:     []string{"dj"},
			Usage:       "diff-jobs <jobname> <releaseurl-A> <releaseurl-B>",
			Description: "show diff between jobs across 2 releases",
			Action: func(c *cli.Context) {
				diff := diff.NewDiff(cacheDir)
				diffset, err := diff.JobDiffBetweenReleases(c.Args()[0], c.Args()[1], c.Args()[2])
				displayDiffAndExit(diffset, err)
			},
		},
	}
	app.Run(os.Args)
}

func displayDiffAndExit(diffset []string, err error) {
	if err == nil && len(diffset) == 0 {
		fmt.Println("no differences found")

	} else if len(diffset) > 0 {

		for i, v := range diffset {
			fmt.Println(i, ": ", v)
		}
		os.Exit(1)

	} else {
		lo.G.Error("error: ", err)
		os.Exit(2)
	}
	os.Exit(0)
}
<commit_msg>[#118197197] changing default output dir to be more enaml branded<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/codegangsta/cli"
	"github.com/xchapter7x/enaml/diff"
	"github.com/xchapter7x/enaml/generators"
	"github.com/xchapter7x/lo"
)

func init() {
	if c := os.Getenv("ENAML_CACHE_DIR"); c != "" {
		cacheDir = c
	}

	if o := os.Getenv("ENAML_OUTPUT_DIR"); o != "" {
		outputDir = o
	}

	os.MkdirAll(cacheDir, 0755)
}

const (
	CacheDir  = ".cache"
	OutputDir = "./enaml-gen"
)

var (
	Version   string
	cacheDir  = CacheDir
	outputDir = OutputDir
)

func main() {
	app := cli.NewApp()
	app.Version = Version
	app.Commands = []cli.Command{
		{
			Name:        "generate-jobs",
			Aliases:     []string{"gj"},
			Usage:       "generate-jobs <releaseurl>",
			Description: "generate golang structs for the jobs in a given release",
			Action: func(c *cli.Context) {
				generators.GenerateReleaseJobsPackage(c.Args().First(), cacheDir, OutputDir)
				println("completed generating release job structs for ", c.Args().First())
			},
		},
		{
			Name:    "diff-release",
			Aliases: []string{"dr"},
			Usage:   "show a diff between 2 releases given",
			Action: func(c *cli.Context) {
				diff := diff.NewDiff(cacheDir)
				diffset, err := diff.ReleaseDiff(c.Args()[0], c.Args()[1])
				displayDiffAndExit(diffset, err)
			},
		},
		{
			Name:        "diff-job",
			Aliases:     []string{"dj"},
			Usage:       "diff-jobs <jobname> <releaseurl-A> <releaseurl-B>",
			Description: "show diff between jobs across 2 releases",
			Action: func(c *cli.Context) {
				diff := diff.NewDiff(cacheDir)
				diffset, err := diff.JobDiffBetweenReleases(c.Args()[0], c.Args()[1], c.Args()[2])
				displayDiffAndExit(diffset, err)
			},
		},
	}
	app.Run(os.Args)
}

func displayDiffAndExit(diffset []string, err error) {
	if err == nil && len(diffset) == 0 {
		fmt.Println("no differences found")

	} else if len(diffset) > 0 {

		for i, v := range diffset {
			fmt.Println(i, ": ", v)
		}
		os.Exit(1)

	} else {
		lo.G.Error("error: ", err)
		os.Exit(2)
	}
	os.Exit(0)
}
<|endoftext|>


<commit_before>package tuple

import (
	"errors"
	"regexp"
	"strconv"
)

var re = regexp.MustCompile("^([^\\[]+)?(\\[[0-9]+\\])?$")

func toError(v interface{}) error {
	if v != nil {
		if e, ok := v.(error); ok {
			return e
		}
		if e, ok := v.(string); ok {
			return errors.New(e)
		}
		return errors.New("Unknown error")
	}
	return nil
}

func split(s string) []string {
	i := 0
	a := []string{}
	t := ""
	rs := []rune(s)
	l := len(rs)
	for i < l {
		r := rs[i]
		switch r {
		case '\\':
			i++
			if i < l {
				t += string(rs[i])
			}
		case '/':
			if t != "" {
				a = append(a, t)
				t = ""
			}
		default:
			t += string(r)
		}
		i++
	}
	if t != "" {
		a = append(a, t)
	}
	return a
}

func ScanMap(m Map, p string, t *Value) (err error) {
	if p == "" {
		return errors.New("emmpty path is not supported")
	}
	//var ok bool
	var v Value
	for _, token := range split(p) {
		sl := re.FindAllStringSubmatch(token, -1)
		if len(sl) == 0 {
			return errors.New("invalid path phrase")
		}
		ss := sl[0]
		if ss[1] != "" {
			mv := m[ss[1]]
			if mv == nil {
				return errors.New("invalid path phrase")
			}
			var err error
			switch mv.Type() {
			case TypeBool:
				v, err = mv.Bool()
			case TypeInt:
				v, err = mv.Int()
			case TypeFloat:
				v, err = mv.Float()
			case TypeString:
				v, err = mv.String()
			case TypeBlob:
				b, err := mv.Blob()
				if err != nil {
					break
				}
				v = &b
			case TypeTimestamp:
				v, err = mv.Timestamp()
			case TypeArray:
				v, err = mv.Array()
			case TypeMap:
				v, err = mv.Map()
			default:
				return errors.New("invalid path phrase")
			}
			if err != nil {
				return err
			}
		}
		// get array index number
		if ss[2] != "" {
			i, err := strconv.Atoi(ss[2][1 : len(ss[2])-1])
			if err != nil {
				return errors.New("invalid array index phrase: " + ss[2])
			}
			if v.Type() != TypeArray {
				return errors.New("invalid array path phrase: " + ss[1])
			}
			a, _ := v.Array()
			found := false
			for n, av := range a {
				if n == i {
					found = true
					v = av
					break
				}
			}
			if !found {
				return errors.New("out of range access: " + ss[1] + ss[2])
			}
		}
	}
	*t = v
	return nil
}
<commit_msg>delete unnecessary type switch, fix typo<commit_after>package tuple

import (
	"errors"
	"regexp"
	"strconv"
)

var re = regexp.MustCompile(`^([^\[]+)?(\[[0-9]+\])?$`)

func toError(v interface{}) error {
	if v != nil {
		if e, ok := v.(error); ok {
			return e
		}
		if e, ok := v.(string); ok {
			return errors.New(e)
		}
		return errors.New("Unknown error")
	}
	return nil
}

func split(s string) []string {
	i := 0
	a := []string{}
	t := ""
	rs := []rune(s)
	l := len(rs)
	for i < l {
		r := rs[i]
		switch r {
		case '\\':
			i++
			if i < l {
				t += string(rs[i])
			}
		case '/':
			if t != "" {
				a = append(a, t)
				t = ""
			}
		default:
			t += string(r)
		}
		i++
	}
	if t != "" {
		a = append(a, t)
	}
	return a
}

func ScanMap(m Map, p string, t *Value) (err error) {
	if p == "" {
		return errors.New("empty path is not supported")
	}
	var v Value
	for _, token := range split(p) {
		sl := re.FindAllStringSubmatch(token, -1)
		if len(sl) == 0 {
			return errors.New("invalid path phrase")
		}
		ss := sl[0]
		if ss[1] != "" {
			mv := m[ss[1]]
			if mv == nil {
				return errors.New("invalid path phrase")
			}
			v = mv
		}
		// get array index number
		if ss[2] != "" {
			i, err := strconv.Atoi(ss[2][1 : len(ss[2])-1])
			if err != nil {
				return errors.New("invalid array index phrase: " + ss[2])
			}
			if v.Type() != TypeArray {
				return errors.New("invalid array path phrase: " + ss[1])
			}
			a, _ := v.Array()
			found := false
			for n, av := range a {
				if n == i {
					found = true
					v = av
					break
				}
			}
			if !found {
				return errors.New("out of range access: " + ss[1] + ss[2])
			}
		}
	}
	*t = v
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"regexp"

	"code.google.com/p/go.net/html"
	"code.google.com/p/go.net/html/atom"
	"github.com/JustinTulloss/hut"
	"github.com/temoto/robotstxt.go"
)

var ogmatcher = regexp.MustCompile("^(og|airbedandbreakfast|twitter):")
var useragent = "Gogetter (https://github.com/JustinTulloss/gogetter) (like GoogleBot)"
var service *hut.Service

type HttpError struct {
	msg        string
	StatusCode int
}

func (e *HttpError) Error() string { return e.msg }

func buildRequest(url string) (*http.Request, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", useragent)
	return req, nil
}

func checkRobotsTxt(fullUrl string) (bool, error) {
	parsed, err := url.Parse(fullUrl)
	if err != nil {
		return false, err
	}
	original := parsed.Path
	parsed.Path = "robots.txt"
	client := http.Client{}
	req, err := buildRequest(parsed.String())
	if err != nil {
		return false, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()
	robots, err := robotstxt.FromResponse(resp)
	if robots == nil {
		// Assume we can crawl if the robots.txt file doesn't work
		return true, nil
	}
	return robots.TestAgent(original, useragent), nil
}

func parseTags(r io.Reader) (map[string]string, *HttpError) {
	node, err := html.Parse(r)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	var findmeta func(*html.Node)
	results := make(map[string]string)
	// Recursively goes through nodes looking for meta nodes that
	// have a property tag that matches the opengraph regex. If it does,
	// Saves the contents to the results map.
	findmeta = func(n *html.Node) {
		if n.Type == html.ElementNode && n.DataAtom == atom.Meta {
			var content, property string
			save := false
			for _, a := range n.Attr {
				if (a.Key == "property" || a.Key == "name") && ogmatcher.FindStringIndex(a.Val) != nil {
					save = true
					property = html.UnescapeString(a.Val)
				}
				if a.Key == "content" {
					content = html.UnescapeString(a.Val)
				}
			}
			if save {
				results[property] = content
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			findmeta(c)
		}
	}
	findmeta(node)
	return results, nil
}

func getTags(url string) (map[string]string, *HttpError) {
	permitted, err := checkRobotsTxt(url)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	if !permitted {
		msg := fmt.Sprintf("Not permitted to fetch %s as a robot", url)
		log.Println(msg)
		return nil, &HttpError{msg, 403}
	}
	client := http.Client{}
	req, _ := buildRequest(url)
	resp, err := client.Do(req)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	log.Printf("Fetched %s\n", url)
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, &HttpError{
			fmt.Sprintf("Could not fetch %s", url),
			resp.StatusCode,
		}
	}
	return parseTags(resp.Body)
}

func handler(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		service.ErrorReply(err, w)
		return
	}
	decodedUrl, err := url.QueryUnescape(r.Form.Get("url"))
	if err != nil {
		service.ErrorReply(err, w)
		return
	}
	tags, httpErr := getTags(decodedUrl)
	if httpErr != nil {
		service.HttpErrorReply(w, httpErr.Error(), httpErr.StatusCode)
		return
	}
	service.Reply(tags, w)
}

func main() {
	service = hut.NewService(nil)
	service.Router.HandleFunc("/", handler)

	protocol, err := service.Env.Get("protocol")
	if err != nil {
		log.Fatal(err)
	}
	if protocol == "http" {
		service.Start()
	} else if len(flag.Args()) != 0 {
		tags, _ := getTags(flag.Arg(0))
		for prop, val := range tags {
			fmt.Printf("%s -- %s\n", prop, val)
		}
	} else {
		panic("Need to use this properly and I need to print usage info!")
	}
}
<commit_msg>Fix moved imports<commit_after>package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"regexp"

	"github.com/JustinTulloss/hut"
	"github.com/temoto/robotstxt.go"
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
)

var ogmatcher = regexp.MustCompile("^(og|airbedandbreakfast|twitter):")
var useragent = "Gogetter (https://github.com/JustinTulloss/gogetter) (like GoogleBot)"
var service *hut.Service

type HttpError struct {
	msg        string
	StatusCode int
}

func (e *HttpError) Error() string { return e.msg }

func buildRequest(url string) (*http.Request, error) {
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("User-Agent", useragent)
	return req, nil
}

func checkRobotsTxt(fullUrl string) (bool, error) {
	parsed, err := url.Parse(fullUrl)
	if err != nil {
		return false, err
	}
	original := parsed.Path
	parsed.Path = "robots.txt"
	client := http.Client{}
	req, err := buildRequest(parsed.String())
	if err != nil {
		return false, err
	}
	resp, err := client.Do(req)
	if err != nil {
		return false, err
	}
	defer resp.Body.Close()
	robots, err := robotstxt.FromResponse(resp)
	if robots == nil {
		// Assume we can crawl if the robots.txt file doesn't work
		return true, nil
	}
	return robots.TestAgent(original, useragent), nil
}

func parseTags(r io.Reader) (map[string]string, *HttpError) {
	node, err := html.Parse(r)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	var findmeta func(*html.Node)
	results := make(map[string]string)
	// Recursively goes through nodes looking for meta nodes that
	// have a property tag that matches the opengraph regex. If it does,
	// Saves the contents to the results map.
	findmeta = func(n *html.Node) {
		if n.Type == html.ElementNode && n.DataAtom == atom.Meta {
			var content, property string
			save := false
			for _, a := range n.Attr {
				if (a.Key == "property" || a.Key == "name") && ogmatcher.FindStringIndex(a.Val) != nil {
					save = true
					property = html.UnescapeString(a.Val)
				}
				if a.Key == "content" {
					content = html.UnescapeString(a.Val)
				}
			}
			if save {
				results[property] = content
			}
		}
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			findmeta(c)
		}
	}
	findmeta(node)
	return results, nil
}

func getTags(url string) (map[string]string, *HttpError) {
	permitted, err := checkRobotsTxt(url)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	if !permitted {
		msg := fmt.Sprintf("Not permitted to fetch %s as a robot", url)
		log.Println(msg)
		return nil, &HttpError{msg, 403}
	}
	client := http.Client{}
	req, _ := buildRequest(url)
	resp, err := client.Do(req)
	if err != nil {
		return nil, &HttpError{err.Error(), 500}
	}
	log.Printf("Fetched %s\n", url)
	defer resp.Body.Close()
	if resp.StatusCode != 200 {
		return nil, &HttpError{
			fmt.Sprintf("Could not fetch %s", url),
			resp.StatusCode,
		}
	}
	return parseTags(resp.Body)
}

func handler(w http.ResponseWriter, r *http.Request) {
	if err := r.ParseForm(); err != nil {
		service.ErrorReply(err, w)
		return
	}
	decodedUrl, err := url.QueryUnescape(r.Form.Get("url"))
	if err != nil {
		service.ErrorReply(err, w)
		return
	}
	tags, httpErr := getTags(decodedUrl)
	if httpErr != nil {
		service.HttpErrorReply(w, httpErr.Error(), httpErr.StatusCode)
		return
	}
	service.Reply(tags, w)
}

func main() {
	service = hut.NewService(nil)
	service.Router.HandleFunc("/", handler)

	protocol, err := service.Env.Get("protocol")
	if err != nil {
		log.Fatal(err)
	}
	if protocol == "http" {
		service.Start()
	} else if len(flag.Args()) != 0 {
		tags, _ := getTags(flag.Arg(0))
		for prop, val := range tags {
			fmt.Printf("%s -- %s\n", prop, val)
		}
	} else {
		panic("Need to use this properly and I need to print usage info!")
	}
}
<|endoftext|>


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

package main

import (
	"flag"
	"fmt"
)

var cmdVersion = &Command{
	RunArgs:     runVersion,
	Usage:       "version",
	Description: "print version information",
	Flag:        flag.NewFlagSet("version", flag.ContinueOnError),
	Help: `
Version prints version information about ht.
	`,
}

var (
	version = "3.6.0"
)

func runVersion(cmd *Command, _ []string) {
	fmt.Printf("ht version %s\n", version)
}
<commit_msg>all: start development cycle for ht 3.7<commit_after>// Copyright 2014 Volker Dobler.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"flag"
	"fmt"
)

var cmdVersion = &Command{
	RunArgs:     runVersion,
	Usage:       "version",
	Description: "print version information",
	Flag:        flag.NewFlagSet("version", flag.ContinueOnError),
	Help: `
Version prints version information about ht.
	`,
}

var (
	version = "3.7.0-beta"
)

func runVersion(cmd *Command, _ []string) {
	fmt.Printf("ht version %s\n", version)
}
<|endoftext|>


<commit_before><commit_msg>api: add RouteReasonNotAllowedByListeners<commit_after><|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/ponzu-cms/ponzu/system/admin"
	"github.com/ponzu-cms/ponzu/system/api"
	"github.com/ponzu-cms/ponzu/system/api/analytics"
	"github.com/ponzu-cms/ponzu/system/db"
	"github.com/ponzu-cms/ponzu/system/tls"

	_ "github.com/ponzu-cms/ponzu/content"
)

var (
	usage     = usageHeader + usageNew + usageGenerate + usageBuild + usageRun
	port      int
	httpsport int
	https     bool
	devhttps  bool

	// for ponzu internal / core development
	dev   bool
	fork  string
	gocmd string
)

func main() {
	flag.Usage = func() {
		fmt.Println(usage)
	}

	flag.IntVar(&port, "port", 8080, "port for ponzu to bind its HTTP listener")
	flag.IntVar(&httpsport, "httpsport", 443, "port for ponzu to bind its HTTPS listener")
	flag.BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
	flag.BoolVar(&devhttps, "devhttps", false, "[dev environment] enable automatic TLS/SSL certificate management")
	flag.BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
	flag.StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
	flag.StringVar(&gocmd, "gocmd", "go", "custom go command if using beta or new release of Go")
	flag.Parse()

	args := flag.Args()

	if len(args) < 1 {
		fmt.Println(usage)
		os.Exit(0)
	}

	switch args[0] {
	case "help", "h":
		if len(args) < 2 {
			fmt.Println(usageHelp)
			fmt.Println(usage)
			os.Exit(0)
		}

		switch args[1] {
		case "new":
			fmt.Println(usageNew)
			os.Exit(0)

		case "generate", "gen", "g":
			fmt.Println(usageGenerate)
			os.Exit(0)

		case "build":
			fmt.Println(usageBuild)
			os.Exit(0)

		case "run":
			fmt.Println(usageRun)
			os.Exit(0)
		}

	case "new":
		if len(args) < 2 {
			fmt.Println(usage)
			os.Exit(0)
		}

		err := newProjectInDir(args[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "generate", "gen", "g":
		if len(args) < 2 {
			flag.PrintDefaults()
			os.Exit(0)
		}

		err := generateContentType(args[1:])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "build":
		err := buildPonzuServer(args)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "run":
		fmt.Println("Running..")
		var addTLS string
		if https {
			addTLS = "--https"
		} else {
			addTLS = "--https=false"
		}

		if devhttps {
			addTLS = "--devhttps"
		}

		var services string
		if len(args) > 1 {
			services = args[1]
		} else {
			services = "admin,api"
		}

		fmt.Println("services:", services)

		serve := exec.Command("./ponzu-server",
			fmt.Sprintf("--port=%d", port),
			fmt.Sprintf("--httpsport=%d", httpsport),
			addTLS,
			"serve",
			services,
		)
		serve.Stderr = os.Stderr
		serve.Stdout = os.Stdout

		err := serve.Start()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		err = serve.Wait()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Println("serve command executed.")

	case "serve", "s":
		db.Init()
		defer db.Close()
		fmt.Println("called db.Init()")

		analytics.Init()
		defer analytics.Close()
		fmt.Println("called analytics.Init()")

		if len(args) > 1 {
			services := strings.Split(args[1], ",")
			fmt.Println("configured to start services:", services)

			for i := range services {
				if services[i] == "api" {
					api.Run()
					fmt.Println("called api.Run()")

				} else if services[i] == "admin" {
					admin.Run()
					fmt.Println("called admin.Run()")

				} else {
					fmt.Println("To execute 'ponzu serve', you must specify which service to run.")
					fmt.Println("$ ponzu --help")
					os.Exit(1)
				}
			}
		}

		// save the https port the system is listening on
		err := db.PutConfig("https_port", fmt.Sprintf("%d", httpsport))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.", err)
		}
		fmt.Println("called db.PutConfig('https_port')")

		// cannot run production HTTPS and development HTTPS together
		if devhttps {
			fmt.Println("Enabling self-signed HTTPS... [DEV]")

			go tls.EnableDev()
			fmt.Println("Server listening on https://localhost:10443 for requests... [DEV]")
			fmt.Println("----")
			fmt.Println("If your browser rejects HTTPS requests, try allowing insecure connections on localhost.")
			fmt.Println("on Chrome, visit chrome://flags/#allow-insecure-localhost")

		} else if https {
			fmt.Println("Enabling HTTPS...")

			go tls.Enable()
			fmt.Printf("Server listening on :%s for HTTPS requests...\n", db.ConfigCache("https_port").(string))
		}

		// save the https port the system is listening on so internal system can make
		// HTTP api calls while in dev or production w/o adding more cli flags
		err = db.PutConfig("http_port", fmt.Sprintf("%d", port))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.", err)
		}
		fmt.Println("called db.PutConfig('http_port')")

		log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
		fmt.Println("called http.ListenAndServe()")

	case "":
		fmt.Println(usage)
		fmt.Println(usageHelp)

	default:
		fmt.Println(usage)
		fmt.Println(usageHelp)
	}
}
<commit_msg>adding generator option to select what to generate<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"
	"os"
	"os/exec"
	"strings"

	"github.com/ponzu-cms/ponzu/system/admin"
	"github.com/ponzu-cms/ponzu/system/api"
	"github.com/ponzu-cms/ponzu/system/api/analytics"
	"github.com/ponzu-cms/ponzu/system/db"
	"github.com/ponzu-cms/ponzu/system/tls"

	_ "github.com/ponzu-cms/ponzu/content"
)

var (
	usage     = usageHeader + usageNew + usageGenerate + usageBuild + usageRun
	port      int
	httpsport int
	https     bool
	devhttps  bool

	// for ponzu internal / core development
	dev   bool
	fork  string
	gocmd string
)

func main() {
	flag.Usage = func() {
		fmt.Println(usage)
	}

	flag.IntVar(&port, "port", 8080, "port for ponzu to bind its HTTP listener")
	flag.IntVar(&httpsport, "httpsport", 443, "port for ponzu to bind its HTTPS listener")
	flag.BoolVar(&https, "https", false, "enable automatic TLS/SSL certificate management")
	flag.BoolVar(&devhttps, "devhttps", false, "[dev environment] enable automatic TLS/SSL certificate management")
	flag.BoolVar(&dev, "dev", false, "modify environment for Ponzu core development")
	flag.StringVar(&fork, "fork", "", "modify repo source for Ponzu core development")
	flag.StringVar(&gocmd, "gocmd", "go", "custom go command if using beta or new release of Go")
	flag.Parse()

	args := flag.Args()

	if len(args) < 1 {
		fmt.Println(usage)
		os.Exit(0)
	}

	switch args[0] {
	case "help", "h":
		if len(args) < 2 {
			fmt.Println(usageHelp)
			fmt.Println(usage)
			os.Exit(0)
		}

		switch args[1] {
		case "new":
			fmt.Println(usageNew)
			os.Exit(0)

		case "generate", "gen", "g":
			fmt.Println(usageGenerate)
			os.Exit(0)

		case "build":
			fmt.Println(usageBuild)
			os.Exit(0)

		case "run":
			fmt.Println(usageRun)
			os.Exit(0)
		}

	case "new":
		if len(args) < 2 {
			fmt.Println(usageNew)
			os.Exit(0)
		}

		err := newProjectInDir(args[1])
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "generate", "gen", "g":
		if len(args) < 3 {
			fmt.Println(usageGenerate)
			os.Exit(0)
		}

		// check what we are asked to generate
		switch args[2] {
		case "content", "c":
			err := generateContentType(args[2:])
			if err != nil {
				fmt.Println(err)
				os.Exit(1)
			}
		}

	case "build":
		err := buildPonzuServer(args)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

	case "run":
		fmt.Println("Running..")
		var addTLS string
		if https {
			addTLS = "--https"
		} else {
			addTLS = "--https=false"
		}

		if devhttps {
			addTLS = "--devhttps"
		}

		var services string
		if len(args) > 1 {
			services = args[1]
		} else {
			services = "admin,api"
		}

		fmt.Println("services:", services)

		serve := exec.Command("./ponzu-server",
			fmt.Sprintf("--port=%d", port),
			fmt.Sprintf("--httpsport=%d", httpsport),
			addTLS,
			"serve",
			services,
		)
		serve.Stderr = os.Stderr
		serve.Stdout = os.Stdout

		err := serve.Start()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		err = serve.Wait()
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		fmt.Println("serve command executed.")

	case "serve", "s":
		db.Init()
		defer db.Close()
		fmt.Println("called db.Init()")

		analytics.Init()
		defer analytics.Close()
		fmt.Println("called analytics.Init()")

		if len(args) > 1 {
			services := strings.Split(args[1], ",")
			fmt.Println("configured to start services:", services)

			for i := range services {
				if services[i] == "api" {
					api.Run()
					fmt.Println("called api.Run()")

				} else if services[i] == "admin" {
					admin.Run()
					fmt.Println("called admin.Run()")

				} else {
					fmt.Println("To execute 'ponzu serve', you must specify which service to run.")
					fmt.Println("$ ponzu --help")
					os.Exit(1)
				}
			}
		}

		// save the https port the system is listening on
		err := db.PutConfig("https_port", fmt.Sprintf("%d", httpsport))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.", err)
		}
		fmt.Println("called db.PutConfig('https_port')")

		// cannot run production HTTPS and development HTTPS together
		if devhttps {
			fmt.Println("Enabling self-signed HTTPS... [DEV]")

			go tls.EnableDev()
			fmt.Println("Server listening on https://localhost:10443 for requests... [DEV]")
			fmt.Println("----")
			fmt.Println("If your browser rejects HTTPS requests, try allowing insecure connections on localhost.")
			fmt.Println("on Chrome, visit chrome://flags/#allow-insecure-localhost")

		} else if https {
			fmt.Println("Enabling HTTPS...")

			go tls.Enable()
			fmt.Printf("Server listening on :%s for HTTPS requests...\n", db.ConfigCache("https_port").(string))
		}

		// save the https port the system is listening on so internal system can make
		// HTTP api calls while in dev or production w/o adding more cli flags
		err = db.PutConfig("http_port", fmt.Sprintf("%d", port))
		if err != nil {
			log.Fatalln("System failed to save config. Please try to run again.", err)
		}
		fmt.Println("called db.PutConfig('http_port')")

		log.Fatalln(http.ListenAndServe(fmt.Sprintf(":%d", port), nil))
		fmt.Println("called http.ListenAndServe()")

	case "":
		fmt.Println(usage)
		fmt.Println(usageHelp)

	default:
		fmt.Println(usage)
		fmt.Println(usageHelp)
	}
}
<|endoftext|>


<commit_before>package main

import "os"
import "io"
import "bufio"
import "bytes"
import "runtime"
import "crypto/aes"
import "crypto/rand"
import "crypto/cipher"

// Number of chained blocks to generate with AES before re-seeding the key
// and CBC initialization vectors.
const NUM_CHAINED_BLOCKS = 1 << 20

func RandGen(comm chan io.Reader, quit chan bool) {
	data := make([]byte, aes.BlockSize*NUM_CHAINED_BLOCKS)
	for {
		// Generate a random new encryption key
		key := make([]byte, aes.BlockSize)
		if num, _ := io.ReadFull(rand.Reader, key); num != aes.BlockSize {
			panic("Could not seed a random cryptographic key.")
		}

		// Create the encryption cipher
		aesCipher, err := aes.NewCipher(key)
		if err != nil {
			panic("Could not create a new AES cipher.")
		}

		// Generate a random initialization vector for cipher block chaining
		vector := make([]byte, aes.BlockSize)
		if num, _ := io.ReadFull(rand.Reader, vector); num != aes.BlockSize {
			panic("Could not seed a random initialization vector.")
		}

		// Use CBC to generate pseudo-random data
		cbcCipher := cipher.NewCBCEncrypter(aesCipher, vector)
		cbcCipher.CryptBlocks(data, data)
		buf := bytes.NewBuffer(data)

		// Send data to main routine
		select {
		case comm <- buf:
			continue
		case <-quit:
			break
		}
	}
}

func main() {
	comm := make(chan io.Reader)
	quit := make(chan bool)

	// Spin off a great number of workers
	runtime.GOMAXPROCS(runtime.NumCPU())
	for i := 0; i < runtime.NumCPU(); i++ {
		go RandGen(comm, quit)
	}

	// Continually read data from workers
	dstBuf := bufio.NewWriter(os.Stdout)
	for {
		srcBuf := <-comm
		if _, err := io.Copy(dstBuf, srcBuf); err != nil {
			close(quit)
			break
		}
	}
}
<commit_msg>Added a command-line parser to gorandom.<commit_after>package main

import "os"
import "io"
import "path"
import "flag"
import "bufio"
import "bytes"
import "runtime"
import "crypto/aes"
import "crypto/rand"
import "crypto/cipher"
import "fmt"

const DESCRIPTION = `
Another pseudo-random number generator (PRNG). This was designed to be a faster
alternative to the built-in /dev/urandom device built into most Linux kernels.
This PRNG is based on the Advanced Encryption Standard (AES) cipher operating
in cipher-block chaining (CBC) mode. This implementation is capable of spawning
multiple rountines that generate pseudo-random data in parallel.

By default, this generator will spawn off a number of routines equal to the
number of logical cores in an attempt to maximize the output. If the output
is not being consumed as fast as data is being generated, routines can block.
As a result, CPU utilization may go down, allowing other processes to run.
`

var NumJobs, NumBlocks int

func RandGen(comm chan io.Reader, quit chan bool) {
	data := make([]byte, aes.BlockSize*NumBlocks)
	for {
		// Generate a random new encryption key
		key := make([]byte, aes.BlockSize)
		if num, _ := io.ReadFull(rand.Reader, key); num != aes.BlockSize {
			panic("Could not seed a random cryptographic key.")
		}

		// Create the encryption cipher
		aesCipher, err := aes.NewCipher(key)
		if err != nil {
			panic("Could not create a new AES cipher.")
		}

		// Generate a random initialization vector for cipher block chaining
		vector := make([]byte, aes.BlockSize)
		if num, _ := io.ReadFull(rand.Reader, vector); num != aes.BlockSize {
			panic("Could not seed a random initialization vector.")
		}

		// Use CBC to generate pseudo-random data
		cbcCipher := cipher.NewCBCEncrypter(aesCipher, vector)
		cbcCipher.CryptBlocks(data, data)
		buf := bytes.NewBuffer(data)

		// Send data to main routine
		select {
		case comm <- buf:
			continue
		case <-quit:
			break
		}
	}
}

func main() {
	comm := make(chan io.Reader)
	quit := make(chan bool)

	// Command-line parser
	fs := flag.NewFlagSet("", flag.ExitOnError)
	fs.Usage = func() {
		cmd := path.Base(os.Args[0])
		fmt.Fprintf(os.Stderr, "Usage: %s [OPTION]...\n", cmd)
		fmt.Fprintln(os.Stderr, DESCRIPTION)
		fs.PrintDefaults()
		fmt.Fprintf(os.Stderr, "\n")
		fmt.Fprintf(os.Stderr, "Report '%s' bugs to joetsai@digital-static.net\n", cmd)
	}
	fs.IntVar(&NumJobs, "jobs", runtime.NumCPU(), "Number of Go-routines jobs to spin off.")
	fs.IntVar(&NumBlocks, "blocks", (1 << 16), "Each routine will generate this many pseudo-random blocks before re-seeding.")
	fs.Parse(os.Args[1:])
	if NumJobs <= 0 {
		fmt.Fprintln(os.Stderr, "Number of jobs must be positive.")
	}
	if NumBlocks <= 0 {
		fmt.Fprintln(os.Stderr, "Number of blocks to generate must be positive.")
	}

	// Spin off a great number of workers
	runtime.GOMAXPROCS(NumJobs)
	for i := 0; i < NumJobs; i++ {
		go RandGen(comm, quit)
	}

	// Continually read data from workers
	dstBuf := bufio.NewWriter(os.Stdout)
	for {
		srcBuf := <-comm
		if _, err := io.Copy(dstBuf, srcBuf); err != nil {
			close(quit)
			break
		}
	}
}
<|endoftext|>