<commit_before>package build

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"neon/util"
	"os"
	"path/filepath"
)

// Build structure
type Build struct {
	File        string
	Dir         string
	Here        string
	Name        string
	Default     []string
	Doc         string
	Scripts     []string
	Properties  util.Object
	Environment map[string]string
	Targets     map[string]*Target
	Context     *Context
	Parents     []*Build
	Index       *Index
	Stack       *Stack
}

// Possible fields for a build file
var FIELDS = []string{"name", "doc", "default", "context", "extends",
	"singleton", "properties", "configuration", "environment", "targets"}

// Make a build from a build file
func NewBuild(file string) (*Build, error) {
	build := &Build{}
	path := util.ExpandUserHome(file)
	build.File = filepath.Base(path)
	base, err := filepath.Abs(filepath.Dir(path))
	if err != nil {
		return nil, fmt.Errorf("getting build file directory: %v", err)
	}
	build.Dir = base
	here, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("getting current directory: %v", err)
	}
	build.Here = here
	source, err := util.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("loading build file '%s': %v", path, err)
	}
	var object util.Object
	err = yaml.Unmarshal(source, &object)
	if err != nil {
		return nil, fmt.Errorf("build must be a map with string keys")
	}
	if err := object.CheckFields(FIELDS); err != nil {
		return nil, fmt.Errorf("parsing build file: %v", err)
	}
	if err := ParseSingleton(object); err != nil {
		return nil, err
	}
	if err := ParseName(object, build); err != nil {
		return nil, err
	}
	if err := ParseDefault(object, build); err != nil {
		return nil, err
	}
	if err := ParseDoc(object, build); err != nil {
		return nil, err
	}
	if err := ParseContext(object, build); err != nil {
		return nil, err
	}
	if err := ParseExtends(object, build); err != nil {
		return nil, err
	}
	if err := ParseProperties(object, build); err != nil {
		return nil, err
	}
	if err := ParseConfiguration(object, build); err != nil {
		return nil, err
	}
	if err := ParseEnvironment(object, build); err != nil {
		return nil, err
	}
	if err := ParseTargets(object, build); err != nil {
		return nil, err
	}
	return build, nil
}

// Parse singleton field of the build
func ParseSingleton(object util.Object) error {
	if object.HasField("singleton") {
		port, err := object.GetInteger("singleton")
		if err != nil {
			return fmt.Errorf("getting singleton port: %v", err)
		}
		if err := util.Singleton(port); err != nil {
			return fmt.Errorf("another instance of the build is already running")
		}
	}
	return nil
}

// Parse name field of the build
func ParseName(object util.Object, build *Build) error {
	if object.HasField("name") {
		name, err := object.GetString("name")
		if err != nil {
			return fmt.Errorf("getting build name: %v", err)
		}
		build.Name = name
	}
	return nil
}

// Parse default field of the build
func ParseDefault(object util.Object, build *Build) error {
	if object.HasField("default") {
		list, err := object.GetListStringsOrString("default")
		if err != nil {
			return fmt.Errorf("getting default targets: %v", err)
		}
		build.Default = list
	}
	return nil
}

// Parse doc field of the build
func ParseDoc(object util.Object, build *Build) error {
	if object.HasField("doc") {
		doc, err := object.GetString("doc")
		if err != nil {
			return fmt.Errorf("getting build doc: %v", err)
		}
		build.Doc = doc
	}
	return nil
}

// Parse context field of the build
func ParseContext(object util.Object, build *Build) error {
	if object.HasField("context") {
		scripts, err := object.GetListStringsOrString("context")
		if err != nil {
			return fmt.Errorf("getting context: %v", err)
		}
		build.Scripts = scripts
	}
	return nil
}

// Parse extends field of the build
func ParseExtends(object util.Object, build *Build) error {
	if object.HasField("extends") {
		parents, err := object.GetListStringsOrString("extends")
		if err != nil {
			return fmt.Errorf("parsing parents: %v", err)
		}
		var extends []*Build
		for _, parent := range parents {
			extend, err := NewBuild(parent)
			if err != nil {
				return fmt.Errorf("laoding parent '%s': %v", parent, err)
			}
			extends = append(extends, extend)
		}
		build.Parents = extends
	}
	return nil
}

// Parse build properties
func ParseProperties(object util.Object, build *Build) error {
	properties := make(map[string]interface{})
	var err error
	if object.HasField("properties") {
		properties, err = object.GetObject("properties")
		if err != nil {
			return fmt.Errorf("parsing properties: %v", err)
		}
	}
	build.Properties = properties
	return nil
}

// Parse build configuration
func ParseConfiguration(object util.Object, build *Build) error {
	if object.HasField("configuration") {
		var config util.Object
		files, err := object.GetListStrings("configuration")
		if err != nil {
			return fmt.Errorf("getting configuration file: %v", err)
		}
		for _, file := range files {
			file = util.ExpandAndJoinToRoot(build.Dir, file)
			source, err := util.ReadFile(file)
			if err != nil {
				return fmt.Errorf("reading configuration file: %v", err)
			}
			err = yaml.Unmarshal(source, &config)
			if err != nil {
				return fmt.Errorf("configuration must be a map with string keys")
			}
			for name, value := range config {
				build.Properties[name] = value
			}
		}
	}
	return nil
}

// Parse build environment
func ParseEnvironment(object util.Object, build *Build) error {
	environment := make(map[string]string)
	if object.HasField("environment") {
		env, err := object.GetObject("environment")
		if err != nil {
			return fmt.Errorf("parsing environmen: %v", err)
		}
		environment, err = env.ToMapStringString()
		if err != nil {
			return fmt.Errorf("getting environment: %v", err)
		}
	}
	build.Environment = environment
	return nil
}

// Parse build targets
func ParseTargets(object util.Object, build *Build) error {
	targets := util.Object(make(map[string]interface{}))
	var err error
	if object.HasField("targets") {
		targets, err = object.GetObject("targets")
		if err != nil {
			return fmt.Errorf("parsing targets: %v", err)
		}
	}
	build.Targets = make(map[string]*Target)
	for name := range targets {
		object, err := targets.GetObject(name)
		if err != nil {
			return fmt.Errorf("parsing target '%s': %v", name, err)
		}
		target, err := NewTarget(build, name, object)
		if err != nil {
			return fmt.Errorf("parsing target '%s': %v", name, err)
		}
		build.Targets[name] = target
	}
	return nil
}

// Return the build properties, including those inherited from parents
func (build *Build) GetProperties() util.Object {
	var properties = make(map[string]interface{})
	for _, parent := range build.Parents {
		for name, value := range parent.GetProperties() {
			properties[name] = value
		}
	}
	for name, value := range build.Properties {
		properties[name] = value
	}
	return properties
}

// Return the build environment, including those inherited from parents
func (build *Build) GetEnvironment() map[string]string {
	var environment = make(map[string]string)
	for _, parent := range build.Parents {
		for name, value := range parent.GetEnvironment() {
			environment[name] = value
		}
	}
	for name, value := range build.Environment {
		environment[name] = value
	}
	return environment
}

// Return the build targets, including those inherited from parents
func (build *Build) GetTargets() map[string]*Target {
	var targets = make(map[string]*Target)
	for _, parent := range build.Parents {
		for name, target := range parent.GetTargets() {
			targets[name] = target
		}
	}
	for name, target := range build.Targets {
		targets[name] = target
	}
	return targets
}

// Return target with given name. If not defined in build, return target
// inherited from parent
func (build *Build) GetTargetByName(name string) *Target {
	target, found := build.Targets[name]
	if found {
		return target
	} else {
		for _, parent := range build.Parents {
			target = parent.GetTargetByName(name)
			if target != nil {
				return target
			}
		}
	}
	return nil
}

// Initialize build:
// - Set build dir and change to it
// - Create context and set it for build
func (build *Build) Init() error {
	os.Chdir(build.Dir)
	context, err := NewContext(build)
	if err != nil {
		return fmt.Errorf("evaluating context: %v", err)
	}
	build.SetDir(build.Dir)
	build.SetContext(context)
	build.SetStack(NewStack())
	return nil
}

// Set the build directory, propagating to parents
func (build *Build) SetDir(dir string) {
	build.Dir = dir
	for _, parent := range build.Parents {
		parent.SetDir(dir)
	}
}

// Set the build context, propagating to parents
func (build *Build) SetContext(context *Context) {
	build.Context = context
	for _, parent := range build.Parents {
		parent.SetContext(context)
	}
}

// Set the build stack, propagating to parents
func (build *Build) SetStack(stack *Stack) {
	build.Stack = stack
	for _, parent := range build.Parents {
		parent.SetStack(stack)
	}
}

// Set command line properties, that overwrite build ones
func (build *Build) SetCommandLineProperties(props string) error {
	var object util.Object
	err := yaml.Unmarshal([]byte(props), &object)
	if err != nil {
		return fmt.Errorf("parsing command line properties: properties must be a map with string keys")
	}
	for name, value := range object {
		build.Properties[name] = value
	}
	return nil
}

// Return default targets. If none is defined in build, return those from
// parents
func (build *Build) GetDefault() []string {
	if len(build.Default) > 0 {
		return build.Default
	} else {
		for _, parent := range build.Parents {
			if len(parent.Default) > 0 {
				return parent.Default
			}
		}
		for _, parent := range build.Parents {
			parentDefault := parent.GetDefault()
			if len(parentDefault) > 0 {
				return parentDefault
			}
		}
	}
	return build.Default
}

// Run build given targets. If no target is given, run default one.
func (build *Build) Run(targets []string) error {
	if len(targets) == 0 {
		targets = build.GetDefault()
		if len(targets) == 0 {
			return fmt.Errorf("no default target")
		}
	}
	for _, target := range targets {
		err := build.RunTarget(target)
		if err != nil {
			return err
		}
	}
	return nil
}

// Run given target
func (build *Build) RunTarget(name string) error {
	target := build.GetTargetByName(name)
	if target == nil {
		return fmt.Errorf("target '%s' not found", name)
	}
	err := target.Run()
	if err != nil {
		return fmt.Errorf("running target '%s': %v", name, err)
	}
	return nil
}

// Run parent target
func (build *Build) RunParentTarget(name string) (bool, error) {
	for _, parent := range build.Parents {
		ok, err := parent.RunTargetRecursive(name)
		if err != nil {
			return ok, fmt.Errorf("running target '%s': %v", name, err)
		}
		if ok {
			return ok, nil
		}
	}
	return false, nil
}

// Run given target recursively
func (build *Build) RunTargetRecursive(name string) (bool, error) {
	target := build.GetTargetByName(name)
	if target == nil {
		return build.RunParentTarget(name)
	}
	err := target.RunSteps()
	if err != nil {
		return true, fmt.Errorf("running target '%s': %v", name, err)
	}
	return false, nil
}
<commit_msg>Release 0.5.0: Bug fix<commit_after>package build

import (
	"fmt"
	"gopkg.in/yaml.v2"
	"neon/util"
	"os"
	"path/filepath"
)

// Build structure
type Build struct {
	File        string
	Dir         string
	Here        string
	Name        string
	Default     []string
	Doc         string
	Scripts     []string
	Properties  util.Object
	Environment map[string]string
	Targets     map[string]*Target
	Context     *Context
	Parents     []*Build
	Index       *Index
	Stack       *Stack
}

// Possible fields for a build file
var FIELDS = []string{"name", "doc", "default", "context", "extends",
	"singleton", "properties", "configuration", "environment", "targets"}

// Make a build from a build file
func NewBuild(file string) (*Build, error) {
	build := &Build{}
	path := util.ExpandUserHome(file)
	build.File = filepath.Base(path)
	base, err := filepath.Abs(filepath.Dir(path))
	if err != nil {
		return nil, fmt.Errorf("getting build file directory: %v", err)
	}
	build.Dir = base
	here, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("getting current directory: %v", err)
	}
	build.Here = here
	source, err := util.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("loading build file '%s': %v", path, err)
	}
	var object util.Object
	err = yaml.Unmarshal(source, &object)
	if err != nil {
		return nil, fmt.Errorf("build must be a map with string keys")
	}
	if err := object.CheckFields(FIELDS); err != nil {
		return nil, fmt.Errorf("parsing build file: %v", err)
	}
	if err := ParseSingleton(object); err != nil {
		return nil, err
	}
	if err := ParseName(object, build); err != nil {
		return nil, err
	}
	if err := ParseDefault(object, build); err != nil {
		return nil, err
	}
	if err := ParseDoc(object, build); err != nil {
		return nil, err
	}
	if err := ParseContext(object, build); err != nil {
		return nil, err
	}
	if err := ParseExtends(object, build); err != nil {
		return nil, err
	}
	if err := ParseProperties(object, build); err != nil {
		return nil, err
	}
	if err := ParseConfiguration(object, build); err != nil {
		return nil, err
	}
	if err := ParseEnvironment(object, build); err != nil {
		return nil, err
	}
	if err := ParseTargets(object, build); err != nil {
		return nil, err
	}
	return build, nil
}

// Parse singleton field of the build
func ParseSingleton(object util.Object) error {
	if object.HasField("singleton") {
		port, err := object.GetInteger("singleton")
		if err != nil {
			return fmt.Errorf("getting singleton port: %v", err)
		}
		if err := util.Singleton(port); err != nil {
			return fmt.Errorf("another instance of the build is already running")
		}
	}
	return nil
}

