<commit_before>package command

import (
	"fmt"
	"strings"

	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/cli"
)

// StateMvCommand is a Command implementation that shows a single resource.
type StateMvCommand struct {
	Meta
	StateMeta
}

func (c *StateMvCommand) Run(args []string) int {
	args = c.Meta.process(args, true)

	// We create two metas to track the two states
	var meta1, meta2 Meta
	cmdFlags := c.Meta.flagSet("state mv")
	cmdFlags.StringVar(&meta1.stateOutPath, "backup", "", "backup")
	cmdFlags.StringVar(&meta1.statePath, "state", DefaultStateFilename, "path")
	cmdFlags.StringVar(&meta2.stateOutPath, "backup-out", "", "backup")
	cmdFlags.StringVar(&meta2.statePath, "state-out", "", "path")
	if err := cmdFlags.Parse(args); err != nil {
		return cli.RunResultHelp
	}
	args = cmdFlags.Args()
	if len(args) != 2 {
		c.Ui.Error("Exactly two arguments expected.\n")
		return cli.RunResultHelp
	}

	// Copy the `-state` flag for output if we weren't given a custom one
	if meta2.statePath == "" {
		meta2.statePath = meta1.statePath
	}

	// Read the from state
	stateFrom, err := c.StateMeta.State(&meta1)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
		return cli.RunResultHelp
	}

	stateFromReal := stateFrom.State()
	if stateFromReal == nil {
		c.Ui.Error(fmt.Sprintf(errStateNotFound))
		return 1
	}

	// Read the destination state
	stateTo := stateFrom
	stateToReal := stateFromReal
	if meta2.statePath != meta1.statePath {
		stateTo, err = c.StateMeta.State(&meta2)
		if err != nil {
			c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
			return cli.RunResultHelp
		}

		stateToReal = stateTo.State()
		if stateToReal == nil {
			stateToReal = terraform.NewState()
		}
	}

	// Filter what we're moving
	filter := &terraform.StateFilter{State: stateFromReal}
	results, err := filter.Filter(args[0])
	if err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMv, err))
		return cli.RunResultHelp
	}
	if len(results) == 0 {
		c.Ui.Output(fmt.Sprintf("Item to move doesn't exist: %s", args[0]))
		return 1
	}

	// Get the item to add to the state
	add := c.addableResult(results)

	// Do the actual move
	if err := stateFromReal.Remove(args[0]); err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMv, err))
		return 1
	}

	if err := stateToReal.Add(args[0], args[1], add); err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMv, err))
		return 1
	}

	// Write the new state
	if err := stateTo.WriteState(stateToReal); err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMvPersist, err))
		return 1
	}

	if err := stateTo.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMvPersist, err))
		return 1
	}

	// Write the old state if it is different
	if stateTo != stateFrom {
		if err := stateFrom.WriteState(stateFromReal); err != nil {
			c.Ui.Error(fmt.Sprintf(errStateMvPersist, err))
			return 1
		}

		if err := stateFrom.PersistState(); err != nil {
			c.Ui.Error(fmt.Sprintf(errStateMvPersist, err))
			return 1
		}
	}

	c.Ui.Output(fmt.Sprintf(
		"Moved %s to %s", args[0], args[1]))
	return 0
}

// addableResult takes the result from a filter operation and returns what to
// call State.Add with. The reason we do this is beacuse in the module case
// we must add the list of all modules returned versus just the root module.
func (c *StateMvCommand) addableResult(results []*terraform.StateFilterResult) interface{} {
	switch v := results[0].Value.(type) {
	case *terraform.ModuleState:
		// If a module state then we should add the full list of modules
		result := []*terraform.ModuleState{v}
		if len(results) > 1 {
			for _, r := range results[1:] {
				if ms, ok := r.Value.(*terraform.ModuleState); ok {
					result = append(result, ms)
				}
			}
		}

		return result

	case *terraform.ResourceState:
		// If a module state then we should add the full list of modules
		result := []*terraform.ResourceState{v}
		if len(results) > 1 {
			for _, r := range results[1:] {
				rs, ok := r.Value.(*terraform.ResourceState)
				if !ok {
					continue
				}

				if rs.Type == v.Type {
					result = append(result, rs)
				}
			}
		}

		// If we only have one item, add it directly
		if len(result) == 1 {
			return result[0]
		}

		return result

	default:
		// By default just add the first result
		return v
	}
}

func (c *StateMvCommand) Help() string {
	helpText := `
Usage: terraform state mv [options] ADDRESS ADDRESS

  Move an item in the state to another location or to a completely different
  state file.

  This command is useful for module refactors (moving items into a module),
  configuration refactors (moving items to a completely different or new
  state file), or generally renaming of resources.

  This command creates a timestamped backup of the state on every invocation.
  This can't be disabled. Due to the destructive nature of this command,
  the backup is ensured by Terraform for safety reasons.

  If you're moving from one state file to a different state file, a backup
  will be created for each state file.

Options:

  -backup=PATH        Path where Terraform should write the backup for the original
                      state. This can't be disabled. If not set, Terraform
                      will write it to the same path as the statefile with
                      a backup extension.

  -backup-out=PATH    Path where Terraform should write the backup for the destination
                      state. This can't be disabled. If not set, Terraform
                      will write it to the same path as the destination state
                      file with a backup extension. This only needs
                      to be specified if -state-out is set to a different path
                      than -state.

  -state=PATH         Path to a Terraform state file to use to look
                      up Terraform-managed resources. By default it will
                      use the state "terraform.tfstate" if it exists.

  -state-out=PATH     Path to the destination state file to move the item
                      to. This defaults to the same statefile. This will
                      overwrite the destination state file.

`
	return strings.TrimSpace(helpText)
}

func (c *StateMvCommand) Synopsis() string {
	return "Move an item in the state"
}

const errStateMv = `Error moving state: %[1]s

Please ensure your addresses and state paths are valid. No
state was persisted. Your existing states are untouched.`

const errStateMvPersist = `Error saving the state: %s

The state wasn't saved properly. If the error happening after a partial
write occurred, a backup file will have been created. Otherwise, the state
is in the same state it was when the operation started.`
<commit_msg>command: correct outdated comment<commit_after>package command

import (
	"fmt"
	"strings"

	"github.com/hashicorp/terraform/terraform"
	"github.com/mitchellh/cli"
)

// StateMvCommand is a Command implementation that shows a single resource.
type StateMvCommand struct {
	Meta
	StateMeta
}

func (c *StateMvCommand) Run(args []string) int {
	args = c.Meta.process(args, true)

	// We create two metas to track the two states
	var meta1, meta2 Meta
	cmdFlags := c.Meta.flagSet("state mv")
	cmdFlags.StringVar(&meta1.stateOutPath, "backup", "", "backup")
	cmdFlags.StringVar(&meta1.statePath, "state", DefaultStateFilename, "path")
	cmdFlags.StringVar(&meta2.stateOutPath, "backup-out", "", "backup")
	cmdFlags.StringVar(&meta2.statePath, "state-out", "", "path")
	if err := cmdFlags.Parse(args); err != nil {
		return cli.RunResultHelp
	}
	args = cmdFlags.Args()
	if len(args) != 2 {
		c.Ui.Error("Exactly two arguments expected.\n")
		return cli.RunResultHelp
	}

	// Copy the `-state` flag for output if we weren't given a custom one
	if meta2.statePath == "" {
		meta2.statePath = meta1.statePath
	}

	// Read the from state
	stateFrom, err := c.StateMeta.State(&meta1)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
		return cli.RunResultHelp
	}

	stateFromReal := stateFrom.State()
	if stateFromReal == nil {
		c.Ui.Error(fmt.Sprintf(errStateNotFound))
		return 1
	}

	// Read the destination state
	stateTo := stateFrom
	stateToReal := stateFromReal
	if meta2.statePath != meta1.statePath {
		stateTo, err = c.StateMeta.State(&meta2)
		if err != nil {
			c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
			return cli.RunResultHelp
		}

		stateToReal = stateTo.State()
		if stateToReal == nil {
			stateToReal = terraform.NewState()
		}
	}

	// Filter what we're moving
	filter := &terraform.StateFilter{State: stateFromReal}
	results, err := filter.Filter(args[0])
	if err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMv, err))
		return cli.RunResultHelp
	}
	if len(results) == 0 {
		c.Ui.Output(fmt.Sprintf("Item to move doesn't exist: %s", args[0]))
		return 1
	}

	// Get the item to add to the state
	add := c.addableResult(results)

	// Do the actual move
	if err := stateFromReal.Remove(args[0]); err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMv, err))
		return 1
	}

	if err := stateToReal.Add(args[0], args[1], add); err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMv, err))
		return 1
	}

	// Write the new state
	if err := stateTo.WriteState(stateToReal); err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMvPersist, err))
		return 1
	}

	if err := stateTo.PersistState(); err != nil {
		c.Ui.Error(fmt.Sprintf(errStateMvPersist, err))
		return 1
	}

	// Write the old state if it is different
	if stateTo != stateFrom {
		if err := stateFrom.WriteState(stateFromReal); err != nil {
			c.Ui.Error(fmt.Sprintf(errStateMvPersist, err))
			return 1
		}

		if err := stateFrom.PersistState(); err != nil {
			c.Ui.Error(fmt.Sprintf(errStateMvPersist, err))
			return 1
		}
	}

	c.Ui.Output(fmt.Sprintf(
		"Moved %s to %s", args[0], args[1]))
	return 0
}

// addableResult takes the result from a filter operation and returns what to
// call State.Add with. The reason we do this is beacuse in the module case
// we must add the list of all modules returned versus just the root module.
func (c *StateMvCommand) addableResult(results []*terraform.StateFilterResult) interface{} {
	switch v := results[0].Value.(type) {
	case *terraform.ModuleState:
		// If a module state then we should add the full list of modules
		result := []*terraform.ModuleState{v}
		if len(results) > 1 {
			for _, r := range results[1:] {
				if ms, ok := r.Value.(*terraform.ModuleState); ok {
					result = append(result, ms)
				}
			}
		}

		return result

	case *terraform.ResourceState:
		// If a resource state with more than one result, it has a multi-count
		// and we need to add all of them.
		result := []*terraform.ResourceState{v}
		if len(results) > 1 {
			for _, r := range results[1:] {
				rs, ok := r.Value.(*terraform.ResourceState)
				if !ok {
					continue
				}

				if rs.Type == v.Type {
					result = append(result, rs)
				}
			}
		}

		// If we only have one item, add it directly
		if len(result) == 1 {
			return result[0]
		}

		return result

	default:
		// By default just add the first result
		return v
	}
}

func (c *StateMvCommand) Help() string {
	helpText := `
Usage: terraform state mv [options] ADDRESS ADDRESS

  Move an item in the state to another location or to a completely different
  state file.

  This command is useful for module refactors (moving items into a module),
  configuration refactors (moving items to a completely different or new
  state file), or generally renaming of resources.

  This command creates a timestamped backup of the state on every invocation.
  This can't be disabled. Due to the destructive nature of this command,
  the backup is ensured by Terraform for safety reasons.

  If you're moving from one state file to a different state file, a backup
  will be created for each state file.

Options:

  -backup=PATH        Path where Terraform should write the backup for the original
                      state. This can't be disabled. If not set, Terraform
                      will write it to the same path as the statefile with
                      a backup extension.

  -backup-out=PATH    Path where Terraform should write the backup for the destination
                      state. This can't be disabled. If not set, Terraform
                      will write it to the same path as the destination state
                      file with a backup extension. This only needs
                      to be specified if -state-out is set to a different path
                      than -state.

  -state=PATH         Path to a Terraform state file to use to look
                      up Terraform-managed resources. By default it will
                      use the state "terraform.tfstate" if it exists.

  -state-out=PATH     Path to the destination state file to move the item
                      to. This defaults to the same statefile. This will
                      overwrite the destination state file.

`
	return strings.TrimSpace(helpText)
}

func (c *StateMvCommand) Synopsis() string {
	return "Move an item in the state"
}

const errStateMv = `Error moving state: %[1]s

Please ensure your addresses and state paths are valid. No
state was persisted. Your existing states are untouched.`

const errStateMvPersist = `Error saving the state: %s

The state wasn't saved properly. If the error happening after a partial
write occurred, a backup file will have been created. Otherwise, the state
is in the same state it was when the operation started.`
<|endoftext|>


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

package commands

import (
	"os"

	"github.com/GoogleContainerTools/kpt/internal/cmdfetchk8sschema"
	"github.com/GoogleContainerTools/kpt/internal/docs/generated/livedocs"
	"github.com/spf13/cobra"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/kubectl/pkg/cmd/util"
	"sigs.k8s.io/cli-utils/cmd/apply"
	"sigs.k8s.io/cli-utils/cmd/destroy"
	"sigs.k8s.io/cli-utils/cmd/diff"
	"sigs.k8s.io/cli-utils/cmd/initcmd"
	"sigs.k8s.io/cli-utils/cmd/preview"
)

