<commit_before>package neurgo

import (
	"testing"
	"github.com/couchbaselabs/go.assert"
	"sync"
)

type Wiretap struct {
	Node
}

type Injector struct {
	Node
}

func TestConnectBidirectional(t *testing.T) {

	neuron := &Neuron{}
	sensor := &Sensor{}

	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron, weights)

	assert.Equals(t, len(sensor.outbound), 1)
	assert.Equals(t, len(neuron.inbound), 1)
	assert.True(t, neuron.inbound[0].channel != nil)
	assert.True(t, sensor.outbound[0].channel != nil)
	assert.Equals(t, len(neuron.inbound[0].weights), len(weights))
	assert.Equals(t, neuron.inbound[0].weights[0], weights[0])

	actuator := &Actuator{}
	neuron.ConnectBidirectional(actuator)
	assert.Equals(t, len(neuron.outbound), 1)
	assert.Equals(t, len(actuator.inbound), 1)
	assert.Equals(t, len(actuator.inbound[0].weights), 0)

}

func TestNetwork(t *testing.T) {

	// create network nodes
	neuron1 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	neuron2 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	sensor := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector := &Injector{}

	// connect nodes together
	injector.ConnectBidirectional(sensor)
	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron1, weights)
	sensor.ConnectBidirectionalWeighted(neuron2, weights)
	neuron1.ConnectBidirectional(actuator)
	neuron2.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{neuron1, neuron2, sensor, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	// inject a value into sensor
	go func() {
		testValue := []float64{1,1,1,1,1}
		injector.outbound[0].channel <- testValue
		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {
		value := <- wiretap.inbound[0].channel
		assert.Equals(t, len(value), 2)
		assert.Equals(t, value[0], float64(110))
		assert.Equals(t, value[1], float64(110))
		wg.Done()
	}()

	wg.Wait()

}

func identity_activation(x float64) float64 {
	return x
}
<commit_msg>add xnor test, so far it seems to be working (still need to assert all cases)<commit_after>package neurgo

import (
	"testing"
	"github.com/couchbaselabs/go.assert"
	"sync"
	"log"
)

type Wiretap struct {
	Node
}

type Injector struct {
	Node
}

func TestConnectBidirectional(t *testing.T) {

	neuron := &Neuron{}
	sensor := &Sensor{}

	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron, weights)

	assert.Equals(t, len(sensor.outbound), 1)
	assert.Equals(t, len(neuron.inbound), 1)
	assert.True(t, neuron.inbound[0].channel != nil)
	assert.True(t, sensor.outbound[0].channel != nil)
	assert.Equals(t, len(neuron.inbound[0].weights), len(weights))
	assert.Equals(t, neuron.inbound[0].weights[0], weights[0])

	actuator := &Actuator{}
	neuron.ConnectBidirectional(actuator)
	assert.Equals(t, len(neuron.outbound), 1)
	assert.Equals(t, len(actuator.inbound), 1)
	assert.Equals(t, len(actuator.inbound[0].weights), 0)

}

func TestNetwork(t *testing.T) {

	// create network nodes
	neuron1 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	neuron2 := &Neuron{Bias: 10, ActivationFunction: identity_activation}
	sensor := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector := &Injector{}

	// connect nodes together
	injector.ConnectBidirectional(sensor)
	weights := []float64{20,20,20,20,20}
	sensor.ConnectBidirectionalWeighted(neuron1, weights)
	sensor.ConnectBidirectionalWeighted(neuron2, weights)
	neuron1.ConnectBidirectional(actuator)
	neuron2.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{neuron1, neuron2, sensor, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	// inject a value into sensor
	go func() {
		testValue := []float64{1,1,1,1,1}
		injector.outbound[0].channel <- testValue
		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {
		value := <- wiretap.inbound[0].channel
		assert.Equals(t, len(value), 2)
		assert.Equals(t, value[0], float64(110))
		assert.Equals(t, value[1], float64(110))
		wg.Done()
	}()

	wg.Wait()

}

func TestXnorNetwork(t *testing.T) {

	// create network nodes
	input_neuron1 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	input_neuron2 := &Neuron{Bias: 0, ActivationFunction: identity_activation}
	hidden_neuron1 := &Neuron{Bias: -30, ActivationFunction: sigmoid}
	hidden_neuron2 := &Neuron{Bias: 10, ActivationFunction: sigmoid}
	output_neuron := &Neuron{Bias: 0, ActivationFunction: sigmoid}

	sensor1 := &Sensor{}
	sensor2 := &Sensor{}
	actuator := &Actuator{}
	wiretap := &Wiretap{}
	injector1 := &Injector{}
	injector2 := &Injector{}

	// connect nodes together
	injector1.ConnectBidirectional(sensor1)
	injector2.ConnectBidirectional(sensor2)
	sensor1.ConnectBidirectionalWeighted(input_neuron1, []float64{1})
	sensor2.ConnectBidirectionalWeighted(input_neuron2, []float64{1})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron1, []float64{20})
	input_neuron1.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-20})
	input_neuron2.ConnectBidirectionalWeighted(hidden_neuron2, []float64{-10})
	hidden_neuron1.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	hidden_neuron2.ConnectBidirectionalWeighted(output_neuron, []float64{20})
	output_neuron.ConnectBidirectional(actuator)
	actuator.ConnectBidirectional(wiretap)

	// spinup node goroutines
	signallers := []Signaller{input_neuron1, input_neuron2, hidden_neuron1, hidden_neuron2, output_neuron, sensor1, sensor2, actuator}
	for _, signaller := range signallers {
		go Run(signaller)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	wg.Add(1)

	// inject a value into sensor
	go func() {
		testValue1 := []float64{0}
		injector1.outbound[0].channel <- testValue1
		testValue2 := []float64{1}
		injector2.outbound[0].channel <- testValue2
		wg.Done()
	}()

	// read the value from wiretap (which taps into actuator)
	go func() {
		value := <- wiretap.inbound[0].channel
		log.Printf("Xnor - Got value from wiretap: %v", value)
		wg.Done()
	}()

	wg.Wait()

}

func identity_activation(x float64) float64 {
	return x
}
<|endoftext|>


<commit_before><commit_msg>Added additional information to the return and fixed a ranging/append bug over a slice with an initialized capacity<commit_after><|endoftext|>


<commit_before>package common

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/eris-ltd/common/go/log" // so we can flush logs on exit/ifexit
	"github.com/mitchellh/go-homedir"
)

var (
	// Convenience Directories
	GoPath  = os.Getenv("GOPATH")
	ErisLtd = filepath.Join(GoPath, "src", "github.com", "eris-ltd")
	ErisGH  = "https://github.com/eris-ltd/"
	// usr, _   = user.Current() // error?!
	ErisRoot          = ResolveErisRoot()
	ErisContainerRoot = "/home/eris/.eris" // XXX: this is used as root in the `eris/base` image

	// Major Directories
	AppsPath      = filepath.Join(ErisRoot, "apps") // previously "dapps"
	ActionsPath   = filepath.Join(ErisRoot, "actions")
	ChainsPath    = filepath.Join(ErisRoot, "chains") // previously "blockchains"
	KeysPath      = filepath.Join(ErisRoot, "keys")
	LanguagesPath = filepath.Join(ErisRoot, "languages")
	RemotesPath   = filepath.Join(ErisRoot, "remotes")
	ServicesPath  = filepath.Join(ErisRoot, "services")
	ScratchPath   = filepath.Join(ErisRoot, "scratch")

	//Deprecated Directories
	BlockchainsPath = filepath.Join(ErisRoot, "blockchains")
	DappsPath       = filepath.Join(ErisRoot, "dapps")

	// Keys
	KeysDataPath = filepath.Join(KeysPath, "data")
	KeyNamesPath = filepath.Join(KeysPath, "names")

	// Scratch Directories (globally coordinated)
	EpmScratchPath     = filepath.Join(ScratchPath, "epm")
	LllcScratchPath    = filepath.Join(ScratchPath, "lllc")
	SolcScratchPath    = filepath.Join(ScratchPath, "sol")
	SerpScratchPath    = filepath.Join(ScratchPath, "ser")
	DataContainersPath = filepath.Join(ScratchPath, "data")

	// Blockchains stuff
	HEAD            = filepath.Join(ChainsPath, "HEAD")
	Refs            = filepath.Join(ChainsPath, "refs")
	DefaultChainDir = filepath.Join(ChainsPath, "default")
)

var MajorDirs = []string{
	ErisRoot, ActionsPath, ChainsPath, DefaultChainDir, DataContainersPath, AppsPath, KeysPath, LanguagesPath, RemotesPath, ServicesPath, KeysDataPath, KeyNamesPath, ScratchPath, EpmScratchPath, LllcScratchPath, SolcScratchPath, SerpScratchPath,
}

//eris update checks if old dirs exist & migrates them
var DirsToMigrate = map[string]string{
	BlockchainsPath: ChainsPath,
	DappsPath:       AppsPath,
}

//---------------------------------------------
// user and process

func Usr() string {
	u, _ := homedir.Dir()
	return u
}

func Exit(err error) {
	status := 0
	if err != nil {
		log.Flush()
		fmt.Println(err)
		status = 1
	}
	os.Exit(status)
}

func IfExit(err error) {
	if err != nil {
		log.Flush()
		fmt.Println(err)
		os.Exit(1)
	}
}

// user and process
//---------------------------------------------------------------------------
// filesystem

func AbsolutePath(Datadir string, filename string) string {
	if filepath.IsAbs(filename) {
		return filename
	}
	return filepath.Join(Datadir, filename)
}

func InitDataDir(Datadir string) error {
	if _, err := os.Stat(Datadir); err != nil {
		if os.IsNotExist(err) {
			if err := os.MkdirAll(Datadir, 0777); err != nil {
				return err
			}
		}
	}
	return nil
}

func ResolveErisRoot() string {
	var eris string
	if os.Getenv("ERIS") != "" {
		eris = os.Getenv("ERIS")
	} else {
		if runtime.GOOS == "windows" {
			home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
			if home == "" {
				home = os.Getenv("USERPROFILE")
			}
			eris = filepath.Join(home, ".eris")
		} else {
			eris = filepath.Join(Usr(), ".eris")
		}
	}
	return eris
}

// Create the default eris tree
func InitErisDir() (err error) {
	for _, d := range MajorDirs {
		err := InitDataDir(d)
		if err != nil {
			return err
		}
	}
	if _, err = os.Stat(HEAD); err != nil {
		_, err = os.Create(HEAD)
	}
	return
}

func ClearDir(dir string) error {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, f := range fs {
		n := f.Name()
		if f.IsDir() {
			if err := os.RemoveAll(filepath.Join(dir, f.Name())); err != nil {
				return err
			}
		} else {
			if err := os.Remove(filepath.Join(dir, n)); err != nil {
				return err
			}
		}
	}
	return nil
}

func Copy(src, dst string) error {
	f, err := os.Stat(src)
	if err != nil {
		return err
	}
	if f.IsDir() {
		tmpDir, err := ioutil.TempDir(os.TempDir(), "eris_copy")
		if err != nil {
			return err
		}
		if err := copyDir(src, tmpDir); err != nil {
			return err
		}
		if err := copyDir(tmpDir, dst); err != nil {
			return err
		}
		// fi, err := os.Stat(src)
		// if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		// 	return err
		// }
		// return os.Rename(tmpDir, dst)
		return nil
	}
	return copyFile(src, dst)
}

// assumes we've done our checking
func copyDir(src, dst string) error {
	fi, err := os.Stat(src)
	if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		return err
	}
	fs, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}

	for _, f := range fs {
		s := filepath.Join(src, f.Name())
		d := filepath.Join(dst, f.Name())
		if f.IsDir() {
			if err := copyDir(s, d); err != nil {
				return err
			}
		} else {
			if err := copyFile(s, d); err != nil {
				return err
			}
		}
	}
	return nil
}

// common golang, really?
func copyFile(src, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}
	return nil
}

func WriteFile(data, path string) error {
	if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
		return err
	}
	writer, err := os.Create(filepath.Join(path))
	defer writer.Close()
	if err != nil {
		return err
	}
	writer.Write([]byte(data))
	return nil
}

// filesystem
//-------------------------------------------------------
// open text editors

func Editor(file string) error {
	editr := os.Getenv("EDITOR")
	if strings.Contains(editr, "/") {
		editr = filepath.Base(editr)
	}
	switch editr {
	case "", "vim", "vi":
		return vi(file)
	case "emacs":
		return emacs(file)
	default:
		return editor(file)
	}
	// return fmt.Errorf("Unknown editor %s", editr)
}