// Parse name field of the build
func ParseName(object util.Object, build *Build) error {
	if object.HasField("name") {
		name, err := object.GetString("name")
		if err != nil {
			return fmt.Errorf("getting build name: %v", err)
		}
		build.Name = name
	}
	return nil
}

// Parse default field of the build
func ParseDefault(object util.Object, build *Build) error {
	if object.HasField("default") {
		list, err := object.GetListStringsOrString("default")
		if err != nil {
			return fmt.Errorf("getting default targets: %v", err)
		}
		build.Default = list
	}
	return nil
}

// Parse doc field of the build
func ParseDoc(object util.Object, build *Build) error {
	if object.HasField("doc") {
		doc, err := object.GetString("doc")
		if err != nil {
			return fmt.Errorf("getting build doc: %v", err)
		}
		build.Doc = doc
	}
	return nil
}

// Parse context field of the build
func ParseContext(object util.Object, build *Build) error {
	if object.HasField("context") {
		scripts, err := object.GetListStringsOrString("context")
		if err != nil {
			return fmt.Errorf("getting context: %v", err)
		}
		build.Scripts = scripts
	}
	return nil
}

// Parse extends field of the build
func ParseExtends(object util.Object, build *Build) error {
	if object.HasField("extends") {
		parents, err := object.GetListStringsOrString("extends")
		if err != nil {
			return fmt.Errorf("parsing parents: %v", err)
		}
		var extends []*Build
		for _, parent := range parents {
			extend, err := NewBuild(parent)
			if err != nil {
				return fmt.Errorf("laoding parent '%s': %v", parent, err)
			}
			extends = append(extends, extend)
		}
		build.Parents = extends
	}
	return nil
}

// Parse build properties
func ParseProperties(object util.Object, build *Build) error {
	properties := make(map[string]interface{})
	var err error
	if object.HasField("properties") {
		properties, err = object.GetObject("properties")
		if err != nil {
			return fmt.Errorf("parsing properties: %v", err)
		}
	}
	build.Properties = properties
	return nil
}

// Parse build configuration
func ParseConfiguration(object util.Object, build *Build) error {
	if object.HasField("configuration") {
		var config util.Object
		files, err := object.GetListStrings("configuration")
		if err != nil {
			return fmt.Errorf("getting configuration file: %v", err)
		}
		for _, file := range files {
			file = util.ExpandAndJoinToRoot(build.Dir, file)
			source, err := util.ReadFile(file)
			if err != nil {
				return fmt.Errorf("reading configuration file: %v", err)
			}
			err = yaml.Unmarshal(source, &config)
			if err != nil {
				return fmt.Errorf("configuration must be a map with string keys")
			}
			for name, value := range config {
				build.Properties[name] = value
			}
		}
	}
	return nil
}

// Parse build environment
func ParseEnvironment(object util.Object, build *Build) error {
	environment := make(map[string]string)
	if object.HasField("environment") {
		env, err := object.GetObject("environment")
		if err != nil {
			return fmt.Errorf("parsing environmen: %v", err)
		}
		environment, err = env.ToMapStringString()
		if err != nil {
			return fmt.Errorf("getting environment: %v", err)
		}
	}
	build.Environment = environment
	return nil
}

// Parse build targets
func ParseTargets(object util.Object, build *Build) error {
	targets := util.Object(make(map[string]interface{}))
	var err error
	if object.HasField("targets") {
		targets, err = object.GetObject("targets")
		if err != nil {
			return fmt.Errorf("parsing targets: %v", err)
		}
	}
	build.Targets = make(map[string]*Target)
	for name := range targets {
		object, err := targets.GetObject(name)
		if err != nil {
			return fmt.Errorf("parsing target '%s': %v", name, err)
		}
		target, err := NewTarget(build, name, object)
		if err != nil {
			return fmt.Errorf("parsing target '%s': %v", name, err)
		}
		build.Targets[name] = target
	}
	return nil
}

// Return the build properties, including those inherited from parents
func (build *Build) GetProperties() util.Object {
	var properties = make(map[string]interface{})
	for _, parent := range build.Parents {
		for name, value := range parent.GetProperties() {
			properties[name] = value
		}
	}
	for name, value := range build.Properties {
		properties[name] = value
	}
	return properties
}

// Return the build environment, including those inherited from parents
func (build *Build) GetEnvironment() map[string]string {
	var environment = make(map[string]string)
	for _, parent := range build.Parents {
		for name, value := range parent.GetEnvironment() {
			environment[name] = value
		}
	}
	for name, value := range build.Environment {
		environment[name] = value
	}
	return environment
}

// Return the build targets, including those inherited from parents
func (build *Build) GetTargets() map[string]*Target {
	var targets = make(map[string]*Target)
	for _, parent := range build.Parents {
		for name, target := range parent.GetTargets() {
			targets[name] = target
		}
	}
	for name, target := range build.Targets {
		targets[name] = target
	}
	return targets
}

// Return target with given name. If not defined in build, return target
// inherited from parent
func (build *Build) GetTargetByName(name string) *Target {
	target, found := build.Targets[name]
	if found {
		return target
	} else {
		for _, parent := range build.Parents {
			target = parent.GetTargetByName(name)
			if target != nil {
				return target
			}
		}
	}
	return nil
}

// Initialize build:
// - Set build dir and change to it
// - Create context and set it for build
func (build *Build) Init() error {
	os.Chdir(build.Dir)
	context, err := NewContext(build)
	if err != nil {
		return fmt.Errorf("evaluating context: %v", err)
	}
	build.SetDir(build.Dir)
	build.SetContext(context)
	build.SetStack(NewStack())
	return nil
}

// Set the build directory, propagating to parents
func (build *Build) SetDir(dir string) {
	build.Dir = dir
	for _, parent := range build.Parents {
		parent.SetDir(dir)
	}
}

// Set the build context, propagating to parents
func (build *Build) SetContext(context *Context) {
	build.Context = context
	for _, parent := range build.Parents {
		parent.SetContext(context)
	}
}

// Set the build stack, propagating to parents
func (build *Build) SetStack(stack *Stack) {
	build.Stack = stack
	for _, parent := range build.Parents {
		parent.SetStack(stack)
	}
}

// Set command line properties, that overwrite build ones
func (build *Build) SetCommandLineProperties(props string) error {
	var object util.Object
	err := yaml.Unmarshal([]byte(props), &object)
	if err != nil {
		return fmt.Errorf("parsing command line properties: properties must be a map with string keys")
	}
	for name, value := range object {
		build.Properties[name] = value
	}
	return nil
}

// Return default targets. If none is defined in build, return those from
// parents
func (build *Build) GetDefault() []string {
	if len(build.Default) > 0 {
		return build.Default
	} else {
		for _, parent := range build.Parents {
			if len(parent.Default) > 0 {
				return parent.Default
			}
		}
		for _, parent := range build.Parents {
			parentDefault := parent.GetDefault()
			if len(parentDefault) > 0 {
				return parentDefault
			}
		}
	}
	return build.Default
}

// Run build given targets. If no target is given, run default one.
func (build *Build) Run(targets []string) error {
	if len(targets) == 0 {
		targets = build.GetDefault()
		if len(targets) == 0 {
			return fmt.Errorf("no default target")
		}
	}
	for _, target := range targets {
		err := build.RunTarget(target)
		if err != nil {
			return err
		}
	}
	return nil
}

// Run given target
func (build *Build) RunTarget(name string) error {
	target := build.GetTargetByName(name)
	if target == nil {
		return fmt.Errorf("target '%s' not found", name)
	}
	err := target.Run()
	if err != nil {
		return fmt.Errorf("running target '%s': %v", name, err)
	}
	return nil
}

// Run parent target
func (build *Build) RunParentTarget(name string) (bool, error) {
	for _, parent := range build.Parents {
		ok, err := parent.RunTargetRecursive(name)
		if err != nil {
			return ok, fmt.Errorf("running target '%s': %v", name, err)
		}
		if ok {
			return ok, nil
		}
	}
	return false, nil
}

// Run given target recursively
func (build *Build) RunTargetRecursive(name string) (bool, error) {
	target := build.GetTargetByName(name)
	if target == nil {
		return build.RunTargetRecursive(name)
	}
	err := target.RunSteps()
	if err != nil {
		return true, fmt.Errorf("running target '%s': %v", name, err)
	}
	return false, nil
}
<|endoftext|>


<commit_before>// Copyright 2011 The Go 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 net

import (
	"context"
	"errors"
	"io"
	"os"
)

func query(ctx context.Context, filename, query string, bufSize int) (res []string, err error) {
	file, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.Seek(0, io.SeekStart)
	if err != nil {
		return
	}
	_, err = file.WriteString(query)
	if err != nil {
		return
	}
	_, err = file.Seek(0, io.SeekStart)
	if err != nil {
		return
	}
	buf := make([]byte, bufSize)
	for {
		n, _ := file.Read(buf)
		if n <= 0 {
			break
		}
		res = append(res, string(buf[:n]))
	}
	return
}

func queryCS(ctx context.Context, net, host, service string) (res []string, err error) {
	switch net {
	case "tcp4", "tcp6":
		net = "tcp"
	case "udp4", "udp6":
		net = "udp"
	}
	if host == "" {
		host = "*"
	}
	return query(ctx, netdir+"/cs", net+"!"+host+"!"+service, 128)
}

func queryCS1(ctx context.Context, net string, ip IP, port int) (clone, dest string, err error) {
	ips := "*"
	if len(ip) != 0 && !ip.IsUnspecified() {
		ips = ip.String()
	}
	lines, err := queryCS(ctx, net, ips, itoa(port))
	if err != nil {
		return
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return "", "", errors.New("bad response from ndb/cs")
	}
	clone, dest = f[0], f[1]
	return
}

func queryDNS(ctx context.Context, addr string, typ string) (res []string, err error) {
	return query(ctx, netdir+"/dns", addr+" "+typ, 1024)
}

// toLower returns a lower-case version of in. Restricting us to
// ASCII is sufficient to handle the IP protocol names and allow
// us to not depend on the strings and unicode packages.
func toLower(in string) string {
	for _, c := range in {
		if 'A' <= c && c <= 'Z' {
			// Has upper case; need to fix.
			out := []byte(in)
			for i := 0; i < len(in); i++ {
				c := in[i]
				if 'A' <= c && c <= 'Z' {
					c += 'a' - 'A'
				}
				out[i] = c
			}
			return string(out)
		}
	}
	return in
}

// lookupProtocol looks up IP protocol name and returns
// the corresponding protocol number.
func lookupProtocol(ctx context.Context, name string) (proto int, err error) {
	lines, err := query(ctx, netdir+"/cs", "!protocol="+toLower(name), 128)
	if err != nil {
		return 0, err
	}
	if len(lines) == 0 {
		return 0, UnknownNetworkError(name)
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, UnknownNetworkError(name)
	}
	s := f[1]
	if n, _, ok := dtoi(s[byteIndex(s, '=')+1:]); ok {
		return n, nil
	}
	return 0, UnknownNetworkError(name)
}

func (*Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
	// Use netdir/cs instead of netdir/dns because cs knows about
	// host names in local network (e.g. from /lib/ndb/local)
	lines, err := queryCS(ctx, "net", host, "1")
	if err != nil {
		return
	}
loop:
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 2 {
			continue
		}
		addr := f[1]
		if i := byteIndex(addr, '!'); i >= 0 {
			addr = addr[:i] // remove port
		}
		if ParseIP(addr) == nil {
			continue
		}
		// only return unique addresses
		for _, a := range addrs {
			if a == addr {
				continue loop
			}
		}
		addrs = append(addrs, addr)
	}
	return
}

func (r *Resolver) lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
	lits, err := r.lookupHost(ctx, host)
	if err != nil {
		return
	}
	for _, lit := range lits {
		host, zone := splitHostZone(lit)
		if ip := ParseIP(host); ip != nil {
			addr := IPAddr{IP: ip, Zone: zone}
			addrs = append(addrs, addr)
		}
	}
	return
}

func (*Resolver) lookupPort(ctx context.Context, network, service string) (port int, err error) {
	switch network {
	case "tcp4", "tcp6":
		network = "tcp"
	case "udp4", "udp6":
		network = "udp"
	}
	lines, err := queryCS(ctx, network, "127.0.0.1", toLower(service))
	if err != nil {
		return
	}
	unknownPortError := &AddrError{Err: "unknown port", Addr: network + "/" + service}
	if len(lines) == 0 {
		return 0, unknownPortError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownPortError
	}
	s := f[1]
	if i := byteIndex(s, '!'); i >= 0 {
		s = s[i+1:] // remove address
	}
	if n, _, ok := dtoi(s); ok {
		return n, nil
	}
	return 0, unknownPortError
}

func (*Resolver) lookupCNAME(ctx context.Context, name string) (cname string, err error) {
	lines, err := queryDNS(ctx, name, "cname")
	if err != nil {
		return
	}
	if len(lines) > 0 {
		if f := getFields(lines[0]); len(f) >= 3 {
			return f[2] + ".", nil
		}
	}
	return "", errors.New("bad response from ndb/dns")
}