func GetLiveCommand(name string, f util.Factory) *cobra.Command {
	liveCmd := &cobra.Command{
		Use:   "live",
		Short: livedocs.LiveShort,
		Long:  livedocs.LiveShort + "\n" + livedocs.LiveLong,
		RunE: func(cmd *cobra.Command, args []string) error {
			h, err := cmd.Flags().GetBool("help")
			if err != nil {
				return err
			}
			if h {
				return cmd.Help()
			}
			return cmd.Usage()
		},
	}

	ioStreams := genericclioptions.IOStreams{
		In:     os.Stdin,
		Out:    os.Stdout,
		ErrOut: os.Stderr,
	}

	initCmd := initcmd.NewCmdInit(ioStreams)
	initCmd.Short = livedocs.InitShort
	initCmd.Long = livedocs.InitShort + "\n" + livedocs.InitLong
	initCmd.Example = livedocs.InitExamples

	applyCmd := apply.ApplyCommand(f, ioStreams)
	_ = applyCmd.Flags().MarkHidden("no-prune")
	applyCmd.Short = livedocs.ApplyShort
	applyCmd.Long = livedocs.ApplyShort + "\n" + livedocs.ApplyLong
	applyCmd.Example = livedocs.ApplyExamples

	previewCmd := preview.GetPreviewRunner(f, ioStreams).Command
	previewCmd.Short = livedocs.PreviewShort
	previewCmd.Long = livedocs.PreviewShort + "\n" + livedocs.PreviewLong
	previewCmd.Example = livedocs.PreviewExamples

	diffCmd := diff.NewCmdDiff(f, ioStreams)
	diffCmd.Short = livedocs.DiffShort
	diffCmd.Long = livedocs.DiffShort + "\n" + livedocs.DiffLong
	diffCmd.Example = livedocs.DiffExamples

	destroyCmd := destroy.GetDestroyRunner(f, ioStreams).Command
	destroyCmd.Short = livedocs.DestroyShort
	destroyCmd.Long = livedocs.DestroyShort + "\n" + livedocs.DestroyLong
	destroyCmd.Example = livedocs.DestroyExamples

	fetchOpenAPICmd := cmdfetchk8sschema.NewCommand(name, f, ioStreams)

	liveCmd.AddCommand(initCmd, applyCmd, previewCmd, diffCmd, destroyCmd,
		fetchOpenAPICmd)

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

package commands

import (
	"os"

	"github.com/GoogleContainerTools/kpt/internal/cmdfetchk8sschema"
	"github.com/GoogleContainerTools/kpt/internal/docs/generated/livedocs"
	"github.com/spf13/cobra"
	"k8s.io/cli-runtime/pkg/genericclioptions"
	"k8s.io/kubectl/pkg/cmd/util"
	"sigs.k8s.io/cli-utils/cmd/apply"
	"sigs.k8s.io/cli-utils/cmd/destroy"
	"sigs.k8s.io/cli-utils/cmd/diff"
	"sigs.k8s.io/cli-utils/cmd/initcmd"
	"sigs.k8s.io/cli-utils/cmd/preview"
	"sigs.k8s.io/cli-utils/cmd/status"
)

func GetLiveCommand(name string, f util.Factory) *cobra.Command {
	liveCmd := &cobra.Command{
		Use:   "live",
		Short: livedocs.LiveShort,
		Long:  livedocs.LiveShort + "\n" + livedocs.LiveLong,
		RunE: func(cmd *cobra.Command, args []string) error {
			h, err := cmd.Flags().GetBool("help")
			if err != nil {
				return err
			}
			if h {
				return cmd.Help()
			}
			return cmd.Usage()
		},
	}

	ioStreams := genericclioptions.IOStreams{
		In:     os.Stdin,
		Out:    os.Stdout,
		ErrOut: os.Stderr,
	}

	initCmd := initcmd.NewCmdInit(ioStreams)
	initCmd.Short = livedocs.InitShort
	initCmd.Long = livedocs.InitShort + "\n" + livedocs.InitLong
	initCmd.Example = livedocs.InitExamples

	applyCmd := apply.ApplyCommand(f, ioStreams)
	_ = applyCmd.Flags().MarkHidden("no-prune")
	applyCmd.Short = livedocs.ApplyShort
	applyCmd.Long = livedocs.ApplyShort + "\n" + livedocs.ApplyLong
	applyCmd.Example = livedocs.ApplyExamples

	previewCmd := preview.GetPreviewRunner(f, ioStreams).Command
	previewCmd.Short = livedocs.PreviewShort
	previewCmd.Long = livedocs.PreviewShort + "\n" + livedocs.PreviewLong
	previewCmd.Example = livedocs.PreviewExamples

	diffCmd := diff.NewCmdDiff(f, ioStreams)
	diffCmd.Short = livedocs.DiffShort
	diffCmd.Long = livedocs.DiffShort + "\n" + livedocs.DiffLong
	diffCmd.Example = livedocs.DiffExamples

	destroyCmd := destroy.GetDestroyRunner(f, ioStreams).Command
	destroyCmd.Short = livedocs.DestroyShort
	destroyCmd.Long = livedocs.DestroyShort + "\n" + livedocs.DestroyLong
	destroyCmd.Example = livedocs.DestroyExamples

	statusCmd := status.StatusCommand(f)
	statusCmd.Short = livedocs.StatusShort
	statusCmd.Long = livedocs.StatusLong
	statusCmd.Example = livedocs.StatusExamples

	fetchOpenAPICmd := cmdfetchk8sschema.NewCommand(name, f, ioStreams)

	liveCmd.AddCommand(initCmd, applyCmd, previewCmd, diffCmd, destroyCmd,
		fetchOpenAPICmd, statusCmd)

	return liveCmd
}
<|endoftext|>


<commit_before>// Copyright © 2014 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package commands

import (
	"fmt"
	"os"

	"github.com/spf13/viper"
	"labix.org/v2/mgo"
	"labix.org/v2/mgo/bson"
)

var mongodbSession *mgo.Session

func init() {
	CreateUniqueIndexes()
}

func DBSession() *mgo.Session {
	connectString := viper.GetString("dbhost") + ":" + viper.GetString("dbport")
	var err error

	if mongodbSession == nil {
		mongodbSession, err = mgo.Dial(connectString)
		if err != nil {
			fmt.Println(err)
			os.Exit(-1)
		}

		if !(viper.GetString("dbusername") == "" && viper.GetString("dbpassword") == "") {
			err = mongodbSession.DB(viper.GetString("dbname")).Login(viper.GetString("dbusername"), viper.GetString("dbpassword"))
			if err != nil {
				fmt.Println(err)
				os.Exit(-1)
			}
		}
	}

	if mongodbSession == nil {
		fmt.Println("unable to connect to MongoDB at", connectString)
		os.Exit(-1)
	}
	return mongodbSession
}

func Items() *mgo.Collection {
	return DB().C("items")
}

func Channels() *mgo.Collection {
	return DB().C("channels")
}

func DB() *mgo.Database {
	return DBSession().DB(viper.GetString("dbname"))
}

func CreateUniqueIndexes() {
	idx := mgo.Index{
		Key:        []string{"key"},
		Unique:     true,
		DropDups:   true,
		Background: true,
		Sparse:     true,
	}

	if err := Items().EnsureIndex(idx); err != nil {
		fmt.Println(err)
	}

	if err := Channels().EnsureIndex(idx); err != nil {
		fmt.Println(err)
	}

	ftidx := mgo.Index{
		Key:        []string{"$text:fullcontent"},
		Unique:     false,
		DropDups:   false,
		Background: true,
		Sparse:     true,
	}

	if err := Items().EnsureIndex(ftidx); err != nil {
		fmt.Println(err)
	}
}

func AllChannels() []Chnl {
	var channels []Chnl
	results2 := Channels().Find(bson.M{}).Sort("-lastbuilddate")
	results2.All(&channels)
	return channels
}
<commit_msg>Move mgo to gopkg.in<commit_after>// Copyright © 2014 Steve Francia <spf@spf13.com>.
//
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package commands

import (
	"fmt"
	"os"

	"github.com/spf13/viper"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

var mongodbSession *mgo.Session

func init() {
	CreateUniqueIndexes()
}

func DBSession() *mgo.Session {
	connectString := viper.GetString("dbhost") + ":" + viper.GetString("dbport")
	var err error

	if mongodbSession == nil {
		mongodbSession, err = mgo.Dial(connectString)
		if err != nil {
			fmt.Println(err)
			os.Exit(-1)
		}

		if !(viper.GetString("dbusername") == "" && viper.GetString("dbpassword") == "") {
			err = mongodbSession.DB(viper.GetString("dbname")).Login(viper.GetString("dbusername"), viper.GetString("dbpassword"))
			if err != nil {
				fmt.Println(err)
				os.Exit(-1)
			}
		}
	}

	if mongodbSession == nil {
		fmt.Println("unable to connect to MongoDB at", connectString)
		os.Exit(-1)
	}
	return mongodbSession
}

func Items() *mgo.Collection {
	return DB().C("items")
}

func Channels() *mgo.Collection {
	return DB().C("channels")
}

func DB() *mgo.Database {
	return DBSession().DB(viper.GetString("dbname"))
}

func CreateUniqueIndexes() {
	idx := mgo.Index{
		Key:        []string{"key"},
		Unique:     true,
		DropDups:   true,
		Background: true,
		Sparse:     true,
	}

	if err := Items().EnsureIndex(idx); err != nil {
		fmt.Println(err)
	}

	if err := Channels().EnsureIndex(idx); err != nil {
		fmt.Println(err)
	}

	ftidx := mgo.Index{
		Key:        []string{"$text:fullcontent"},
		Unique:     false,
		DropDups:   false,
		Background: true,
		Sparse:     true,
	}

	if err := Items().EnsureIndex(ftidx); err != nil {
		fmt.Println(err)
	}
}

func AllChannels() []Chnl {
	var channels []Chnl
	results2 := Channels().Find(bson.M{}).Sort("-lastbuilddate")
	results2.All(&channels)
	return channels
}
<|endoftext|>


<commit_before>package commands

// Version
const version = "v0.42-alpha"
<commit_msg>version bump<commit_after>package commands

// Version
const version = "v0.50-beta"
<|endoftext|>


<commit_before>package common

import (
	"log"

	"engo.io/ecs"
	"engo.io/engo"
	"engo.io/engo/math"
)

// SpaceComponent keeps track of the position, size, and rotation of entities.
type SpaceComponent struct {
	Position engo.Point
	Width    float32
	Height   float32
	Rotation float32 // angle in degrees for the rotation to apply clockwise.
}

// SetCenter positions the space component according to its center instead of its
// top-left point (this avoids doing the same math each time in your systems)
func (sc *SpaceComponent) SetCenter(p engo.Point) {
	xDelta := sc.Width / 2
	yDelta := sc.Height / 2
	// update position according to point being used as our center
	if sc.Rotation == 0 {
		sc.Position.X = p.X - xDelta
		sc.Position.Y = p.Y - yDelta
		return
	}
	sin, cos := math.Sincos(sc.Rotation * math.Pi / 180)
	xDelta = (sc.Width*cos - sc.Height*sin) / 2
	yDelta = (sc.Height*cos + sc.Width*sin) / 2
	sc.Position.X = p.X - xDelta
	sc.Position.Y = p.Y - yDelta
}

// Center gets the center position of the space component instead of its
// top-left point (this avoids doing the same math each time in your systems)
func (sc *SpaceComponent) Center() engo.Point {
	xDelta := sc.Width / 2
	yDelta := sc.Height / 2
	p := sc.Position
	if sc.Rotation == 0 {
		return engo.Point{X: p.X + xDelta, Y: p.Y + yDelta}
	}
	sin, cos := math.Sincos(sc.Rotation * math.Pi / 180)
	xDelta = (sc.Width*cos - sc.Height*sin) / 2
	yDelta = (sc.Height*cos + sc.Width*sin) / 2
	return engo.Point{X: p.X + xDelta, Y: p.Y + yDelta}
}

// AABB returns the minimum and maximum point for the given SpaceComponent. It hereby takes into account the
// rotation of the Component - it may very well be that the Minimum as given by engo.AABB, is smaller than the Position
// of the object (i.e. when rotated).
//
// This basically returns the "outer rectangle" of the plane defined by the `SpaceComponent`. Since this returns two
// points, a minimum and a maximum, the "rectangle" resulting from this `AABB`, is not rotated in any way. However,
// depending on the rotation of the `SpaceComponent`, this `AABB` may be larger than the original `SpaceComponent`.
func (sc SpaceComponent) AABB() engo.AABB {
	if sc.Rotation == 0 {
		return engo.AABB{
			Min: sc.Position,
			Max: engo.Point{X: sc.Position.X + sc.Width, Y: sc.Position.Y + sc.Height},
		}
	}

	corners := sc.Corners()

	var (
		xMin float32 = math.MaxFloat32
		xMax float32 = -math.MaxFloat32
		yMin float32 = math.MaxFloat32
		yMax float32 = -math.MaxFloat32
	)

	for i := 0; i < 4; i++ {
		if corners[i].X < xMin {
			xMin = corners[i].X
		} else if corners[i].X > xMax {
			xMax = corners[i].X
		}
		if corners[i].Y < yMin {
			yMin = corners[i].Y
		}
		if corners[i].Y > yMax {
			yMax = corners[i].Y
		}
	}

	return engo.AABB{Max: engo.Point{X: xMin, Y: yMin}, Min: engo.Point{X: xMax, Y: yMax}}
}

// Corners returns the location of the four corners of the rectangular plane defined by the `SpaceComponent`, taking
// into account any possible rotation.
func (sc SpaceComponent) Corners() (points [4]engo.Point) {
	points[0].X = sc.Position.X
	points[0].Y = sc.Position.Y

	sin, cos := math.Sincos(sc.Rotation * math.Pi / 180)

	points[1].X = points[0].X + sc.Width*cos
	points[1].Y = points[0].Y + sc.Width*sin

	points[2].X = points[0].X - sc.Height*sin
	points[2].Y = points[0].Y + sc.Height*cos

	points[3].X = points[0].X + sc.Width*cos - sc.Height*sin
	points[3].Y = points[0].Y + sc.Height*cos + sc.Width*sin

	return
}

// Contains indicates whether or not the given point is within the rectangular plane as defined by this `SpaceComponent`.
// If it's on the border, it is considered "not within".
func (sc SpaceComponent) Contains(p engo.Point) bool {
	points := sc.Corners()

	halfArea := (sc.Width * sc.Height) / 2

	for i := 0; i < 4; i++ {
		for j := i + 1; j < 4; j++ {
			if t := triangleArea(points[i], points[j], p); t > halfArea || engo.FloatEqual(t, halfArea) {
				return false
			}
		}
	}

	return true
}

// triangleArea computes the area of the triangle given by the three points
func triangleArea(p1, p2, p3 engo.Point) float32 {
	// Law of cosines states: (note a2 = math.Pow(a, 2))
	// a2 = b2 + c2 - 2bc*cos(alpha)
	// This ends in: alpha = arccos ((-a2 + b2 + c2)/(2bc))
	a := p1.PointDistance(p3)
	b := p1.PointDistance(p2)
	c := p2.PointDistance(p3)
	alpha := math.Acos((-math.Pow(a, 2) + math.Pow(b, 2) + math.Pow(c, 2)) / (2 * b * c))

	// Law of sines state: a / sin(alpha) = c / sin(gamma)
	height := (c / math.Sin(math.Pi/2)) * math.Sin(alpha)

	return (b * height) / 2
}

// CollisionComponent keeps track of the entity's collisions.
//
// Main tells the system to check all collisions against this entity.
//
// Group tells which collision group his entity belongs to.
//
// Extra is the allowed buffer for detecting collisions.
//
// Collides is all the groups this component collides with ORed together
type CollisionComponent struct {
	// if a.Main & (bitwise) b.Group, items can collide
	// if a.Main == 0, it will not loop for other items
	Main, Group CollisionGroup
	Extra       engo.Point
	Collides    CollisionGroup
}

// CollisionMessage is sent whenever a collision is detected by the CollisionSystem.
type CollisionMessage struct {
	Entity collisionEntity
	To     collisionEntity
	Groups CollisionGroup
}

// CollisionGroup is intended to be used in bitwise comparisons
// The user is expected to create a const ( a = 1 << iota \n b \n c etc)
// for the different kinds of collisions they hope to use
type CollisionGroup byte

// Type implements the engo.Message interface
func (CollisionMessage) Type() string { return "CollisionMessage" }

type collisionEntity struct {
	*ecs.BasicEntity
	*CollisionComponent
	*SpaceComponent
}

// CollisionSystem is a system that detects collisions between entities, sends a message if collisions
// are detected, and updates their SpaceComponent so entities cannot pass through Solids.
type CollisionSystem struct {
	// Solids, used to tell which collisions should be treated as solid by bitwise comparison.
	// if a.Main & b.Group & sys.Solids{ Collisions are treated as solid.  }
	Solids CollisionGroup

	entities []collisionEntity
}

// Add adds an entity to the CollisionSystem. To be added, the entity has to have a basic, collision, and space component.
func (c *CollisionSystem) Add(basic *ecs.BasicEntity, collision *CollisionComponent, space *SpaceComponent) {
	c.entities = append(c.entities, collisionEntity{basic, collision, space})
}

// AddByInterface Provides a simple way to add an entity to the system that satisfies Collisionable. Any entity containing, BasicEntity,CollisionComponent, and SpaceComponent anonymously, automatically does this.
func (c *CollisionSystem) AddByInterface(o Collisionable) {
	c.Add(o.GetBasicEntity(), o.GetCollisionComponent(), o.GetSpaceComponent())
}

// Remove removes an entity from the CollisionSystem.
func (c *CollisionSystem) Remove(basic ecs.BasicEntity) {
	delete := -1
	for index, e := range c.entities {
		if e.BasicEntity.ID() == basic.ID() {
			delete = index
			break
		}
	}
	if delete >= 0 {
		c.entities = append(c.entities[:delete], c.entities[delete+1:]...)
	}
}

// Update checks the entities for collision with eachother. Only Main entities are check for collision explicitly.
// If one of the entities are solid, the SpaceComponent is adjusted so that the other entities don't pass through it.
func (c *CollisionSystem) Update(dt float32) {
	for i1, e1 := range c.entities {
		if e1.CollisionComponent.Main == 0 {
			//Main cannot pass bitwise comparison with any other items. Do not loop.
			continue // with other entities
		}

		entityAABB := e1.SpaceComponent.AABB()
		offset := engo.Point{X: e1.CollisionComponent.Extra.X / 2, Y: e1.CollisionComponent.Extra.Y / 2}
		entityAABB.Min.X -= offset.X
		entityAABB.Min.Y -= offset.Y
		entityAABB.Max.X += offset.X
		entityAABB.Max.Y += offset.Y

		var collided CollisionGroup

		for i2, e2 := range c.entities {
			if i1 == i2 {
				continue // with other entities, because we won't collide with ourselves
			}
			cgroup := e1.CollisionComponent.Main & e2.CollisionComponent.Group
			if cgroup == 0 {
				continue //Items are not in a comparible group dont bother
			}

			otherAABB := e2.SpaceComponent.AABB()
			offset = engo.Point{X: e2.CollisionComponent.Extra.X / 2, Y: e2.CollisionComponent.Extra.Y / 2}
			otherAABB.Min.X -= offset.X
			otherAABB.Min.Y -= offset.Y
			otherAABB.Max.X += offset.X
			otherAABB.Max.Y += offset.Y

			if IsIntersecting(entityAABB, otherAABB) {
				if cgroup&c.Solids > 0 {
					mtd := MinimumTranslation(entityAABB, otherAABB)
					e1.SpaceComponent.Position.X += mtd.X
					e1.SpaceComponent.Position.Y += mtd.Y
				}

				//collided can now list the types of collision
				collided = collided | cgroup
				engo.Mailbox.Dispatch(CollisionMessage{Entity: e1, To: e2, Groups: cgroup})
			}
		}

		e1.CollisionComponent.Collides = collided
	}
}

// IsIntersecting tells if two engo.AABBs intersect.
func IsIntersecting(rect1 engo.AABB, rect2 engo.AABB) bool {
	if rect1.Max.X > rect2.Min.X && rect1.Min.X < rect2.Max.X && rect1.Max.Y > rect2.Min.Y && rect1.Min.Y < rect2.Max.Y {
		return true
	}

	return false
}

// MinimumTranslation tells how much an entity has to move to no longer overlap another entity.
func MinimumTranslation(rect1 engo.AABB, rect2 engo.AABB) engo.Point {
	mtd := engo.Point{}

	left := rect2.Min.X - rect1.Max.X
	right := rect2.Max.X - rect1.Min.X
	top := rect2.Min.Y - rect1.Max.Y
	bottom := rect2.Max.Y - rect1.Min.Y

	if left > 0 || right < 0 {
		log.Println("Box aint intercepting")
		return mtd
		//box doesn't intercept
	}

	if top > 0 || bottom < 0 {
		log.Println("Box aint intercepting")
		return mtd
		//box doesn't intercept
	}
	if math.Abs(left) < right {
		mtd.X = left
	} else {
		mtd.X = right
	}

	if math.Abs(top) < bottom {
		mtd.Y = top
	} else {
		mtd.Y = bottom
	}

	if math.Abs(mtd.X) < math.Abs(mtd.Y) {
		mtd.Y = 0
	} else {
		mtd.X = 0
	}

	return mtd
}
<commit_msg>Added collision of equals<commit_after>package common

import (
	"log"

	"engo.io/ecs"
	"engo.io/engo"
	"engo.io/engo/math"
)

// SpaceComponent keeps track of the position, size, and rotation of entities.
type SpaceComponent struct {
	Position engo.Point
	Width    float32
	Height   float32
	Rotation float32 // angle in degrees for the rotation to apply clockwise.
}

// SetCenter positions the space component according to its center instead of its
// top-left point (this avoids doing the same math each time in your systems)
func (sc *SpaceComponent) SetCenter(p engo.Point) {
	xDelta := sc.Width / 2
	yDelta := sc.Height / 2
	// update position according to point being used as our center
	if sc.Rotation == 0 {
		sc.Position.X = p.X - xDelta
		sc.Position.Y = p.Y - yDelta
		return
	}
	sin, cos := math.Sincos(sc.Rotation * math.Pi / 180)
	xDelta = (sc.Width*cos - sc.Height*sin) / 2
	yDelta = (sc.Height*cos + sc.Width*sin) / 2
	sc.Position.X = p.X - xDelta
	sc.Position.Y = p.Y - yDelta
}

// Center gets the center position of the space component instead of its
// top-left point (this avoids doing the same math each time in your systems)
func (sc *SpaceComponent) Center() engo.Point {
	xDelta := sc.Width / 2
	yDelta := sc.Height / 2
	p := sc.Position
	if sc.Rotation == 0 {
		return engo.Point{X: p.X + xDelta, Y: p.Y + yDelta}
	}
	sin, cos := math.Sincos(sc.Rotation * math.Pi / 180)
	xDelta = (sc.Width*cos - sc.Height*sin) / 2
	yDelta = (sc.Height*cos + sc.Width*sin) / 2
	return engo.Point{X: p.X + xDelta, Y: p.Y + yDelta}
}

// AABB returns the minimum and maximum point for the given SpaceComponent. It hereby takes into account the
// rotation of the Component - it may very well be that the Minimum as given by engo.AABB, is smaller than the Position
// of the object (i.e. when rotated).
//
// This basically returns the "outer rectangle" of the plane defined by the `SpaceComponent`. Since this returns two
// points, a minimum and a maximum, the "rectangle" resulting from this `AABB`, is not rotated in any way. However,
// depending on the rotation of the `SpaceComponent`, this `AABB` may be larger than the original `SpaceComponent`.
func (sc SpaceComponent) AABB() engo.AABB {
	if sc.Rotation == 0 {
		return engo.AABB{
			Min: sc.Position,
			Max: engo.Point{X: sc.Position.X + sc.Width, Y: sc.Position.Y + sc.Height},
		}
	}

	corners := sc.Corners()

	var (
		xMin float32 = math.MaxFloat32
		xMax float32 = -math.MaxFloat32
		yMin float32 = math.MaxFloat32
		yMax float32 = -math.MaxFloat32
	)

	for i := 0; i < 4; i++ {
		if corners[i].X < xMin {
			xMin = corners[i].X
		} else if corners[i].X > xMax {
			xMax = corners[i].X
		}
		if corners[i].Y < yMin {
			yMin = corners[i].Y
		}
		if corners[i].Y > yMax {
			yMax = corners[i].Y
		}
	}

	return engo.AABB{Max: engo.Point{X: xMin, Y: yMin}, Min: engo.Point{X: xMax, Y: yMax}}
}

// Corners returns the location of the four corners of the rectangular plane defined by the `SpaceComponent`, taking
// into account any possible rotation.
func (sc SpaceComponent) Corners() (points [4]engo.Point) {
	points[0].X = sc.Position.X
	points[0].Y = sc.Position.Y

	sin, cos := math.Sincos(sc.Rotation * math.Pi / 180)

	points[1].X = points[0].X + sc.Width*cos
	points[1].Y = points[0].Y + sc.Width*sin

	points[2].X = points[0].X - sc.Height*sin
	points[2].Y = points[0].Y + sc.Height*cos

	points[3].X = points[0].X + sc.Width*cos - sc.Height*sin
	points[3].Y = points[0].Y + sc.Height*cos + sc.Width*sin

	return
}

// Contains indicates whether or not the given point is within the rectangular plane as defined by this `SpaceComponent`.
// If it's on the border, it is considered "not within".
func (sc SpaceComponent) Contains(p engo.Point) bool {
	points := sc.Corners()

	halfArea := (sc.Width * sc.Height) / 2

	for i := 0; i < 4; i++ {
		for j := i + 1; j < 4; j++ {
			if t := triangleArea(points[i], points[j], p); t > halfArea || engo.FloatEqual(t, halfArea) {
				return false
			}
		}
	}

	return true
}

// triangleArea computes the area of the triangle given by the three points
func triangleArea(p1, p2, p3 engo.Point) float32 {
	// Law of cosines states: (note a2 = math.Pow(a, 2))
	// a2 = b2 + c2 - 2bc*cos(alpha)
	// This ends in: alpha = arccos ((-a2 + b2 + c2)/(2bc))
	a := p1.PointDistance(p3)
	b := p1.PointDistance(p2)
	c := p2.PointDistance(p3)
	alpha := math.Acos((-math.Pow(a, 2) + math.Pow(b, 2) + math.Pow(c, 2)) / (2 * b * c))

	// Law of sines state: a / sin(alpha) = c / sin(gamma)
	height := (c / math.Sin(math.Pi/2)) * math.Sin(alpha)

	return (b * height) / 2
}

// CollisionComponent keeps track of the entity's collisions.
//
// Main tells the system to check all collisions against this entity.
//
// Group tells which collision group his entity belongs to.
//
// Extra is the allowed buffer for detecting collisions.
//
// Collides is all the groups this component collides with ORed together
type CollisionComponent struct {
	// if a.Main & (bitwise) b.Group, items can collide
	// if a.Main == 0, it will not loop for other items
	Main, Group CollisionGroup
	Extra       engo.Point
	Collides    CollisionGroup
}

// CollisionMessage is sent whenever a collision is detected by the CollisionSystem.
type CollisionMessage struct {
	Entity collisionEntity
	To     collisionEntity
	Groups CollisionGroup
}

// CollisionGroup is intended to be used in bitwise comparisons
// The user is expected to create a const ( a = 1 << iota \n b \n c etc)
// for the different kinds of collisions they hope to use
type CollisionGroup byte

// Type implements the engo.Message interface
func (CollisionMessage) Type() string { return "CollisionMessage" }

type collisionEntity struct {
	*ecs.BasicEntity
	*CollisionComponent
	*SpaceComponent
}

// CollisionSystem is a system that detects collisions between entities, sends a message if collisions
// are detected, and updates their SpaceComponent so entities cannot pass through Solids.
type CollisionSystem struct {
	// Solids, used to tell which collisions should be treated as solid by bitwise comparison.
	// if a.Main & b.Group & sys.Solids{ Collisions are treated as solid.  }
	Solids CollisionGroup

	entities []collisionEntity
}

// Add adds an entity to the CollisionSystem. To be added, the entity has to have a basic, collision, and space component.
func (c *CollisionSystem) Add(basic *ecs.BasicEntity, collision *CollisionComponent, space *SpaceComponent) {
	c.entities = append(c.entities, collisionEntity{basic, collision, space})
}

// AddByInterface Provides a simple way to add an entity to the system that satisfies Collisionable. Any entity containing, BasicEntity,CollisionComponent, and SpaceComponent anonymously, automatically does this.
func (c *CollisionSystem) AddByInterface(o Collisionable) {
	c.Add(o.GetBasicEntity(), o.GetCollisionComponent(), o.GetSpaceComponent())
}

// Remove removes an entity from the CollisionSystem.
func (c *CollisionSystem) Remove(basic ecs.BasicEntity) {
	delete := -1
	for index, e := range c.entities {
		if e.BasicEntity.ID() == basic.ID() {
			delete = index
			break
		}
	}
	if delete >= 0 {
		c.entities = append(c.entities[:delete], c.entities[delete+1:]...)
	}
}

// Update checks the entities for collision with eachother. Only Main entities are check for collision explicitly.
// If one of the entities are solid, the SpaceComponent is adjusted so that the other entities don't pass through it.
func (c *CollisionSystem) Update(dt float32) {
	for i1, e1 := range c.entities {
		if e1.CollisionComponent.Main == 0 {
			//Main cannot pass bitwise comparison with any other items. Do not loop.
			continue // with other entities
		}

		entityAABB := e1.SpaceComponent.AABB()
		offset := engo.Point{X: e1.CollisionComponent.Extra.X / 2, Y: e1.CollisionComponent.Extra.Y / 2}
		entityAABB.Min.X -= offset.X
		entityAABB.Min.Y -= offset.Y
		entityAABB.Max.X += offset.X
		entityAABB.Max.Y += offset.Y

		var collided CollisionGroup

		for i2, e2 := range c.entities {
			if i1 == i2 {
				continue // with other entities, because we won't collide with ourselves
			}
			cgroup := e1.CollisionComponent.Main & e2.CollisionComponent.Group
			if cgroup == 0 {
				continue //Items are not in a comparible group dont bother
			}

			otherAABB := e2.SpaceComponent.AABB()
			offset = engo.Point{X: e2.CollisionComponent.Extra.X / 2, Y: e2.CollisionComponent.Extra.Y / 2}
			otherAABB.Min.X -= offset.X
			otherAABB.Min.Y -= offset.Y
			otherAABB.Max.X += offset.X
			otherAABB.Max.Y += offset.Y

			if IsIntersecting(entityAABB, otherAABB) {
				if cgroup&c.Solids > 0 {
					mtd := MinimumTranslation(entityAABB, otherAABB)
					if e1.CollisionComponent.Main&e2.CollisionComponent.Main&c.Solids != 0 {
						//collision of equals (both main)
						e1.SpaceComponent.Position.X += mtd.X / 2
						e1.SpaceComponent.Position.Y += mtd.Y / 2
						e2.SpaceComponent.Position.X -= mtd.X / 2
						e2.SpaceComponent.Position.Y -= mtd.Y / 2
					} else {
						//collision with one main
						e1.SpaceComponent.Position.X += mtd.X
						e1.SpaceComponent.Position.Y += mtd.Y
					}
				}

				//collided can now list the types of collision
				collided = collided | cgroup
				engo.Mailbox.Dispatch(CollisionMessage{Entity: e1, To: e2, Groups: cgroup})
			}
		}

		e1.CollisionComponent.Collides = collided
	}
}

// IsIntersecting tells if two engo.AABBs intersect.
func IsIntersecting(rect1 engo.AABB, rect2 engo.AABB) bool {
	if rect1.Max.X > rect2.Min.X && rect1.Min.X < rect2.Max.X && rect1.Max.Y > rect2.Min.Y && rect1.Min.Y < rect2.Max.Y {
		return true
	}

	return false
}

// MinimumTranslation tells how much an entity has to move to no longer overlap another entity.
func MinimumTranslation(rect1 engo.AABB, rect2 engo.AABB) engo.Point {
	mtd := engo.Point{}

	left := rect2.Min.X - rect1.Max.X
	right := rect2.Max.X - rect1.Min.X
	top := rect2.Min.Y - rect1.Max.Y
	bottom := rect2.Max.Y - rect1.Min.Y

	if left > 0 || right < 0 {
		log.Println("Box aint intercepting")
		return mtd
		//box doesn't intercept
	}

	if top > 0 || bottom < 0 {
		log.Println("Box aint intercepting")
		return mtd
		//box doesn't intercept
	}
	if math.Abs(left) < right {
		mtd.X = left
	} else {
		mtd.X = right
	}

	if math.Abs(top) < bottom {
		mtd.Y = top
	} else {
		mtd.Y = bottom
	}

	if math.Abs(mtd.X) < math.Abs(mtd.Y) {
		mtd.Y = 0
	} else {
		mtd.X = 0
	}

	return mtd
}
<|endoftext|>


<commit_before>package common

import (
	"bufio"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"github.com/mholt/archiver"
	"github.com/mitchellh/go-homedir"
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"bytes"
)

// ExtensionImpl provides API for an extension
type ExtensionImpl interface {
	ID() string
	DecorateStackTemplate(assetName string, stackName string, templateBody io.Reader) (io.Reader, error)
	DecorateStackParameters(stackName string, stackParameters map[string]string) (map[string]string, error)
	DecorateStackTags(stackName string, stackTags map[string]string) (map[string]string, error)
}

// BaseExtensionImpl basic no-op extension
type BaseExtensionImpl struct {
	id string
}

// DecorateStackTemplate don't decorate, just return
func (ext *BaseExtensionImpl) DecorateStackTemplate(assetName string, stackName string, inTemplate io.Reader) (io.Reader, error) {
	return inTemplate, nil
}

// DecorateStackParameters don't decorate, just return
func (ext *BaseExtensionImpl) DecorateStackParameters(stackName string, stackParameters map[string]string) (map[string]string, error) {
	return stackParameters, nil
}

// DecorateStackTags don't decorate, just return
func (ext *BaseExtensionImpl) DecorateStackTags(stackName string, stackTags map[string]string) (map[string]string, error) {
	return stackTags, nil
}

// ID returns unique id for extension
func (ext *BaseExtensionImpl) ID() string {
	return ext.id
}

// ExtensionsManager provides API for running extensions
type ExtensionsManager interface {
	ExtensionImpl
	AddExtension(extension ExtensionImpl) error
}

// Implementation of ExtensionsManager
type extensionsManager struct {
	BaseExtensionImpl
	extensions []ExtensionImpl
}

// Create a new extensionsManager
func newExtensionsManager() (ExtensionsManager, error) {
	extMgr := &extensionsManager{
		BaseExtensionImpl{""},
		make([]ExtensionImpl, 0),
	}
	return extMgr, nil
}
func (extMgr *extensionsManager) AddExtension(extension ExtensionImpl) error {
	if extension == nil {
		return fmt.Errorf("extension was nil")
	}
	// ensure extension isn't already loaded
	for _, existingExt := range extMgr.extensions {
		if existingExt.ID() == extension.ID() {
			return fmt.Errorf("extension '%s' already loaded...skipping", extension.ID())
		}
	}
	extMgr.extensions = append(extMgr.extensions, extension)
	return nil
}

// DecorateStackTemplate for all extensions
func (extMgr *extensionsManager) DecorateStackTemplate(assetName string, stackName string, inTemplate io.Reader) (io.Reader, error) {
	outTemplate := inTemplate
	for _, ext := range extMgr.extensions {
		var err error
		outTemplate, err = ext.DecorateStackTemplate(assetName, stackName, outTemplate)
		if err != nil {
			return nil, err
		}
	}
	return outTemplate, nil
}

// DecorateStackParameters for all extensions
func (extMgr *extensionsManager) DecorateStackParameters(stackName string, stackParameters map[string]string) (map[string]string, error) {
	outParams := stackParameters
	for _, ext := range extMgr.extensions {
		var err error
		outParams, err = ext.DecorateStackParameters(stackName, outParams)
		if err != nil {
			return nil, err
		}
	}
	return outParams, nil
}

// DecorateStackTags for all extensions
func (extMgr *extensionsManager) DecorateStackTags(stackName string, stackTags map[string]string) (map[string]string, error) {
	outTags := stackTags
	for _, ext := range extMgr.extensions {
		var err error
		outTags, err = ext.DecorateStackTags(stackName, outTags)
		if err != nil {
			return nil, err
		}
	}
	return outTags, nil
}

// Extension for template overrides in mu.yml
type templateOverrideExtension struct {
	BaseExtensionImpl
	stackNameMatcher *regexp.Regexp
	decoration       interface{}
}

func newTemplateOverrideExtension(stackNamePattern string, template interface{}) ExtensionImpl {
	id := fmt.Sprintf("templateOverride:%s", stackNamePattern)
	ext := &templateOverrideExtension{
		BaseExtensionImpl{id},
		regexp.MustCompile(fmt.Sprintf("^%s$", stackNamePattern)),
		template,
	}
	return ext
}

// DecorateStackTemplate from overrides in mu.yml
func (ext *templateOverrideExtension) DecorateStackTemplate(assetName string, stackName string, inTemplate io.Reader) (io.Reader, error) {
	if ext.stackNameMatcher.MatchString(stackName) {
		return decorateTemplate(inTemplate, ext.decoration)
	}
	return inTemplate, nil
}

// Extension for tag overrides in mu.yml
type tagOverrideExtension struct {
	BaseExtensionImpl
	stackNameMatcher *regexp.Regexp
	tags             map[string]string
}

func newTagOverrideExtension(stackNamePattern string, tags map[string]string) ExtensionImpl {
	id := fmt.Sprintf("tagOverride:%s", stackNamePattern)
	ext := &tagOverrideExtension{
		BaseExtensionImpl{id},
		regexp.MustCompile(fmt.Sprintf("^%s$", stackNamePattern)),
		tags,
	}
	return ext
}

// DecorateStackTags from overrides in mu.yml
func (ext *tagOverrideExtension) DecorateStackTags(stackName string, stackTags map[string]string) (map[string]string, error) {
	if ext.stackNameMatcher.MatchString(stackName) {
		for k, v := range ext.tags {
			stackTags[k] = v
		}
	}
	return stackTags, nil
}

// Extension for param overrides in mu.yml
type paramOverrideExtension struct {
	BaseExtensionImpl
	stackNameMatcher *regexp.Regexp
	params           map[string]string
}

func newParameterOverrideExtension(stackNamePattern string, params map[string]string) ExtensionImpl {
	id := fmt.Sprintf("paramOverride:%s", stackNamePattern)
	ext := &paramOverrideExtension{
		BaseExtensionImpl{id},
		regexp.MustCompile(fmt.Sprintf("^%s$", stackNamePattern)),
		params,
	}
	return ext
}

// DecorateStackParameters from overrides in mu.yml
func (ext *paramOverrideExtension) DecorateStackParameters(stackName string, stackParams map[string]string) (map[string]string, error) {
	if ext.stackNameMatcher.MatchString(stackName) {
		for k, v := range ext.params {
			stackParams[k] = v
		}
	}
	return stackParams, nil
}

// Extension for archives of templates
type templateArchiveExtension struct {
	BaseExtensionImpl
	path string
	mode TemplateUpdateMode
}

// List of valid template update modes
type TemplateUpdateMode string
const (
	TemplateUpdateReplace       TemplateUpdateMode = "replace"
	TemplateUpdateMerge         = "merge"
)

func newTemplateArchiveExtension(u *url.URL, artifactManager ArtifactManager) (ExtensionImpl, error) {
	log.Debugf("Loading extension from '%s'", u)

	userdir, err := homedir.Dir()
	if err != nil {
		return nil, err
	}
	extensionsDirectory := filepath.Join(userdir, ".mu", "extensions")

	extID := urlToID(u)
	ext := &templateArchiveExtension{
		BaseExtensionImpl{u.String()},
		filepath.Join(extensionsDirectory, extID),
		TemplateUpdateMerge,
	}

	if fi, err := os.Stat(u.Path); u.Scheme == "file" && err == nil && fi.IsDir() {
		ext.path = u.Path
		log.Debugf("Loaded extension from '%s'", u.Path)
	} else {
		// check for existing etag
		etag := ""
		etagBytes, err := ioutil.ReadFile(filepath.Join(ext.path, ".etag"))
		if err == nil {
			etag = string(etagBytes)
		}

		body, etag, err := artifactManager.GetArtifact(u.String(), etag)
		if err != nil {
			return nil, err
		}

		if body != nil {
			defer body.Close()

			// empty dir
			os.RemoveAll(ext.path)
			os.MkdirAll(ext.path, 0700)

			// write out archive to dir
			err = extractArchive(ext.path, body)
			if err != nil {
				return nil, err
			}

			// write new etag
			err = ioutil.WriteFile(filepath.Join(ext.path, ".etag"), []byte(etag), 0644)
			if err != nil {
				return nil, err
			}
			log.Debugf("Loaded extension from '%s' [id=%s]", u, ext.id)
		} else {
			log.Debugf("Loaded extension from cache [id=%s]", ext.id)
		}

	}

	// try loading the extension manifest
	extManifest := make(map[interface{}]interface{})
	extManifestFile, err := ioutil.ReadFile(filepath.Join(ext.path, "mu-extension.yml"))
	if err == nil {
		err = yaml.Unmarshal(extManifestFile, extManifest)
		if err != nil {
			log.Debugf("error unmarshalling mu-extension.yml: %s", err)
		} else {
			if v, ok := extManifest["templateUpdateMode"]; ok {
				ext.mode = TemplateUpdateMode(v.(string))
			}
		}
	} else {
		log.Debugf("error reading mu-extension.yml: %s", err)
	}

	// log info about the new extension
	if name, ok := extManifest["name"]; ok {
		if version, ok := extManifest["version"]; ok {
			log.Infof("Loaded extension %s (version=%v)", name, version)
		} else {
			log.Infof("Loaded extension %s", name)
		}
	} else {
		log.Infof("Loaded extension %s", u)
	}

	return ext, nil
}

// DecorateStackTemplate from template files in archive
func (ext *templateArchiveExtension) DecorateStackTemplate(assetName string, stackName string, inTemplate io.Reader) (io.Reader, error) {
	outTemplate := inTemplate
	if ext.mode == TemplateUpdateReplace {
		log.Debugf("Replacing input template")
		inTemplate = bytes.NewBufferString("")
	}
	assetPath := filepath.Join(ext.path, assetName)
	yamlFile, err := ioutil.ReadFile(assetPath)
	if err != nil {
		log.Debugf("Unable to find asset '%s' in extension '%s': %s", assetName, ext.id, err)
	} else {
		decoration := make(map[interface{}]interface{})
		err = yaml.Unmarshal(yamlFile, decoration)
		if err != nil {
			log.Warningf("Unable to parse asset '%s' in extension '%s': %s", assetName, ext.id, err)
		} else {
			return decorateTemplate(inTemplate, decoration)
		}
	}
	return outTemplate, nil
}

func urlToID(u *url.URL) string {
	h := sha1.New()
	h.Write([]byte(u.String()))
	return hex.EncodeToString(h.Sum(nil))
}

func extractArchive(destPath string, archive io.ReadCloser) error {
	reader := bufio.NewReader(archive)
	headBytes, err := reader.Peek(512)
	if err != nil {
		return err
	}
	contentType := http.DetectContentType(headBytes)
	log.Debugf("Extracting type '%s'", contentType)

	switch contentType {
	case "application/x-gzip":
		return archiver.TarGz.Read(reader, destPath)
	case "application/zip":
		return archiver.Zip.Read(reader, destPath)
	default:
		return fmt.Errorf("unable to handle archive of content-type '%s'", contentType)
	}
}
<commit_msg>update comments to make linter stop yelling<commit_after>package common

import (
	"bufio"
	"bytes"
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"github.com/mholt/archiver"
	"github.com/mitchellh/go-homedir"
	"gopkg.in/yaml.v2"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
)

// ExtensionImpl provides API for an extension
type ExtensionImpl interface {
	ID() string
	DecorateStackTemplate(assetName string, stackName string, templateBody io.Reader) (io.Reader, error)
	DecorateStackParameters(stackName string, stackParameters map[string]string) (map[string]string, error)
	DecorateStackTags(stackName string, stackTags map[string]string) (map[string]string, error)
}

// BaseExtensionImpl basic no-op extension
type BaseExtensionImpl struct {
	id string
}

// DecorateStackTemplate don't decorate, just return
func (ext *BaseExtensionImpl) DecorateStackTemplate(assetName string, stackName string, inTemplate io.Reader) (io.Reader, error) {
	return inTemplate, nil
}

// DecorateStackParameters don't decorate, just return
func (ext *BaseExtensionImpl) DecorateStackParameters(stackName string, stackParameters map[string]string) (map[string]string, error) {
	return stackParameters, nil
}

// DecorateStackTags don't decorate, just return
func (ext *BaseExtensionImpl) DecorateStackTags(stackName string, stackTags map[string]string) (map[string]string, error) {
	return stackTags, nil
}

// ID returns unique id for extension
func (ext *BaseExtensionImpl) ID() string {
	return ext.id
}

// ExtensionsManager provides API for running extensions
type ExtensionsManager interface {
	ExtensionImpl
	AddExtension(extension ExtensionImpl) error
}

// Implementation of ExtensionsManager
type extensionsManager struct {
	BaseExtensionImpl
	extensions []ExtensionImpl
}

// Create a new extensionsManager
func newExtensionsManager() (ExtensionsManager, error) {
	extMgr := &extensionsManager{
		BaseExtensionImpl{""},
		make([]ExtensionImpl, 0),
	}
	return extMgr, nil
}
func (extMgr *extensionsManager) AddExtension(extension ExtensionImpl) error {
	if extension == nil {
		return fmt.Errorf("extension was nil")
	}
	// ensure extension isn't already loaded
	for _, existingExt := range extMgr.extensions {
		if existingExt.ID() == extension.ID() {
			return fmt.Errorf("extension '%s' already loaded...skipping", extension.ID())
		}
	}
	extMgr.extensions = append(extMgr.extensions, extension)
	return nil
}

// DecorateStackTemplate for all extensions
func (extMgr *extensionsManager) DecorateStackTemplate(assetName string, stackName string, inTemplate io.Reader) (io.Reader, error) {
	outTemplate := inTemplate
	for _, ext := range extMgr.extensions {
		var err error
		outTemplate, err = ext.DecorateStackTemplate(assetName, stackName, outTemplate)
		if err != nil {
			return nil, err
		}
	}
	return outTemplate, nil
}

// DecorateStackParameters for all extensions
func (extMgr *extensionsManager) DecorateStackParameters(stackName string, stackParameters map[string]string) (map[string]string, error) {
	outParams := stackParameters
	for _, ext := range extMgr.extensions {
		var err error
		outParams, err = ext.DecorateStackParameters(stackName, outParams)
		if err != nil {
			return nil, err
		}
	}
	return outParams, nil
}

// DecorateStackTags for all extensions
func (extMgr *extensionsManager) DecorateStackTags(stackName string, stackTags map[string]string) (map[string]string, error) {
	outTags := stackTags
	for _, ext := range extMgr.extensions {
		var err error
		outTags, err = ext.DecorateStackTags(stackName, outTags)
		if err != nil {
			return nil, err
		}
	}
	return outTags, nil
}

// Extension for template overrides in mu.yml
type templateOverrideExtension struct {
	BaseExtensionImpl
	stackNameMatcher *regexp.Regexp
	decoration       interface{}
}

func newTemplateOverrideExtension(stackNamePattern string, template interface{}) ExtensionImpl {
	id := fmt.Sprintf("templateOverride:%s", stackNamePattern)
	ext := &templateOverrideExtension{
		BaseExtensionImpl{id},
		regexp.MustCompile(fmt.Sprintf("^%s$", stackNamePattern)),
		template,
	}
	return ext
}

// DecorateStackTemplate from overrides in mu.yml
func (ext *templateOverrideExtension) DecorateStackTemplate(assetName string, stackName string, inTemplate io.Reader) (io.Reader, error) {
	if ext.stackNameMatcher.MatchString(stackName) {
		return decorateTemplate(inTemplate, ext.decoration)
	}
	return inTemplate, nil
}

// Extension for tag overrides in mu.yml
type tagOverrideExtension struct {
	BaseExtensionImpl
	stackNameMatcher *regexp.Regexp
	tags             map[string]string
}

func newTagOverrideExtension(stackNamePattern string, tags map[string]string) ExtensionImpl {
	id := fmt.Sprintf("tagOverride:%s", stackNamePattern)
	ext := &tagOverrideExtension{
		BaseExtensionImpl{id},
		regexp.MustCompile(fmt.Sprintf("^%s$", stackNamePattern)),
		tags,
	}
	return ext
}

// DecorateStackTags from overrides in mu.yml
func (ext *tagOverrideExtension) DecorateStackTags(stackName string, stackTags map[string]string) (map[string]string, error) {
	if ext.stackNameMatcher.MatchString(stackName) {
		for k, v := range ext.tags {
			stackTags[k] = v
		}
	}
	return stackTags, nil
}

// Extension for param overrides in mu.yml
type paramOverrideExtension struct {
	BaseExtensionImpl
	stackNameMatcher *regexp.Regexp
	params           map[string]string
}

func newParameterOverrideExtension(stackNamePattern string, params map[string]string) ExtensionImpl {
	id := fmt.Sprintf("paramOverride:%s", stackNamePattern)
	ext := &paramOverrideExtension{
		BaseExtensionImpl{id},
		regexp.MustCompile(fmt.Sprintf("^%s$", stackNamePattern)),
		params,
	}
	return ext
}

// DecorateStackParameters from overrides in mu.yml
func (ext *paramOverrideExtension) DecorateStackParameters(stackName string, stackParams map[string]string) (map[string]string, error) {
	if ext.stackNameMatcher.MatchString(stackName) {
		for k, v := range ext.params {
			stackParams[k] = v
		}
	}
	return stackParams, nil
}

// Extension for archives of templates
type templateArchiveExtension struct {
	BaseExtensionImpl
	path string
	mode TemplateUpdateMode
}

// TemplateUpdateMode of valid template update modes
type TemplateUpdateMode string

// list of update modes
const (
	TemplateUpdateReplace TemplateUpdateMode = "replace"
	TemplateUpdateMerge                      = "merge"
)

func newTemplateArchiveExtension(u *url.URL, artifactManager ArtifactManager) (ExtensionImpl, error) {
	log.Debugf("Loading extension from '%s'", u)

	userdir, err := homedir.Dir()
	if err != nil {
		return nil, err
	}
	extensionsDirectory := filepath.Join(userdir, ".mu", "extensions")

	extID := urlToID(u)
	ext := &templateArchiveExtension{
		BaseExtensionImpl{u.String()},
		filepath.Join(extensionsDirectory, extID),
		TemplateUpdateMerge,
	}

	if fi, err := os.Stat(u.Path); u.Scheme == "file" && err == nil && fi.IsDir() {
		ext.path = u.Path
		log.Debugf("Loaded extension from '%s'", u.Path)
	} else {
		// check for existing etag
		etag := ""
		etagBytes, err := ioutil.ReadFile(filepath.Join(ext.path, ".etag"))
		if err == nil {
			etag = string(etagBytes)
		}

		body, etag, err := artifactManager.GetArtifact(u.String(), etag)
		if err != nil {
			return nil, err
		}

		if body != nil {
			defer body.Close()

			// empty dir
			os.RemoveAll(ext.path)
			os.MkdirAll(ext.path, 0700)

			// write out archive to dir
			err = extractArchive(ext.path, body)
			if err != nil {
				return nil, err
			}

			// write new etag
			err = ioutil.WriteFile(filepath.Join(ext.path, ".etag"), []byte(etag), 0644)
			if err != nil {
				return nil, err
			}
			log.Debugf("Loaded extension from '%s' [id=%s]", u, ext.id)
		} else {
			log.Debugf("Loaded extension from cache [id=%s]", ext.id)
		}

	}

	// try loading the extension manifest
	extManifest := make(map[interface{}]interface{})
	extManifestFile, err := ioutil.ReadFile(filepath.Join(ext.path, "mu-extension.yml"))
	if err == nil {
		err = yaml.Unmarshal(extManifestFile, extManifest)
		if err != nil {
			log.Debugf("error unmarshalling mu-extension.yml: %s", err)
		} else {
			if v, ok := extManifest["templateUpdateMode"]; ok {
				ext.mode = TemplateUpdateMode(v.(string))
			}
		}
	} else {
		log.Debugf("error reading mu-extension.yml: %s", err)
	}

	// log info about the new extension
	if name, ok := extManifest["name"]; ok {
		if version, ok := extManifest["version"]; ok {
			log.Infof("Loaded extension %s (version=%v)", name, version)
		} else {
			log.Infof("Loaded extension %s", name)
		}
	} else {
		log.Infof("Loaded extension %s", u)
	}

	return ext, nil
}

// DecorateStackTemplate from template files in archive
func (ext *templateArchiveExtension) DecorateStackTemplate(assetName string, stackName string, inTemplate io.Reader) (io.Reader, error) {
	outTemplate := inTemplate
	if ext.mode == TemplateUpdateReplace {
		log.Debugf("Replacing input template")
		inTemplate = bytes.NewBufferString("")
	}
	assetPath := filepath.Join(ext.path, assetName)
	yamlFile, err := ioutil.ReadFile(assetPath)
	if err != nil {
		log.Debugf("Unable to find asset '%s' in extension '%s': %s", assetName, ext.id, err)
	} else {
		decoration := make(map[interface{}]interface{})
		err = yaml.Unmarshal(yamlFile, decoration)
		if err != nil {
			log.Warningf("Unable to parse asset '%s' in extension '%s': %s", assetName, ext.id, err)
		} else {
			return decorateTemplate(inTemplate, decoration)
		}
	}
	return outTemplate, nil
}

func urlToID(u *url.URL) string {
	h := sha1.New()
	h.Write([]byte(u.String()))
	return hex.EncodeToString(h.Sum(nil))
}

func extractArchive(destPath string, archive io.ReadCloser) error {
	reader := bufio.NewReader(archive)
	headBytes, err := reader.Peek(512)
	if err != nil {
		return err
	}
	contentType := http.DetectContentType(headBytes)
	log.Debugf("Extracting type '%s'", contentType)

	switch contentType {
	case "application/x-gzip":
		return archiver.TarGz.Read(reader, destPath)
	case "application/zip":
		return archiver.Zip.Read(reader, destPath)
	default:
		return fmt.Errorf("unable to handle archive of content-type '%s'", contentType)
	}
}
<|endoftext|>


<commit_before>package net

import (
	"net"
)

var (
	onesCount = make(map[byte]byte)
)

type IPNet struct {
	cache map[uint32]byte
}

func NewIPNet() *IPNet {
	return &IPNet{
		cache: make(map[uint32]byte, 1024),
	}
}

func ipToUint32(ip net.IP) uint32 {
	value := uint32(0)
	for _, b := range []byte(ip) {
		value <<= 8
		value += uint32(b)
	}
	return value
}

func ipMaskToByte(mask net.IPMask) byte {
	value := byte(0)
	for _, b := range []byte(mask) {
		value += onesCount[b]
	}
	return value
}

func (this *IPNet) Add(ipNet *net.IPNet) {
	ipv4 := ipNet.IP.To4()
	if ipv4 == nil {
		// For now, we don't support IPv6
		return
	}
	mask := ipMaskToByte(ipNet.Mask)
	this.AddIP(ipv4, mask)
}

func (this *IPNet) AddIP(ip []byte, mask byte) {
	k := ipToUint32(ip)
	existing, found := this.cache[k]
	if !found || existing > mask {
		this.cache[k] = mask
	}
}

func (this *IPNet) Contains(ip net.IP) bool {
	ipv4 := ip.To4()
	if ipv4 == nil {
		return false
	}
	originalValue := ipToUint32(ipv4)

	if entry, found := this.cache[originalValue]; found {
		if entry == 0 {
			return true
		}
	}

	mask := uint32(0)
	for maskbit := byte(1); maskbit <= 32; maskbit++ {
		mask += 1 << uint32(32-maskbit)

		maskedValue := originalValue & mask
		if entry, found := this.cache[maskedValue]; found {
			if entry == maskbit {
				return true
			}
		}
	}
	return false
}

func (this *IPNet) IsEmpty() bool {
	return len(this.cache) == 0
}

func init() {
	value := byte(0)
	for mask := byte(1); mask <= 8; mask++ {
		value += 1 << byte(8-mask)
		onesCount[value] = mask
	}
}
<commit_msg>fix ip check in ipnet<commit_after>package net

import (
	"net"
)

var (
	onesCount = make(map[byte]byte)
)

type IPNet struct {
	cache map[uint32]byte
}

func NewIPNet() *IPNet {
	return &IPNet{
		cache: make(map[uint32]byte, 1024),
	}
}

func ipToUint32(ip net.IP) uint32 {
	value := uint32(0)
	for _, b := range []byte(ip) {
		value <<= 8
		value += uint32(b)
	}
	return value
}

func ipMaskToByte(mask net.IPMask) byte {
	value := byte(0)
	for _, b := range []byte(mask) {
		value += onesCount[b]
	}
	return value
}

func (this *IPNet) Add(ipNet *net.IPNet) {
	ipv4 := ipNet.IP.To4()
	if ipv4 == nil {
		// For now, we don't support IPv6
		return
	}
	mask := ipMaskToByte(ipNet.Mask)
	this.AddIP(ipv4, mask)
}

func (this *IPNet) AddIP(ip []byte, mask byte) {
	k := ipToUint32(ip)
	existing, found := this.cache[k]
	if !found || existing > mask {
		this.cache[k] = mask
	}
}

func (this *IPNet) Contains(ip net.IP) bool {
	ipv4 := ip.To4()
	if ipv4 == nil {
		return false
	}
	originalValue := ipToUint32(ipv4)

	if entry, found := this.cache[originalValue]; found {
		if entry == 32 {
			return true
		}
	}

	mask := uint32(0)
	for maskbit := byte(1); maskbit <= 32; maskbit++ {
		mask += 1 << uint32(32-maskbit)

		maskedValue := originalValue & mask
		if entry, found := this.cache[maskedValue]; found {
			if entry == maskbit {
				return true
			}
		}
	}
	return false
}

func (this *IPNet) IsEmpty() bool {
	return len(this.cache) == 0
}

func init() {
	value := byte(0)
	for mask := byte(1); mask <= 8; mask++ {
		value += 1 << byte(8-mask)
		onesCount[value] = mask
	}
}
<|endoftext|>


<commit_before>package net

import (
	"net"
)

var (
	onesCount = make(map[byte]byte)
)

type IPNet struct {
	cache map[uint32]byte
}

func NewIPNet() *IPNet {
	return &IPNet{
		cache: make(map[uint32]byte, 1024),
	}
}

func ipToUint32(ip net.IP) uint32 {
	value := uint32(0)
	for _, b := range []byte(ip) {
		value <<= 8
		value += uint32(b)
	}
	return value
}

func ipMaskToByte(mask net.IPMask) byte {
	value := byte(0)
	for _, b := range []byte(mask) {
		value += onesCount[b]
	}
	return value
}

func (n *IPNet) Add(ipNet *net.IPNet) {
	ipv4 := ipNet.IP.To4()
	if ipv4 == nil {
		// For now, we don't support IPv6
		return
	}
	mask := ipMaskToByte(ipNet.Mask)
	n.AddIP(ipv4, mask)
}

func (n *IPNet) AddIP(ip []byte, mask byte) {
	k := ipToUint32(ip)
	existing, found := n.cache[k]
	if !found || existing > mask {
		n.cache[k] = mask
	}
}

func (n *IPNet) Contains(ip net.IP) bool {
	ipv4 := ip.To4()
	if ipv4 == nil {
		return false
	}
	originalValue := ipToUint32(ipv4)

	if entry, found := n.cache[originalValue]; found {
		if entry == 32 {
			return true
		}
	}

	mask := uint32(0)
	for maskbit := byte(1); maskbit <= 32; maskbit++ {
		mask += 1 << uint32(32-maskbit)

		maskedValue := originalValue & mask
		if entry, found := n.cache[maskedValue]; found {
			if entry == maskbit {
				return true
			}
		}
	}
	return false
}

func (n *IPNet) IsEmpty() bool {
	return len(n.cache) == 0
}

func init() {
	value := byte(0)
	for mask := byte(1); mask <= 8; mask++ {
		value += 1 << byte(8-mask)
		onesCount[value] = mask
	}
}
<commit_msg>Leverage math bitx<commit_after>package net

import (
	"math/bits"
	"net"
)

type IPNet struct {
	cache map[uint32]byte
}

func NewIPNet() *IPNet {
	return &IPNet{
		cache: make(map[uint32]byte, 1024),
	}
}

func ipToUint32(ip net.IP) uint32 {
	value := uint32(0)
	for _, b := range []byte(ip) {
		value <<= 8
		value += uint32(b)
	}
	return value
}

func ipMaskToByte(mask net.IPMask) byte {
	value := byte(0)
	for _, b := range []byte(mask) {
		value += byte(bits.OnesCount8(b))
	}
	return value
}

func (n *IPNet) Add(ipNet *net.IPNet) {
	ipv4 := ipNet.IP.To4()
	if ipv4 == nil {
		// For now, we don't support IPv6
		return
	}
	mask := ipMaskToByte(ipNet.Mask)
	n.AddIP(ipv4, mask)
}

func (n *IPNet) AddIP(ip []byte, mask byte) {
	k := ipToUint32(ip)
	existing, found := n.cache[k]
	if !found || existing > mask {
		n.cache[k] = mask
	}
}

func (n *IPNet) Contains(ip net.IP) bool {
	ipv4 := ip.To4()
	if ipv4 == nil {
		return false
	}
	originalValue := ipToUint32(ipv4)

	if entry, found := n.cache[originalValue]; found {
		if entry == 32 {
			return true
		}
	}

	mask := uint32(0)
	for maskbit := byte(1); maskbit <= 32; maskbit++ {
		mask += 1 << uint32(32-maskbit)

		maskedValue := originalValue & mask
		if entry, found := n.cache[maskedValue]; found {
			if entry == maskbit {
				return true
			}
		}
	}
	return false
}

func (n *IPNet) IsEmpty() bool {
	return len(n.cache) == 0
}
<|endoftext|>


<commit_before>package models

import "labix.org/v2/mgo/bson"

type Workspace struct {
	ObjectId   bson.ObjectId `bson:"_id" json:"_id"`
	Name       string        `bson:"name" json:"name"`
	Slug       string        `bson:"slug" json:"slug"`
	ChannelId  string        `bson:"channelId" json:"channelId"`
	MachineUID string        `bson:"machineUId" json:"machineUId"`
	Owner      string        `bson:"owner" json:"owner"`
	RootPath   string        `bson:"rootPath" json:"rootPath"`
	Layout     interface{}   `bson:"layout" json:"layout"`
}
<commit_msg>Workspace: Added MachineLabel IsDefault fields into workspace.go.<commit_after>package models

import "labix.org/v2/mgo/bson"

type Workspace struct {
	ObjectId     bson.ObjectId `bson:"_id" json:"_id"`
	Name         string        `bson:"name" json:"name"`
	Slug         string        `bson:"slug" json:"slug"`
	ChannelId    string        `bson:"channelId" json:"channelId"`
	MachineUID   string        `bson:"machineUId" json:"machineUId"`
	MachineLabel string        `bson:"machineLabel" json:"machineLabel"`
	Owner        string        `bson:"owner" json:"owner"`
	RootPath     string        `bson:"rootPath" json:"rootPath"`
	IsDefault    bool          `bson:"isDefault" json:"isDefault"`
	Layout       interface{}   `bson:"layout" json:"layout"`
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"koding/go-webserver/templates"
	"koding/tools/config"
	"net/http"
)

type HomeContent struct {
	Version       string
	Runtime       config.RuntimeOptions
	User          *LoggedInUser
	Title         string
	Description   string
	ShareUrl      string
	GpImage       string
	FbImage       string
	TwImage       string
	Impersonating bool
}

func writeLoggedInHomeToResp(w http.ResponseWriter, u *LoggedInUser) {
	homeTmpl := buildHomeTemplate(templates.LoggedInHome)

	imp, ok := u.Get("Impersonating")
	if !ok {
		imp = false
	}

	impBool, ok := imp.(bool)
	if !ok {
		impBool = false
	}

	hc := buildHomeContent()
	hc.Runtime = conf.Client.RuntimeOptions
	hc.User = u
	hc.Impersonating = impBool

	var buf bytes.Buffer
	if err := homeTmpl.Execute(&buf, hc); err != nil {
		Log.Error("Failed to render loggedin page: %s", err)
		writeLoggedOutHomeToResp(w)

		return
	}

	fmt.Fprintf(w, buf.String())
}

func writeLoggedOutHomeToResp(w http.ResponseWriter) {
	homeTmpl := buildHomeTemplate(templates.LoggedOutHome)

	hc := buildHomeContent()

	var buf bytes.Buffer
	if err := homeTmpl.Execute(&buf, hc); err != nil {
		Log.Error("Failed to render loggedout page: %s", err)
	}

	fmt.Fprintf(w, buf.String())
}

func buildHomeContent() HomeContent {
	hc := HomeContent{
		Version:     conf.Version,
		ShareUrl:    conf.Client.RuntimeOptions.MainUri,
		Title:       kodingTitle,
		Description: kodingDescription,
		GpImage:     kodingGpImage,
		FbImage:     kodingFbImage,
		TwImage:     kodingTwImage,
	}

	return hc
}

func buildHomeTemplate(content string) *template.Template {
	homeTmpl := template.Must(template.New("home").Parse(content))
	headerTmpl := template.Must(template.New("header").Parse(templates.Header))
	analyticsTmpl := template.Must(template.New("analytics").Parse(templates.Analytics))

	homeTmpl.AddParseTree("header", headerTmpl.Tree)
	homeTmpl.AddParseTree("analytics", analyticsTmpl.Tree)

	return homeTmpl
}
<commit_msg>gowebserver: fix bug where %<x> in post bodies was evaluated to  MISSING<commit_after>package main

import (
	"bytes"
	"fmt"
	"html/template"
	"koding/go-webserver/templates"
	"koding/tools/config"
	"net/http"
)

type HomeContent struct {
	Version       string
	Runtime       config.RuntimeOptions
	User          *LoggedInUser
	Title         string
	Description   string
	ShareUrl      string
	GpImage       string
	FbImage       string
	TwImage       string
	Impersonating bool
}

func writeLoggedInHomeToResp(w http.ResponseWriter, u *LoggedInUser) {
	homeTmpl := buildHomeTemplate(templates.LoggedInHome)

	imp, ok := u.Get("Impersonating")
	if !ok {
		imp = false
	}

	impBool, ok := imp.(bool)
	if !ok {
		impBool = false
	}

	hc := buildHomeContent()
	hc.Runtime = conf.Client.RuntimeOptions
	hc.User = u
	hc.Impersonating = impBool

	var buf bytes.Buffer
	if err := homeTmpl.Execute(&buf, hc); err != nil {
		Log.Error("Failed to render loggedin page: %s", err)
		writeLoggedOutHomeToResp(w)

		return
	}

	fmt.Fprint(w, buf.String())
}

func writeLoggedOutHomeToResp(w http.ResponseWriter) {
	homeTmpl := buildHomeTemplate(templates.LoggedOutHome)

	hc := buildHomeContent()

	var buf bytes.Buffer
	if err := homeTmpl.Execute(&buf, hc); err != nil {
		Log.Error("Failed to render loggedout page: %s", err)
	}

	fmt.Fprint(w, buf.String())
}

func buildHomeContent() HomeContent {
	hc := HomeContent{
		Version:     conf.Version,
		ShareUrl:    conf.Client.RuntimeOptions.MainUri,
		Title:       kodingTitle,
		Description: kodingDescription,
		GpImage:     kodingGpImage,
		FbImage:     kodingFbImage,
		TwImage:     kodingTwImage,
	}

	return hc
}

func buildHomeTemplate(content string) *template.Template {
	homeTmpl := template.Must(template.New("home").Parse(content))
	headerTmpl := template.Must(template.New("header").Parse(templates.Header))
	analyticsTmpl := template.Must(template.New("analytics").Parse(templates.Analytics))

	homeTmpl.AddParseTree("header", headerTmpl.Tree)
	homeTmpl.AddParseTree("analytics", analyticsTmpl.Tree)

	return homeTmpl
}
<|endoftext|>


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

package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"v.io/v23"
	"v.io/v23/options"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/security/access"

	"v.io/x/ref"
	"v.io/x/ref/lib/signals"
	"v.io/x/ref/runtime/factories/generic"
	"v.io/x/ref/services/identity/identitylib"
	"v.io/x/ref/services/mounttable/mounttablelib"
	"v.io/x/ref/test/expect"
	"v.io/x/ref/test/modules"
)

const (
	RunMTCommand = "runMT"
	stdoutLog    = "tmp/runner.stdout.log" // Used as stdout drain when shutting down.
	stderrLog    = "tmp/runner.stderr.log" // Used as stderr drain when shutting down.
)

var (
	runTestsWatch bool
)

func init() {
	modules.RegisterChild(RunMTCommand, "", runMT)
	flag.BoolVar(&runTestsWatch, "runTestsWatch", false, "if true runs the tests in watch mode")
}

func runMT(stdin io.Reader, stdout, stderr io.Writer, env map[string]string, args ...string) error {
	ctx, shutdown := v23.Init()
	defer shutdown()

	lspec := v23.GetListenSpec(ctx)
	server, err := v23.NewServer(ctx, options.ServesMountTable(true))
	if err != nil {
		return fmt.Errorf("root failed: %v", err)
	}
	mp := args[0]
	mt, err := mounttablelib.NewMountTableDispatcher("", "", "mounttable")
	if err != nil {
		return fmt.Errorf("mounttablelib.NewMountTableDispatcher failed: %s", err)
	}
	eps, err := server.Listen(lspec)
	if err != nil {
		return fmt.Errorf("server.Listen failed: %s", err)
	}
	if err := server.ServeDispatcher(mp, mt); err != nil {
		return fmt.Errorf("root failed: %s", err)
	}
	fmt.Fprintf(stdout, "PID=%d\n", os.Getpid())
	for _, ep := range eps {
		fmt.Fprintf(stdout, "MT_NAME=%s\n", ep.Name())
	}
	modules.WaitForEOF(stdin)
	return nil
}

// Helper function to simply print an error and then exit.
func exitOnError(err error, desc string) {
	if err != nil {
		fmt.Fprintln(os.Stderr, desc, err)
		os.Exit(1)
	}
}

// updateVars captures the vars from the given Handle's stdout and adds them to
// the given vars map, overwriting existing entries.
func updateVars(h modules.Handle, vars map[string]string, varNames ...string) error {
	varsToAdd := map[string]bool{}
	for _, v := range varNames {
		varsToAdd[v] = true
	}
	numLeft := len(varsToAdd)

	s := expect.NewSession(nil, h.Stdout(), 30*time.Second)
	for {
		l := s.ReadLine()
		if err := s.OriginalError(); err != nil {
			return err // EOF or otherwise
		}
		parts := strings.Split(l, "=")
		if len(parts) != 2 {
			return fmt.Errorf("Unexpected line: %s", l)
		}
		if _, ok := varsToAdd[parts[0]]; ok {
			numLeft--
			vars[parts[0]] = parts[1]
			if numLeft == 0 {
				break
			}
		}
	}
	return nil
}

func main() {
	if modules.IsModulesChildProcess() {
		exitOnError(modules.Dispatch(), "Failed to dispatch module")
		return
	}

	// If we ever get a SIGHUP (terminal closes), then end the program.
	signalChannel := make(chan os.Signal)
	signal.Notify(signalChannel, syscall.SIGHUP)
	go func() {
		sig := <-signalChannel
		switch sig {
		case syscall.SIGHUP:
			os.Exit(1)
		}
	}()

	// Try running the program; on failure, exit with error status code.
	if !run() {
		os.Exit(1)
	}
}

// Runs the services and cleans up afterwards.
// Returns true if the run was successful.
func run() bool {
	ctx, shutdown := v23.Init()
	defer shutdown()

	// In order to prevent conflicts, tests and webapp use different mounttable ports.
	port := 8884
	cottagePort := 8885
	housePort := 8886
	host := "localhost"

	// Start a new shell module.
	vars := map[string]string{}
	sh, err := modules.NewShell(ctx, nil, false, nil)
	if err != nil {
		panic(fmt.Sprintf("modules.NewShell: %s", err))
	}

	// Collect the output of this shell on termination.
	err = os.MkdirAll("tmp", 0750)
	exitOnError(err, "Could not make temp directory")
	outFile, err := os.Create(stdoutLog)
	exitOnError(err, "Could not open stdout log file")
	defer outFile.Close()
	errFile, err := os.Create(stderrLog)
	exitOnError(err, "Could not open stderr log file")
	defer errFile.Close()
	defer sh.Cleanup(outFile, errFile)

	// Run a mounttable for tests
	hRoot, err := sh.Start(RunMTCommand, nil, "--v23.tcp.protocol=wsh", fmt.Sprintf("--v23.tcp.address=%s:%d", host, port), "root")
	exitOnError(err, "Failed to start root mount table")
	exitOnError(updateVars(hRoot, vars, "MT_NAME"), "Failed to get MT_NAME")
	defer hRoot.Shutdown(outFile, errFile)

	// Set ref.EnvNamespacePrefix env var, consumed downstream.
	sh.SetVar(ref.EnvNamespacePrefix, vars["MT_NAME"])
	v23.GetNamespace(ctx).SetRoots(vars["MT_NAME"])

	// Run the cottage mounttable at host/cottage.
	hCottage, err := sh.Start(RunMTCommand, nil, "--v23.tcp.protocol=wsh", fmt.Sprintf("--v23.tcp.address=%s:%d", host, cottagePort), "cottage")
	exitOnError(err, "Failed to start cottage mount table")
	expect.NewSession(nil, hCottage.Stdout(), 30*time.Second)
	defer hCottage.Shutdown(outFile, errFile)

	// run the house mounttable at host/house.
	hHouse, err := sh.Start(RunMTCommand, nil, "--v23.tcp.protocol=wsh", fmt.Sprintf("--v23.tcp.address=%s:%d", host, housePort), "house")
	exitOnError(err, "Failed to start house mount table")
	expect.NewSession(nil, hHouse.Stdout(), 30*time.Second)
	defer hHouse.Shutdown(outFile, errFile)

	// Just print out the collected variables. This is for debugging purposes.
	bytes, err := json.Marshal(vars)
	exitOnError(err, "Failed to marshal the collected variables")
	fmt.Println(string(bytes))

	// Also set HOUSE_MOUNTTABLE (used in the tests)
	os.Setenv("HOUSE_MOUNTTABLE", fmt.Sprintf("/%s:%d", host, housePort))

	lspec := v23.GetListenSpec(ctx)
	lspec.Addrs = rpc.ListenAddrs{{"wsh", ":0"}}
	// Allow all processes started by this runner to use the proxy.
	proxyACL := access.AccessList{In: security.DefaultBlessingPatterns(v23.GetPrincipal(ctx))}
	proxyShutdown, proxyEndpoint, err := generic.NewProxy(ctx, lspec, proxyACL, "test/proxy")
	exitOnError(err, "Failed to start proxy")
	defer proxyShutdown()
	vars["PROXY_NAME"] = proxyEndpoint.Name()

	hIdentityd, err := sh.Start(identitylib.TestIdentitydCommand, nil, "--v23.tcp.protocol=wsh", "--v23.tcp.address=:0", "--v23.proxy=test/proxy", "--http-addr=localhost:0")
	exitOnError(err, "Failed to start identityd")
	exitOnError(updateVars(hIdentityd, vars, "TEST_IDENTITYD_NAME", "TEST_IDENTITYD_HTTP_ADDR"), "Failed to obtain identityd address")
	defer hIdentityd.Shutdown(outFile, errFile)

	// Setup a lot of environment variables; these are used for the tests and building the test extension.
	os.Setenv(ref.EnvNamespacePrefix, vars["MT_NAME"])
	os.Setenv("PROXY_ADDR", vars["PROXY_NAME"])
	os.Setenv("IDENTITYD", fmt.Sprintf("%s/google", vars["TEST_IDENTITYD_NAME"]))
	os.Setenv("IDENTITYD_BLESSING_URL", fmt.Sprintf("%s/auth/blessing-root", vars["TEST_IDENTITYD_HTTP_ADDR"]))
	os.Setenv("DEBUG", "false")

	testsOk := runProva()

	fmt.Println("Cleaning up launched services...")
	return testsOk

	// Not in a test, so run until the program is killed.
	<-signals.ShutdownOnSignals(ctx)
	return true
}

// Run the prova tests and convert its tap output to xunit.
func runProva() bool {
	// This is also useful information for routing the test output.
	V23_ROOT := os.Getenv("V23_ROOT")
	VANADIUM_JS := fmt.Sprintf("%s/release/javascript/core", V23_ROOT)
	VANADIUM_BROWSER := fmt.Sprintf("%s/release/projects/browser", V23_ROOT)

	TAP_XUNIT := fmt.Sprintf("%s/node_modules/.bin/tap-xunit", VANADIUM_BROWSER)
	XUNIT_OUTPUT_FILE := os.Getenv("XUNIT_OUTPUT_FILE")
	if XUNIT_OUTPUT_FILE == "" {
		XUNIT_OUTPUT_FILE = fmt.Sprintf("%s/test_output.xml", os.Getenv("TMPDIR"))
	}
	TAP_XUNIT_OPTIONS := " --package=namespace-browser"

	// Make sure we're in the right folder when we run make test-extension.
	vbroot, err := os.Open(VANADIUM_BROWSER)
	exitOnError(err, "Failed to open vanadium browser dir")
	err = vbroot.Chdir()
	exitOnError(err, "Failed to change to vanadium browser dir")

	// Make the test-extension, this should also remove the old one.
	fmt.Println("Rebuilding test extension...")
	cmdExtensionClean := exec.Command("rm", "-fr", fmt.Sprintf("%s/extension/build-test", VANADIUM_JS))
	err = cmdExtensionClean.Run()
	exitOnError(err, "Failed to clean test extension")
	cmdExtensionBuild := exec.Command("make", "-C", fmt.Sprintf("%s/extension", VANADIUM_JS), "build-test")
	err = cmdExtensionBuild.Run()
	exitOnError(err, "Failed to build test extension")

	// These are the basic prova options.
	options := []string{
		"test/**/*.js",
		"--browser",
		"--includeFilenameAsPackage",
		"--launch",
		"chrome",
		"--plugin",
		"proxyquireify/plugin",
		"--transform",
		"envify,./main-transform",
		"--log",
		"tmp/chrome.log",
		fmt.Sprintf("--options=--load-extension=%s/extension/build-test/,--ignore-certificate-errors,--enable-logging=stderr", VANADIUM_JS),
	}

	// Normal tests have a few more options and a different port from the watch tests.
	var PROVA_PORT int
	if !runTestsWatch {
		PROVA_PORT = 8893
		options = append(options, "--headless", "--quit", "--progress", "--tap")
		fmt.Printf("\033[34m-Executing tests. See %s for test xunit output.\033[0m\n", XUNIT_OUTPUT_FILE)
	} else {
		PROVA_PORT = 8894
		fmt.Println("\033[34m-Running tests in watch mode.\033[0m")
	}
	options = append(options, "--port", fmt.Sprintf("%d", PROVA_PORT))

	// This is the prova command.
	cmdProva := exec.Command(
		fmt.Sprintf("%s/node_modules/.bin/prova", VANADIUM_BROWSER),
		options...,
	)
	fmt.Printf("\033[34m-Go to \033[32mhttp://0.0.0.0:%d\033[34m to see tests running.\033[0m\n", PROVA_PORT)
	fmt.Println(cmdProva)

	// Collect the prova stdout. This information needs to be sent to xunit.
	provaOut, err := cmdProva.StdoutPipe()
	exitOnError(err, "Failed to get prova stdout pipe")

	// Setup the tap to xunit command. It uses Prova's stdout as input.
	// The output will got the xunit output file.
	cmdTap := exec.Command(TAP_XUNIT, TAP_XUNIT_OPTIONS)
	cmdTap.Stdin = io.TeeReader(provaOut, os.Stdout) // Tee the prova output to see it on the console too.
	outfile, err := os.Create(XUNIT_OUTPUT_FILE)
	exitOnError(err, "Failed to create xunit output file")
	defer outfile.Close()
	bufferedWriter := bufio.NewWriter(outfile)
	cmdTap.Stdout = bufferedWriter
	defer bufferedWriter.Flush() // Ensure that the full xunit output is written.

	// We start the tap command...
	err = cmdTap.Start()
	exitOnError(err, "Failed to start tap to xunit command")

	// Meanwhile, run Prova to completion. If there was an error, print ERROR, otherwise PASS.
	err = cmdProva.Run()
	testsOk := true
	if err != nil {
		fmt.Println(err)
		fmt.Println("\033[31m\033[1mERROR\033[0m")
		testsOk = false
	} else {
		fmt.Println("\033[32m\033[1mPASS\033[0m")
	}

	// Wait for tap to xunit to finish itself off. This file will be ready for reading by Jenkins.
	fmt.Println("Converting Tap output to XUnit")
	err = cmdTap.Wait()
	exitOnError(err, "Failed tap to xunit conversion")

	return testsOk
}
<commit_msg>browser: Change test/modules registration mechanism.<commit_after>// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"os"
	"os/exec"
	"os/signal"
	"strings"
	"syscall"
	"time"

	"v.io/v23"
	"v.io/v23/options"
	"v.io/v23/rpc"
	"v.io/v23/security"
	"v.io/v23/security/access"

	"v.io/x/ref"
	"v.io/x/ref/runtime/factories/generic"
	"v.io/x/ref/services/identity/identitylib"
	"v.io/x/ref/services/mounttable/mounttablelib"
	"v.io/x/ref/test/expect"
	"v.io/x/ref/test/modules"
)