func emacs(file string) error {
	cmd := exec.Command("emacs", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func vi(file string) error {
	cmd := exec.Command("vim", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func editor(file string) error {
	cmd := exec.Command(os.Getenv("EDITOR"), file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<commit_msg>reorg of dirs; add personal services directory; deprecate LanguagesPath -> LanguagesScratchPath<commit_after>package common

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/eris-ltd/common/go/log" // so we can flush logs on exit/ifexit
	"github.com/mitchellh/go-homedir"
)

var (
	// Convenience Directories
	GoPath            = os.Getenv("GOPATH")
	ErisLtd           = filepath.Join(GoPath, "src", "github.com", "eris-ltd") // CSK: to deprecate
	ErisGo            = filepath.Join(GoPath, "src", "github.com", "eris-ltd") // CSK: to keep
	ErisGH            = "https://github.com/eris-ltd/"
	ErisRoot          = ResolveErisRoot()
	ErisContainerRoot = "/home/eris/.eris" // XXX: this is used as root in the `eris/base` image

	// Major Directories
	ActionsPath  = filepath.Join(ErisRoot, "actions")
	AppsPath     = filepath.Join(ErisRoot, "apps")   // previously "dapps"
	ChainsPath   = filepath.Join(ErisRoot, "chains") // previously "blockchains"
	KeysPath     = filepath.Join(ErisRoot, "keys")
	RemotesPath  = filepath.Join(ErisRoot, "remotes")
	ScratchPath  = filepath.Join(ErisRoot, "scratch")
	ServicesPath = filepath.Join(ErisRoot, "services")

	// Chains Directories
	HEAD             = filepath.Join(ChainsPath, "HEAD")
	DefaultChainPath = filepath.Join(ChainsPath, "default")
	AccountsTypePath = filepath.Join(ChainsPath, "account-types")

	// Keys Directories
	KeysDataPath = filepath.Join(KeysPath, "data")
	KeyNamesPath = filepath.Join(KeysPath, "names")

	// Scratch Directories (basically eris' cache) (globally coordinated)
	DataContainersPath   = filepath.Join(ScratchPath, "data")
	LanguagesScratchPath = filepath.Join(ScratchPath, "languages") // previously "~/.eris/languages"
	LllcScratchPath      = filepath.Join(ScratchPath, "lllc")
	SolcScratchPath      = filepath.Join(ScratchPath, "sol")
	SerpScratchPath      = filepath.Join(ScratchPath, "ser")

	// Services Directories
	PersonalServicesPath = filepath.Join(ServicesPath, "global")

	// Deprecated Directories (remove on 0.12 release)
	BlockchainsPath = filepath.Join(ErisRoot, "blockchains")
	DappsPath       = filepath.Join(ErisRoot, "dapps")
	LanguagesPath   = filepath.Join(ErisRoot, "languages")
)

var MajorDirs = []string{
	ErisRoot,
	ActionsPath,
	AppsPath,
	ChainsPath,
	DefaultChainPath,
	AccountsTypePath,
	KeysPath,
	KeysDataPath,
	KeyNamesPath,
	RemotesPath,
	ScratchPath,
	DataContainersPath,
	LanguagesScratchPath,
	LllcScratchPath,
	SolcScratchPath,
	SerpScratchPath,
	ServicesPath,
	PersonalServicesPath,
}

//eris update checks if old dirs exist & migrates them
var DirsToMigrate = map[string]string{
	BlockchainsPath: ChainsPath,
	DappsPath:       AppsPath,
	LanguagesPath:   LanguagesScratchPath,
}

//---------------------------------------------
// user and process

func Usr() string {
	u, _ := homedir.Dir()
	return u
}

func Exit(err error) {
	status := 0
	if err != nil {
		log.Flush()
		fmt.Println(err)
		status = 1
	}
	os.Exit(status)
}

func IfExit(err error) {
	if err != nil {
		log.Flush()
		fmt.Println(err)
		os.Exit(1)
	}
}

// user and process
//---------------------------------------------------------------------------
// filesystem

func AbsolutePath(Datadir string, filename string) string {
	if filepath.IsAbs(filename) {
		return filename
	}
	return filepath.Join(Datadir, filename)
}

func InitDataDir(Datadir string) error {
	if _, err := os.Stat(Datadir); err != nil {
		if os.IsNotExist(err) {
			if err := os.MkdirAll(Datadir, 0777); err != nil {
				return err
			}
		}
	}
	return nil
}

// TODO: [csk] give this a default string if folks want it somewhere besides ~/.eris ...?
func ResolveErisRoot() string {
	var eris string
	if os.Getenv("ERIS") != "" {
		eris = os.Getenv("ERIS")
	} else {
		if runtime.GOOS == "windows" {
			home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
			if home == "" {
				home = os.Getenv("USERPROFILE")
			}
			eris = filepath.Join(home, ".eris")
		} else {
			eris = filepath.Join(Usr(), ".eris")
		}
	}
	return eris
}

// Create the default eris tree
func InitErisDir() (err error) {
	for _, d := range MajorDirs {
		err := InitDataDir(d)
		if err != nil {
			return err
		}
	}
	if _, err = os.Stat(HEAD); err != nil {
		_, err = os.Create(HEAD)
	}
	return
}

func ClearDir(dir string) error {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, f := range fs {
		n := f.Name()
		if f.IsDir() {
			if err := os.RemoveAll(filepath.Join(dir, f.Name())); err != nil {
				return err
			}
		} else {
			if err := os.Remove(filepath.Join(dir, n)); err != nil {
				return err
			}
		}
	}
	return nil
}

func Copy(src, dst string) error {
	f, err := os.Stat(src)
	if err != nil {
		return err
	}
	if f.IsDir() {
		tmpDir, err := ioutil.TempDir(os.TempDir(), "eris_copy")
		if err != nil {
			return err
		}
		if err := copyDir(src, tmpDir); err != nil {
			return err
		}
		if err := copyDir(tmpDir, dst); err != nil {
			return err
		}
		return nil
	}
	return copyFile(src, dst)
}

// assumes we've done our checking
func copyDir(src, dst string) error {
	fi, err := os.Stat(src)
	if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		return err
	}
	fs, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}

	for _, f := range fs {
		s := filepath.Join(src, f.Name())
		d := filepath.Join(dst, f.Name())
		if f.IsDir() {
			if err := copyDir(s, d); err != nil {
				return err
			}
		} else {
			if err := copyFile(s, d); err != nil {
				return err
			}
		}
	}
	return nil
}

// common golang, really?
func copyFile(src, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}
	return nil
}

func WriteFile(data, path string) error {
	if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
		return err
	}
	writer, err := os.Create(filepath.Join(path))
	defer writer.Close()
	if err != nil {
		return err
	}
	writer.Write([]byte(data))
	return nil
}

// filesystem
//-------------------------------------------------------
// open text editors

func Editor(file string) error {
	editr := os.Getenv("EDITOR")
	if strings.Contains(editr, "/") {
		editr = filepath.Base(editr)
	}
	switch editr {
	case "", "vim", "vi":
		return vi(file)
	case "emacs":
		return emacs(file)
	default:
		return editor(file)
	}
}

func emacs(file string) error {
	cmd := exec.Command("emacs", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func vi(file string) error {
	cmd := exec.Command("vim", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func editor(file string) error {
	cmd := exec.Command(os.Getenv("EDITOR"), file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<|endoftext|>


<commit_before>package common

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/eris-ltd/common/go/log" // so we can flush logs on exit/ifexit
	"github.com/mitchellh/go-homedir"
)

var (
	// Convenience Directories
	GoPath            = os.Getenv("GOPATH")
	ErisLtd           = filepath.Join(GoPath, "src", "github.com", "eris-ltd") // CSK: to deprecate
	ErisGo            = filepath.Join(GoPath, "src", "github.com", "eris-ltd") // CSK: to keep
	ErisGH            = "https://github.com/eris-ltd/"
	ErisRoot          = ResolveErisRoot()
	ErisContainerRoot = "/home/eris/.eris" // XXX: this is used as root in the `eris/base` image

	// Major Directories
	ActionsPath  = filepath.Join(ErisRoot, "actions")
	AppsPath     = filepath.Join(ErisRoot, "apps")   // previously "dapps"
	ChainsPath   = filepath.Join(ErisRoot, "chains") // previously "blockchains"
	KeysPath     = filepath.Join(ErisRoot, "keys")
	RemotesPath  = filepath.Join(ErisRoot, "remotes")
	ScratchPath  = filepath.Join(ErisRoot, "scratch")
	ServicesPath = filepath.Join(ErisRoot, "services")

	// Chains Directories
	HEAD             = filepath.Join(ChainsPath, "HEAD")
	DefaultChainPath = filepath.Join(ChainsPath, "default")
	AccountsTypePath = filepath.Join(ChainsPath, "account-types")

	// Keys Directories
	KeysDataPath = filepath.Join(KeysPath, "data")
	KeyNamesPath = filepath.Join(KeysPath, "names")

	// Scratch Directories (basically eris' cache) (globally coordinated)
	DataContainersPath   = filepath.Join(ScratchPath, "data")
	LanguagesScratchPath = filepath.Join(ScratchPath, "languages") // previously "~/.eris/languages"
	LllcScratchPath      = filepath.Join(ScratchPath, "lllc")
	SolcScratchPath      = filepath.Join(ScratchPath, "sol")
	SerpScratchPath      = filepath.Join(ScratchPath, "ser")

	// Services Directories
	PersonalServicesPath = filepath.Join(ServicesPath, "global")

	// Deprecated Directories (remove on 0.12 release)
	BlockchainsPath = filepath.Join(ErisRoot, "blockchains")
	DappsPath       = filepath.Join(ErisRoot, "dapps")
	LanguagesPath   = filepath.Join(ErisRoot, "languages")
)

var MajorDirs = []string{
	ErisRoot,
	ActionsPath,
	AppsPath,
	ChainsPath,
	DefaultChainPath,
	AccountsTypePath,
	KeysPath,
	KeysDataPath,
	KeyNamesPath,
	RemotesPath,
	ScratchPath,
	DataContainersPath,
	LanguagesScratchPath,
	LllcScratchPath,
	SolcScratchPath,
	SerpScratchPath,
	ServicesPath,
	PersonalServicesPath,
}

//eris update checks if old dirs exist & migrates them
var DirsToMigrate = map[string]string{
	BlockchainsPath: ChainsPath,
	DappsPath:       AppsPath,
	LanguagesPath:   LanguagesScratchPath,
}

//---------------------------------------------
// user and process

func Usr() string {
	u, _ := homedir.Dir()
	return u
}

func Exit(err error) {
	status := 0
	if err != nil {
		log.Flush()
		fmt.Println(err)
		status = 1
	}
	os.Exit(status)
}

func IfExit(err error) {
	if err != nil {
		log.Flush()
		fmt.Println(err)
		os.Exit(1)
	}
}

// user and process
//---------------------------------------------------------------------------
// filesystem

func AbsolutePath(Datadir string, filename string) string {
	if filepath.IsAbs(filename) {
		return filename
	}
	return filepath.Join(Datadir, filename)
}

func InitDataDir(Datadir string) error {
	if _, err := os.Stat(Datadir); err != nil {
		if os.IsNotExist(err) {
			if err := os.MkdirAll(Datadir, 0777); err != nil {
				return err
			}
		}
	}
	return nil
}

// TODO: [csk] give this a default string if folks want it somewhere besides ~/.eris ...?
func ResolveErisRoot() string {
	var eris string
	if os.Getenv("ERIS") != "" {
		eris = os.Getenv("ERIS")
	} else {
		if runtime.GOOS == "windows" {
			home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
			if home == "" {
				home = os.Getenv("USERPROFILE")
			}
			eris = filepath.Join(home, ".eris")
		} else {
			eris = filepath.Join(Usr(), ".eris")
		}
	}
	return eris
}

// Create the default eris tree
func InitErisDir() (err error) {
	for _, d := range MajorDirs {
		err := InitDataDir(d)
		if err != nil {
			return err
		}
	}
	if _, err = os.Stat(HEAD); err != nil {
		_, err = os.Create(HEAD)
	}
	return
}

func ClearDir(dir string) error {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, f := range fs {
		n := f.Name()
		if f.IsDir() {
			if err := os.RemoveAll(filepath.Join(dir, f.Name())); err != nil {
				return err
			}
		} else {
			if err := os.Remove(filepath.Join(dir, n)); err != nil {
				return err
			}
		}
	}
	return nil
}

func Copy(src, dst string) error {
	f, err := os.Stat(src)
	if err != nil {
		return err
	}
	if f.IsDir() {
		tmpDir, err := ioutil.TempDir(os.TempDir(), "eris_copy")
		if err != nil {
			return err
		}
		if err := copyDir(src, tmpDir); err != nil {
			return err
		}
		if err := copyDir(tmpDir, dst); err != nil {
			return err
		}
		return nil
	}
	return copyFile(src, dst)
}

// assumes we've done our checking
func copyDir(src, dst string) error {
	fi, err := os.Stat(src)
	if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		return err
	}
	fs, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}

	for _, f := range fs {
		s := filepath.Join(src, f.Name())
		d := filepath.Join(dst, f.Name())
		if f.IsDir() {
			if err := copyDir(s, d); err != nil {
				return err
			}
		} else {
			if err := copyFile(s, d); err != nil {
				return err
			}
		}
	}
	return nil
}

// common golang, really?
func copyFile(src, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}
	return nil
}

func WriteFile(data, path string) error {
	if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
		return err
	}
	writer, err := os.Create(filepath.Join(path))
	defer writer.Close()
	if err != nil {
		return err
	}
	writer.Write([]byte(data))
	return nil
}

// filesystem
//-------------------------------------------------------
// open text editors

func Editor(file string) error {
	editr := os.Getenv("EDITOR")
	if strings.Contains(editr, "/") {
		editr = filepath.Base(editr)
	}
	switch editr {
	case "", "vim", "vi":
		return vi(file)
	case "emacs":
		return emacs(file)
	default:
		return editor(file)
	}
}

func emacs(file string) error {
	cmd := exec.Command("emacs", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func vi(file string) error {
	cmd := exec.Command("vim", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func editor(file string) error {
	cmd := exec.Command(os.Getenv("EDITOR"), file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<commit_msg>add some more layering to dirs<commit_after>package common

import (
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"runtime"
	"strings"

	"github.com/eris-ltd/common/go/log" // so we can flush logs on exit/ifexit
	"github.com/mitchellh/go-homedir"
)

var (
	// Convenience Directories
	GoPath            = os.Getenv("GOPATH")
	ErisLtd           = filepath.Join(GoPath, "src", "github.com", "eris-ltd") // CSK: to deprecate
	ErisGo            = filepath.Join(GoPath, "src", "github.com", "eris-ltd") // CSK: to keep
	ErisGH            = "https://github.com/eris-ltd/"
	ErisRoot          = ResolveErisRoot()
	ErisContainerRoot = "/home/eris/.eris" // XXX: this is used as root in the `eris/base` image

	// Major Directories
	ActionsPath  = filepath.Join(ErisRoot, "actions")
	AppsPath     = filepath.Join(ErisRoot, "apps")   // previously "dapps"
	ChainsPath   = filepath.Join(ErisRoot, "chains") // previously "blockchains"
	KeysPath     = filepath.Join(ErisRoot, "keys")
	RemotesPath  = filepath.Join(ErisRoot, "remotes")
	ScratchPath  = filepath.Join(ErisRoot, "scratch")
	ServicesPath = filepath.Join(ErisRoot, "services")

	// Chains Directories
	HEAD             = filepath.Join(ChainsPath, "HEAD")
	DefaultChainPath = filepath.Join(ChainsPath, "default")
	AccountsTypePath = filepath.Join(ChainsPath, "account-types")

	// Keys Directories
	KeysDataPath = filepath.Join(KeysPath, "data")
	KeyNamesPath = filepath.Join(KeysPath, "names")

	// Scratch Directories (basically eris' cache) (globally coordinated)
	DataContainersPath   = filepath.Join(ScratchPath, "data")
	LanguagesScratchPath = filepath.Join(ScratchPath, "languages") // previously "~/.eris/languages"
	LllcScratchPath      = filepath.Join(ScratchPath, "lllc")
	SolcScratchPath      = filepath.Join(ScratchPath, "sol")
	SerpScratchPath      = filepath.Join(ScratchPath, "ser")

	// Services Directories
	PersonalServicesPath = filepath.Join(ServicesPath, "global")

	// Deprecated Directories (remove on 0.12 release)
	BlockchainsPath = filepath.Join(ErisRoot, "blockchains")
	DappsPath       = filepath.Join(ErisRoot, "dapps")
	LanguagesPath   = filepath.Join(ErisRoot, "languages")
)

var MajorDirs = []string{
	ErisRoot,
	ActionsPath,
	AppsPath,
	ChainsPath,
	DefaultChainPath,
	AccountsTypePath,
	KeysPath,
	KeysDataPath,
	KeyNamesPath,
	RemotesPath,
	ScratchPath,
	DataContainersPath,
	LanguagesScratchPath,
	LllcScratchPath,
	SolcScratchPath,
	SerpScratchPath,
	ServicesPath,
	PersonalServicesPath,
}

// These should only be used by specific tooling rather than eris-cli level
var ChainsDirs = []string{
	ChainsPath,
	DefaultChainPath,
	AccountsTypePath,
}

// These should only be used by specific tooling rather than eris-cli level
var KeysDirs = []string{
	KeysPath,
	KeysDataPath,
	KeyNamesPath,
}

// These should only be used by specific tooling rather than eris-cli level
var ServicesDirs = []string{
	ServicesPath,
	PersonalServicesPath,
}

// These should only be used by specific tooling rather than eris-cli level
var ScratchDirs = []string{
	ScratchPath,
	DataContainersPath,
	LanguagesScratchPath,
	LllcScratchPath,
	SolcScratchPath,
	SerpScratchPath,
}

//eris update checks if old dirs exist & migrates them
var DirsToMigrate = map[string]string{
	BlockchainsPath: ChainsPath,
	DappsPath:       AppsPath,
	LanguagesPath:   LanguagesScratchPath,
}

//---------------------------------------------
// user and process

func Usr() string {
	u, _ := homedir.Dir()
	return u
}

func Exit(err error) {
	status := 0
	if err != nil {
		log.Flush()
		fmt.Println(err)
		status = 1
	}
	os.Exit(status)
}

func IfExit(err error) {
	if err != nil {
		log.Flush()
		fmt.Println(err)
		os.Exit(1)
	}
}

// user and process
//---------------------------------------------------------------------------
// filesystem

func AbsolutePath(Datadir string, filename string) string {
	if filepath.IsAbs(filename) {
		return filename
	}
	return filepath.Join(Datadir, filename)
}

func InitDataDir(Datadir string) error {
	if _, err := os.Stat(Datadir); err != nil {
		if os.IsNotExist(err) {
			if err := os.MkdirAll(Datadir, 0777); err != nil {
				return err
			}
		}
	}
	return nil
}

// TODO: [csk] give this a default string if folks want it somewhere besides ~/.eris ...?
func ResolveErisRoot() string {
	var eris string
	if os.Getenv("ERIS") != "" {
		eris = os.Getenv("ERIS")
	} else {
		if runtime.GOOS == "windows" {
			home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
			if home == "" {
				home = os.Getenv("USERPROFILE")
			}
			eris = filepath.Join(home, ".eris")
		} else {
			eris = filepath.Join(Usr(), ".eris")
		}
	}
	return eris
}

// Create the default eris tree
func InitErisDir() (err error) {
	for _, d := range MajorDirs {
		err := InitDataDir(d)
		if err != nil {
			return err
		}
	}
	if _, err = os.Stat(HEAD); err != nil {
		_, err = os.Create(HEAD)
	}
	return
}

func ClearDir(dir string) error {
	fs, err := ioutil.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, f := range fs {
		n := f.Name()
		if f.IsDir() {
			if err := os.RemoveAll(filepath.Join(dir, f.Name())); err != nil {
				return err
			}
		} else {
			if err := os.Remove(filepath.Join(dir, n)); err != nil {
				return err
			}
		}
	}
	return nil
}

func Copy(src, dst string) error {
	f, err := os.Stat(src)
	if err != nil {
		return err
	}
	if f.IsDir() {
		tmpDir, err := ioutil.TempDir(os.TempDir(), "eris_copy")
		if err != nil {
			return err
		}
		if err := copyDir(src, tmpDir); err != nil {
			return err
		}
		if err := copyDir(tmpDir, dst); err != nil {
			return err
		}
		return nil
	}
	return copyFile(src, dst)
}

// assumes we've done our checking
func copyDir(src, dst string) error {
	fi, err := os.Stat(src)
	if err := os.MkdirAll(dst, fi.Mode()); err != nil {
		return err
	}
	fs, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}

	for _, f := range fs {
		s := filepath.Join(src, f.Name())
		d := filepath.Join(dst, f.Name())
		if f.IsDir() {
			if err := copyDir(s, d); err != nil {
				return err
			}
		} else {
			if err := copyFile(s, d); err != nil {
				return err
			}
		}
	}
	return nil
}

// common golang, really?
func copyFile(src, dst string) error {
	r, err := os.Open(src)
	if err != nil {
		return err
	}
	defer r.Close()

	w, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer w.Close()

	_, err = io.Copy(w, r)
	if err != nil {
		return err
	}
	return nil
}

func WriteFile(data, path string) error {
	if err := os.MkdirAll(filepath.Dir(path), 0775); err != nil {
		return err
	}
	writer, err := os.Create(filepath.Join(path))
	defer writer.Close()
	if err != nil {
		return err
	}
	writer.Write([]byte(data))
	return nil
}

// filesystem
//-------------------------------------------------------
// open text editors

func Editor(file string) error {
	editr := os.Getenv("EDITOR")
	if strings.Contains(editr, "/") {
		editr = filepath.Base(editr)
	}
	switch editr {
	case "", "vim", "vi":
		return vi(file)
	case "emacs":
		return emacs(file)
	default:
		return editor(file)
	}
}

func emacs(file string) error {
	cmd := exec.Command("emacs", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func vi(file string) error {
	cmd := exec.Command("vim", file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}

func editor(file string) error {
	cmd := exec.Command(os.Getenv("EDITOR"), file)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	return cmd.Run()
}
<|endoftext|>


<commit_before>package gobottest

import "testing"

func TestAssert(t *testing.T) {
	err := ""
	errFunc = func(t *testing.T, message string) {
		err = message
	}

	Assert(t, 1, 1)
	if err != "" {
		t.Errorf("Assert failed: 1 should equal 1")
	}

	Assert(t, 1, 2)
	if err == "" {
		t.Errorf("Assert failed: 1 should not equal 2")
	}
}

func TestRefute(t *testing.T) {
	err := ""
	errFunc = func(t *testing.T, message string) {
		err = message
	}

	Refute(t, 1, 2)
	if err != "" {
		t.Errorf("Refute failed: 1 should not be 2")
	}

	Refute(t, 1, 1)
	if err == "" {
		t.Errorf("Refute failed: 1 should not be 1")
	}
}
<commit_msg>test generated error messages as well<commit_after>package gobottest

import "testing"

func TestAssert(t *testing.T) {
	err := ""
	errFunc = func(t *testing.T, message string) {
		err = message
	}

	Assert(t, 1, 1)
	if err != "" {
		t.Errorf("Assert failed: 1 should equal 1")
	}

	Assert(t, 1, 2)
	if err != `gobottest_test.go:16: 1 - "int", should equal,  2 - "int"` {
		t.Errorf("Assert failed: 1 should not equal 2")
	}
}

func TestRefute(t *testing.T) {
	err := ""
	errFunc = func(t *testing.T, message string) {
		err = message
	}

	Refute(t, 1, 2)
	if err != "" {
		t.Errorf("Refute failed: 1 should not be 2")
	}

	Refute(t, 1, 1)
	if err != `gobottest_test.go:33: 1 - "int", should not equal,  1 - "int"` {
		t.Errorf("Refute failed: 1 should not be 1")
	}
}
<|endoftext|>


<commit_before>package folder

import (
	"fmt"
	"github.com/gost-c/gost-cli/colors"
	"github.com/gost-c/gost-cli/commands/push"
	"github.com/gost-c/gost-cli/utils"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

// Run is sub command runner for push
func Run(path string, description string, notIgnoreFolder bool, ignores []string) {
	if len(ignores) == 0 {
		ignores = utils.DefaultIgnoreFolders
	}
	fmt.Println(ignores)
	f, err := GetFiles(path, notIgnoreFolder, ignores)
	if err != nil {
		utils.Fail(fmt.Sprintf("Parse files error: %s", colors.Red(err.Error())))
		return
	}
	push.PushGost(f, description)
}

// GetFiles get files from path
func GetFiles(path string, notIgnoreFolder bool, ignores []string) ([]push.File, error) {
	var fs []push.File
	igf := utils.ToMap(ignores)
	igfiles := utils.ToMap(utils.DefaultIgnoreFiles)
	err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			if isHiddenPath(path) && !notIgnoreFolder {
				fmt.Printf("%s Skip hidden folder: %15s\n", colors.Blue("-->"), colors.Red(path))
				return filepath.SkipDir
			}
			if _, ok := igf[path]; ok {
				fmt.Printf("%s Skip folder: %15s\n", colors.Blue("-->"), colors.Red(path))
				return filepath.SkipDir
			}
			fmt.Printf("%s Parse folder: %15s\n", colors.Blue("-->"), colors.Purple(path))
			return nil
		}
		if len(fs) > utils.MaxFilesCount {
			return utils.ErrMaxFilesCount
		}
		fmt.Printf("%s Reading file: %15s\n", colors.Blue("-->"), colors.Cyan(path))
		content, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}
		f := push.File{
			Filename: path,
			Content:  string(content),
		}
		_, shouldIgnore := igfiles[info.Name()]

		if f.Content != "" && !shouldIgnore {
			fs = append(fs, f)
		} else {
			fmt.Printf("%s Skip file: %15s\n", colors.Blue("-->"), colors.Red(path))
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return fs, nil
}

func isHiddenPath(p string) bool {
	arr := strings.Split(p, "/")
	for _, v := range arr {
		if v == "." || v == ".." || v == "" {
			continue
		}
		if v[:1] == "." {
			return true
		}
	}
	return false
}
<commit_msg>tweak: disable debug log<commit_after>package folder

import (
	"fmt"
	"github.com/gost-c/gost-cli/colors"
	"github.com/gost-c/gost-cli/commands/push"
	"github.com/gost-c/gost-cli/utils"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

// Run is sub command runner for push
func Run(path string, description string, notIgnoreFolder bool, ignores []string) {
	if len(ignores) == 0 {
		ignores = utils.DefaultIgnoreFolders
	}
	f, err := GetFiles(path, notIgnoreFolder, ignores)
	if err != nil {
		utils.Fail(fmt.Sprintf("Parse files error: %s", colors.Red(err.Error())))
		return
	}
	push.PushGost(f, description)
}

// GetFiles get files from path
func GetFiles(path string, notIgnoreFolder bool, ignores []string) ([]push.File, error) {
	var fs []push.File
	igf := utils.ToMap(ignores)
	igfiles := utils.ToMap(utils.DefaultIgnoreFiles)
	err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			if isHiddenPath(path) && !notIgnoreFolder {
				fmt.Printf("%s Skip hidden folder: %15s\n", colors.Blue("-->"), colors.Red(path))
				return filepath.SkipDir
			}
			if _, ok := igf[path]; ok {
				fmt.Printf("%s Skip folder: %15s\n", colors.Blue("-->"), colors.Red(path))
				return filepath.SkipDir
			}
			fmt.Printf("%s Parse folder: %15s\n", colors.Blue("-->"), colors.Purple(path))
			return nil
		}
		if len(fs) > utils.MaxFilesCount {
			return utils.ErrMaxFilesCount
		}
		fmt.Printf("%s Reading file: %15s\n", colors.Blue("-->"), colors.Cyan(path))
		content, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}
		f := push.File{
			Filename: path,
			Content:  string(content),
		}
		_, shouldIgnore := igfiles[info.Name()]

		if f.Content != "" && !shouldIgnore {
			fs = append(fs, f)
		} else {
			fmt.Printf("%s Skip file: %15s\n", colors.Blue("-->"), colors.Red(path))
		}

		return nil
	})
	if err != nil {
		return nil, err
	}

	return fs, nil
}

func isHiddenPath(p string) bool {
	arr := strings.Split(p, "/")
	for _, v := range arr {
		if v == "." || v == ".." || v == "" {
			continue
		}
		if v[:1] == "." {
			return true
		}
	}
	return false
}
<|endoftext|>


<commit_before>// This is free and unencumbered software released into the public
// domain.  For more information, see <http://unlicense.org> or the
// accompanying UNLICENSE file.

package input

import (
	"context"
	"fmt"
	"log"
	"sort"

	"github.com/nelsam/gxui"
	"github.com/nelsam/vidar/commander/bind"
	"github.com/nelsam/vidar/commander/input"
	"github.com/nelsam/vidar/editor"
)

type Binder interface {
	Bindable(name string) bind.Bindable
	Execute(bind.Bindable)
}

type textChangeHook interface {
	init(input.Editor, []rune)
	textChanged(input.Editor, []input.Edit) error
}

// Handler is vidar's default input handler.  It takes the runes typed
// and writes them to the editor's text box, allowing plugins to bind to text
// change events.
//
// It can be overridden by installing a plugin that implements
// commander.Handler.
//
// TODO: Remove the need for so much of the editor's methods.  Ideally, we should
// be able to do what we need to do with just input.Editor.  This may require
// expanding input.Editor some, but we shouldn't need editor.Controller for so
// much of what we're doing.  Basic editing should be handleable by the editor.
type Handler struct {
	driver gxui.Driver
	binder Binder

	hooks      []textChangeHook
	applied    []AppliedChangeHook
	cancellers []Canceler
	confirmers []Confirmer
}

func New(d gxui.Driver, b Binder) *Handler {
	return &Handler{driver: d, binder: b}
}

func (e *Handler) Name() string {
	return "input-handler"
}

func (e *Handler) New() input.Handler {
	return New(e.driver, e.binder)
}

func (e *Handler) Bind(b bind.Bindable) (input.Handler, error) {
	newH := New(e.driver, e.binder)
	newH.hooks = append(newH.hooks, e.hooks...)
	newH.applied = append(newH.applied, e.applied...)
	newH.cancellers = append(newH.cancellers, e.cancellers...)
	newH.confirmers = append(newH.confirmers, e.confirmers...)

	didBind := false
	if c, isCanceler := b.(Canceler); isCanceler {
		newH.cancellers = append(newH.cancellers, c)
		didBind = true
	}

	if c, isConfirmer := b.(Confirmer); isConfirmer {
		newH.confirmers = append(newH.confirmers, c)
		didBind = true
	}

	if a, ok := b.(AppliedChangeHook); ok {
		didBind = true
		newH.applied = append(newH.applied, a)
	}
	switch src := b.(type) {
	case ChangeHook:
		didBind = true
		r := &hookReader{hook: src, driver: e.driver}
		r.start()
		newH.hooks = append(newH.hooks, r)
	case ContextChangeHook:
		didBind = true
		newH.hooks = append(newH.hooks, &ctxHookReader{hook: src, driver: newH.driver})
	}

	if !didBind {
		return nil, fmt.Errorf("input.Handler: type %T did not implement any known hook type", b)
	}

	return newH, nil
}

func (e *Handler) Init(newEditor input.Editor, contents []rune) {
	for _, h := range e.hooks {
		h.init(newEditor, contents)
	}
}

func (h *Handler) Apply(e input.Editor, edits ...input.Edit) {
	editor := e.(*editor.CodeEditor)
	c := editor.Controller()
	text := c.TextRunes()
	delta := 0
	sort.Slice(edits, func(i, j int) bool {
		return edits[i].At < edits[j].At
	})
	for i, edit := range edits {
		// It's a pretty common problem that the edit.Old and/or edit.New is
		// a slice of the actual data being edited, so copy it to preserve the
		// edit.
		edit.Old = clone(edit.Old)
		edit.New = clone(edit.New)
		edit.At += delta
		edits[i] = edit

		oldE := edit.At + len(edit.Old)
		newE := edit.At + len(edit.New)
		if oldE != newE {
			if newE > oldE {
				text = append(text, make([]rune, newE-oldE)...)
			}
			copy(text[newE:], text[oldE:])
			if oldE > newE {
				text = text[:len(text)-(oldE-newE)]
			}
		}
		copy(text[edit.At:newE], edit.New)
		delta += newE - oldE
	}
	c.Deselect(false)
	h.driver.CallSync(func() {
		c.SetTextRunesNoEvent(text)
		h.textEdited(e, edits)
	})
}

func (e *Handler) HandleEvent(focused input.Editor, ev gxui.KeyboardEvent) {
	if ev.Modifier&^gxui.ModShift != 0 {
		// This Handler, at least for now, doesn't handle key bindings.
		return
	}
	editor := focused.(*editor.CodeEditor)
	ctrl := editor.Controller()
	switch ev.Key {
	case gxui.KeyEnter:
		for _, c := range e.confirmers {
			if c.Confirm(focused) {
				return
			}
		}
		var edits []input.Edit
		for _, s := range editor.Controller().Selections() {
			if s.Start() < 0 {
				continue
			}
			edits = append(edits, input.Edit{
				At:  s.Start(),
				Old: ctrl.TextRunes()[s.Start():s.End()],
				New: []rune{'\n'},
			})
		}
		e.Apply(focused, edits...)
	case gxui.KeyEscape:
		for _, c := range e.cancellers {
			if c.Cancel(focused) {
				return
			}
		}
		for _, h := range e.hooks {
			// if esc is pressed without any cancellers waiting, cancel *all*
			// working text change hooks that can be cancelled.
			if canceler, ok := h.(Canceler); ok {
				_ = canceler.Cancel(focused)
			}
		}
	case gxui.KeyBackspace, gxui.KeyDelete:
		var edits []input.Edit
		for _, s := range editor.Controller().Selections() {
			if s.Start() < 0 {
				continue
			}
			edit := input.Edit{
				At:  s.Start(),
				Old: ctrl.TextRunes()[s.Start():s.End()],
			}
			if s.Start() == s.End() {
				if ev.Key == gxui.KeyBackspace {
					edit.At--
				}
				edit.Old = ctrl.TextRunes()[edit.At : edit.At+1]
			}
			edits = append(edits, edit)
		}
		e.Apply(focused, edits...)
	}
}

func (e *Handler) HandleInput(focused input.Editor, ev gxui.KeyStrokeEvent) {
	if ev.Modifier&^gxui.ModShift != 0 {
		return
	}
	editor := focused.(*editor.CodeEditor)
	ctrl := editor.Controller()
	var edits []input.Edit
	for _, s := range editor.Controller().Selections() {
		edits = append(edits, input.Edit{
			At:  s.Start(),
			Old: ctrl.TextRunes()[s.Start():s.End()],
			New: []rune{ev.Character},
		})
	}
	e.Apply(focused, edits...)
}

func (e *Handler) textEdited(focused input.Editor, edits []input.Edit) {
	for _, a := range e.applied {
		a.Applied(focused, edits)
	}
	for _, h := range e.hooks {
		if err := h.textChanged(focused, edits); err != nil {
			log.Printf("Hook %v failed: %s", h, err)
		}
	}
}

func clone(t []rune) []rune {
	newT := make([]rune, len(t))
	copy(newT, t)
	return newT
}

func contextDone(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		return true
	default:
		return false
	}
}
<commit_msg>Fix bug with input.Handler and delete on position 0<commit_after>// This is free and unencumbered software released into the public
// domain.  For more information, see <http://unlicense.org> or the
// accompanying UNLICENSE file.

package input

import (
	"context"
	"fmt"
	"log"
	"sort"

	"github.com/nelsam/gxui"
	"github.com/nelsam/vidar/commander/bind"
	"github.com/nelsam/vidar/commander/input"
	"github.com/nelsam/vidar/editor"
)

type Binder interface {
	Bindable(name string) bind.Bindable
	Execute(bind.Bindable)
}

type textChangeHook interface {
	init(input.Editor, []rune)
	textChanged(input.Editor, []input.Edit) error
}

// Handler is vidar's default input handler.  It takes the runes typed
// and writes them to the editor's text box, allowing plugins to bind to text
// change events.
//
// It can be overridden by installing a plugin that implements
// commander.Handler.
//
// TODO: Remove the need for so much of the editor's methods.  Ideally, we should
// be able to do what we need to do with just input.Editor.  This may require
// expanding input.Editor some, but we shouldn't need editor.Controller for so
// much of what we're doing.  Basic editing should be handleable by the editor.
type Handler struct {
	driver gxui.Driver
	binder Binder

	hooks      []textChangeHook
	applied    []AppliedChangeHook
	cancellers []Canceler
	confirmers []Confirmer
}

func New(d gxui.Driver, b Binder) *Handler {
	return &Handler{driver: d, binder: b}
}

func (e *Handler) Name() string {
	return "input-handler"
}

func (e *Handler) New() input.Handler {
	return New(e.driver, e.binder)
}

func (e *Handler) Bind(b bind.Bindable) (input.Handler, error) {
	newH := New(e.driver, e.binder)
	newH.hooks = append(newH.hooks, e.hooks...)
	newH.applied = append(newH.applied, e.applied...)
	newH.cancellers = append(newH.cancellers, e.cancellers...)
	newH.confirmers = append(newH.confirmers, e.confirmers...)

	didBind := false
	if c, isCanceler := b.(Canceler); isCanceler {
		newH.cancellers = append(newH.cancellers, c)
		didBind = true
	}

	if c, isConfirmer := b.(Confirmer); isConfirmer {
		newH.confirmers = append(newH.confirmers, c)
		didBind = true
	}

	if a, ok := b.(AppliedChangeHook); ok {
		didBind = true
		newH.applied = append(newH.applied, a)
	}
	switch src := b.(type) {
	case ChangeHook:
		didBind = true
		r := &hookReader{hook: src, driver: e.driver}
		r.start()
		newH.hooks = append(newH.hooks, r)
	case ContextChangeHook:
		didBind = true
		newH.hooks = append(newH.hooks, &ctxHookReader{hook: src, driver: newH.driver})
	}

	if !didBind {
		return nil, fmt.Errorf("input.Handler: type %T did not implement any known hook type", b)
	}

	return newH, nil
}

func (e *Handler) Init(newEditor input.Editor, contents []rune) {
	for _, h := range e.hooks {
		h.init(newEditor, contents)
	}
}

func (h *Handler) Apply(e input.Editor, edits ...input.Edit) {
	editor := e.(*editor.CodeEditor)
	c := editor.Controller()
	text := c.TextRunes()
	delta := 0
	sort.Slice(edits, func(i, j int) bool {
		return edits[i].At < edits[j].At
	})
	for i, edit := range edits {
		// It's a pretty common problem that the edit.Old and/or edit.New is
		// a slice of the actual data being edited, so copy it to preserve the
		// edit.
		edit.Old = clone(edit.Old)
		edit.New = clone(edit.New)
		edit.At += delta
		edits[i] = edit

		oldE := edit.At + len(edit.Old)
		newE := edit.At + len(edit.New)
		if oldE != newE {
			if newE > oldE {
				text = append(text, make([]rune, newE-oldE)...)
			}
			copy(text[newE:], text[oldE:])
			if oldE > newE {
				text = text[:len(text)-(oldE-newE)]
			}
		}
		copy(text[edit.At:newE], edit.New)
		delta += newE - oldE
	}
	c.Deselect(false)
	h.driver.CallSync(func() {
		c.SetTextRunesNoEvent(text)
		h.textEdited(e, edits)
	})
}

func (e *Handler) HandleEvent(focused input.Editor, ev gxui.KeyboardEvent) {
	if ev.Modifier&^gxui.ModShift != 0 {
		// This Handler, at least for now, doesn't handle key bindings.
		return
	}
	editor := focused.(*editor.CodeEditor)
	ctrl := editor.Controller()
	switch ev.Key {
	case gxui.KeyEnter:
		for _, c := range e.confirmers {
			if c.Confirm(focused) {
				return
			}
		}
		var edits []input.Edit
		for _, s := range editor.Controller().Selections() {
			if s.Start() < 0 {
				continue
			}
			edits = append(edits, input.Edit{
				At:  s.Start(),
				Old: ctrl.TextRunes()[s.Start():s.End()],
				New: []rune{'\n'},
			})
		}
		e.Apply(focused, edits...)
	case gxui.KeyEscape:
		for _, c := range e.cancellers {
			if c.Cancel(focused) {
				return
			}
		}
		for _, h := range e.hooks {
			// if esc is pressed without any cancellers waiting, cancel *all*
			// working text change hooks that can be cancelled.
			if canceler, ok := h.(Canceler); ok {
				_ = canceler.Cancel(focused)
			}
		}
	case gxui.KeyBackspace, gxui.KeyDelete:
		var edits []input.Edit
		for _, s := range editor.Controller().Selections() {
			if s.Start() < 0 {
				continue
			}
			edit := input.Edit{
				At:  s.Start(),
				Old: ctrl.TextRunes()[s.Start():s.End()],
			}
			if s.Start() == s.End() {
				if ev.Key == gxui.KeyBackspace {
					if edit.At == 0 {
						continue
					}
					edit.At--
				}
				edit.Old = ctrl.TextRunes()[edit.At : edit.At+1]
			}
			edits = append(edits, edit)
		}
		e.Apply(focused, edits...)
	}
}

func (e *Handler) HandleInput(focused input.Editor, ev gxui.KeyStrokeEvent) {
	if ev.Modifier&^gxui.ModShift != 0 {
		return
	}
	editor := focused.(*editor.CodeEditor)
	ctrl := editor.Controller()
	var edits []input.Edit
	for _, s := range editor.Controller().Selections() {
		edits = append(edits, input.Edit{
			At:  s.Start(),
			Old: ctrl.TextRunes()[s.Start():s.End()],
			New: []rune{ev.Character},
		})
	}
	e.Apply(focused, edits...)
}

func (e *Handler) textEdited(focused input.Editor, edits []input.Edit) {
	for _, a := range e.applied {
		a.Applied(focused, edits)
	}
	for _, h := range e.hooks {
		if err := h.textChanged(focused, edits); err != nil {
			log.Printf("Hook %v failed: %s", h, err)
		}
	}
}

func clone(t []rune) []rune {
	newT := make([]rune, len(t))
	copy(newT, t)
	return newT
}

func contextDone(ctx context.Context) bool {
	select {
	case <-ctx.Done():
		return true
	default:
		return false
	}
}
<|endoftext|>


<commit_before>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package node

import (
	"time"

	"github.com/ava-labs/avalanchego/utils/constants"
	"github.com/ava-labs/avalanchego/version"
)

var (
	Version                      = version.NewDefaultVersion(constants.PlatformName, 1, 4, 0)
	MinimumCompatibleVersion     = version.NewDefaultVersion(constants.PlatformName, 1, 4, 0)
	PrevMinimumCompatibleVersion = version.NewDefaultVersion(constants.PlatformName, 1, 3, 0)
	MinimumUnmaskedVersion       = version.NewDefaultVersion(constants.PlatformName, 1, 1, 0)
	PrevMinimumUnmaskedVersion   = version.NewDefaultVersion(constants.PlatformName, 1, 0, 0)
	VersionParser                = version.NewDefaultParser()

	ApricotPhase0Times = map[uint32]time.Time{
		constants.MainnetID: time.Date(2020, time.December, 8, 3, 0, 0, 0, time.UTC),
		constants.FujiID:    time.Date(2020, time.December, 5, 5, 0, 0, 0, time.UTC),
	}
	ApricotPhase0DefaultTime = time.Date(2020, time.December, 5, 5, 0, 0, 0, time.UTC)

	ApricotPhase1Times = map[uint32]time.Time{
		constants.MainnetID: time.Date(2021, time.March, 31, 14, 0, 0, 0, time.UTC),
		constants.FujiID:    time.Date(2021, time.March, 26, 14, 0, 0, 0, time.UTC),
	}
	ApricotPhase1DefaultTime = time.Date(2020, time.December, 5, 5, 0, 0, 0, time.UTC)

	ApricotPhase2Times = map[uint32]time.Time{
		constants.MainnetID: time.Date(2021, time.May, 10, 11, 0, 0, 0, time.UTC),
		constants.FujiID:    time.Date(2021, time.May, 5, 14, 0, 0, 0, time.UTC),
	}
	ApricotPhase2DefaultTime = time.Date(2020, time.December, 5, 5, 0, 0, 0, time.UTC)
)

func GetApricotPhase0Time(networkID uint32) time.Time {
	if upgradeTime, exists := ApricotPhase0Times[networkID]; exists {
		return upgradeTime
	}
	return ApricotPhase0DefaultTime
}

func GetApricotPhase1Time(networkID uint32) time.Time {
	if upgradeTime, exists := ApricotPhase1Times[networkID]; exists {
		return upgradeTime
	}
	return ApricotPhase1DefaultTime
}

func GetApricotPhase2Time(networkID uint32) time.Time {
	if upgradeTime, exists := ApricotPhase2Times[networkID]; exists {
		return upgradeTime
	}
	return ApricotPhase2DefaultTime
}
<commit_msg>version bump<commit_after>// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package node

import (
	"time"

	"github.com/ava-labs/avalanchego/utils/constants"
	"github.com/ava-labs/avalanchego/version"
)

var (
	Version                      = version.NewDefaultVersion(constants.PlatformName, 1, 4, 1)
	MinimumCompatibleVersion     = version.NewDefaultVersion(constants.PlatformName, 1, 4, 0)
	PrevMinimumCompatibleVersion = version.NewDefaultVersion(constants.PlatformName, 1, 3, 0)
	MinimumUnmaskedVersion       = version.NewDefaultVersion(constants.PlatformName, 1, 1, 0)
	PrevMinimumUnmaskedVersion   = version.NewDefaultVersion(constants.PlatformName, 1, 0, 0)
	VersionParser                = version.NewDefaultParser()

	ApricotPhase0Times = map[uint32]time.Time{
		constants.MainnetID: time.Date(2020, time.December, 8, 3, 0, 0, 0, time.UTC),
		constants.FujiID:    time.Date(2020, time.December, 5, 5, 0, 0, 0, time.UTC),
	}
	ApricotPhase0DefaultTime = time.Date(2020, time.December, 5, 5, 0, 0, 0, time.UTC)

	ApricotPhase1Times = map[uint32]time.Time{
		constants.MainnetID: time.Date(2021, time.March, 31, 14, 0, 0, 0, time.UTC),
		constants.FujiID:    time.Date(2021, time.March, 26, 14, 0, 0, 0, time.UTC),
	}
	ApricotPhase1DefaultTime = time.Date(2020, time.December, 5, 5, 0, 0, 0, time.UTC)

	ApricotPhase2Times = map[uint32]time.Time{
		constants.MainnetID: time.Date(2021, time.May, 10, 11, 0, 0, 0, time.UTC),
		constants.FujiID:    time.Date(2021, time.May, 5, 14, 0, 0, 0, time.UTC),
	}
	ApricotPhase2DefaultTime = time.Date(2020, time.December, 5, 5, 0, 0, 0, time.UTC)
)

func GetApricotPhase0Time(networkID uint32) time.Time {
	if upgradeTime, exists := ApricotPhase0Times[networkID]; exists {
		return upgradeTime
	}
	return ApricotPhase0DefaultTime
}

func GetApricotPhase1Time(networkID uint32) time.Time {
	if upgradeTime, exists := ApricotPhase1Times[networkID]; exists {
		return upgradeTime
	}
	return ApricotPhase1DefaultTime
}

func GetApricotPhase2Time(networkID uint32) time.Time {
	if upgradeTime, exists := ApricotPhase2Times[networkID]; exists {
		return upgradeTime
	}
	return ApricotPhase2DefaultTime
}
<|endoftext|>


<commit_before>package graph

import (
	"reflect"
	"testing"
)

func TestWorkingGraph(t *testing.T) {
	g := NewGraph()

	// Graph node names
	nodeNames := []string{
		"A",
		"B",
		"C",
		"D",
		"E",
	}

	// Map containing the node names and the actual node instance
	nodes := make(map[string]*Node)

	// Create nodes and add them to the graph
	for _, name := range nodeNames {
		n := NewNode(name)
		nodes[name] = n
		g.AddNode(n)
	}

	// Connect the nodes in the graph
	//
	// A
	// B -> C
	// C -> D
	// D -> E
	// E -> A
	//
	g.AddEdge(nodes["B"], nodes["C"])
	g.AddEdge(nodes["C"], nodes["D"])
	g.AddEdge(nodes["D"], nodes["E"])
	g.AddEdge(nodes["E"], nodes["A"])

	// Excepted result after topological sort
	wantSorted := []string{
		"A",
		"E",
		"D",
		"C",
		"B",
	}

	gotNodes, err := g.Sort()
	if err != nil {
		t.Error(err)
	}

	gotSorted := make([]string, 0)
	for _, node := range gotNodes {
		gotSorted = append(gotSorted, node.Name)
	}

	if !reflect.DeepEqual(wantSorted, gotSorted) {
		t.Errorf("Want %q, got %q graph", wantSorted, gotSorted)
	}
}
<commit_msg>tests: test for graphs with circular dependencies<commit_after>package graph

import (
	"reflect"
	"testing"
)

func TestWorkingGraph(t *testing.T) {
	g := NewGraph()

	// Graph node names
	nodeNames := []string{
		"A",
		"B",
		"C",
		"D",
		"E",
	}

	// Map containing the node names and the actual node instance
	nodes := make(map[string]*Node)

	// Create nodes and add them to the graph
	for _, name := range nodeNames {
		n := NewNode(name)
		nodes[name] = n
		g.AddNode(n)
	}

	// Connect the nodes in the graph
	//
	// A
	// B -> C
	// C -> D
	// D -> E
	// E -> A
	//
	g.AddEdge(nodes["B"], nodes["C"])
	g.AddEdge(nodes["C"], nodes["D"])
	g.AddEdge(nodes["D"], nodes["E"])
	g.AddEdge(nodes["E"], nodes["A"])

	// Excepted result after topological sort
	wantSorted := []string{
		"A",
		"E",
		"D",
		"C",
		"B",
	}

	gotNodes, err := g.Sort()
	if err != nil {
		t.Error(err)
	}

	gotSorted := make([]string, 0)
	for _, node := range gotNodes {
		gotSorted = append(gotSorted, node.Name)
	}

	if !reflect.DeepEqual(wantSorted, gotSorted) {
		t.Errorf("Want %q, got %q graph", wantSorted, gotSorted)
	}
}

func TestCircularGraph(t *testing.T) {
	g := NewGraph()

	// Node names
	nodeNames := []string{
		"A",
		"B",
		"C",
		"D",
		"E",
	}

	// Map containing the node names and the actual node instance
	nodes := make(map[string]*Node)

	// Create nodes and add them to the graph
	for _, name := range nodeNames {
		n := NewNode(name)
		nodes[name] = n
		g.AddNode(n)
	}

	// Connect the nodes in the graph
	//
	// A
	// B -> C
	// C -> D
	// D -> E
	// E -> D  <- Circular dependency here
	//
	g.AddEdge(nodes["B"], nodes["C"])
	g.AddEdge(nodes["C"], nodes["D"])
	g.AddEdge(nodes["D"], nodes["E"])
	g.AddEdge(nodes["E"], nodes["D"])

	_, err := g.Sort()
	if err != ErrCircularDependency {
		t.Errorf("want a circular dependency error, got %s", err)
	}
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
//

package config

import (
	"github.com/Juniper/contrail-go-api"
	"github.com/Juniper/contrail-go-api/types"
	"fmt"
	"regexp"
	"strconv"
	"strings"
)

type NetworkInfo struct {
	Uuid string
	Name string
	AdminState bool
	NetworkId int
	Transit bool
	Mode string
	Subnets []string
	Policies []string
	RouteTargets []string
}

func buildNetworkInfo(net *types.VirtualNetwork, detail bool) (
	*NetworkInfo, error) {
	var subnets []string
	var policies []string

	refList, err := net.GetNetworkIpamRefs()
	if err != nil {
		return nil, err
	}

	for _, ref := range refList {
		attr := ref.Attr.(types.VnSubnetsType)
		for _, ipamSubnet := range attr.IpamSubnets {
			subnets = append(subnets, fmt.Sprintf("%s/%d",
				ipamSubnet.Subnet.IpPrefix,
				ipamSubnet.Subnet.IpPrefixLen))
		}
	}

	if detail {
		refList, err = net.GetNetworkPolicyRefs()
		for _, ref := range refList {
			policies = append(policies, strings.Join(ref.To, ":"))
		}
	}

	info := &NetworkInfo{
		net.GetUuid(),
		net.GetName(),
		net.GetIdPerms().Enable,
		net.GetVirtualNetworkProperties().NetworkId,
		net.GetVirtualNetworkProperties().AllowTransit,
		net.GetVirtualNetworkProperties().ForwardingMode,
		subnets,
		policies,
		net.GetRouteTargetList().RouteTarget,
	}
	return info, err
}

func NetworkShow(client *contrail.Client, uuid string, detail bool) (
	*NetworkInfo, error) {
	obj, err := client.FindByUuid("virtual-network", uuid)
	if err != nil {
		return nil, err
	}
	return buildNetworkInfo(obj.(*types.VirtualNetwork), detail)
}

func NetworkList(client *contrail.Client, project_id string, detail bool) (
	[]*NetworkInfo, error) {
	fields := []string{"network_ipams"}
	if detail {
		fields = append(fields, "network_policys")
	}
	networks, err := client.ListDetailByParent(
		"virtual-network", project_id, fields, 0)
	if err != nil {
		return nil, err
	}

	var networkList []*NetworkInfo
	for _, reference := range networks {
		info, err := buildNetworkInfo(
			reference.(*types.VirtualNetwork), detail)
		if err != nil {
			return nil, err
		}
		networkList = append(networkList, info)
	}

	return networkList, nil
}

func CreateNetworkWithSubnet(
	client *contrail.Client, project_id, name, prefix string) (
		string, error) {

	expr := regexp.MustCompile(`(([0-9]{1,3}\.){3}[0-9]{1,3})/([0-9]{1,2})`)
	match := expr.FindStringSubmatch(prefix)
	if match == nil {
		return "", fmt.Errorf("Invalid subnet prefix %s", prefix)
	}
	address := match[1]
	prefixlen, _ := strconv.Atoi(match[3])

	obj, err := client.FindByUuid("project", project_id)
	if err != nil {
		return "", err
	}

	project := obj.(*types.Project)
	refList, err := project.GetNetworkIpams()
	if err != nil {
		return "", err
	}

	var ipam *types.NetworkIpam
	if len(refList) > 0 {
		obj, err := client.FindByUuid("network-ipam", refList[0].Uuid)
		if err != nil {
			return "", err
		}
		ipam = obj.(*types.NetworkIpam)
	} else {
		obj, err := client.FindByName("network-ipam",
			"default-domain:default-project:default-network-ipam")
		if err != nil {
			return "", err
		}
		ipam = obj.(*types.NetworkIpam)
	}

	net := new(types.VirtualNetwork)
	net.SetParent(project)
	net.SetName(name)

	subnets := types.VnSubnetsType{}
	subnets.AddIpamSubnets(
		&types.IpamSubnetType{
			Subnet: types.SubnetType{address, prefixlen}})
	net.AddNetworkIpam(ipam, subnets)
	err = client.Create(net)
	if err != nil {
		return "", err
	}
	return net.GetUuid(), nil
}

func CreateNetwork(client *contrail.Client, project_id, name string) (
	string, error) {

	obj, err := client.FindByUuid("project", project_id)
	if err != nil {
		return "", err
	}

	project := obj.(*types.Project)

	net := new(types.VirtualNetwork)
	net.SetParent(project)
	net.SetName(name)

	err = client.Create(net)
	if err != nil {
		return "", err
	}
	return net.GetUuid(), nil
}
<commit_msg>Use pointer to Subnet<commit_after>//
// Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
//

package config

import (
	"github.com/Juniper/contrail-go-api"
	"github.com/Juniper/contrail-go-api/types"
	"fmt"
	"regexp"
	"strconv"
	"strings"
)

type NetworkInfo struct {
	Uuid string
	Name string
	AdminState bool
	NetworkId int
	Transit bool
	Mode string
	Subnets []string
	Policies []string
	RouteTargets []string
}

func buildNetworkInfo(net *types.VirtualNetwork, detail bool) (
	*NetworkInfo, error) {
	var subnets []string
	var policies []string

	refList, err := net.GetNetworkIpamRefs()
	if err != nil {
		return nil, err
	}

	for _, ref := range refList {
		attr := ref.Attr.(types.VnSubnetsType)
		for _, ipamSubnet := range attr.IpamSubnets {
			subnets = append(subnets, fmt.Sprintf("%s/%d",
				ipamSubnet.Subnet.IpPrefix,
				ipamSubnet.Subnet.IpPrefixLen))
		}
	}

	if detail {
		refList, err = net.GetNetworkPolicyRefs()
		for _, ref := range refList {
			policies = append(policies, strings.Join(ref.To, ":"))
		}
	}

	info := &NetworkInfo{
		net.GetUuid(),
		net.GetName(),
		net.GetIdPerms().Enable,
		net.GetVirtualNetworkProperties().NetworkId,
		net.GetVirtualNetworkProperties().AllowTransit,
		net.GetVirtualNetworkProperties().ForwardingMode,
		subnets,
		policies,
		net.GetRouteTargetList().RouteTarget,
	}
	return info, err
}

func NetworkShow(client *contrail.Client, uuid string, detail bool) (
	*NetworkInfo, error) {
	obj, err := client.FindByUuid("virtual-network", uuid)
	if err != nil {
		return nil, err
	}
	return buildNetworkInfo(obj.(*types.VirtualNetwork), detail)
}

func NetworkList(client *contrail.Client, project_id string, detail bool) (
	[]*NetworkInfo, error) {
	fields := []string{"network_ipams"}
	if detail {
		fields = append(fields, "network_policys")
	}
	networks, err := client.ListDetailByParent(
		"virtual-network", project_id, fields, 0)
	if err != nil {
		return nil, err
	}

	var networkList []*NetworkInfo
	for _, reference := range networks {
		info, err := buildNetworkInfo(
			reference.(*types.VirtualNetwork), detail)
		if err != nil {
			return nil, err
		}
		networkList = append(networkList, info)
	}

	return networkList, nil
}

func CreateNetworkWithSubnet(
	client *contrail.Client, project_id, name, prefix string) (
		string, error) {

	expr := regexp.MustCompile(`(([0-9]{1,3}\.){3}[0-9]{1,3})/([0-9]{1,2})`)
	match := expr.FindStringSubmatch(prefix)
	if match == nil {
		return "", fmt.Errorf("Invalid subnet prefix %s", prefix)
	}
	address := match[1]
	prefixlen, _ := strconv.Atoi(match[3])

	obj, err := client.FindByUuid("project", project_id)
	if err != nil {
		return "", err
	}

	project := obj.(*types.Project)
	refList, err := project.GetNetworkIpams()
	if err != nil {
		return "", err
	}

	var ipam *types.NetworkIpam
	if len(refList) > 0 {
		obj, err := client.FindByUuid("network-ipam", refList[0].Uuid)
		if err != nil {
			return "", err
		}
		ipam = obj.(*types.NetworkIpam)
	} else {
		obj, err := client.FindByName("network-ipam",
			"default-domain:default-project:default-network-ipam")
		if err != nil {
			return "", err
		}
		ipam = obj.(*types.NetworkIpam)
	}

	net := new(types.VirtualNetwork)
	net.SetParent(project)
	net.SetName(name)

	subnets := types.VnSubnetsType{}
	subnets.AddIpamSubnets(
		&types.IpamSubnetType{
			Subnet: &types.SubnetType{address, prefixlen}})
	net.AddNetworkIpam(ipam, subnets)
	err = client.Create(net)
	if err != nil {
		return "", err
	}
	return net.GetUuid(), nil
}

func CreateNetwork(client *contrail.Client, project_id, name string) (
	string, error) {

	obj, err := client.FindByUuid("project", project_id)
	if err != nil {
		return "", err
	}

	project := obj.(*types.Project)

	net := new(types.VirtualNetwork)
	net.SetParent(project)
	net.SetName(name)

	err = client.Create(net)
	if err != nil {
		return "", err
	}
	return net.GetUuid(), nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"

	"github.com/gin-gonic/gin"
)

const VERSION = "0.1.1"

type Response struct {
	Success bool   `json:"success"`
	Message string `json:"message"`
}

type StatusResponse struct {
	Running  bool   `json:"running"`            // True if player is running
	File     string `json:"file"`               // Path to current media file
	Name     string `json:"name"`               // Titleized filename
	Position string `json:"position,omitempty"` // Current position in the movie
	Duration string `json:"duration,omitempty"` // Movie duration
}

type FileEntry struct {
	Filename string `json:"filename"`
	IsDir    bool   `json:"directory"`
}

var (
	// Regular expression to match all supported video files
	RegexFormats = regexp.MustCompile(`.(avi|mpg|mov|flv|wmv|asf|mpeg|m4v|divx|mp4|mkv)$`)

	// Regular expression to convert filenames to titles
	RegexBrackets = regexp.MustCompile(`[\(\[\]\)]`)
	RegexYear     = regexp.MustCompile(`((19|20)[\d]{2})`)
	RegexEpisode  = regexp.MustCompile(`(?i)S[\d]+E[\d]+`)
	RegexJunk     = regexp.MustCompile(`(?i)(1080p|720p|3d|brrip|bluray|webrip|x264|aac)`)
	RegexSpace    = regexp.MustCompile(`\s{2,}`)

	// OMXPlayer control commands, these are piped via STDIN to omxplayer process
	Commands = map[string]string{
		"pause":             "p",            // Pause/continue playback
		"stop":              "q",            // Stop playback and exit
		"volume_up":         "+",            // Change volume by +3dB
		"volume_down":       "-",            // Change volume by -3dB
		"subtitles":         "s",            // Enable/disable subtitles
		"seek_back":         "\x1b\x5b\x44", // Seek -30 seconds
		"seek_back_fast":    "\x1b\x5b\x42", // Seek -600 second
		"seek_forward":      "\x1b\x5b\x43", // Seek +30 second
		"seek_forward_fast": "\x1b\x5b\x41", // Seek +600 seconds
	}

	MediaPath   string         // Path where all media files are stored
	OmxPath     string         // Path to omxplayer executable
	Omx         *exec.Cmd      // Child process for spawning omxplayer
	OmxIn       io.WriteCloser // Child process STDIN pipe to send commands
	Command     chan string    // Channel to pass along commands to the player routine
	CurrentFile string         // Currently playing media file name
	Zeroconf    bool           // Enable Zeroconf discovery
	Frontend    bool           // Serve frontend app
	stream      *Stream        // Current stream
)

func httpBrowse(c *gin.Context) {
	path := c.Request.FormValue("path")

	if path != "" {
		path = fmt.Sprintf("%s/%s", MediaPath, path)
	} else {
		path = MediaPath
	}

	c.JSON(200, scanPath(path))
}

func httpCommand(c *gin.Context) {
	val := c.Params.ByName("command")

	if _, ok := Commands[val]; !ok {
		c.JSON(400, Response{false, "Invalid command"})
		return
	}

	fmt.Println("Received command:", val)

	// Handle requested commmand
	Command <- val

	c.JSON(200, Response{true, "OK"})
}

func httpServe(c *gin.Context) {
	file := c.Request.URL.Query().Get("file")
	if file == "" {
		return
	}

	file = fmt.Sprintf("%s/%s", MediaPath, file)
	if !fileExists(file) {
		c.String(404, "Not found")
		return
	}

	if !omxCanPlay(file) {
		c.String(400, "Invalid format")
		return
	}

	http.ServeFile(c.Writer, c.Request, file)
}

func httpPlay(c *gin.Context) {
	if omxIsActive() {
		c.JSON(400, Response{false, "Player is already running"})
		return
	}

	file := c.Request.FormValue("file")
	if file == "" {
		c.JSON(400, Response{false, "File is required"})
		return
	}

	file = fmt.Sprintf("%s/%s", MediaPath, file)

	if !fileExists(file) {
		c.JSON(400, Response{false, "File does not exist"})
		return
	}

	if !omxCanPlay(file) {
		c.JSON(400, Response{false, "File cannot be played"})
		return
	}

	go omxPlay(file)

	c.JSON(200, Response{true, "OK"})
}

func httpRemoveFile(c *gin.Context) {
	file := strings.TrimSpace(c.Request.FormValue("file"))
	if file == "" {
		c.JSON(400, Response{false, "File is required"})
		return
	}

	fullPath := fmt.Sprintf("%s/%s", MediaPath, file)
	if !fileExists(fullPath) {
		c.JSON(400, Response{false, "File does not exist"})
		return
	}

	if err := os.RemoveAll(fullPath); err != nil {
		c.JSON(400, Response{false, err.Error()})
		return
	}

	c.JSON(200, Response{true, "OK"})
}

func httpStatus(c *gin.Context) {
	resp := StatusResponse{
		Running: omxIsActive(),
		File:    CurrentFile,
		Name:    fileToTitle(filepath.Base(CurrentFile)),
	}

	if stream != nil {
		resp.Duration = durationFromSeconds(stream.duration)
		resp.Position = stream.pos.String()
	}

	c.JSON(200, resp)
}

func httpIndex(c *gin.Context) {
	data, err := Asset("static/index.html")

	if err != nil {
		c.String(400, err.Error())
		return
	}

	c.Data(200, "text/html; charset=utf-8", data)
}

// Retrieve information about the host: uptime, storage, etc
func httpHost(c *gin.Context) {
	output := map[string]string{}
	commands := map[string]string{
		"os":      "uname -a",
		"uptime":  "uptime",
		"storage": "df -m",
		"memory":  "free -m",
	}

	wg := &sync.WaitGroup{}
	wg.Add(len(commands))

	for k, v := range commands {
		go func(key, name string) {
			defer wg.Done()

			args := strings.Split(name, " ")

			out := bytes.NewBuffer(nil)
			cmd := exec.Command(args[0], args[1:]...)
			cmd.Stdout = out
			cmd.Stderr = out

			if err := cmd.Run(); err != nil {
				log.Println("Failed to execute command", k, err)
				output[key] = "N/A"
				return
			}

			output[key] = strings.TrimSpace(out.String())
		}(k, v)
	}

	wg.Wait()

	c.JSON(200, map[string]interface{}{
		"uptime":  output["uptime"],
		"os":      output["os"],
		"storage": parseStorageInfo(output["storage"]),
		"memory":  parseMemoryInfo(output["memory"]),
	})
}

func terminate(message string, code int) {
	fmt.Println(message)
	os.Exit(code)
}

func usage() {
	terminate("Usage: omxremote path/to/media/dir", 0)
}

func init() {
	var printVersion bool

	flag.StringVar(&MediaPath, "media", "./", "Path to media files")
	flag.BoolVar(&Frontend, "frontend", true, "Enable frontend applicaiton")
	flag.BoolVar(&Zeroconf, "zeroconf", false, "Enable service advertisement with Zeroconf")
	flag.BoolVar(&printVersion, "v", false, "Print version")
	flag.Parse()

	if printVersion {
		fmt.Printf("omxremote v%v\n", VERSION)
		os.Exit(0)
	}
}

func main() {
	// Expand media path if needed
	MediaPath = strings.Replace(MediaPath, "~", os.Getenv("HOME"), 1)

	// Get path from arguments and remove trailing slash
	MediaPath = strings.TrimRight(MediaPath, "/")

	if !fileExists(MediaPath) {
		terminate(fmt.Sprintf("Directory does not exist: %s", MediaPath), 1)
	}

	// Check if player is installed
	if omxDetect() != nil {
		terminate("omxplayer is not installed", 1)
	}

	// Make sure nothing is running
	omxCleanup()

	// Start a remote command listener
	go omxListen()

	// Start zeroconf service advertisement
	if Zeroconf {
		stopZeroconf := make(chan bool)
		go startZeroConfAdvertisement(stopZeroconf)
	}

	// Disable debugging mode
	gin.SetMode("release")

	// Setup HTTP server
	router := gin.Default()

	// Handle CORS
	router.Use(func(c *gin.Context) {
		c.Header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Expose-Headers", "*")
	})

	// Server frontend application only if its enabled
	if Frontend == true {
		router.GET("/", httpIndex)
	}

	router.GET("/status", httpStatus)
	router.GET("/browse", httpBrowse)
	router.GET("/play", httpPlay)
	router.GET("/serve", httpServe)
	router.POST("/remove", httpRemoveFile)
	router.GET("/command/:command", httpCommand)
	router.GET("/host", httpHost)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	host := os.Getenv("HOST")
	if host == "" {
		host = "0.0.0.0"
	}

	fmt.Println("Starting server on " + host + ":" + port)
	router.Run(host + ":" + port)
}
<commit_msg>Enable zeroconf by default<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
	"sync"

	"github.com/gin-gonic/gin"
)

const VERSION = "0.1.1"

type Response struct {
	Success bool   `json:"success"`
	Message string `json:"message"`
}

type StatusResponse struct {
	Running  bool   `json:"running"`            // True if player is running
	File     string `json:"file"`               // Path to current media file
	Name     string `json:"name"`               // Titleized filename
	Position string `json:"position,omitempty"` // Current position in the movie
	Duration string `json:"duration,omitempty"` // Movie duration
}

type FileEntry struct {
	Filename string `json:"filename"`
	IsDir    bool   `json:"directory"`
}

var (
	// Regular expression to match all supported video files
	RegexFormats = regexp.MustCompile(`.(avi|mpg|mov|flv|wmv|asf|mpeg|m4v|divx|mp4|mkv)$`)

	// Regular expression to convert filenames to titles
	RegexBrackets = regexp.MustCompile(`[\(\[\]\)]`)
	RegexYear     = regexp.MustCompile(`((19|20)[\d]{2})`)
	RegexEpisode  = regexp.MustCompile(`(?i)S[\d]+E[\d]+`)
	RegexJunk     = regexp.MustCompile(`(?i)(1080p|720p|3d|brrip|bluray|webrip|x264|aac)`)
	RegexSpace    = regexp.MustCompile(`\s{2,}`)

	// OMXPlayer control commands, these are piped via STDIN to omxplayer process
	Commands = map[string]string{
		"pause":             "p",            // Pause/continue playback
		"stop":              "q",            // Stop playback and exit
		"volume_up":         "+",            // Change volume by +3dB
		"volume_down":       "-",            // Change volume by -3dB
		"subtitles":         "s",            // Enable/disable subtitles
		"seek_back":         "\x1b\x5b\x44", // Seek -30 seconds
		"seek_back_fast":    "\x1b\x5b\x42", // Seek -600 second
		"seek_forward":      "\x1b\x5b\x43", // Seek +30 second
		"seek_forward_fast": "\x1b\x5b\x41", // Seek +600 seconds
	}

	MediaPath   string         // Path where all media files are stored
	OmxPath     string         // Path to omxplayer executable
	Omx         *exec.Cmd      // Child process for spawning omxplayer
	OmxIn       io.WriteCloser // Child process STDIN pipe to send commands
	Command     chan string    // Channel to pass along commands to the player routine
	CurrentFile string         // Currently playing media file name
	Zeroconf    bool           // Enable Zeroconf discovery
	Frontend    bool           // Serve frontend app
	stream      *Stream        // Current stream
)

func httpBrowse(c *gin.Context) {
	path := c.Request.FormValue("path")

	if path != "" {
		path = fmt.Sprintf("%s/%s", MediaPath, path)
	} else {
		path = MediaPath
	}

	c.JSON(200, scanPath(path))
}

func httpCommand(c *gin.Context) {
	val := c.Params.ByName("command")

	if _, ok := Commands[val]; !ok {
		c.JSON(400, Response{false, "Invalid command"})
		return
	}

	fmt.Println("Received command:", val)

	// Handle requested commmand
	Command <- val

	c.JSON(200, Response{true, "OK"})
}

func httpServe(c *gin.Context) {
	file := c.Request.URL.Query().Get("file")
	if file == "" {
		return
	}

	file = fmt.Sprintf("%s/%s", MediaPath, file)
	if !fileExists(file) {
		c.String(404, "Not found")
		return
	}

	if !omxCanPlay(file) {
		c.String(400, "Invalid format")
		return
	}

	http.ServeFile(c.Writer, c.Request, file)
}

func httpPlay(c *gin.Context) {
	if omxIsActive() {
		c.JSON(400, Response{false, "Player is already running"})
		return
	}

	file := c.Request.FormValue("file")
	if file == "" {
		c.JSON(400, Response{false, "File is required"})
		return
	}

	file = fmt.Sprintf("%s/%s", MediaPath, file)

	if !fileExists(file) {
		c.JSON(400, Response{false, "File does not exist"})
		return
	}

	if !omxCanPlay(file) {
		c.JSON(400, Response{false, "File cannot be played"})
		return
	}

	go omxPlay(file)

	c.JSON(200, Response{true, "OK"})
}

func httpRemoveFile(c *gin.Context) {
	file := strings.TrimSpace(c.Request.FormValue("file"))
	if file == "" {
		c.JSON(400, Response{false, "File is required"})
		return
	}

	fullPath := fmt.Sprintf("%s/%s", MediaPath, file)
	if !fileExists(fullPath) {
		c.JSON(400, Response{false, "File does not exist"})
		return
	}

	if err := os.RemoveAll(fullPath); err != nil {
		c.JSON(400, Response{false, err.Error()})
		return
	}

	c.JSON(200, Response{true, "OK"})
}

func httpStatus(c *gin.Context) {
	resp := StatusResponse{
		Running: omxIsActive(),
		File:    CurrentFile,
		Name:    fileToTitle(filepath.Base(CurrentFile)),
	}

	if stream != nil {
		resp.Duration = durationFromSeconds(stream.duration)
		resp.Position = stream.pos.String()
	}

	c.JSON(200, resp)
}

func httpIndex(c *gin.Context) {
	data, err := Asset("static/index.html")

	if err != nil {
		c.String(400, err.Error())
		return
	}

	c.Data(200, "text/html; charset=utf-8", data)
}

// Retrieve information about the host: uptime, storage, etc
func httpHost(c *gin.Context) {
	output := map[string]string{}
	commands := map[string]string{
		"os":      "uname -a",
		"uptime":  "uptime",
		"storage": "df -m",
		"memory":  "free -m",
	}

	wg := &sync.WaitGroup{}
	wg.Add(len(commands))

	for k, v := range commands {
		go func(key, name string) {
			defer wg.Done()

			args := strings.Split(name, " ")

			out := bytes.NewBuffer(nil)
			cmd := exec.Command(args[0], args[1:]...)
			cmd.Stdout = out
			cmd.Stderr = out

			if err := cmd.Run(); err != nil {
				log.Println("Failed to execute command", k, err)
				output[key] = "N/A"
				return
			}

			output[key] = strings.TrimSpace(out.String())
		}(k, v)
	}

	wg.Wait()

	c.JSON(200, map[string]interface{}{
		"uptime":  output["uptime"],
		"os":      output["os"],
		"storage": parseStorageInfo(output["storage"]),
		"memory":  parseMemoryInfo(output["memory"]),
	})
}

func terminate(message string, code int) {
	fmt.Println(message)
	os.Exit(code)
}

func usage() {
	terminate("Usage: omxremote path/to/media/dir", 0)
}

func init() {
	var printVersion bool

	flag.StringVar(&MediaPath, "media", "./", "Path to media files")
	flag.BoolVar(&Frontend, "frontend", true, "Enable frontend applicaiton")
	flag.BoolVar(&Zeroconf, "zeroconf", true, "Enable service advertisement with Zeroconf")
	flag.BoolVar(&printVersion, "v", false, "Print version")
	flag.Parse()

	if printVersion {
		fmt.Printf("omxremote v%v\n", VERSION)
		os.Exit(0)
	}
}

func main() {
	// Expand media path if needed
	MediaPath = strings.Replace(MediaPath, "~", os.Getenv("HOME"), 1)

	// Get path from arguments and remove trailing slash
	MediaPath = strings.TrimRight(MediaPath, "/")

	if !fileExists(MediaPath) {
		terminate(fmt.Sprintf("Directory does not exist: %s", MediaPath), 1)
	}

	// Check if player is installed
	if omxDetect() != nil {
		terminate("omxplayer is not installed", 1)
	}

	// Make sure nothing is running
	omxCleanup()

	// Start a remote command listener
	go omxListen()

	// Start zeroconf service advertisement
	if Zeroconf {
		stopZeroconf := make(chan bool)
		go startZeroConfAdvertisement(stopZeroconf)
	}

	// Disable debugging mode
	gin.SetMode("release")

	// Setup HTTP server
	router := gin.Default()

	// Handle CORS
	router.Use(func(c *gin.Context) {
		c.Header("Access-Control-Allow-Methods", "GET, POST, OPTIONS")
		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Expose-Headers", "*")
	})

	// Server frontend application only if its enabled
	if Frontend == true {
		router.GET("/", httpIndex)
	}

	router.GET("/status", httpStatus)
	router.GET("/browse", httpBrowse)
	router.GET("/play", httpPlay)
	router.GET("/serve", httpServe)
	router.POST("/remove", httpRemoveFile)
	router.GET("/command/:command", httpCommand)
	router.GET("/host", httpHost)

	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	host := os.Getenv("HOST")
	if host == "" {
		host = "0.0.0.0"
	}

	fmt.Println("Starting server on " + host + ":" + port)
	router.Run(host + ":" + port)
}
<|endoftext|>


<commit_before>package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"net/http"

	"github.com/proidiot/gone/log"
)

// HTTPMultiServer implements the Pullcord server interface with an HTTP handler
// and multiple listeners.
type HTTPMultiServer struct {
	Listeners []net.Listener
	Handler   http.Handler
}

func init() {
	e := RegisterResourceType(
		"httpmultiserver",
		func() json.Unmarshaler {
			return new(HTTPServer)
		},
	)

	if e != nil {
		panic(e)
	}
}

// UnmarshalJSON implements encoding/json.Unmarshaler.
func (s *HTTPMultiServer) UnmarshalJSON(d []byte) error {
	var t struct {
		Listeners []Resource
		Handler   Resource
	}

	dec := json.NewDecoder(bytes.NewReader(d))
	if e := dec.Decode(&t); e != nil {
		return e
	}

	s.Listeners = make([]net.Listener, len(t.Listeners))

	for _, r := range t.Listeners {
		l, ok := r.Unmarshalled.(net.Listener)
		if !ok {
			return UnexpectedResourceType
		}
		s.Listeners = append(s.Listeners, l)
	}

  var ok bool
	s.Handler, ok = t.Handler.Unmarshalled.(http.Handler)
	if !ok {
		return UnexpectedResourceType
	}

	return nil
}

// Serve implements .../pullcord/Server.
func (s *HTTPMultiServer) Serve() error {
	log.Debug(
		fmt.Sprintf(
			"Serving with listeners %#v and handler %#v",
			s.Listeners,
			s.Handler,
		),
	)
	defer func() {
		_ = s.Close()
	}()

	errChan := make(chan error)
	for _, l := range s.Listeners {
		go func(gl net.Listener, gErrChan chan<- error) {
			log.Notice(
				fmt.Sprintf(
					"Starting server at %s...",
					gl.Addr(),
				),
			)
			gErrChan <- http.Serve(gl, s.Handler)
		}(l, errChan)
	}

	err := <-errChan

	go func(gErrChan <-chan error, eat int) {
		for ; eat > 0; eat-- {
			_ = <-gErrChan
		}
	}(errChan, len(s.Listeners)-1)

	return err
}

// Close implements .../pullcord/Server.
func (s *HTTPMultiServer) Close() error {
	var err error
	for _, l := range s.Listeners {
		log.Info(fmt.Sprintf("Closing server at %s...", l.Addr()))
		thisErr := l.Close()
		if err == nil && thisErr != nil {
			err = thisErr
		}
	}
	return err
}
<commit_msg>Apparently merge enjoys screwing with gofmt.<commit_after>package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"net/http"

	"github.com/proidiot/gone/log"
)

// HTTPMultiServer implements the Pullcord server interface with an HTTP handler
// and multiple listeners.
type HTTPMultiServer struct {
	Listeners []net.Listener
	Handler   http.Handler
}

func init() {
	e := RegisterResourceType(
		"httpmultiserver",
		func() json.Unmarshaler {
			return new(HTTPServer)
		},
	)

	if e != nil {
		panic(e)
	}
}

// UnmarshalJSON implements encoding/json.Unmarshaler.
func (s *HTTPMultiServer) UnmarshalJSON(d []byte) error {
	var t struct {
		Listeners []Resource
		Handler   Resource
	}

	dec := json.NewDecoder(bytes.NewReader(d))
	if e := dec.Decode(&t); e != nil {
		return e
	}

	s.Listeners = make([]net.Listener, len(t.Listeners))

	for _, r := range t.Listeners {
		l, ok := r.Unmarshalled.(net.Listener)
		if !ok {
			return UnexpectedResourceType
		}
		s.Listeners = append(s.Listeners, l)
	}

	var ok bool
	s.Handler, ok = t.Handler.Unmarshalled.(http.Handler)
	if !ok {
		return UnexpectedResourceType
	}

	return nil
}

// Serve implements .../pullcord/Server.
func (s *HTTPMultiServer) Serve() error {
	log.Debug(
		fmt.Sprintf(
			"Serving with listeners %#v and handler %#v",
			s.Listeners,
			s.Handler,
		),
	)
	defer func() {
		_ = s.Close()
	}()

	errChan := make(chan error)
	for _, l := range s.Listeners {
		go func(gl net.Listener, gErrChan chan<- error) {
			log.Notice(
				fmt.Sprintf(
					"Starting server at %s...",
					gl.Addr(),
				),
			)
			gErrChan <- http.Serve(gl, s.Handler)
		}(l, errChan)
	}

	err := <-errChan

	go func(gErrChan <-chan error, eat int) {
		for ; eat > 0; eat-- {
			_ = <-gErrChan
		}
	}(errChan, len(s.Listeners)-1)

	return err
}

// Close implements .../pullcord/Server.
func (s *HTTPMultiServer) Close() error {
	var err error
	for _, l := range s.Listeners {
		log.Info(fmt.Sprintf("Closing server at %s...", l.Addr()))
		thisErr := l.Close()
		if err == nil && thisErr != nil {
			err = thisErr
		}
	}
	return err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/BytemarkHosting/bytemark-client/lib"
	"github.com/BytemarkHosting/bytemark-client/lib/brain"
	"github.com/BytemarkHosting/bytemark-client/mocks"
	"github.com/urfave/cli"
	"io/ioutil"
	"os"
	"testing"
)

var defVM lib.VirtualMachineName
var defGroup lib.GroupName

func baseTestSetup(t *testing.T, admin bool) (config *mocks.Config, client *mocks.Client) {
	config = new(mocks.Config)
	client = new(mocks.Client)
	config.When("GetBool", "admin").Return(admin, nil)
	global.Client = client
	global.Config = config

	app, err := baseAppSetup()
	if err != nil {
		t.Fatal(err)
	}
	global.App = app
	oldWriter := global.App.Writer
	global.App.Writer = ioutil.Discard
	for _, c := range commands {
		//config.When("Get", "token").Return("no-not-a-token")

		// the issue is that Command.FullName() is dependent on Command.commandNamePath.
		// Command.commandNamePath is filled in when the parent's Command.startApp is called
		// and startApp is only called when you actually try to run that command or one of
		// its subcommands. So we run "bytemark <command> help" on all commands that have
		// subcommands in order to get every subcommand to have a correct Command.commandPath

		if c.Subcommands != nil && len(c.Subcommands) > 0 {
			fmt.Fprintf(os.Stderr, c.Name)
			_ = global.App.Run([]string{"bytemark.test", c.Name, "help"})
		}
	}
	global.App.Writer = oldWriter
	return
}

func traverseAllCommands(cmds []cli.Command, fn func(cli.Command)) {
	if cmds == nil {
		return
	}
	for _, c := range cmds {
		fn(c)
		traverseAllCommands(c.Subcommands, fn)
	}
}

func getFixtureVM() brain.VirtualMachine {
	return brain.VirtualMachine{
		Name:     "test-server",
		Hostname: "test-server.test-group",
		GroupID:  1,
	}
}

func getFixtureGroup() brain.Group {
	vms := make([]*brain.VirtualMachine, 1, 1)
	vm := getFixtureVM()
	vms[0] = &vm

	return brain.Group{
		Name:            "test-group",
		VirtualMachines: vms,
	}
}
<commit_msg>remove logging for main_test - simplifies test output significantly.<commit_after>package main

import (
	"github.com/BytemarkHosting/bytemark-client/lib"
	"github.com/BytemarkHosting/bytemark-client/lib/brain"
	"github.com/BytemarkHosting/bytemark-client/mocks"
	"github.com/urfave/cli"
	"io/ioutil"
	"testing"
)

var defVM lib.VirtualMachineName
var defGroup lib.GroupName

func baseTestSetup(t *testing.T, admin bool) (config *mocks.Config, client *mocks.Client) {
	config = new(mocks.Config)
	client = new(mocks.Client)
	config.When("GetBool", "admin").Return(admin, nil)
	global.Client = client
	global.Config = config

	app, err := baseAppSetup()
	if err != nil {
		t.Fatal(err)
	}
	global.App = app
	oldWriter := global.App.Writer
	global.App.Writer = ioutil.Discard
	for _, c := range commands {
		//config.When("Get", "token").Return("no-not-a-token")

		// the issue is that Command.FullName() is dependent on Command.commandNamePath.
		// Command.commandNamePath is filled in when the parent's Command.startApp is called
		// and startApp is only called when you actually try to run that command or one of
		// its subcommands. So we run "bytemark <command> help" on all commands that have
		// subcommands in order to get every subcommand to have a correct Command.commandPath

		if c.Subcommands != nil && len(c.Subcommands) > 0 {
			_ = global.App.Run([]string{"bytemark.test", c.Name, "help"})
		}
	}
	global.App.Writer = oldWriter
	return
}

func traverseAllCommands(cmds []cli.Command, fn func(cli.Command)) {
	if cmds == nil {
		return
	}
	for _, c := range cmds {
		fn(c)
		traverseAllCommands(c.Subcommands, fn)
	}
}

func getFixtureVM() brain.VirtualMachine {
	return brain.VirtualMachine{
		Name:     "test-server",
		Hostname: "test-server.test-group",
		GroupID:  1,
	}
}

func getFixtureGroup() brain.Group {
	vms := make([]*brain.VirtualMachine, 1, 1)
	vm := getFixtureVM()
	vms[0] = &vm

	return brain.Group{
		Name:            "test-group",
		VirtualMachines: vms,
	}
}
<|endoftext|>