func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
	var target string
	if service == "" && proto == "" {
		target = name
	} else {
		target = "_" + service + "._" + proto + "." + name
	}
	lines, err := queryDNS(ctx, target, "srv")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 6 {
			continue
		}
		port, _, portOk := dtoi(f[4])
		priority, _, priorityOk := dtoi(f[3])
		weight, _, weightOk := dtoi(f[2])
		if !(portOk && priorityOk && weightOk) {
			continue
		}
		addrs = append(addrs, &SRV{absDomainName([]byte(f[5])), uint16(port), uint16(priority), uint16(weight)})
		cname = absDomainName([]byte(f[0]))
	}
	byPriorityWeight(addrs).sort()
	return
}

func (*Resolver) lookupMX(ctx context.Context, name string) (mx []*MX, err error) {
	lines, err := queryDNS(ctx, name, "mx")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 4 {
			continue
		}
		if pref, _, ok := dtoi(f[2]); ok {
			mx = append(mx, &MX{absDomainName([]byte(f[3])), uint16(pref)})
		}
	}
	byPref(mx).sort()
	return
}

func (*Resolver) lookupNS(ctx context.Context, name string) (ns []*NS, err error) {
	lines, err := queryDNS(ctx, name, "ns")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		ns = append(ns, &NS{absDomainName([]byte(f[2]))})
	}
	return
}

func (*Resolver) lookupTXT(ctx context.Context, name string) (txt []string, err error) {
	lines, err := queryDNS(ctx, name, "txt")
	if err != nil {
		return
	}
	for _, line := range lines {
		if i := byteIndex(line, '\t'); i >= 0 {
			txt = append(txt, absDomainName([]byte(line[i+1:])))
		}
	}
	return
}

func (*Resolver) lookupAddr(ctx context.Context, addr string) (name []string, err error) {
	arpa, err := reverseaddr(addr)
	if err != nil {
		return
	}
	lines, err := queryDNS(ctx, arpa, "ptr")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		name = append(name, absDomainName([]byte(f[2])))
	}
	return
}
<commit_msg>net: handle "dns failure" as errNoSuchHost on Plan 9<commit_after>// Copyright 2011 The Go 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 net

import (
	"context"
	"errors"
	"io"
	"os"
)

func query(ctx context.Context, filename, query string, bufSize int) (res []string, err error) {
	file, err := os.OpenFile(filename, os.O_RDWR, 0)
	if err != nil {
		return
	}
	defer file.Close()

	_, err = file.Seek(0, io.SeekStart)
	if err != nil {
		return
	}
	_, err = file.WriteString(query)
	if err != nil {
		return
	}
	_, err = file.Seek(0, io.SeekStart)
	if err != nil {
		return
	}
	buf := make([]byte, bufSize)
	for {
		n, _ := file.Read(buf)
		if n <= 0 {
			break
		}
		res = append(res, string(buf[:n]))
	}
	return
}

func queryCS(ctx context.Context, net, host, service string) (res []string, err error) {
	switch net {
	case "tcp4", "tcp6":
		net = "tcp"
	case "udp4", "udp6":
		net = "udp"
	}
	if host == "" {
		host = "*"
	}
	return query(ctx, netdir+"/cs", net+"!"+host+"!"+service, 128)
}

func queryCS1(ctx context.Context, net string, ip IP, port int) (clone, dest string, err error) {
	ips := "*"
	if len(ip) != 0 && !ip.IsUnspecified() {
		ips = ip.String()
	}
	lines, err := queryCS(ctx, net, ips, itoa(port))
	if err != nil {
		return
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return "", "", errors.New("bad response from ndb/cs")
	}
	clone, dest = f[0], f[1]
	return
}

func queryDNS(ctx context.Context, addr string, typ string) (res []string, err error) {
	return query(ctx, netdir+"/dns", addr+" "+typ, 1024)
}

// toLower returns a lower-case version of in. Restricting us to
// ASCII is sufficient to handle the IP protocol names and allow
// us to not depend on the strings and unicode packages.
func toLower(in string) string {
	for _, c := range in {
		if 'A' <= c && c <= 'Z' {
			// Has upper case; need to fix.
			out := []byte(in)
			for i := 0; i < len(in); i++ {
				c := in[i]
				if 'A' <= c && c <= 'Z' {
					c += 'a' - 'A'
				}
				out[i] = c
			}
			return string(out)
		}
	}
	return in
}

// lookupProtocol looks up IP protocol name and returns
// the corresponding protocol number.
func lookupProtocol(ctx context.Context, name string) (proto int, err error) {
	lines, err := query(ctx, netdir+"/cs", "!protocol="+toLower(name), 128)
	if err != nil {
		return 0, err
	}
	if len(lines) == 0 {
		return 0, UnknownNetworkError(name)
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, UnknownNetworkError(name)
	}
	s := f[1]
	if n, _, ok := dtoi(s[byteIndex(s, '=')+1:]); ok {
		return n, nil
	}
	return 0, UnknownNetworkError(name)
}

func (*Resolver) lookupHost(ctx context.Context, host string) (addrs []string, err error) {
	// Use netdir/cs instead of netdir/dns because cs knows about
	// host names in local network (e.g. from /lib/ndb/local)
	lines, err := queryCS(ctx, "net", host, "1")
	if err != nil {
		if stringsHasSuffix(err.Error(), "dns failure") {
			err = errNoSuchHost
		}
		return
	}
loop:
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 2 {
			continue
		}
		addr := f[1]
		if i := byteIndex(addr, '!'); i >= 0 {
			addr = addr[:i] // remove port
		}
		if ParseIP(addr) == nil {
			continue
		}
		// only return unique addresses
		for _, a := range addrs {
			if a == addr {
				continue loop
			}
		}
		addrs = append(addrs, addr)
	}
	return
}

func (r *Resolver) lookupIP(ctx context.Context, host string) (addrs []IPAddr, err error) {
	lits, err := r.lookupHost(ctx, host)
	if err != nil {
		return
	}
	for _, lit := range lits {
		host, zone := splitHostZone(lit)
		if ip := ParseIP(host); ip != nil {
			addr := IPAddr{IP: ip, Zone: zone}
			addrs = append(addrs, addr)
		}
	}
	return
}

func (*Resolver) lookupPort(ctx context.Context, network, service string) (port int, err error) {
	switch network {
	case "tcp4", "tcp6":
		network = "tcp"
	case "udp4", "udp6":
		network = "udp"
	}
	lines, err := queryCS(ctx, network, "127.0.0.1", toLower(service))
	if err != nil {
		return
	}
	unknownPortError := &AddrError{Err: "unknown port", Addr: network + "/" + service}
	if len(lines) == 0 {
		return 0, unknownPortError
	}
	f := getFields(lines[0])
	if len(f) < 2 {
		return 0, unknownPortError
	}
	s := f[1]
	if i := byteIndex(s, '!'); i >= 0 {
		s = s[i+1:] // remove address
	}
	if n, _, ok := dtoi(s); ok {
		return n, nil
	}
	return 0, unknownPortError
}

func (*Resolver) lookupCNAME(ctx context.Context, name string) (cname string, err error) {
	lines, err := queryDNS(ctx, name, "cname")
	if err != nil {
		return
	}
	if len(lines) > 0 {
		if f := getFields(lines[0]); len(f) >= 3 {
			return f[2] + ".", nil
		}
	}
	return "", errors.New("bad response from ndb/dns")
}

func (*Resolver) lookupSRV(ctx context.Context, service, proto, name string) (cname string, addrs []*SRV, err error) {
	var target string
	if service == "" && proto == "" {
		target = name
	} else {
		target = "_" + service + "._" + proto + "." + name
	}
	lines, err := queryDNS(ctx, target, "srv")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 6 {
			continue
		}
		port, _, portOk := dtoi(f[4])
		priority, _, priorityOk := dtoi(f[3])
		weight, _, weightOk := dtoi(f[2])
		if !(portOk && priorityOk && weightOk) {
			continue
		}
		addrs = append(addrs, &SRV{absDomainName([]byte(f[5])), uint16(port), uint16(priority), uint16(weight)})
		cname = absDomainName([]byte(f[0]))
	}
	byPriorityWeight(addrs).sort()
	return
}

func (*Resolver) lookupMX(ctx context.Context, name string) (mx []*MX, err error) {
	lines, err := queryDNS(ctx, name, "mx")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 4 {
			continue
		}
		if pref, _, ok := dtoi(f[2]); ok {
			mx = append(mx, &MX{absDomainName([]byte(f[3])), uint16(pref)})
		}
	}
	byPref(mx).sort()
	return
}

func (*Resolver) lookupNS(ctx context.Context, name string) (ns []*NS, err error) {
	lines, err := queryDNS(ctx, name, "ns")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		ns = append(ns, &NS{absDomainName([]byte(f[2]))})
	}
	return
}

func (*Resolver) lookupTXT(ctx context.Context, name string) (txt []string, err error) {
	lines, err := queryDNS(ctx, name, "txt")
	if err != nil {
		return
	}
	for _, line := range lines {
		if i := byteIndex(line, '\t'); i >= 0 {
			txt = append(txt, absDomainName([]byte(line[i+1:])))
		}
	}
	return
}