const (
	stdoutLog = "tmp/runner.stdout.log" // Used as stdout drain when shutting down.
	stderrLog = "tmp/runner.stderr.log" // Used as stderr drain when shutting down.
)

var (
	runTestsWatch bool
)

func init() {
	flag.BoolVar(&runTestsWatch, "runTestsWatch", false, "if true runs the tests in watch mode")
}

var runMT = modules.Register(func(env *modules.Env, args ...string) error {
	ctx, shutdown := v23.Init()
	defer shutdown()

	lspec := v23.GetListenSpec(ctx)
	server, err := v23.NewServer(ctx, options.ServesMountTable(true))
	if err != nil {
		return fmt.Errorf("root failed: %v", err)
	}
	mp := args[0]
	mt, err := mounttablelib.NewMountTableDispatcher("", "", "mounttable")
	if err != nil {
		return fmt.Errorf("mounttablelib.NewMountTableDispatcher failed: %s", err)
	}
	eps, err := server.Listen(lspec)
	if err != nil {
		return fmt.Errorf("server.Listen failed: %s", err)
	}
	if err := server.ServeDispatcher(mp, mt); err != nil {
		return fmt.Errorf("root failed: %s", err)
	}
	fmt.Fprintf(env.Stdout, "PID=%d\n", os.Getpid())
	for _, ep := range eps {
		fmt.Fprintf(env.Stdout, "MT_NAME=%s\n", ep.Name())
	}
	modules.WaitForEOF(env.Stdin)
	return nil
}, "runMT")

// Helper function to simply print an error and then exit.
func exitOnError(err error, desc string) {
	if err != nil {
		fmt.Fprintln(os.Stderr, desc, err)
		os.Exit(1)
	}
}

// updateVars captures the vars from the given Handle's stdout and adds them to
// the given vars map, overwriting existing entries.
func updateVars(h modules.Handle, vars map[string]string, varNames ...string) error {
	varsToAdd := map[string]bool{}
	for _, v := range varNames {
		varsToAdd[v] = true
	}
	numLeft := len(varsToAdd)

	s := expect.NewSession(nil, h.Stdout(), 30*time.Second)
	for {
		l := s.ReadLine()
		if err := s.OriginalError(); err != nil {
			return err // EOF or otherwise
		}
		parts := strings.Split(l, "=")
		if len(parts) != 2 {
			return fmt.Errorf("Unexpected line: %s", l)
		}
		if _, ok := varsToAdd[parts[0]]; ok {
			numLeft--
			vars[parts[0]] = parts[1]
			if numLeft == 0 {
				break
			}
		}
	}
	return nil
}

func main() {
	if modules.IsChildProcess() {
		exitOnError(modules.Dispatch(), "Failed to dispatch module")
		return
	}

	// If we ever get a SIGHUP (terminal closes), then end the program.
	signalChannel := make(chan os.Signal)
	signal.Notify(signalChannel, syscall.SIGHUP)
	go func() {
		sig := <-signalChannel
		switch sig {
		case syscall.SIGHUP:
			os.Exit(1)
		}
	}()

	// Try running the program; on failure, exit with error status code.
	if !run() {
		os.Exit(1)
	}
}