func (*Resolver) lookupAddr(ctx context.Context, addr string) (name []string, err error) {
	arpa, err := reverseaddr(addr)
	if err != nil {
		return
	}
	lines, err := queryDNS(ctx, arpa, "ptr")
	if err != nil {
		return
	}
	for _, line := range lines {
		f := getFields(line)
		if len(f) < 3 {
			continue
		}
		name = append(name, absDomainName([]byte(f[2])))
	}
	return
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsproxy_test

import (
	"testing"

	"github.com/jacobsa/gcloud/gcs/mock_gcs"
	"github.com/jacobsa/gcsfuse/gcsproxy"
	. "github.com/jacobsa/ogletest"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

func TestOgletest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Invariant-checking object proxy
////////////////////////////////////////////////////////////////////////

// A wrapper around ObjectProxy that calls CheckInvariants whenever invariants
// should hold. For catching logic errors early in the test.
type checkingObjectProxy struct {
	wrapped *gcsproxy.ObjectProxy
}

func (op *checkingObjectProxy) NoteLatest(o *storage.Object) error {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.NoteLatest(o)
}

func (op *checkingObjectProxy) Size() (uint64, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Size()
}

func (op *checkingObjectProxy) ReadAt(b []byte, o int64) (int, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.ReadAt(b, o)
}

func (op *checkingObjectProxy) WriteAt(b []byte, o int64) (int, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.WriteAt(b, o)
}

func (op *checkingObjectProxy) Truncate(n uint64) error {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Truncate(n)
}

func (op *checkingObjectProxy) Sync(ctx context.Context) (*storage.Object, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Sync(ctx)
}

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type ObjectProxyTest struct {
	objectName string
	bucket     mock_gcs.MockBucket
	op         checkingObjectProxy
}

var _ SetUpInterface = &ObjectProxyTest{}

func (t *ObjectProxyTest) SetUp(ti *TestInfo) {
	t.objectName = "some/object"
	t.bucket = mock_gcs.NewMockBucket(ti.MockController, "bucket")

	var err error
	t.op.wrapped, err = gcsproxy.NewObjectProxy(
		t.bucket,
		t.objectName)

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

////////////////////////////////////////////////////////////////////////
// No source object
////////////////////////////////////////////////////////////////////////

// A test whose initial conditions are a fresh object proxy without a source
// object set.
type NoSourceObjectTest struct {
	ObjectProxyTest
}

var _ SetUpInterface = &NoSourceObjectTest{}

func init() { RegisterTestSuite(&NoSourceObjectTest{}) }

func (t *NoSourceObjectTest) DoesFoo() {
	AssertTrue(false, "TODO")
}

////////////////////////////////////////////////////////////////////////
// Source object present
////////////////////////////////////////////////////////////////////////

// A test whose initial conditions are an object proxy branching from a source
// object in the bucket.
type SourceObjectPresentTest struct {
	ObjectProxyTest
}

var _ SetUpInterface = &SourceObjectPresentTest{}

func init() { RegisterTestSuite(&SourceObjectPresentTest{}) }

func (t *SourceObjectPresentTest) SetUp(ti *TestInfo)

func (t *SourceObjectPresentTest) DoesFoo() {
	AssertTrue(false, "TODO")
}
<commit_msg>Implemented SourceObjectPresentTest.SetUp.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)

package gcsproxy_test

import (
	"testing"

	"github.com/jacobsa/gcloud/gcs/mock_gcs"
	"github.com/jacobsa/gcsfuse/gcsproxy"
	. "github.com/jacobsa/ogletest"
	"golang.org/x/net/context"
	"google.golang.org/cloud/storage"
)

func TestOgletest(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Invariant-checking object proxy
////////////////////////////////////////////////////////////////////////

// A wrapper around ObjectProxy that calls CheckInvariants whenever invariants
// should hold. For catching logic errors early in the test.
type checkingObjectProxy struct {
	wrapped *gcsproxy.ObjectProxy
}

func (op *checkingObjectProxy) NoteLatest(o *storage.Object) error {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.NoteLatest(o)
}

func (op *checkingObjectProxy) Size() (uint64, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Size()
}

func (op *checkingObjectProxy) ReadAt(b []byte, o int64) (int, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.ReadAt(b, o)
}

func (op *checkingObjectProxy) WriteAt(b []byte, o int64) (int, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.WriteAt(b, o)
}

func (op *checkingObjectProxy) Truncate(n uint64) error {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Truncate(n)
}

func (op *checkingObjectProxy) Sync(ctx context.Context) (*storage.Object, error) {
	op.wrapped.CheckInvariants()
	defer op.wrapped.CheckInvariants()
	return op.wrapped.Sync(ctx)
}

////////////////////////////////////////////////////////////////////////
// Boilerplate
////////////////////////////////////////////////////////////////////////

type ObjectProxyTest struct {
	objectName string
	bucket     mock_gcs.MockBucket
	op         checkingObjectProxy
}

var _ SetUpInterface = &ObjectProxyTest{}

func (t *ObjectProxyTest) SetUp(ti *TestInfo) {
	t.objectName = "some/object"
	t.bucket = mock_gcs.NewMockBucket(ti.MockController, "bucket")

	var err error
	t.op.wrapped, err = gcsproxy.NewObjectProxy(
		t.bucket,
		t.objectName)

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

////////////////////////////////////////////////////////////////////////
// No source object
////////////////////////////////////////////////////////////////////////

// A test whose initial conditions are a fresh object proxy without a source
// object set.
type NoSourceObjectTest struct {
	ObjectProxyTest
}

var _ SetUpInterface = &NoSourceObjectTest{}

func init() { RegisterTestSuite(&NoSourceObjectTest{}) }

func (t *NoSourceObjectTest) DoesFoo() {
	AssertTrue(false, "TODO")
}

////////////////////////////////////////////////////////////////////////
// Source object present
////////////////////////////////////////////////////////////////////////

// A test whose initial conditions are an object proxy branching from a source
// object in the bucket.
type SourceObjectPresentTest struct {
	ObjectProxyTest
	sourceObject storage.Object
}

var _ SetUpInterface = &SourceObjectPresentTest{}

func init() { RegisterTestSuite(&SourceObjectPresentTest{}) }

func (t *SourceObjectPresentTest) SetUp(ti *TestInfo) {
	t.ObjectProxyTest.SetUp(ti)

	// Set up the source object.
	t.sourceObject = storage.Object{
		Name:       t.objectName,
		Generation: 123,
		Size:       456,
	}

	if err := t.op.NoteLatest(&t.sourceObject); err != nil {
		panic(err)
	}
}

func (t *SourceObjectPresentTest) DoesFoo() {
	AssertTrue(false, "TODO")
}
<|endoftext|>


<commit_before>//
// addr.go -- address tools
//
package samtun

import (
  "bitbucket.org/majestrate/sam3"
  "net"
)
// maps b32 -> ip
type addrMap map[string]string

// given ip get b32
func (m addrMap) IP(b32 string) (ip string) {
  ip, _ = m[b32]
  return
}

// given b32 get ip
func (m addrMap) B32(ip string) string {
  for k, v := range m {
    if v == ip {
      return k
    }
  }
  return ""
}

// take a link message and filter the packets
// return a link frame that has corrected addresses
// returns nil if we have a packet from someone unmapped
func (m addrMap) filterMessage(msg linkMessage, ourAddr sam3.I2PAddr) (frame linkFrame) {
  dst := net.ParseIP(m.IP(ourAddr.Base32()))
  src := net.ParseIP(m.IP(msg.addr.Base32()))
  if dst == nil || src == nil {
    // bad address
    frame = nil
  } else {
    for _, pkt := range msg.frame {
      pkt.setDst(dst)
      pkt.setSrc(src)
      frame = append(frame, pkt)
    }
  }
  return
}
<commit_msg>fix out of bounds<commit_after>//
// addr.go -- address tools
//
package samtun

import (
  "bitbucket.org/majestrate/sam3"
  "net"
)
// maps b32 -> ip
type addrMap map[string]string

// given ip get b32
func (m addrMap) IP(b32 string) (ip string) {
  ip, _ = m[b32]
  return
}

// given b32 get ip
func (m addrMap) B32(ip string) string {
  for k, v := range m {
    if v == ip {
      return k
    }
  }
  return ""
}

// take a link message and filter the packets
// return a link frame that has corrected addresses
// returns nil if we have a packet from someone unmapped
func (m addrMap) filterMessage(msg linkMessage, ourAddr sam3.I2PAddr) (frame linkFrame) {
  dst := net.ParseIP(m.IP(ourAddr.Base32()))
  src := net.ParseIP(m.IP(msg.addr.Base32()))
  if dst == nil || src == nil {
    // bad address
    frame = nil
  } else {
    for _, pkt := range msg.frame {
      if pkt == nil && len(pkt) > 20 {
        // back packet
      } else {
        pkt.setDst(dst)
        pkt.setSrc(src)
        frame = append(frame, pkt)
      }
    }
  }
  return
}
<|endoftext|>


<commit_before>package main

import (
    "log"
    "net/http"
    "runtime"
    "github.com/gorilla/pat"
    "github.com/mediaRepository/api"
)

func main() {

    r := pat.New()

    //Creating routes
    r.Get("/healthcheck", http.HandlerFunc(api.HealthCheckHandler))
    r.Get("/upload", http.HandlerFunc(api.PostFormUploadFile))
    r.Post("/upload", http.HandlerFunc(api.UploadFileHandler))

    log.Println("Staring server: getting num cpu")
    runtime.GOMAXPROCS(runtime.NumCPU())

    log.Println("Server listening on 4321")
    http.ListenAndServe(":4321", r)
}

<commit_msg>Fixing format: running gofmt in file server.go<commit_after>package main

import (
	"github.com/gorilla/pat"
	"github.com/mediaRepository/api"
	"log"
	"net/http"
	"runtime"
)

func main() {

	r := pat.New()

	//Creating routes
	r.Get("/healthcheck", http.HandlerFunc(api.HealthCheckHandler))
	r.Get("/upload", http.HandlerFunc(api.PostFormUploadFile))
	r.Post("/upload", http.HandlerFunc(api.UploadFileHandler))

	log.Println("Staring server: getting num cpu")
	runtime.GOMAXPROCS(runtime.NumCPU())

	log.Println("Server listening on 4321")
	http.ListenAndServe(":4321", r)
}
<|endoftext|>


<commit_before>package main

import (
	"errors"

	"github.com/gopherjs/gopherjs/js"
)

func jsError(x interface{}) (err error) {
	if x == nil {
		return
	}

	if jsErr, ok := x.(*js.Error); ok {
		err = errors.New(jsErr.Get("message").Str())
		return
	}

	err = x.(error)
	return
}

func jsInvoke(name string, function js.Object, args ...interface{}) (ok bool) {
	defer func() {
		if err := jsError(recover()); err != nil {
			println(name + " invocation error: " + err.Error())
		}
	}()

	function.Invoke(args...)

	ok = true
	return
}

func NewArray() js.Object {
	return js.Global.Get("Array").New()
}

func NewUint8Array(arrayBuffer js.Object) js.Object {
	return js.Global.Get("Uint8Array").New(arrayBuffer)
}

func NewObject() js.Object {
	return js.Global.Get("Object").New()
}

func EncodeURIComponent(s string) string {
	return js.Global.Call("encodeURIComponent", s).Str()
}

func ParseJSON(json string) (object js.Object, err error) {
	defer func() {
		err = jsError(recover())
	}()

	object = js.Global.Get("JSON").Call("parse", json)
	return
}

func StringifyJSON(object interface{}) (json string, err error) {
	defer func() {
		err = jsError(recover())
	}()

	json = js.Global.Get("JSON").Call("stringify", object).Str()
	return
}

func Random() float64 {
	return js.Global.Get("Math").Call("random").Float()
}

func SetTimeout(callback func(), timeout Duration) (id js.Object) {
	return js.Global.Call("setTimeout", callback, timeout)
}

func ClearTimeout(id js.Object) {
	js.Global.Call("clearTimeout", id)
}
<commit_msg>avoid empty error messages<commit_after>package main

import (
	"errors"

	"github.com/gopherjs/gopherjs/js"
)

func jsError(x interface{}) (err error) {
	if x == nil {
		return
	}

	if jsErr, ok := x.(*js.Error); ok {
		msg := jsErr.Get("message").Str()
		if msg == "" {
			msg = "error"
		}

		err = errors.New(msg)
		return
	}

	err = x.(error)
	return
}

func jsInvoke(name string, function js.Object, args ...interface{}) (ok bool) {
	defer func() {
		if err := jsError(recover()); err != nil {
			println(name + " invocation error: " + err.Error())
		}
	}()

	function.Invoke(args...)

	ok = true
	return
}

func NewArray() js.Object {
	return js.Global.Get("Array").New()
}

func NewUint8Array(arrayBuffer js.Object) js.Object {
	return js.Global.Get("Uint8Array").New(arrayBuffer)
}

func NewObject() js.Object {
	return js.Global.Get("Object").New()
}

func EncodeURIComponent(s string) string {
	return js.Global.Call("encodeURIComponent", s).Str()
}

func ParseJSON(json string) (object js.Object, err error) {
	defer func() {
		err = jsError(recover())
	}()

	object = js.Global.Get("JSON").Call("parse", json)
	return
}

func StringifyJSON(object interface{}) (json string, err error) {
	defer func() {
		err = jsError(recover())
	}()

	json = js.Global.Get("JSON").Call("stringify", object).Str()
	return
}

func Random() float64 {
	return js.Global.Get("Math").Call("random").Float()
}

func SetTimeout(callback func(), timeout Duration) (id js.Object) {
	return js.Global.Call("setTimeout", callback, timeout)
}

func ClearTimeout(id js.Object) {
	js.Global.Call("clearTimeout", id)
}
<|endoftext|>


<commit_before>// Copyright 2017 The Go 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 cpu

const CacheLinePadSize = 64

func doinit() {
	options = []option{
		{Name: "aes", Feature: &ARM64.HasAES},
		{Name: "pmull", Feature: &ARM64.HasPMULL},
		{Name: "sha1", Feature: &ARM64.HasSHA1},
		{Name: "sha2", Feature: &ARM64.HasSHA2},
		{Name: "sha512", Feature: &ARM64.HasSHA512},
		{Name: "crc32", Feature: &ARM64.HasCRC32},
		{Name: "atomics", Feature: &ARM64.HasATOMICS},
		{Name: "cpuid", Feature: &ARM64.HasCPUID},
		{Name: "isNeoverseN1", Feature: &ARM64.IsNeoverseN1},
		{Name: "isZeus", Feature: &ARM64.IsZeus},
	}

	// arm64 uses different ways to detect CPU features at runtime depending on the operating system.
	osInit()
}

func getisar0() uint64

func getMIDR() uint64
<commit_msg>internal/cpu: fix cpu cacheLineSize for arm64 darwin(a.k.a. M1)<commit_after>// Copyright 2017 The Go 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 cpu

// CacheLinePadSize is used to prevent false sharing of cache lines.
// We choose 128 because Apple Silicon, a.k.a. M1, has 128-byte cache line size.
// It doesn't cost much and is much more future-proof.
const CacheLinePadSize = 128

func doinit() {
	options = []option{
		{Name: "aes", Feature: &ARM64.HasAES},
		{Name: "pmull", Feature: &ARM64.HasPMULL},
		{Name: "sha1", Feature: &ARM64.HasSHA1},
		{Name: "sha2", Feature: &ARM64.HasSHA2},
		{Name: "sha512", Feature: &ARM64.HasSHA512},
		{Name: "crc32", Feature: &ARM64.HasCRC32},
		{Name: "atomics", Feature: &ARM64.HasATOMICS},
		{Name: "cpuid", Feature: &ARM64.HasCPUID},
		{Name: "isNeoverseN1", Feature: &ARM64.IsNeoverseN1},
		{Name: "isZeus", Feature: &ARM64.IsZeus},
	}

	// arm64 uses different ways to detect CPU features at runtime depending on the operating system.
	osInit()
}

func getisar0() uint64

func getMIDR() uint64
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"sort"
	"strings"

	cli "gopkg.in/urfave/cli.v2"
	yaml "gopkg.in/yaml.v2"

	"github.com/jgillich/nixbench/modules"
)

// VERSION is set at build time
var VERSION = "master"

func main() {

	moduleNames := []string{}
	for key := range modules.Modules {
		moduleNames = append(moduleNames, key)
	}

	app := &cli.App{
		Name:        "nixbench",
		Usage:       "A better benchmarking tool for servers",
		Description: fmt.Sprintf("Loaded modules: %s", strings.Trim(fmt.Sprintf("%v", moduleNames), "[]")),
		Version:     VERSION,
		Flags: []cli.Flag{
			&cli.BoolFlag{
				Name:  "yaml",
				Usage: "Output as yaml",
			},
			&cli.BoolFlag{
				Name:  "all",
				Usage: "Run all modules",
			},
			&cli.StringSliceFlag{
				Name:    "module",
				Aliases: []string{"m"},
				Usage:   "Modules to enable",
				Value:   cli.NewStringSlice("host", "cpu", "disk", "net", "geekbench"),
			},
		},
		Action: func(c *cli.Context) error {
			if !c.Bool("yaml") {
				fmt.Printf("nixbench %s - https://github.com/jgillich/nixbench", VERSION)
			}

			enabledModules := c.StringSlice("modules")

			if c.Bool("all") {
				enabledModules = moduleNames
			}

			sort.Strings(enabledModules)

			for _, name := range enabledModules {
				module, ok := modules.Modules[name]

				if !ok {
					return fmt.Errorf("unknown module '%s'", name)
				}

				if err := module.Run(); err != nil {
					return err
				}

				if c.Bool("yaml") {
					var r map[string]interface{} = map[string]interface{}{}
					r[name] = module
					yml, err := yaml.Marshal(r)
					if err != nil {
						return err
					}
					fmt.Printf(string(yml))
				} else {
					fmt.Printf("\n\n%s\n", name)
					for i := 1; i <= len(name); i++ {
						fmt.Print("-")
					}
					fmt.Print("\n")
					module.Print()
				}
			}

			return nil
		},
	}

	app.Run(os.Args)
}
<commit_msg>fix no modules being run<commit_after>package main

import (
	"fmt"
	"os"
	"sort"
	"strings"

	cli "gopkg.in/urfave/cli.v2"
	yaml "gopkg.in/yaml.v2"

	"github.com/jgillich/nixbench/modules"
)

// VERSION is set at build time
var VERSION = "master"

func main() {

	moduleNames := []string{}
	for key := range modules.Modules {
		moduleNames = append(moduleNames, key)
	}

	app := &cli.App{
		Name:        "nixbench",
		Usage:       "A better benchmarking tool for servers",
		Description: fmt.Sprintf("Loaded modules: %s", strings.Trim(fmt.Sprintf("%v", moduleNames), "[]")),
		Version:     VERSION,
		Flags: []cli.Flag{
			&cli.BoolFlag{
				Name:  "yaml",
				Usage: "Output as yaml",
			},
			&cli.BoolFlag{
				Name:  "all",
				Usage: "Run all modules",
			},
			&cli.StringSliceFlag{
				Name:    "module",
				Aliases: []string{"m"},
				Usage:   "Modules to enable",
				Value:   cli.NewStringSlice("host", "cpu", "disk", "net", "geekbench"),
			},
		},
		Action: func(c *cli.Context) error {
			if !c.Bool("yaml") {
				fmt.Printf("nixbench %s - https://github.com/jgillich/nixbench", VERSION)
			}

			enabledModules := c.StringSlice("module")

			if c.Bool("all") {
				enabledModules = moduleNames
			}

			sort.Strings(enabledModules)

			for _, name := range enabledModules {
				module, ok := modules.Modules[name]

				if !ok {
					return fmt.Errorf("unknown module '%s'", name)
				}

				if err := module.Run(); err != nil {
					return err
				}

				if c.Bool("yaml") {
					var r map[string]interface{} = map[string]interface{}{}
					r[name] = module
					yml, err := yaml.Marshal(r)
					if err != nil {
						return err
					}
					fmt.Printf(string(yml))
				} else {
					fmt.Printf("\n\n%s\n", name)
					for i := 1; i <= len(name); i++ {
						fmt.Print("-")
					}
					fmt.Print("\n")
					module.Print()
				}
			}

			return nil
		},
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package command

import (
	"context"
	"fmt"
	"net/http"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/iamapi"
	"github.com/chrislusf/seaweedfs/weed/pb"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/util"
	"github.com/gorilla/mux"
	"time"
)

var (
	iamStandaloneOptions IamOptions
)

type IamOptions struct {
	filer   *string
	masters *string
	port    *int
}

func init() {
	cmdIam.Run = runIam // break init cycle
	iamStandaloneOptions.filer = cmdIam.Flag.String("filer", "localhost:8888", "filer server address")
	iamStandaloneOptions.masters = cmdIam.Flag.String("master", "localhost:9333", "comma-separated master servers")
	iamStandaloneOptions.port = cmdIam.Flag.Int("port", 8111, "iam server http listen port")
}

var cmdIam = &Command{
	UsageLine: "iam [-port=8111] [-filer=<ip:port>] [-masters=<ip:port>,<ip:port>]",
	Short:     "start a iam API compatible server",
	Long:      "start a iam API compatible server.",
}

func runIam(cmd *Command, args []string) bool {
	return iamStandaloneOptions.startIamServer()
}

func (iamopt *IamOptions) startIamServer() bool {
	filerGrpcAddress, err := pb.ParseFilerGrpcAddress(*iamopt.filer)
	if err != nil {
		glog.Fatal(err)
		return false
	}

	grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
	for {
		err = pb.WithGrpcFilerClient(filerGrpcAddress, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
			resp, err := client.GetFilerConfiguration(context.Background(), &filer_pb.GetFilerConfigurationRequest{})
			if err != nil {
				return fmt.Errorf("get filer %s configuration: %v", filerGrpcAddress, err)
			}
			glog.V(0).Infof("IAM read filer configuration: %s", resp)
			return nil
		})
		if err != nil {
			glog.V(0).Infof("wait to connect to filer %s grpc address %s", *iamopt.filer, filerGrpcAddress)
			time.Sleep(time.Second)
		} else {
			glog.V(0).Infof("connected to filer %s grpc address %s", *iamopt.filer, filerGrpcAddress)
			break
		}
	}

	router := mux.NewRouter().SkipClean(true)
	_, iamApiServer_err := iamapi.NewIamApiServer(router, &iamapi.IamServerOption{
		Filer:            *iamopt.filer,
		Port:             *iamopt.port,
		FilerGrpcAddress: filerGrpcAddress,
		GrpcDialOption:   grpcDialOption,
	})
	glog.V(0).Info("NewIamApiServer created")
	if iamApiServer_err != nil {
		glog.Fatalf("IAM API Server startup error: %v", iamApiServer_err)
	}

	httpS := &http.Server{Handler: router}

	listenAddress := fmt.Sprintf(":%d", *iamopt.port)
	iamApiListener, err := util.NewListener(listenAddress, time.Duration(10)*time.Second)
	if err != nil {
		glog.Fatalf("IAM API Server listener on %s error: %v", listenAddress, err)
	}

	glog.V(0).Infof("Start Seaweed IAM API Server %s at http port %d", util.Version(), *iamopt.port)
	if err = httpS.Serve(iamApiListener); err != nil {
		glog.Fatalf("IAM API Server Fail to serve: %v", err)
	}

	return true
}
<commit_msg>fix get filerGrpcAddress<commit_after>package command

import (
	"context"
	"fmt"
	"net/http"

	"github.com/chrislusf/seaweedfs/weed/glog"
	"github.com/chrislusf/seaweedfs/weed/iamapi"
	"github.com/chrislusf/seaweedfs/weed/pb"
	"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
	"github.com/chrislusf/seaweedfs/weed/security"
	"github.com/chrislusf/seaweedfs/weed/util"
	"github.com/gorilla/mux"
	"time"
)

var (
	iamStandaloneOptions IamOptions
)

type IamOptions struct {
	filer   *string
	masters *string
	port    *int
}

func init() {
	cmdIam.Run = runIam // break init cycle
	iamStandaloneOptions.filer = cmdIam.Flag.String("filer", "localhost:8888", "filer server address")
	iamStandaloneOptions.masters = cmdIam.Flag.String("master", "localhost:9333", "comma-separated master servers")
	iamStandaloneOptions.port = cmdIam.Flag.Int("port", 8111, "iam server http listen port")
}

var cmdIam = &Command{
	UsageLine: "iam [-port=8111] [-filer=<ip:port>] [-masters=<ip:port>,<ip:port>]",
	Short:     "start a iam API compatible server",
	Long:      "start a iam API compatible server.",
}

func runIam(cmd *Command, args []string) bool {
	return iamStandaloneOptions.startIamServer()
}

func (iamopt *IamOptions) startIamServer() bool {
	filerGrpcAddress, err := pb.ParseServerToGrpcAddress(*iamopt.filer)
	if err != nil {
		glog.Fatal(err)
		return false
	}

	grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
	for {
		err = pb.WithGrpcFilerClient(filerGrpcAddress, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
			resp, err := client.GetFilerConfiguration(context.Background(), &filer_pb.GetFilerConfigurationRequest{})
			if err != nil {
				return fmt.Errorf("get filer %s configuration: %v", filerGrpcAddress, err)
			}
			glog.V(0).Infof("IAM read filer configuration: %s", resp)
			return nil
		})
		if err != nil {
			glog.V(0).Infof("wait to connect to filer %s grpc address %s", *iamopt.filer, filerGrpcAddress)
			time.Sleep(time.Second)
		} else {
			glog.V(0).Infof("connected to filer %s grpc address %s", *iamopt.filer, filerGrpcAddress)
			break
		}
	}

	router := mux.NewRouter().SkipClean(true)
	_, iamApiServer_err := iamapi.NewIamApiServer(router, &iamapi.IamServerOption{
		Filer:            *iamopt.filer,
		Port:             *iamopt.port,
		FilerGrpcAddress: filerGrpcAddress,
		GrpcDialOption:   grpcDialOption,
	})
	glog.V(0).Info("NewIamApiServer created")
	if iamApiServer_err != nil {
		glog.Fatalf("IAM API Server startup error: %v", iamApiServer_err)
	}

	httpS := &http.Server{Handler: router}

	listenAddress := fmt.Sprintf(":%d", *iamopt.port)
	iamApiListener, err := util.NewListener(listenAddress, time.Duration(10)*time.Second)
	if err != nil {
		glog.Fatalf("IAM API Server listener on %s error: %v", listenAddress, err)
	}

	glog.V(0).Infof("Start Seaweed IAM API Server %s at http port %d", util.Version(), *iamopt.port)
	if err = httpS.Serve(iamApiListener); err != nil {
		glog.Fatalf("IAM API Server Fail to serve: %v", err)
	}

	return true
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/gorilla/websocket"
	"log"
)

type Client struct {
	// websocket connection
	conn *websocket.Conn
	// buffered channel of outbound messages
	send          chan []byte // what to send?
	authenticated bool
}

func newClient(c *websocket.Conn) *Client {
	return &Client{
		conn: c,
		send: make(chan []byte, 256),
	}
}

func (c *Client) readPump() {
	defer func() {
		c.conn.Close()
	}()

	for {
		body := make(map[string]string)
		err := c.conn.ReadJSON(&body)
		if err != nil {
			log.Printf("read error: %s", err)
			break
		}

		log.Printf("message body: %s", body)
		GameServerInstance.incomingMessageBuffer <- newMessage(c, &body)
		// need to put this message into a queue of messages to be handled
		/*
			if !c.authenticated {
				// must authenticate first, only allowable message
				if !c.authenticate(message) {
					// TODO some sort of useful response here
					log.Printf("Failed to authenticate %s", message)
				} else {
					// TODO do login (create player, land into a room, and so on)
					p := world.NewPlayer(message["player_name"], message["player_name"])
					//p.Room = world.World.StartRoom
					c.Player = p
				}
			} else {
				// TODO do someting useful with message
			}
		*/
		//c.send <- []byte("abcdefg")
	}
}

func (c *Client) writePump() {
	defer func() {
		c.conn.Close()
	}()

	for {
		select {
		case message := <-c.send:
			log.Printf("writing %s", message)
			c.conn.WriteMessage(websocket.TextMessage, message)
		}
	}
}

func (c *Client) authenticate(message map[string]string) bool {
	// TODO authenticate stuff..
	c.authenticated = true
	return true
}
<commit_msg>remove comments<commit_after>package main

import (
	"github.com/gorilla/websocket"
	"log"
)

type Client struct {
	// websocket connection
	conn *websocket.Conn
	// buffered channel of outbound messages
	send          chan []byte // what to send?
	authenticated bool
}

func newClient(c *websocket.Conn) *Client {
	return &Client{
		conn: c,
		send: make(chan []byte, 256),
	}
}

func (c *Client) readPump() {
	defer func() {
		c.conn.Close()
	}()

	for {
		body := make(map[string]string)
		err := c.conn.ReadJSON(&body)
		if err != nil {
			log.Printf("read error: %s", err)
			break
		}
		log.Printf("message body: %s", body)
		GameServerInstance.incomingMessageBuffer <- newMessage(c, &body)
		//c.send <- []byte("abcdefg")
	}
}

func (c *Client) writePump() {
	defer func() {
		c.conn.Close()
	}()

	for {
		select {
		case message := <-c.send:
			log.Printf("writing %s", message)
			c.conn.WriteMessage(websocket.TextMessage, message)
		}
	}
}

func (c *Client) authenticate(message map[string]string) bool {
	// TODO authenticate stuff..
	c.authenticated = true
	return true
}
<|endoftext|>


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

package render

import (
	"bytes"
	"io"
	"path"
	"sort"
	"strconv"
	"strings"

	"github.com/googlecodelabs/tools/claat/types"
	htmlTemplate "html/template"
)

// MD renders nodes as markdown for the target env.
func Qwiklabs(env string, nodes ...types.Node) (string, error) {
	var buf bytes.Buffer
	if err := WriteQwiklabs(&buf, env, nodes...); err != nil {
		return "", err
	}
	return buf.String(), nil
}

// WriteMD does the same as MD but outputs rendered markup to w.
func WriteQwiklabs(w io.Writer, env string, nodes ...types.Node) error {
	qw := qwiklabsWriter{w: w, env: env}
	return qw.write(nodes...)
}

type qwiklabsWriter struct {
	w         io.Writer // output writer
	env       string    // target environment
	err       error     // error during any writeXxx methods
	lineStart bool
}

func (qw *qwiklabsWriter) writeBytes(b []byte) {
	if qw.err != nil {
		return
	}
	qw.lineStart = len(b) > 0 && b[len(b)-1] == '\n'
	_, qw.err = qw.w.Write(b)
}

func (qw *qwiklabsWriter) writeString(s string) {
	qw.writeBytes([]byte(s))
}

func (qw *qwiklabsWriter) writeEscape(s string) {
	htmlTemplate.HTMLEscape(qw.w, []byte(s))
}

func (qw *qwiklabsWriter) space() {
	if !qw.lineStart {
		qw.writeString(" ")
	}
}

func (qw *qwiklabsWriter) newBlock() {
	if !qw.lineStart {
		qw.writeBytes(newLine)
	}
	qw.writeBytes(newLine)
}

func (qw *qwiklabsWriter) matchEnv(v []string) bool {
	if len(v) == 0 || qw.env == "" {
		return true
	}
	i := sort.SearchStrings(v, qw.env)
	return i < len(v) && v[i] == qw.env
}

func (qw *qwiklabsWriter) write(nodes ...types.Node) error {
	for _, n := range nodes {
		if !qw.matchEnv(n.Env()) {
			continue
		}
		switch n := n.(type) {
		case *types.TextNode:
			qw.text(n)
		case *types.ImageNode:
			qw.image(n)
		case *types.URLNode:
			qw.url(n)
		case *types.ButtonNode:
			qw.write(n.Content.Nodes...)
		case *types.CodeNode:
			qw.code(n)
		case *types.ListNode:
			qw.list(n)
		case *types.ImportNode:
			if len(n.Content.Nodes) == 0 {
				break
			}
			qw.write(n.Content.Nodes...)
		case *types.ItemsListNode:
			qw.itemsList(n)
		case *types.GridNode:
			qw.grid(n)
		case *types.InfoboxNode:
			qw.infobox(n)
		//case *types.SurveyNode:
		//	qw.survey(n)
		case *types.HeaderNode:
			qw.header(n)
		//case *types.YouTubeNode:
		//	qw.youtube(n)
		}
		if qw.err != nil {
			return qw.err
		}
	}
	return nil
}

func (qw *qwiklabsWriter) text(n *types.TextNode) {
	if n.Bold {
		qw.writeString("__")
	}
	if n.Italic {
		qw.writeString(" *")
	}
	if n.Code {
		qw.writeString("`")
	}
	qw.writeString(n.Value)
	if n.Code {
		qw.writeString("`")
	}
	if n.Italic {
		qw.writeString("* ")
	}
	if n.Bold {
		qw.writeString("__")
	}
}

func (qw *qwiklabsWriter) image(n *types.ImageNode) {
	qw.space()
	qw.writeString("![")
	qw.writeString(path.Base(n.Src))
	qw.writeString("](")
	qw.writeString(n.Src)
	qw.writeString(")")
}

func (qw *qwiklabsWriter) url(n *types.URLNode) {
	qw.space()
	if n.URL != "" {
		qw.writeString("[")
	}
	for _, cn := range n.Content.Nodes {
		if t, ok := cn.(*types.TextNode); ok {
			qw.writeString(t.Value)
		}
	}
	if n.URL != "" {
		qw.writeString("](")
		qw.writeString(n.URL)
		qw.writeString(")")
	}
}

func (qw *qwiklabsWriter) code(n *types.CodeNode) {
	qw.newBlock()
	defer qw.writeBytes(newLine)
	if n.Term {
		var buf bytes.Buffer
		const prefix = "    "
		lineStart := true
		for _, r := range n.Value {
			if lineStart {
				buf.WriteString(prefix)
			}
			buf.WriteRune(r)
			lineStart = r == '\n'
		}
		qw.writeBytes(buf.Bytes())
		return
	}
	qw.writeString("```")
	qw.writeString(n.Lang)
	qw.writeBytes(newLine)
	qw.writeString(n.Value)
	if !qw.lineStart {
		qw.writeBytes(newLine)
	}
	qw.writeString("```")
}

func (qw *qwiklabsWriter) list(n *types.ListNode) {
	if n.Block() == true {
		qw.newBlock()
	}
	qw.write(n.Nodes...)
	if !qw.lineStart {
		qw.writeBytes(newLine)
	}
}

func (qw *qwiklabsWriter) itemsList(n *types.ItemsListNode) {
	qw.newBlock()
	for i, item := range n.Items {
		s := "* "
		if n.Type() == types.NodeItemsList && n.Start > 0 {
			s = strconv.Itoa(i+n.Start) + ". "
		}
		qw.writeString(s)
		qw.write(item.Nodes...)
		if !qw.lineStart {
			qw.writeBytes(newLine)
		}
	}
}

func (qw *qwiklabsWriter) grid(n *types.GridNode) {
	qw.newBlock()
	for _, r := range n.Rows {
		qw.writeString("|")
		for _, c := range r {
			qw.write(c.Content.Nodes...)
			qw.writeString("|")
		}
		qw.writeString("\n")
	}
}

func (qw *qwiklabsWriter) infobox(n *types.InfoboxNode) {
	// Note: There is no defined mapping of a Codelabs info box to any default
	//   Markdown syntax. We have decided to mix raw HTML into our Qwiklabs
	//   Markdown documents.
	// Future work: We may choose to extend the Markdown syntax more rigorously.
	qw.newBlock()
	qw.writeString(`<div class="codelabs-infobox codelabs-infobox-`)
	qw.writeEscape(string(n.Kind))
	qw.writeString(`">`)

	// Take advantage of the existing HTML writer to transform
	// the body of thi infobox.
	WriteHTML(qw.w, qw.env, n.Content.Nodes...)

	qw.writeString("
")

	// Alternatively we could use the HTML renderers output for the whole node
	// not just its contents.
	//WriteHTML(qw.w, qw.env, n)
}

func (qw *qwiklabsWriter) header(n *types.HeaderNode) {
	qw.newBlock()
	qw.writeString(strings.Repeat("#", n.Level+1))
	qw.writeString(" ")
	qw.write(n.Content.Nodes...)
	if !qw.lineStart {
		qw.writeBytes(newLine)
	}
}
<commit_msg>claat: render grid as HTML in qwiklabs format<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package render

import (
	"fmt"
	"bytes"
	"io"
	"path"
	"sort"
	"strconv"
	"strings"

	"github.com/googlecodelabs/tools/claat/types"
	htmlTemplate "html/template"
)

// MD renders nodes as markdown for the target env.
func Qwiklabs(env string, nodes ...types.Node) (string, error) {
	var buf bytes.Buffer
	if err := WriteQwiklabs(&buf, env, nodes...); err != nil {
		return "", err
	}
	return buf.String(), nil
}

// WriteMD does the same as MD but outputs rendered markup to w.
func WriteQwiklabs(w io.Writer, env string, nodes ...types.Node) error {
	qw := qwiklabsWriter{w: w, env: env}
	return qw.write(nodes...)
}

type qwiklabsWriter struct {
	w         io.Writer // output writer
	env       string    // target environment
	err       error     // error during any writeXxx methods
	lineStart bool
}

func (qw *qwiklabsWriter) writeBytes(b []byte) {
	if qw.err != nil {
		return
	}
	qw.lineStart = len(b) > 0 && b[len(b)-1] == '\n'
	_, qw.err = qw.w.Write(b)
}

func (qw *qwiklabsWriter) writeString(s string) {
	qw.writeBytes([]byte(s))
}

func (qw *qwiklabsWriter) writeFmt(f string, a ...interface{}) {
	qw.writeString(fmt.Sprintf(f, a...))
}

func (qw *qwiklabsWriter) writeEscape(s string) {
	htmlTemplate.HTMLEscape(qw.w, []byte(s))
}

func (qw *qwiklabsWriter) space() {
	if !qw.lineStart {
		qw.writeString(" ")
	}
}

func (qw *qwiklabsWriter) newBlock() {
	if !qw.lineStart {
		qw.writeBytes(newLine)
	}
	qw.writeBytes(newLine)
}

func (qw *qwiklabsWriter) matchEnv(v []string) bool {
	if len(v) == 0 || qw.env == "" {
		return true
	}
	i := sort.SearchStrings(v, qw.env)
	return i < len(v) && v[i] == qw.env
}

func (qw *qwiklabsWriter) write(nodes ...types.Node) error {
	for _, n := range nodes {
		if !qw.matchEnv(n.Env()) {
			continue
		}
		switch n := n.(type) {
		case *types.TextNode:
			qw.text(n)
		case *types.ImageNode:
			qw.image(n)
		case *types.URLNode:
			qw.url(n)
		case *types.ButtonNode:
			qw.write(n.Content.Nodes...)
		case *types.CodeNode:
			qw.code(n)
		case *types.ListNode:
			qw.list(n)
		case *types.ImportNode:
			if len(n.Content.Nodes) == 0 {
				break
			}
			qw.write(n.Content.Nodes...)
		case *types.ItemsListNode:
			qw.itemsList(n)
		case *types.GridNode:
			qw.grid(n)
		case *types.InfoboxNode:
			qw.infobox(n)
		//case *types.SurveyNode:
		//	qw.survey(n)
		case *types.HeaderNode:
			qw.header(n)
		//case *types.YouTubeNode:
		//	qw.youtube(n)
		}
		if qw.err != nil {
			return qw.err
		}
	}
	return nil
}

func (qw *qwiklabsWriter) text(n *types.TextNode) {
	if n.Bold {
		qw.writeString("__")
	}
	if n.Italic {
		qw.writeString(" *")
	}
	if n.Code {
		qw.writeString("`")
	}
	qw.writeString(n.Value)
	if n.Code {
		qw.writeString("`")
	}
	if n.Italic {
		qw.writeString("* ")
	}
	if n.Bold {
		qw.writeString("__")
	}
}

func (qw *qwiklabsWriter) image(n *types.ImageNode) {
	qw.space()
	qw.writeString("![")
	qw.writeString(path.Base(n.Src))
	qw.writeString("](")
	qw.writeString(n.Src)
	qw.writeString(")")
}

func (qw *qwiklabsWriter) url(n *types.URLNode) {
	qw.space()
	if n.URL != "" {
		qw.writeString("[")
	}
	for _, cn := range n.Content.Nodes {
		if t, ok := cn.(*types.TextNode); ok {
			qw.writeString(t.Value)
		}
	}
	if n.URL != "" {
		qw.writeString("](")
		qw.writeString(n.URL)
		qw.writeString(")")
	}
}

func (qw *qwiklabsWriter) code(n *types.CodeNode) {
	qw.newBlock()
	defer qw.writeBytes(newLine)
	if n.Term {
		var buf bytes.Buffer
		const prefix = "    "
		lineStart := true
		for _, r := range n.Value {
			if lineStart {
				buf.WriteString(prefix)
			}
			buf.WriteRune(r)
			lineStart = r == '\n'
		}
		qw.writeBytes(buf.Bytes())
		return
	}
	qw.writeString("```")
	qw.writeString(n.Lang)
	qw.writeBytes(newLine)
	qw.writeString(n.Value)
	if !qw.lineStart {
		qw.writeBytes(newLine)
	}
	qw.writeString("```")
}

func (qw *qwiklabsWriter) list(n *types.ListNode) {
	if n.Block() == true {
		qw.newBlock()
	}
	qw.write(n.Nodes...)
	if !qw.lineStart {
		qw.writeBytes(newLine)
	}
}

func (qw *qwiklabsWriter) itemsList(n *types.ItemsListNode) {
	qw.newBlock()
	for i, item := range n.Items {
		s := "* "
		if n.Type() == types.NodeItemsList && n.Start > 0 {
			s = strconv.Itoa(i+n.Start) + ". "
		}
		qw.writeString(s)
		qw.write(item.Nodes...)
		if !qw.lineStart {
			qw.writeBytes(newLine)
		}
	}
}

func (qw *qwiklabsWriter) grid(n *types.GridNode) {
	// Note: There is no defined mapping of a google doc table to any default
	//   Markdown syntax. We have decided to mix raw HTML into our Qwiklabs
	//   Markdown documents.
	// TODO: Extend the Markdown syntax more rigorously.
	qw.newBlock()
	qw.writeString("
\n")
	for _, r := range n.Rows {
		qw.writeString("
")
		for _, c := range r {
			qw.writeFmt(`<td colspan="%d" rowspan="%d">`, c.Colspan, c.Rowspan)
			// Use the existing HTML writer to transform the infobox body content.
			WriteHTML(qw.w, qw.env, c.Content.Nodes...)
			qw.writeString("	")
		}
		qw.writeString("
\n")
	}
	qw.writeString("
")
}

func (qw *qwiklabsWriter) infobox(n *types.InfoboxNode) {
	// Note: There is no defined mapping of a Codelabs info box to any default
	//   Markdown syntax. We have decided to mix raw HTML into our Qwiklabs
	//   Markdown documents.
	// TODO: Extend the Markdown syntax more rigorously.
	qw.newBlock()
	qw.writeString(`<div class="codelabs-infobox codelabs-infobox-`)
	qw.writeEscape(string(n.Kind))
	qw.writeString(`">`)

	// Use the existing HTML writer to transform the infobox body content.
	WriteHTML(qw.w, qw.env, n.Content.Nodes...)

	qw.writeString("
")
}

func (qw *qwiklabsWriter) header(n *types.HeaderNode) {
	qw.newBlock()
	qw.writeString(strings.Repeat("#", n.Level+1))
	qw.writeString(" ")
	qw.write(n.Content.Nodes...)
	if !qw.lineStart {
		qw.writeBytes(newLine)
	}
}
<|endoftext|>


<commit_before>// +build ignore

package main

// Control a stepper motor (28BJY-48)
//
// Datasheet:
// http://www.raspberrypi-spy.co.uk/wp-content/uploads/2012/07/Stepper-Motor-28BJY-48-Datasheet.pdf
//
// this is a port of Matt Hawkins' example impl from
// http://www.raspberrypi-spy.co.uk/2012/07/stepper-motor-control-in-python/
// (link privides additional instructions for wiring your pi)

import (
	"flag"
	"fmt"
	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/rpi"
	"os"
	"os/signal"
	"time"
)

func main() {
	stepWait := flag.Int("step-delay", 10, "milliseconds between steps")
	flag.Parse()

	if err := embd.InitGPIO(); err != nil {
		panic(err)
	}
	defer embd.CloseGPIO()

	// Physical pins 11,15,16,18
	// GPIO17,GPIO22,GPIO23,GPIO24
	stepPinNums := []int{17, 22, 23, 24}

	stepPins := make([]embd.DigitalPin, 4)

	for i, pinNum := range stepPinNums {
		pin, err := embd.NewDigitalPin(pinNum)
		if err != nil {
			panic(err)
		}
		defer pin.Close()
		if err := pin.SetDirection(embd.Out); err != nil {
			panic(err)
		}
		if err := pin.Write(embd.Low); err != nil {
			panic(err)
		}
		defer func() {
			if err := pin.SetDirection(embd.In); err != nil {
				panic(err)
			}
		}()

		stepPins[i] = pin
	}

	// Define advanced sequence
	// as shown in manufacturers datasheet
	seq := [][]int{
		[]int{1, 0, 0, 0},
		[]int{1, 1, 0, 0},
		[]int{0, 1, 0, 0},
		[]int{0, 1, 1, 0},
		[]int{0, 0, 1, 0},
		[]int{0, 0, 1, 1},
		[]int{0, 0, 0, 1},
		[]int{1, 0, 0, 1},
	}

	stepCount := len(seq) - 1
	stepDir := 2 // Set to 1 or 2 for clockwise, -1 or -2 for counter-clockwise

	// Start main loop
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, os.Interrupt, os.Kill)
	defer signal.Stop(quit)

	stepCounter := 0
	for {
		select {
		case <-time.After(time.Duration(*stepWait) * time.Millisecond):
			for i, pin := range stepPins {
				if seq[stepCounter][i] != 0 {
					fmt.Printf("Enable pin %d, step %d\n", i, stepCounter)
					if err := pin.Write(embd.High); err != nil {
						panic(err)
					}
				} else {
					if err := pin.Write(embd.Low); err != nil {
						panic(err)
					}

				}
			}
			stepCounter += stepDir

			// If we reach the end of the sequence start again
			if stepCounter >= stepCount {
				stepCounter = 0
			} else if stepCounter < 0 {
				stepCounter = stepCount
			}
		case <-quit:
			return
		}
	}

}
<commit_msg>style updates and using ticker to time steps<commit_after>// +build ignore

package main

// Control a stepper motor (28BJY-48)
//
// Datasheet:
// http://www.raspberrypi-spy.co.uk/wp-content/uploads/2012/07/Stepper-Motor-28BJY-48-Datasheet.pdf
//
// this is a port of Matt Hawkins' example impl from
// http://www.raspberrypi-spy.co.uk/2012/07/stepper-motor-control-in-python/
// (link privides additional instructions for wiring your pi)

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"time"

	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/rpi"
)

func main() {
	stepDelay := flag.Int("step-delay", 10, "milliseconds between steps")
	flag.Parse()

	if err := embd.InitGPIO(); err != nil {
		panic(err)
	}
	defer embd.CloseGPIO()

	// Physical pins 11,15,16,18 on rasp pi
	// GPIO17,GPIO22,GPIO23,GPIO24
	stepPinNums := []int{17, 22, 23, 24}

	stepPins := make([]embd.DigitalPin, 4)

	for i, pinNum := range stepPinNums {
		pin, err := embd.NewDigitalPin(pinNum)
		if err != nil {
			panic(err)
		}
		defer pin.Close()
		if err := pin.SetDirection(embd.Out); err != nil {
			panic(err)
		}
		if err := pin.Write(embd.Low); err != nil {
			panic(err)
		}
		defer func() {
			if err := pin.SetDirection(embd.In); err != nil {
				panic(err)
			}
		}()

		stepPins[i] = pin
	}

	// Define sequence described in manufacturer's datasheet
	seq := [][]int{
		[]int{1, 0, 0, 0},
		[]int{1, 1, 0, 0},
		[]int{0, 1, 0, 0},
		[]int{0, 1, 1, 0},
		[]int{0, 0, 1, 0},
		[]int{0, 0, 1, 1},
		[]int{0, 0, 0, 1},
		[]int{1, 0, 0, 1},
	}

	stepCount := len(seq) - 1
	stepDir := 2 // Set to 1 or 2 for clockwise, -1 or -2 for counter-clockwise

	quit := make(chan os.Signal, 1)
	signal.Notify(quit, os.Interrupt, os.Kill)
	defer signal.Stop(quit)

	// Start main loop
	ticker := time.NewTicker(time.Duration(*stepDelay) * time.Millisecond)

	var stepCounter int
	for {
		select {
		case <-ticker.C:

			// set pins to appropriate values for given position in the sequence
			for i, pin := range stepPins {
				if seq[stepCounter][i] != 0 {
					fmt.Printf("Enable pin %d, step %d\n", i, stepCounter)
					if err := pin.Write(embd.High); err != nil {
						panic(err)
					}
				} else {
					if err := pin.Write(embd.Low); err != nil {
						panic(err)
					}

				}
			}
			stepCounter += stepDir

			// If we reach the end of the sequence start again
			if stepCounter >= stepCount {
				stepCounter = 0
			} else if stepCounter < 0 {
				stepCounter = stepCount
			}

		case <-quit:
			ticker.Stop()
			return
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"encoding/json"
	"math/rand"
	"strconv"
	"io/ioutil"
	"io"
	"strings"
	"os"
)

var (
	GET_HANDLER = "GET"
	POST_HANDLER = "POST"
	WORKING_DIR, _ = os.Getwd()
	BASE_DIR = WORKING_DIR + "/"
	store map[int]map[string]interface{} = make(map[int]map[string]interface{})
	requestHandlers map[string]handler = make(map[string]handler)
)

type handler func(w http.ResponseWriter, r *http.Request)

func handle(w http.ResponseWriter, r *http.Request) {
	handler := requestHandlers[r.Method]
	handler(w, r)
}

func readBodyToJson(body io.ReadCloser) (map[string]interface{}, error) {
	var out map[string]interface{}
	data, err := ioutil.ReadAll(body)

	if err == nil {
		err = json.Unmarshal(data, &out)

		if err == nil {
			id := rand.Int()
			out["__id"] = id

			store[id] = out
		}
	}

	return out, err
}

func writeJsonToDisk(jsonBlob map[string]interface{}) error {
	id := strconv.Itoa(jsonBlob["__id"].(int))
	file, err := os.Create(BASE_DIR + "jsons/" + id)

	if err == nil {
		var jsonAsString []byte
		jsonAsString, err = json.Marshal(jsonBlob)

		if err == nil {
			_, err = file.Write(jsonAsString)
		}
	}

	return err
}

func getPacketByKey(key string) (map[string]interface{}, error) {
	var out map[string]interface{}
	filepath := BASE_DIR + "jsons/" + key
	bytes, err := ioutil.ReadFile(filepath)

	if err == nil {
		err = json.Unmarshal(bytes, &out)
	}

	return out, err
}

func setupRoutes() {
	os.Mkdir(BASE_DIR + "jsons", 0777)

	requestHandlers[GET_HANDLER] = func(w http.ResponseWriter, r *http.Request) {
		key := strings.TrimLeft(r.URL.Path, "/")
		var write string

		packet, err := getPacketByKey(key)

		if err == nil {
			var bytes []byte
			bytes, err = json.Marshal(packet)

			if err == nil {
				write = string(bytes)
			}
		}

		if err != nil {
			write = err.Error()
		}

		fmt.Fprintf(w, write)
	}

	requestHandlers[POST_HANDLER] = func(w http.ResponseWriter, r *http.Request) {
		var write string

		out, err := readBodyToJson(r.Body)

		if err == nil {
			err = writeJsonToDisk(out)

			if err == nil {
				var toret []byte
				toret, err = json.Marshal(out)
				write = string(toret)
			}
		}

		if err != nil {
			write = err.Error()
		}

		fmt.Fprintf(w, write)
	}
}

func main() {
	setupRoutes()
	http.HandleFunc("/", handle)

	port := "8080"
	fmt.Println("Webserver listening at port: " + port)
	http.ListenAndServe(":" + port, nil)
}
<commit_msg>Refactoring directory variables.<commit_after>package main

import (
	"fmt"
	"net/http"
	"encoding/json"
	"math/rand"
	"strconv"
	"io/ioutil"
	"io"
	"strings"
	"os"
)

var (
	GET_HANDLER = "GET"
	POST_HANDLER = "POST"
	WORKING_DIR, _ = os.Getwd()
	JSON_DIR = WORKING_DIR + "/jsons/"
	store map[int]map[string]interface{} = make(map[int]map[string]interface{})
	requestHandlers map[string]handler = make(map[string]handler)
)

type handler func(w http.ResponseWriter, r *http.Request)

func handle(w http.ResponseWriter, r *http.Request) {
	handler := requestHandlers[r.Method]
	handler(w, r)
}

func readBodyToJson(body io.ReadCloser) (map[string]interface{}, error) {
	var out map[string]interface{}
	data, err := ioutil.ReadAll(body)

	if err == nil {
		err = json.Unmarshal(data, &out)

		if err == nil {
			id := rand.Int()
			out["__id"] = id

			store[id] = out
		}
	}

	return out, err
}

func writeJsonToDisk(jsonBlob map[string]interface{}) error {
	id := strconv.Itoa(jsonBlob["__id"].(int))
	file, err := os.Create(JSON_DIR + id)

	if err == nil {
		var jsonAsString []byte
		jsonAsString, err = json.Marshal(jsonBlob)

		if err == nil {
			_, err = file.Write(jsonAsString)
		}
	}

	return err
}

func getPacketByKey(key string) (map[string]interface{}, error) {
	var out map[string]interface{}
	filepath := JSON_DIR + key
	bytes, err := ioutil.ReadFile(filepath)

	if err == nil {
		err = json.Unmarshal(bytes, &out)
	}

	return out, err
}

func setupRoutes() {
	os.Mkdir(JSON_DIR, 0777)

	requestHandlers[GET_HANDLER] = func(w http.ResponseWriter, r *http.Request) {
		key := strings.TrimLeft(r.URL.Path, "/")
		var write string

		packet, err := getPacketByKey(key)

		if err == nil {
			var bytes []byte
			bytes, err = json.Marshal(packet)

			if err == nil {
				write = string(bytes)
			}
		}

		if err != nil {
			write = err.Error()
		}

		fmt.Fprintf(w, write)
	}

	requestHandlers[POST_HANDLER] = func(w http.ResponseWriter, r *http.Request) {
		var write string

		out, err := readBodyToJson(r.Body)

		if err == nil {
			err = writeJsonToDisk(out)

			if err == nil {
				var toret []byte
				toret, err = json.Marshal(out)
				write = string(toret)
			}
		}

		if err != nil {
			write = err.Error()
		}

		fmt.Fprintf(w, write)
	}
}

func main() {
	setupRoutes()
	http.HandleFunc("/", handle)

	port := "8080"
	fmt.Println("Webserver listening at port: " + port)
	http.ListenAndServe(":" + port, nil)
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/bobziuchkovski/writ"
)

//SubcommandObject is a literal struct that implements a subcommand
type SubcommandObject interface {
	//The name the command is registered as
	Name() string
	//The description of the command to register
	Description() string

	//HelpText is the prose decription of what this command does.
	HelpText() string

	//The aliases to register for
	Aliases() []string
	//The rest of the usage string, which will be appened to "NAME "
	Usage() string
	//SubcommandObjects should return the list of sub comamnds, or nil if a
	//terminal command.
	SubcommandObjects() []SubcommandObject
	//The command to actually run
	Run(p writ.Path, positional []string)

	//Config returns a writ.Command object. Should return the same object on
	//repeated calls.
	WritCommand() *writ.Command
	WritOptions() []*writ.Option
	//WritParentOptions returns a series of frames back up to the root command
	//with options. They aren't regeistered, per se, but are used to generate
	//help for all options.
	WritParentOptions() []*ParentOptions
	//WritHelp should return a Help config object for this command
	WritHelp() writ.Help

	TopLevelStruct() SubcommandObject
	SetTopLevelStruct(top SubcommandObject)

	Base() *boardgameUtil
	SetBase(base *boardgameUtil)

	Parent() SubcommandObject
	//SetParent will be called with the command's parent object.
	SetParent(parent SubcommandObject)
}

type ParentOptions struct {
	Name    string
	Options []*writ.Option
	Cmd     *writ.Command
}

type baseSubCommand struct {
	parent         SubcommandObject
	topLevelStruct SubcommandObject
	writCommand    *writ.Command
	base           *boardgameUtil
}

func (b *baseSubCommand) Base() *boardgameUtil {
	return b.base
}

func (b *baseSubCommand) SetBase(base *boardgameUtil) {
	b.base = base
}

func (b *baseSubCommand) optionGroupForObject(name string, cmd *writ.Command, options []*writ.Option) *writ.OptionGroup {

	if len(options) == 0 {
		return nil
	}

	optionNames := make([]string, len(options))
	for i, opt := range options {
		optionNames[i] = opt.Names[0]
	}
	group := cmd.GroupOptions(optionNames...)
	if name == "" {
		group.Header = "Options:"
	} else {
		group.Header = "Options for " + name + ":"
	}

	return &group

}

func (b *baseSubCommand) WritHelp() writ.Help {

	if b.WritCommand() == nil {
		return writ.Help{}
	}

	obj := b.TopLevelStruct()

	//TODO: pop this in as well
	var result writ.Help

	result.Header = obj.HelpText()

	baseSubCommands := obj.SubcommandObjects()

	if len(baseSubCommands) > 0 {

		subCmdNames := make([]string, len(baseSubCommands))
		for i, obj := range baseSubCommands {
			subCmdNames[i] = obj.Name()
		}

		group := b.WritCommand().GroupCommands(subCmdNames...)
		group.Header = "Subcommands:"
		result.CommandGroups = append(result.CommandGroups, group)

	}

	group := b.optionGroupForObject("", obj.WritCommand(), obj.WritOptions())
	if group != nil {
		result.OptionGroups = append(result.OptionGroups, *group)
	}

	for _, parentOptions := range obj.WritParentOptions() {
		group := b.optionGroupForObject(parentOptions.Name, parentOptions.Cmd, parentOptions.Options)
		if group != nil {
			result.OptionGroups = append(result.OptionGroups, *group)
		}
	}

	result.Usage = "Usage: " + FullName(obj) + " " + obj.Usage()

	return result
}

func (b *baseSubCommand) WritCommand() *writ.Command {
	if b.writCommand != nil {
		return b.writCommand
	}

	obj := b.TopLevelStruct()

	subCommands := obj.SubcommandObjects()
	subConfigs := make([]*writ.Command, len(subCommands))
	for i, command := range subCommands {
		subConfigs[i] = command.WritCommand()
	}

	config := &writ.Command{
		Name:        obj.Name(),
		Description: obj.Description(),
		Aliases:     obj.Aliases(),
		Subcommands: subConfigs,
		Options:     obj.WritOptions(),
	}

	b.writCommand = config

	config.Help = obj.WritHelp()

	return config
}

func (b *baseSubCommand) WritParentOptions() []*ParentOptions {
	var result []*ParentOptions

	obj := b.TopLevelStruct()

	obj = obj.Parent()

	for obj != nil {

		parentOptions := &ParentOptions{
			Name:    obj.Name(),
			Options: obj.WritOptions(),
			Cmd:     obj.WritCommand(),
		}

		result = append(result, parentOptions)

		obj = obj.Parent()
	}

	return result
}

func (b *baseSubCommand) TopLevelStruct() SubcommandObject {
	return b.topLevelStruct
}

func (b *baseSubCommand) SetTopLevelStruct(top SubcommandObject) {
	b.topLevelStruct = top
}

func (b *baseSubCommand) SetParent(parent SubcommandObject) {
	b.parent = parent
}

func (b *baseSubCommand) Parent() SubcommandObject {
	return b.parent
}

func (b *baseSubCommand) Aliases() []string {
	return nil
}

func (b *baseSubCommand) Description() string {
	return ""
}

func (b *baseSubCommand) Usage() string {
	return ""
}

//HelpText defaults to description
func (b *baseSubCommand) HelpText() string {
	return b.TopLevelStruct().Description()
}

func (b *baseSubCommand) SubcommandObjects() []SubcommandObject {
	return nil
}

func (b *baseSubCommand) WritOptions() []*writ.Option {
	return nil
}

func setupParents(cmd SubcommandObject, parent SubcommandObject, base *boardgameUtil) {

	cmd.SetParent(parent)
	cmd.SetTopLevelStruct(cmd)
	cmd.SetBase(base)

	if parent == nil {
		base = cmd.(*boardgameUtil)
	}

	for _, subCmd := range cmd.SubcommandObjects() {
		setupParents(subCmd, cmd, base)
	}

}

func FullName(cmd SubcommandObject) string {
	if cmd.Parent() == nil {
		return cmd.Name()
	}
	return FullName(cmd.Parent()) + " " + cmd.Name()
}

func strMatchesObject(str string, s SubcommandObject) bool {
	if s.Name() == str {
		return true
	}

	for _, alias := range s.Aliases() {
		if alias == str {
			return true
		}
	}

	return false
}

//selectSubcommandObject takes a subcommand object and a path. It verifes the
//first item is us, then identifies the nexct object to recurse into based on
//Names of SubcommandObjects.
func selectSubcommandObject(s SubcommandObject, p []string) SubcommandObject {

	if !strMatchesObject(p[0], s) {
		return nil
	}

	if len(p) < 2 {
		return s
	}

	nextCommand := p[1]

	for _, obj := range s.SubcommandObjects() {
		//We don't need to check alises, because the main library already did
		//the command/object matching
		if strMatchesObject(nextCommand, obj) {
			return selectSubcommandObject(obj, p[1:])
		}
	}

	return nil
}
<commit_msg>Continue fixing lint warnings in boardgame-util. Part of #552.<commit_after>package main

import (
	"github.com/bobziuchkovski/writ"
)

//SubcommandObject is a literal struct that implements a subcommand
type SubcommandObject interface {
	//The name the command is registered as
	Name() string
	//The description of the command to register
	Description() string

	//HelpText is the prose decription of what this command does.
	HelpText() string

	//The aliases to register for
	Aliases() []string
	//The rest of the usage string, which will be appened to "NAME "
	Usage() string
	//SubcommandObjects should return the list of sub comamnds, or nil if a
	//terminal command.
	SubcommandObjects() []SubcommandObject
	//The command to actually run
	Run(p writ.Path, positional []string)

	//Config returns a writ.Command object. Should return the same object on
	//repeated calls.
	WritCommand() *writ.Command
	WritOptions() []*writ.Option
	//WritparentOptions returns a series of frames back up to the root command
	//with options. They aren't regeistered, per se, but are used to generate
	//help for all options.
	WritparentOptions() []*parentOptions
	//WritHelp should return a Help config object for this command
	WritHelp() writ.Help

	TopLevelStruct() SubcommandObject
	SetTopLevelStruct(top SubcommandObject)

	Base() *boardgameUtil
	SetBase(base *boardgameUtil)

	Parent() SubcommandObject
	//SetParent will be called with the command's parent object.
	SetParent(parent SubcommandObject)
}

type parentOptions struct {
	Name    string
	Options []*writ.Option
	Cmd     *writ.Command
}

type baseSubCommand struct {
	parent         SubcommandObject
	topLevelStruct SubcommandObject
	writCommand    *writ.Command
	base           *boardgameUtil
}

func (b *baseSubCommand) Base() *boardgameUtil {
	return b.base
}

func (b *baseSubCommand) SetBase(base *boardgameUtil) {
	b.base = base
}

func (b *baseSubCommand) optionGroupForObject(name string, cmd *writ.Command, options []*writ.Option) *writ.OptionGroup {

	if len(options) == 0 {
		return nil
	}

	optionNames := make([]string, len(options))
	for i, opt := range options {
		optionNames[i] = opt.Names[0]
	}
	group := cmd.GroupOptions(optionNames...)
	if name == "" {
		group.Header = "Options:"
	} else {
		group.Header = "Options for " + name + ":"
	}

	return &group

}

func (b *baseSubCommand) WritHelp() writ.Help {

	if b.WritCommand() == nil {
		return writ.Help{}
	}

	obj := b.TopLevelStruct()

	//TODO: pop this in as well
	var result writ.Help

	result.Header = obj.HelpText()

	baseSubCommands := obj.SubcommandObjects()

	if len(baseSubCommands) > 0 {

		subCmdNames := make([]string, len(baseSubCommands))
		for i, obj := range baseSubCommands {
			subCmdNames[i] = obj.Name()
		}

		group := b.WritCommand().GroupCommands(subCmdNames...)
		group.Header = "Subcommands:"
		result.CommandGroups = append(result.CommandGroups, group)

	}

	group := b.optionGroupForObject("", obj.WritCommand(), obj.WritOptions())
	if group != nil {
		result.OptionGroups = append(result.OptionGroups, *group)
	}

	for _, parentOptions := range obj.WritparentOptions() {
		group := b.optionGroupForObject(parentOptions.Name, parentOptions.Cmd, parentOptions.Options)
		if group != nil {
			result.OptionGroups = append(result.OptionGroups, *group)
		}
	}

	result.Usage = "Usage: " + FullName(obj) + " " + obj.Usage()

	return result
}

func (b *baseSubCommand) WritCommand() *writ.Command {
	if b.writCommand != nil {
		return b.writCommand
	}

	obj := b.TopLevelStruct()

	subCommands := obj.SubcommandObjects()
	subConfigs := make([]*writ.Command, len(subCommands))
	for i, command := range subCommands {
		subConfigs[i] = command.WritCommand()
	}

	config := &writ.Command{
		Name:        obj.Name(),
		Description: obj.Description(),
		Aliases:     obj.Aliases(),
		Subcommands: subConfigs,
		Options:     obj.WritOptions(),
	}

	b.writCommand = config

	config.Help = obj.WritHelp()

	return config
}

func (b *baseSubCommand) WritparentOptions() []*parentOptions {
	var result []*parentOptions

	obj := b.TopLevelStruct()

	obj = obj.Parent()

	for obj != nil {

		parentOptions := &parentOptions{
			Name:    obj.Name(),
			Options: obj.WritOptions(),
			Cmd:     obj.WritCommand(),
		}

		result = append(result, parentOptions)

		obj = obj.Parent()
	}

	return result
}

func (b *baseSubCommand) TopLevelStruct() SubcommandObject {
	return b.topLevelStruct
}

func (b *baseSubCommand) SetTopLevelStruct(top SubcommandObject) {
	b.topLevelStruct = top
}

func (b *baseSubCommand) SetParent(parent SubcommandObject) {
	b.parent = parent
}

func (b *baseSubCommand) Parent() SubcommandObject {
	return b.parent
}

func (b *baseSubCommand) Aliases() []string {
	return nil
}

func (b *baseSubCommand) Description() string {
	return ""
}

func (b *baseSubCommand) Usage() string {
	return ""
}

//HelpText defaults to description
func (b *baseSubCommand) HelpText() string {
	return b.TopLevelStruct().Description()
}

func (b *baseSubCommand) SubcommandObjects() []SubcommandObject {
	return nil
}

func (b *baseSubCommand) WritOptions() []*writ.Option {
	return nil
}

func setupParents(cmd SubcommandObject, parent SubcommandObject, base *boardgameUtil) {

	cmd.SetParent(parent)
	cmd.SetTopLevelStruct(cmd)
	cmd.SetBase(base)

	if parent == nil {
		base = cmd.(*boardgameUtil)
	}

	for _, subCmd := range cmd.SubcommandObjects() {
		setupParents(subCmd, cmd, base)
	}

}

func FullName(cmd SubcommandObject) string {
	if cmd.Parent() == nil {
		return cmd.Name()
	}
	return FullName(cmd.Parent()) + " " + cmd.Name()
}

func strMatchesObject(str string, s SubcommandObject) bool {
	if s.Name() == str {
		return true
	}

	for _, alias := range s.Aliases() {
		if alias == str {
			return true
		}
	}

	return false
}

//selectSubcommandObject takes a subcommand object and a path. It verifes the
//first item is us, then identifies the nexct object to recurse into based on
//Names of SubcommandObjects.
func selectSubcommandObject(s SubcommandObject, p []string) SubcommandObject {

	if !strMatchesObject(p[0], s) {
		return nil
	}

	if len(p) < 2 {
		return s
	}

	nextCommand := p[1]

	for _, obj := range s.SubcommandObjects() {
		//We don't need to check alises, because the main library already did
		//the command/object matching
		if strMatchesObject(nextCommand, obj) {
			return selectSubcommandObject(obj, p[1:])
		}
	}

	return nil
}
<|endoftext|>