// Runs the services and cleans up afterwards.
// Returns true if the run was successful.
func run() bool {
	ctx, shutdown := v23.Init()
	defer shutdown()

	// In order to prevent conflicts, tests and webapp use different mounttable ports.
	port := 8884
	cottagePort := 8885
	housePort := 8886
	host := "localhost"

	// Start a new shell module.
	vars := map[string]string{}
	sh, err := modules.NewShell(ctx, nil, false, nil)
	if err != nil {
		panic(fmt.Sprintf("modules.NewShell: %s", err))
	}

	// Collect the output of this shell on termination.
	err = os.MkdirAll("tmp", 0750)
	exitOnError(err, "Could not make temp directory")
	outFile, err := os.Create(stdoutLog)
	exitOnError(err, "Could not open stdout log file")
	defer outFile.Close()
	errFile, err := os.Create(stderrLog)
	exitOnError(err, "Could not open stderr log file")
	defer errFile.Close()
	defer sh.Cleanup(outFile, errFile)

	// Run a mounttable for tests
	hRoot, err := sh.Start(nil, runMT, "--v23.tcp.protocol=wsh", fmt.Sprintf("--v23.tcp.address=%s:%d", host, port), "root")
	exitOnError(err, "Failed to start root mount table")
	exitOnError(updateVars(hRoot, vars, "MT_NAME"), "Failed to get MT_NAME")
	defer hRoot.Shutdown(outFile, errFile)

	// Set ref.EnvNamespacePrefix env var, consumed downstream.
	sh.SetVar(ref.EnvNamespacePrefix, vars["MT_NAME"])
	v23.GetNamespace(ctx).SetRoots(vars["MT_NAME"])

	// Run the cottage mounttable at host/cottage.
	hCottage, err := sh.Start(nil, runMT, "--v23.tcp.protocol=wsh", fmt.Sprintf("--v23.tcp.address=%s:%d", host, cottagePort), "cottage")
	exitOnError(err, "Failed to start cottage mount table")
	expect.NewSession(nil, hCottage.Stdout(), 30*time.Second)
	defer hCottage.Shutdown(outFile, errFile)

	// run the house mounttable at host/house.
	hHouse, err := sh.Start(nil, runMT, "--v23.tcp.protocol=wsh", fmt.Sprintf("--v23.tcp.address=%s:%d", host, housePort), "house")
	exitOnError(err, "Failed to start house mount table")
	expect.NewSession(nil, hHouse.Stdout(), 30*time.Second)
	defer hHouse.Shutdown(outFile, errFile)

	// Just print out the collected variables. This is for debugging purposes.
	bytes, err := json.Marshal(vars)
	exitOnError(err, "Failed to marshal the collected variables")
	fmt.Println(string(bytes))

	// Also set HOUSE_MOUNTTABLE (used in the tests)
	os.Setenv("HOUSE_MOUNTTABLE", fmt.Sprintf("/%s:%d", host, housePort))

	lspec := v23.GetListenSpec(ctx)
	lspec.Addrs = rpc.ListenAddrs{{"wsh", ":0"}}
	// Allow all processes started by this runner to use the proxy.
	proxyACL := access.AccessList{In: security.DefaultBlessingPatterns(v23.GetPrincipal(ctx))}
	proxyShutdown, proxyEndpoint, err := generic.NewProxy(ctx, lspec, proxyACL, "test/proxy")
	exitOnError(err, "Failed to start proxy")
	defer proxyShutdown()
	vars["PROXY_NAME"] = proxyEndpoint.Name()

	hIdentityd, err := sh.Start(nil, identitylib.TestIdentityd, "--v23.tcp.protocol=wsh", "--v23.tcp.address=:0", "--v23.proxy=test/proxy", "--http-addr=localhost:0")
	exitOnError(err, "Failed to start identityd")
	exitOnError(updateVars(hIdentityd, vars, "TEST_IDENTITYD_NAME", "TEST_IDENTITYD_HTTP_ADDR"), "Failed to obtain identityd address")
	defer hIdentityd.Shutdown(outFile, errFile)

	// Setup a lot of environment variables; these are used for the tests and building the test extension.
	os.Setenv(ref.EnvNamespacePrefix, vars["MT_NAME"])
	os.Setenv("PROXY_ADDR", vars["PROXY_NAME"])
	os.Setenv("IDENTITYD", fmt.Sprintf("%s/google", vars["TEST_IDENTITYD_NAME"]))
	os.Setenv("IDENTITYD_BLESSING_URL", fmt.Sprintf("%s/auth/blessing-root", vars["TEST_IDENTITYD_HTTP_ADDR"]))
	os.Setenv("DEBUG", "false")

	testsOk := runProva()

	fmt.Println("Cleaning up launched services...")
	return testsOk
}

// Run the prova tests and convert its tap output to xunit.
func runProva() bool {
	// This is also useful information for routing the test output.
	V23_ROOT := os.Getenv("V23_ROOT")
	VANADIUM_JS := fmt.Sprintf("%s/release/javascript/core", V23_ROOT)
	VANADIUM_BROWSER := fmt.Sprintf("%s/release/projects/browser", V23_ROOT)

	TAP_XUNIT := fmt.Sprintf("%s/node_modules/.bin/tap-xunit", VANADIUM_BROWSER)
	XUNIT_OUTPUT_FILE := os.Getenv("XUNIT_OUTPUT_FILE")
	if XUNIT_OUTPUT_FILE == "" {
		XUNIT_OUTPUT_FILE = fmt.Sprintf("%s/test_output.xml", os.Getenv("TMPDIR"))
	}
	TAP_XUNIT_OPTIONS := " --package=namespace-browser"

	// Make sure we're in the right folder when we run make test-extension.
	vbroot, err := os.Open(VANADIUM_BROWSER)
	exitOnError(err, "Failed to open vanadium browser dir")
	err = vbroot.Chdir()
	exitOnError(err, "Failed to change to vanadium browser dir")

	// Make the test-extension, this should also remove the old one.
	fmt.Println("Rebuilding test extension...")
	cmdExtensionClean := exec.Command("rm", "-fr", fmt.Sprintf("%s/extension/build-test", VANADIUM_JS))
	err = cmdExtensionClean.Run()
	exitOnError(err, "Failed to clean test extension")
	cmdExtensionBuild := exec.Command("make", "-C", fmt.Sprintf("%s/extension", VANADIUM_JS), "build-test")
	err = cmdExtensionBuild.Run()
	exitOnError(err, "Failed to build test extension")

	// These are the basic prova options.
	options := []string{
		"test/**/*.js",
		"--browser",
		"--includeFilenameAsPackage",
		"--launch",
		"chrome",
		"--plugin",
		"proxyquireify/plugin",
		"--transform",
		"envify,./main-transform",
		"--log",
		"tmp/chrome.log",
		fmt.Sprintf("--options=--load-extension=%s/extension/build-test/,--ignore-certificate-errors,--enable-logging=stderr", VANADIUM_JS),
	}

	// Normal tests have a few more options and a different port from the watch tests.
	var PROVA_PORT int
	if !runTestsWatch {
		PROVA_PORT = 8893
		options = append(options, "--headless", "--quit", "--progress", "--tap")
		fmt.Printf("\033[34m-Executing tests. See %s for test xunit output.\033[0m\n", XUNIT_OUTPUT_FILE)
	} else {
		PROVA_PORT = 8894
		fmt.Println("\033[34m-Running tests in watch mode.\033[0m")
	}
	options = append(options, "--port", fmt.Sprintf("%d", PROVA_PORT))

	// This is the prova command.
	cmdProva := exec.Command(
		fmt.Sprintf("%s/node_modules/.bin/prova", VANADIUM_BROWSER),
		options...,
	)
	fmt.Printf("\033[34m-Go to \033[32mhttp://0.0.0.0:%d\033[34m to see tests running.\033[0m\n", PROVA_PORT)
	fmt.Println(cmdProva)

	// Collect the prova stdout. This information needs to be sent to xunit.
	provaOut, err := cmdProva.StdoutPipe()
	exitOnError(err, "Failed to get prova stdout pipe")

	// Setup the tap to xunit command. It uses Prova's stdout as input.
	// The output will got the xunit output file.
	cmdTap := exec.Command(TAP_XUNIT, TAP_XUNIT_OPTIONS)
	cmdTap.Stdin = io.TeeReader(provaOut, os.Stdout) // Tee the prova output to see it on the console too.
	outfile, err := os.Create(XUNIT_OUTPUT_FILE)
	exitOnError(err, "Failed to create xunit output file")
	defer outfile.Close()
	bufferedWriter := bufio.NewWriter(outfile)
	cmdTap.Stdout = bufferedWriter
	defer bufferedWriter.Flush() // Ensure that the full xunit output is written.

	// We start the tap command...
	err = cmdTap.Start()
	exitOnError(err, "Failed to start tap to xunit command")

	// Meanwhile, run Prova to completion. If there was an error, print ERROR, otherwise PASS.
	err = cmdProva.Run()
	testsOk := true
	if err != nil {
		fmt.Println(err)
		fmt.Println("\033[31m\033[1mERROR\033[0m")
		testsOk = false
	} else {
		fmt.Println("\033[32m\033[1mPASS\033[0m")
	}

	// Wait for tap to xunit to finish itself off. This file will be ready for reading by Jenkins.
	fmt.Println("Converting Tap output to XUnit")
	err = cmdTap.Wait()
	exitOnError(err, "Failed tap to xunit conversion")

	return testsOk
}
<|endoftext|>