<commit_before>package main

import (
	"os"
	"os/signal"

	"github.com/pkg/errors"

	"github.com/havoc-io/mutagen/agent"
	"github.com/havoc-io/mutagen/cmd"
	"github.com/havoc-io/mutagen/session"
	"github.com/havoc-io/mutagen/stream"
)

var agentUsage = `usage: mutagen-agent should not be manually invoked
`

func main() {
	// Parse flags.
	flagSet := cmd.NewFlagSet("mutagen-agent", agentUsage, []int{1})
	mode := flagSet.ParseOrDie(os.Args[1:])[0]

	// Handle based on mode.
	if mode == agent.ModeInstall {
		// Invoke installation.
		if err := agent.Install(); err != nil {
			cmd.Fatal(errors.Wrap(err, "unable to install"))
		}
	} else if mode == agent.ModeEndpoint {
		// Serve an endpoint on standard input/output and monitor for its
		// termination.
		endpointTermination := make(chan error, 1)
		go func() {
			endpointTermination <- session.ServeEndpoint(
				stream.New(os.Stdin, os.Stdout, os.Stdout),
			)
		}()

		// Wait for termination from a signal or the endpoint.
		signalTermination := make(chan os.Signal, 1)
		signal.Notify(signalTermination, cmd.TerminationSignals...)
		select {
		case sig := <-signalTermination:
			cmd.Fatal(errors.Errorf("terminated by signal: %s", sig))
		case err := <-endpointTermination:
			cmd.Fatal(errors.Wrap(err, "endpoint terminated"))
		}
	} else {
		cmd.Fatal(errors.Errorf("unknown mode: %s", mode))
	}
}
<commit_msg>Reinstated agent side of version handshake.<commit_after>package main

import (
	"os"
	"os/signal"

	"github.com/pkg/errors"

	"github.com/havoc-io/mutagen"
	"github.com/havoc-io/mutagen/agent"
	"github.com/havoc-io/mutagen/cmd"
	"github.com/havoc-io/mutagen/session"
	"github.com/havoc-io/mutagen/stream"
)

var agentUsage = `usage: mutagen-agent should not be manually invoked
`

func main() {
	// Parse flags.
	flagSet := cmd.NewFlagSet("mutagen-agent", agentUsage, []int{1})
	mode := flagSet.ParseOrDie(os.Args[1:])[0]

	// Handle install.
	if mode == agent.ModeInstall {
		if err := agent.Install(); err != nil {
			cmd.Fatal(errors.Wrap(err, "unable to install"))
		}
		return
	}

	// Create a stream on standard input/output.
	stdio := stream.New(os.Stdin, os.Stdout, os.Stdout)

	// Perform a handshake.
	if err := mutagen.SendVersion(stdio); err != nil {
		cmd.Fatal(errors.Wrap(err, "unable to transmit version"))
	}

	// Handle based on mode.
	if mode == agent.ModeEndpoint {
		// Serve an endpoint on standard input/output and monitor for its
		// termination.
		endpointTermination := make(chan error, 1)
		go func() {
			endpointTermination <- session.ServeEndpoint(stdio)
		}()

		// Wait for termination from a signal or the endpoint.
		signalTermination := make(chan os.Signal, 1)
		signal.Notify(signalTermination, cmd.TerminationSignals...)
		select {
		case sig := <-signalTermination:
			cmd.Fatal(errors.Errorf("terminated by signal: %s", sig))
		case err := <-endpointTermination:
			cmd.Fatal(errors.Wrap(err, "endpoint terminated"))
		}
	} else {
		cmd.Fatal(errors.Errorf("unknown mode: %s", mode))
	}
}
<|endoftext|>


<commit_before>package node

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

	"github.com/docker/swarm-v2/api"
	"github.com/docker/swarm-v2/cmd/swarmctl/common"
	"github.com/spf13/cobra"
)

var (
	listCmd = &cobra.Command{
		Use:   "ls",
		Short: "List nodes",
		RunE: func(cmd *cobra.Command, args []string) error {
			flags := cmd.Flags()

			quiet, err := flags.GetBool("quiet")
			if err != nil {
				return err
			}

			c, err := common.Dial(cmd)
			if err != nil {
				return err
			}
			r, err := c.ListNodes(common.Context(cmd), &api.ListNodesRequest{})
			if err != nil {
				return err
			}

			var output func(n *api.Node)

			if !quiet {
				w := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0)
				defer func() {
					// Ignore flushing errors - there's nothing we can do.
					_ = w.Flush()
				}()
				common.PrintHeader(w, "ID", "Name", "Status", "Availability/Membership", "Manager status", "Leader")
				output = func(n *api.Node) {
					spec := &n.Spec
					name := spec.Annotations.Name
					membership := spec.Availability.String()
					if n.Certificate.Status.State != api.IssuanceStateIssued && n.Certificate.Status.State != api.IssuanceStateRenew {
						membership = spec.Membership.String()
					}
					if name == "" && n.Description != nil {
						name = n.Description.Hostname
					}
					leader := ""
					if n.Manager != nil && n.Manager.Raft.Status.Leader {
						leader = "*"
					}
					reachability := ""
					if n.Manager != nil {
						reachability = n.Manager.Raft.Status.Reachability.String()
					}
					if reachability == "" && spec.Role == api.NodeRoleManager {
						reachability = "UNKNOWN"
					}

					fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
						n.ID,
						name,
						n.Status.State.String(),
						membership,
						reachability,
						leader,
					)
				}
			} else {
				output = func(n *api.Node) { fmt.Println(n.ID) }
			}

			for _, n := range r.Nodes {
				output(n)
			}
			return nil
		},
	}
)

func init() {
	listCmd.Flags().BoolP("quiet", "q", false, "Only display IDs")
}
<commit_msg>swarmctl: Do not squash availability/membership together.<commit_after>package node

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

	"github.com/docker/swarm-v2/api"
	"github.com/docker/swarm-v2/cmd/swarmctl/common"
	"github.com/spf13/cobra"
)

var (
	listCmd = &cobra.Command{
		Use:   "ls",
		Short: "List nodes",
		RunE: func(cmd *cobra.Command, args []string) error {
			flags := cmd.Flags()

			quiet, err := flags.GetBool("quiet")
			if err != nil {
				return err
			}

			c, err := common.Dial(cmd)
			if err != nil {
				return err
			}
			r, err := c.ListNodes(common.Context(cmd), &api.ListNodesRequest{})
			if err != nil {
				return err
			}

			var output func(n *api.Node)

			if !quiet {
				w := tabwriter.NewWriter(os.Stdout, 0, 4, 2, ' ', 0)
				defer func() {
					// Ignore flushing errors - there's nothing we can do.
					_ = w.Flush()
				}()
				common.PrintHeader(w, "ID", "Name", "Membership", "Status", "Availability", "Manager status")
				output = func(n *api.Node) {
					spec := &n.Spec
					name := spec.Annotations.Name
					availability := spec.Availability.String()
					membership := spec.Membership.String()

					if name == "" && n.Description != nil {
						name = n.Description.Hostname
					}
					reachability := ""
					if n.Manager != nil {
						reachability = n.Manager.Raft.Status.Reachability.String()
						if n.Manager.Raft.Status.Leader {
							reachability = reachability + " *"
						}
					}
					if reachability == "" && spec.Role == api.NodeRoleManager {
						reachability = "UNKNOWN"
					}

					fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\n",
						n.ID,
						name,
						membership,
						n.Status.State.String(),
						availability,
						reachability,
					)
				}
			} else {
				output = func(n *api.Node) { fmt.Println(n.ID) }
			}

			for _, n := range r.Nodes {
				output(n)
			}
			return nil
		},
	}
)

func init() {
	listCmd.Flags().BoolP("quiet", "q", false, "Only display IDs")
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"github.com/whosonfirst/go-whosonfirst-csv"
	"gopkg.in/redis.v1"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	_ "time"
)

func main() {

	var dryrun = flag.Bool("dryrun", false, "Just show which files would be updated but don't actually do anything.")

	var redis_host = flag.String("redis-host", "localhost", "Redis host")
	var redis_port = flag.Int("redis-port", 6379, "Redis port")
	var redis_channel = flag.String("redis-channel", "updated", "Redis channel")

	var repo = flag.String("repo", "", "The path to a valid Who's On First repo to run updates from")
	var start_commit = flag.String("start-commit", "", "A valid Git commit hash to start updates from. If empty then the current hash will be used.")
	var stop_commit = flag.String("stop-commit", "HEAD", "A valid Git commit hash to limit updates to.")

	flag.Parse()

	_, err := os.Stat(*repo)

	if os.IsNotExist(err) {
		log.Fatal("Repo does not exist", *repo)
	}

	cwd, err := os.Getwd()

	if err != nil {
		log.Fatal(err)
	}

	// I wish this wasn't necessary. I wish I could make sense of the
	// libgit2 documentation... (20161222/thisisaaronland)

	// See also: https://github.com/whosonfirst/go-whosonfirst-updated/issues/1

	err = os.Chdir(*repo)

	if err != nil {
		log.Fatal(err)
	}

	// https://git-scm.com/docs/git-diff

	if *start_commit == "" {

		git_args := []string{
			"log", "--pretty=format:%H", "-n", "1",
		}

		log.Println(strings.Join(git_args, " "))

		cmd := exec.Command("git", git_args...)
		hash, err := cmd.Output()

		if err != nil {
			log.Fatal("Can not determined start hash for %s", *repo)
		}

		log.Printf("Current hash %s\n", hash)
		*start_commit = string(hash)
	}

	git_args := []string{
		"log", "--pretty=format:#%H", "--name-only",
	}

	commit_range := fmt.Sprintf("%s^...%s", *start_commit, *stop_commit)
	git_args = append(git_args, commit_range)

	log.Println(strings.Join(git_args, " "))

	cmd := exec.Command("git", git_args...)
	out, err := cmd.Output()

	os.Chdir(cwd)

	if err != nil {
		log.Fatal(err)
	}

	var b bytes.Buffer
	buf := bufio.NewWriter(&b)

	fieldnames := []string{"hash", "repo", "path"}
	writer, err := csv.NewDictWriter(buf, fieldnames)

	var hash string

	for _, ln := range strings.Split(string(out), "\n") {

		if strings.HasPrefix(ln, "#") {
			hash = strings.Replace(ln, "#", "", 1)
		}

		if strings.HasSuffix(ln, ".geojson") {

			row := make(map[string]string)
			row["hash"] = hash
			row["repo"] = filepath.Base(*repo)
			row["path"] = ln

			writer.WriteRow(row)
		}
	}

	buf.Flush()

	log.Println(b.String())

	if !*dryrun {
		redis_endpoint := fmt.Sprintf("%s:%d", *redis_host, *redis_port)

		redis_client := redis.NewTCPClient(&redis.Options{
			Addr: redis_endpoint,
		})

		defer redis_client.Close()

		redis_client.Publish(*redis_channel, b.String())
	}

	// log.Printf("%s", files)
}
<commit_msg>more better logging; handle pubsub errors<commit_after>package main

import (
	"bufio"
	"bytes"
	"flag"
	"fmt"
	"github.com/whosonfirst/go-whosonfirst-csv"
	"gopkg.in/redis.v1"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	_ "time"
)

func main() {

	var dryrun = flag.Bool("dryrun", false, "Just show which files would be updated but don't actually do anything.")
	var verbose = flag.Bool("verbose", false, "Enable verbose logging.")

	var redis_host = flag.String("redis-host", "localhost", "Redis host")
	var redis_port = flag.Int("redis-port", 6379, "Redis port")
	var redis_channel = flag.String("redis-channel", "updated", "Redis channel")

	var repo = flag.String("repo", "", "The path to a valid Who's On First repo to run updates from")
	var start_commit = flag.String("start-commit", "", "A valid Git commit hash to start updates from. If empty then the current hash will be used.")
	var stop_commit = flag.String("stop-commit", "", "A valid Git commit hash to limit updates to.")

	flag.Parse()

	_, err := os.Stat(*repo)

	if os.IsNotExist(err) {
		log.Fatal("Repo does not exist", *repo)
	}

	cwd, err := os.Getwd()

	if err != nil {
		log.Fatal(err)
	}

	// I wish this wasn't necessary. I wish I could make sense of the
	// libgit2 documentation... (20161222/thisisaaronland)

	// See also: https://github.com/whosonfirst/go-whosonfirst-updated/issues/1

	err = os.Chdir(*repo)

	if err != nil {
		log.Fatal(err)
	}

	// https://git-scm.com/docs/git-diff

	if *start_commit == "" {

		git_args := []string{
			"log", "--pretty=format:%H", "-n", "1",
		}

		log.Println(strings.Join(git_args, " "))

		cmd := exec.Command("git", git_args...)
		hash, err := cmd.Output()

		if err != nil {
			log.Fatal("Can not determined start hash for %s", *repo)
		}

		log.Printf("Current hash %s\n", hash)
		*start_commit = string(hash)
	}

	git_args := []string{
		"log", "--pretty=format:#%H", "--name-only",
	}

	var commit_range string

	if *stop_commit == "" {
		commit_range = *start_commit
	} else {
		commit_range = fmt.Sprintf("%s^...%s", *start_commit, *stop_commit)
	}

	git_args = append(git_args, commit_range)

	log.Println(strings.Join(git_args, " "))

	cmd := exec.Command("git", git_args...)
	out, err := cmd.Output()

	os.Chdir(cwd)

	if err != nil {
		log.Fatal(err)
	}

	var b bytes.Buffer
	buf := bufio.NewWriter(&b)

	// please add support for multiwriters here to send
	// verbose output to STDOUT

	fieldnames := []string{"hash", "repo", "path"}
	writer, err := csv.NewDictWriter(buf, fieldnames)

	var hash string

	rows := 0

	for _, ln := range strings.Split(string(out), "\n") {

		if strings.HasPrefix(ln, "#") {
			hash = strings.Replace(ln, "#", "", 1)
		}

		if strings.HasSuffix(ln, ".geojson") {

			row := make(map[string]string)
			row["hash"] = hash
			row["repo"] = filepath.Base(*repo)
			row["path"] = ln

			writer.WriteRow(row)
			rows += 1
		}
	}

	buf.Flush()

	// see above inre multiwriters...

	if *verbose {
		log.Println(b.String())
	}

	log.Printf("sending %d rows\n", rows)

	if !*dryrun {

		redis_endpoint := fmt.Sprintf("%s:%d", *redis_host, *redis_port)

		redis_client := redis.NewTCPClient(&redis.Options{
			Addr: redis_endpoint,
		})

		defer redis_client.Close()

		rsp := redis_client.Publish(*redis_channel, b.String())
		err := rsp.Err()

		/*

			For example...

			./bin/wof-updated-replay -repo /usr/local/data/whosonfirst-data -start-commit 2569568cd91df9a682c01793930009a9e2850e90
			2017/08/03 15:04:45 log --pretty=format:#%H --name-only 2569568cd91df9a682c01793930009a9e2850e90
			2017/08/03 15:05:32 sending 6609492 rows
			2017/08/03 15:05:33 write tcp 127.0.0.1:49847->127.0.0.1:6379: write: connection reset by peer

			I suppose there is a config flag somewhere in the Redis/PubSub stack to enable MASSIVE messages?
			I haven't found it yet if it exists (20170803/thisisaaronland)

		*/

		if err != nil {
			log.Fatal(err)
		}
	}

	os.Exit(0)
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package codegen

import (
	"fmt"
	"strings"

	"github.com/pkg/errors"
	"go.uber.org/thriftrw/compile"
)

// TypeConverter can generate a function body that converts two thriftrw
// FieldGroups from one to another. It's assumed that the converted code
// operates on two variables, "in" and "out" and that both are a go struct.
type TypeConverter struct {
	Lines  []string
	Helper PackageNameResolver
}

// PackageNameResolver interface allows for resolving what the
// package name for a thrift file is. This depends on where the
// thrift-based structs are generated.
type PackageNameResolver interface {
	TypePackageName(thriftFile string) (string, error)
}

func (c *TypeConverter) getGoTypeName(
	valueType compile.TypeSpec,
) (string, error) {
	switch s := valueType.(type) {
	case *compile.BoolSpec:
		return "bool", nil
	case *compile.I8Spec:
		return "int8", nil
	case *compile.I16Spec:
		return "int16", nil
	case *compile.I32Spec:
		return "int32", nil
	case *compile.I64Spec:
		return "int64", nil
	case *compile.DoubleSpec:
		return "float64", nil
	case *compile.StringSpec:
		return "string", nil
	case *compile.BinarySpec:
		return "[]byte", nil
	case *compile.MapSpec:
		panic("Not Implemented")
	case *compile.SetSpec:
		panic("Not Implemented")
	case *compile.ListSpec:
		panic("Not Implemented")
	case *compile.EnumSpec, *compile.StructSpec, *compile.TypedefSpec:
		return c.getIdentifierName(s)
	default:
		panic(fmt.Sprintf("Unknown type (%T) %v", valueType, valueType))
	}
}

func (c *TypeConverter) getIdentifierName(
	fieldType compile.TypeSpec,
) (string, error) {
	pkgName, err := c.Helper.TypePackageName(fieldType.ThriftFile())
	if err != nil {
		return "", errors.Wrapf(
			err,
			"could not lookup fieldType when building converter for %s :",
			fieldType.ThriftName(),
		)
	}
	typeName := pkgName + "." + fieldType.ThriftName()
	return typeName, nil
}

func (c *TypeConverter) genStructConverter(
	keyPrefix string,
	indent string,
	fromFields []*compile.FieldSpec,
	toFields []*compile.FieldSpec,
) error {
	for i := 0; i < len(toFields); i++ {
		toField := toFields[i]

		var fromField *compile.FieldSpec
		for j := 0; j < len(fromFields); j++ {
			if fromFields[j].Name == toField.Name {
				fromField = fromFields[j]
				break
			}
		}

		if fromField == nil {
			return errors.Errorf(
				"cannot map by name for the field %s",
				toField.Name,
			)
		}

		prefix := indent + "out." + keyPrefix + strings.Title(toField.Name)
		postfix := "in." + keyPrefix + strings.Title(fromField.Name)

		// Override thrift type names to avoid naming collisions between endpoint
		// and client types.
		switch toFieldType := toField.Type.(type) {
		case *compile.BoolSpec:
			var line string
			if toField.Required {
				line = prefix + " = bool(" + postfix + ")"
			} else {
				line = prefix + " = (*bool)(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.I8Spec:
			var line string
			if toField.Required {
				line = prefix + " = int8(" + postfix + ")"
			} else {
				line = prefix + " = (*int8)(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.I16Spec:
			var line string
			if toField.Required {
				line = prefix + " = int16(" + postfix + ")"
			} else {
				line = prefix + " = (*int16)(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.I32Spec:
			var line string
			if toField.Required {
				line = prefix + " = int32(" + postfix + ")"
			} else {
				line = prefix + " = (*int32)(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.EnumSpec:
			typeName, err := c.getIdentifierName(toField.Type)
			if err != nil {
				return err
			}

			var line string
			if toField.Required {
				line = prefix + " = " + typeName + "(" + postfix + ")"
			} else {
				line = prefix + " = (*" + typeName + ")(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.I64Spec:
			var line string
			if toField.Required {
				line = prefix + " = int64(" + postfix + ")"
			} else {
				line = prefix + " = (*int64)(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.DoubleSpec:
			var line string
			if toField.Required {
				line = prefix + " = float64(" + postfix + ")"
			} else {
				line = prefix + " = (*float64)(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.StringSpec:
			var line string
			if toField.Required {
				line = prefix + " = string(" + postfix + ")"
			} else {
				line = prefix + " = (*string)(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.BinarySpec:
			line := prefix + " = []byte(" + postfix + ")"
			c.Lines = append(c.Lines, line)
		case *compile.TypedefSpec:
			typeName, err := c.getIdentifierName(toField.Type)
			if err != nil {
				return err
			}

			var line string
			if toField.Required {
				line = prefix + " = " + typeName + "(" + postfix + ")"
			} else {
				line = prefix + " = (*" + typeName + ")(" + postfix + ")"
			}
			c.Lines = append(c.Lines, line)

		case *compile.StructSpec:
			typeName, err := c.getIdentifierName(toField.Type)
			if err != nil {
				return err
			}
			subToFields := toFieldType.Fields

			fromFieldType, ok := fromField.Type.(*compile.StructSpec)
			if !ok {
				return errors.Errorf(
					"could not convert struct fields, "+
						"incompatible type for %s :",
					toField.Name,
				)
			}

			line := "if " + postfix + " != nil {"
			c.Lines = append(c.Lines, line)

			line = "	" + prefix + " = &" + typeName + "{}"
			c.Lines = append(c.Lines, line)

			subFromFields := fromFieldType.Fields
			err = c.genStructConverter(
				keyPrefix+strings.Title(toField.Name)+".",
				indent+"	",
				subFromFields,
				subToFields,
			)
			if err != nil {
				return err
			}

			line = "} else {"
			c.Lines = append(c.Lines, line)

			line = "	" + prefix + " = nil"
			c.Lines = append(c.Lines, line)

			line = "}"
			c.Lines = append(c.Lines, line)

		case *compile.ListSpec:
			typeName, err := c.getGoTypeName(toFieldType.ValueSpec)
			if err != nil {
				return err
			}

			_, isStruct := toFieldType.ValueSpec.(*compile.StructSpec)
			if isStruct {
				line := prefix + " = make([]*" +
					typeName + ", len(" + postfix + "))"
				c.Lines = append(c.Lines, line)
			} else {
				line := prefix + " = make([]" +
					typeName + ", len(" + postfix + "))"
				c.Lines = append(c.Lines, line)
			}

			line := "for index, value := range " + postfix + " {"
			c.Lines = append(c.Lines, line)

			if isStruct {
				line = prefix + "[index] = " + "(*" + typeName + ")(value)"
				c.Lines = append(c.Lines, line)
			} else {
				line = prefix + "[index] = " + typeName + "(value)"
				c.Lines = append(c.Lines, line)
			}

			line = "}"
			c.Lines = append(c.Lines, line)

		default:
			// fmt.Printf("Unknown type %s for field %s \n",
			// 	toField.Type.TypeCode().String(), toField.Name,
			// )

			// pkgName, err := h.TypePackageName(toField.Type.ThriftFile())
			// if err != nil {
			// 	return nil, err
			// }
			// typeName := pkgName + "." + toField.Type.ThriftName()
			// line := prefix + "(*" + typeName + ")" + postfix
			// c.Lines = append(c.Lines, line)
		}
	}

	return nil
}

// GenStructConverter will add lines to the TypeConverter for mapping
// from one go struct to another based on two thriftrw.FieldGroups
func (c *TypeConverter) GenStructConverter(
	fromFields []*compile.FieldSpec,
	toFields []*compile.FieldSpec,
) error {
	err := c.genStructConverter("", "", fromFields, toFields)
	if err != nil {
		return err
	}

	return nil
}
<commit_msg>codegen/type_converter: rename variable for clarity<commit_after>// Copyright (c) 2017 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package codegen

import (
	"fmt"
	"strings"

	"github.com/pkg/errors"
	"go.uber.org/thriftrw/compile"
)

// TypeConverter can generate a function body that converts two thriftrw
// FieldGroups from one to another. It's assumed that the converted code
// operates on two variables, "in" and "out" and that both are a go struct.
type TypeConverter struct {
	Lines  []string
	Helper PackageNameResolver
}

// PackageNameResolver interface allows for resolving what the
// package name for a thrift file is. This depends on where the
// thrift-based structs are generated.
type PackageNameResolver interface {
	TypePackageName(thriftFile string) (string, error)
}

func (c *TypeConverter) getGoTypeName(
	valueType compile.TypeSpec,
) (string, error) {
	switch s := valueType.(type) {
	case *compile.BoolSpec:
		return "bool", nil
	case *compile.I8Spec:
		return "int8", nil
	case *compile.I16Spec:
		return "int16", nil
	case *compile.I32Spec:
		return "int32", nil
	case *compile.I64Spec:
		return "int64", nil
	case *compile.DoubleSpec:
		return "float64", nil
	case *compile.StringSpec:
		return "string", nil
	case *compile.BinarySpec:
		return "[]byte", nil
	case *compile.MapSpec:
		panic("Not Implemented")
	case *compile.SetSpec:
		panic("Not Implemented")
	case *compile.ListSpec:
		panic("Not Implemented")
	case *compile.EnumSpec, *compile.StructSpec, *compile.TypedefSpec:
		return c.getIdentifierName(s)
	default:
		panic(fmt.Sprintf("Unknown type (%T) %v", valueType, valueType))
	}
}

func (c *TypeConverter) getIdentifierName(
	fieldType compile.TypeSpec,
) (string, error) {
	pkgName, err := c.Helper.TypePackageName(fieldType.ThriftFile())
	if err != nil {
		return "", errors.Wrapf(
			err,
			"could not lookup fieldType when building converter for %s :",
			fieldType.ThriftName(),
		)
	}
	typeName := pkgName + "." + fieldType.ThriftName()
	return typeName, nil
}

func (c *TypeConverter) genStructConverter(
	keyPrefix string,
	indent string,
	fromFields []*compile.FieldSpec,
	toFields []*compile.FieldSpec,
) error {
	for i := 0; i < len(toFields); i++ {
		toField := toFields[i]

		var fromField *compile.FieldSpec
		for j := 0; j < len(fromFields); j++ {
			if fromFields[j].Name == toField.Name {
				fromField = fromFields[j]
				break
			}
		}

		if fromField == nil {
			return errors.Errorf(
				"cannot map by name for the field %s",
				toField.Name,
			)
		}

		toIdentifier := indent + "out." + keyPrefix + strings.Title(toField.Name)
		fromIdentifier := "in." + keyPrefix + strings.Title(fromField.Name)

		// Override thrift type names to avoid naming collisions between endpoint
		// and client types.
		switch toFieldType := toField.Type.(type) {
		case *compile.BoolSpec:
			var line string
			if toField.Required {
				line = toIdentifier + " = bool(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*bool)(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.I8Spec:
			var line string
			if toField.Required {
				line = toIdentifier + " = int8(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*int8)(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.I16Spec:
			var line string
			if toField.Required {
				line = toIdentifier + " = int16(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*int16)(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.I32Spec:
			var line string
			if toField.Required {
				line = toIdentifier + " = int32(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*int32)(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.EnumSpec:
			typeName, err := c.getIdentifierName(toField.Type)
			if err != nil {
				return err
			}

			var line string
			if toField.Required {
				line = toIdentifier + " = " + typeName + "(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*" + typeName + ")(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.I64Spec:
			var line string
			if toField.Required {
				line = toIdentifier + " = int64(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*int64)(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.DoubleSpec:
			var line string
			if toField.Required {
				line = toIdentifier + " = float64(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*float64)(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.StringSpec:
			var line string
			if toField.Required {
				line = toIdentifier + " = string(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*string)(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)
		case *compile.BinarySpec:
			line := toIdentifier + " = []byte(" + fromIdentifier + ")"
			c.Lines = append(c.Lines, line)
		case *compile.TypedefSpec:
			typeName, err := c.getIdentifierName(toField.Type)
			if err != nil {
				return err
			}

			var line string
			if toField.Required {
				line = toIdentifier + " = " + typeName + "(" + fromIdentifier + ")"
			} else {
				line = toIdentifier + " = (*" + typeName + ")(" + fromIdentifier + ")"
			}
			c.Lines = append(c.Lines, line)

		case *compile.StructSpec:
			typeName, err := c.getIdentifierName(toField.Type)
			if err != nil {
				return err
			}
			subToFields := toFieldType.Fields

			fromFieldType, ok := fromField.Type.(*compile.StructSpec)
			if !ok {
				return errors.Errorf(
					"could not convert struct fields, "+
						"incompatible type for %s :",
					toField.Name,
				)
			}

			line := "if " + fromIdentifier + " != nil {"
			c.Lines = append(c.Lines, line)

			line = "	" + toIdentifier + " = &" + typeName + "{}"
			c.Lines = append(c.Lines, line)

			subFromFields := fromFieldType.Fields
			err = c.genStructConverter(
				keyPrefix+strings.Title(toField.Name)+".",
				indent+"	",
				subFromFields,
				subToFields,
			)
			if err != nil {
				return err
			}

			line = "} else {"
			c.Lines = append(c.Lines, line)

			line = "	" + toIdentifier + " = nil"
			c.Lines = append(c.Lines, line)

			line = "}"
			c.Lines = append(c.Lines, line)

		case *compile.ListSpec:
			typeName, err := c.getGoTypeName(toFieldType.ValueSpec)
			if err != nil {
				return err
			}

			_, isStruct := toFieldType.ValueSpec.(*compile.StructSpec)
			if isStruct {
				line := toIdentifier + " = make([]*" +
					typeName + ", len(" + fromIdentifier + "))"
				c.Lines = append(c.Lines, line)
			} else {
				line := toIdentifier + " = make([]" +
					typeName + ", len(" + fromIdentifier + "))"
				c.Lines = append(c.Lines, line)
			}

			line := "for index, value := range " + fromIdentifier + " {"
			c.Lines = append(c.Lines, line)

			if isStruct {
				line = toIdentifier + "[index] = " +
					"(*" + typeName + ")(value)"
				c.Lines = append(c.Lines, line)
			} else {
				line = toIdentifier + "[index] = " +
					typeName + "(value)"
				c.Lines = append(c.Lines, line)
			}

			line = "}"
			c.Lines = append(c.Lines, line)

		default:
			// fmt.Printf("Unknown type %s for field %s \n",
			// 	toField.Type.TypeCode().String(), toField.Name,
			// )

			// pkgName, err := h.TypePackageName(toField.Type.ThriftFile())
			// if err != nil {
			// 	return nil, err
			// }
			// typeName := pkgName + "." + toField.Type.ThriftName()
			// line := prefix + "(*" + typeName + ")" + postfix
			// c.Lines = append(c.Lines, line)
		}
	}

	return nil
}

// GenStructConverter will add lines to the TypeConverter for mapping
// from one go struct to another based on two thriftrw.FieldGroups
func (c *TypeConverter) GenStructConverter(
	fromFields []*compile.FieldSpec,
	toFields []*compile.FieldSpec,
) error {
	err := c.genStructConverter("", "", fromFields, toFields)
	if err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package container

import (
	"fmt"

	"golang.org/x/net/context"

	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	"github.com/docker/docker/pkg/archive"
	"github.com/spf13/cobra"
)

type diffOptions struct {
	container string
}

// NewDiffCommand creates a new cobra.Command for `docker diff`
func NewDiffCommand(dockerCli *command.DockerCli) *cobra.Command {
	var opts diffOptions

	return &cobra.Command{
		Use:   "diff CONTAINER",
		Short: "Inspect changes on a container's filesystem",
		Args:  cli.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.container = args[0]
			return runDiff(dockerCli, &opts)
		},
	}
}

func runDiff(dockerCli *command.DockerCli, opts *diffOptions) error {
	if opts.container == "" {
		return fmt.Errorf("Container name cannot be empty")
	}
	ctx := context.Background()

	changes, err := dockerCli.Client().ContainerDiff(ctx, opts.container)
	if err != nil {
		return err
	}

	for _, change := range changes {
		var kind string
		switch change.Kind {
		case archive.ChangeModify:
			kind = "C"
		case archive.ChangeAdd:
			kind = "A"
		case archive.ChangeDelete:
			kind = "D"
		}
		fmt.Fprintf(dockerCli.Out(), "%s %s\n", kind, change.Path)
	}

	return nil
}
<commit_msg>Clarify what docker diff shows<commit_after>package container

import (
	"fmt"

	"golang.org/x/net/context"

	"github.com/docker/docker/cli"
	"github.com/docker/docker/cli/command"
	"github.com/docker/docker/pkg/archive"
	"github.com/spf13/cobra"
)

type diffOptions struct {
	container string
}

// NewDiffCommand creates a new cobra.Command for `docker diff`
func NewDiffCommand(dockerCli *command.DockerCli) *cobra.Command {
	var opts diffOptions

	return &cobra.Command{
		Use:   "diff CONTAINER",
		Short: "Inspect changes to files or directories on a container's filesystem",
		Args:  cli.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			opts.container = args[0]
			return runDiff(dockerCli, &opts)
		},
	}
}

func runDiff(dockerCli *command.DockerCli, opts *diffOptions) error {
	if opts.container == "" {
		return fmt.Errorf("Container name cannot be empty")
	}
	ctx := context.Background()

	changes, err := dockerCli.Client().ContainerDiff(ctx, opts.container)
	if err != nil {
		return err
	}

	for _, change := range changes {
		var kind string
		switch change.Kind {
		case archive.ChangeModify:
			kind = "C"
		case archive.ChangeAdd:
			kind = "A"
		case archive.ChangeDelete:
			kind = "D"
		}
		fmt.Fprintf(dockerCli.Out(), "%s %s\n", kind, change.Path)
	}

	return nil
}
<|endoftext|>


<commit_before>package commands

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

	"github.com/git-lfs/git-lfs/lfs"
	"github.com/git-lfs/git-lfs/localstorage"
	"github.com/git-lfs/git-lfs/subprocess"

	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/tools"
	"github.com/spf13/cobra"
)

var (
	cloneFlags git.CloneFlags

	cloneSkipRepoInstall bool
)

func cloneCommand(cmd *cobra.Command, args []string) {
	requireGitVersion()

	if git.Config.IsGitVersionAtLeast("2.15.0") {
		msg := []string{
			"WARNING: 'git lfs clone' is deprecated and will not be updated",
			"          with new flags from 'git clone'",
			"",
			"'git clone' has been updated in upstream Git to have comparable",
			"speeds to 'git lfs clone'.",
		}

		fmt.Fprintln(os.Stderr, strings.Join(msg, "\n"))
	}

	// We pass all args to git clone
	err := git.CloneWithoutFilters(cloneFlags, args)
	if err != nil {
		Exit("Error(s) during clone:\n%v", err)
	}

	// now execute pull (need to be inside dir)
	cwd, err := tools.Getwd()
	if err != nil {
		Exit("Unable to derive current working dir: %v", err)
	}

	// Either the last argument was a relative or local dir, or we have to
	// derive it from the clone URL
	clonedir, err := filepath.Abs(args[len(args)-1])
	if err != nil || !tools.DirExists(clonedir) {
		// Derive from clone URL instead
		base := path.Base(args[len(args)-1])
		if strings.HasSuffix(base, ".git") {
			base = base[:len(base)-4]
		}
		clonedir, _ = filepath.Abs(base)
		if !tools.DirExists(clonedir) {
			Exit("Unable to find clone dir at %q", clonedir)
		}
	}

	err = os.Chdir(clonedir)
	if err != nil {
		Exit("Unable to change directory to clone dir %q: %v", clonedir, err)
	}

	// Make sure we pop back to dir we started in at the end
	defer os.Chdir(cwd)

	// Also need to derive dirs now
	localstorage.ResolveDirs()
	requireInRepo()

	// Now just call pull with default args
	// Support --origin option to clone
	var remote string
	if len(cloneFlags.Origin) > 0 {
		remote = cloneFlags.Origin
	} else {
		remote = "origin"
	}

	ref, err := git.CurrentRef()

	if ref != nil {
		includeArg, excludeArg := getIncludeExcludeArgs(cmd)
		filter := buildFilepathFilter(cfg, includeArg, excludeArg)
		if cloneFlags.NoCheckout || cloneFlags.Bare {
			// If --no-checkout or --bare then we shouldn't check out, just fetch instead
			cfg.CurrentRemote = remote
			fetchRef(ref.Name, filter)
		} else {
			pull(remote, filter)
			err := postCloneSubmodules(args)
			if err != nil {
				Exit("Error performing 'git lfs pull' for submodules: %v", err)
			}
		}
	} else {
		Print("Repository is unborn, unable to fetch any LFS assets")
	}

	if !cloneSkipRepoInstall {
		// If --skip-repo wasn't given, install repo-level hooks while
		// we're still in the checkout directory.

		if err := lfs.InstallHooks(false); err != nil {
			ExitWithError(err)
		}
	}
}

func postCloneSubmodules(args []string) error {
	// In git 2.9+ the filter option will have been passed through to submodules
	// So we need to lfs pull inside each
	if !git.Config.IsGitVersionAtLeast("2.9.0") {
		// In earlier versions submodules would have used smudge filter
		return nil
	}
	// Also we only do this if --recursive or --recurse-submodules was provided
	if !cloneFlags.Recursive && !cloneFlags.RecurseSubmodules {
		return nil
	}

	// Use `git submodule foreach --recursive` to cascade into nested submodules
	// Also good to call a new instance of git-lfs rather than do things
	// inside this instance, since that way we get a clean env in that subrepo
	cmd := subprocess.ExecCommand("git", "submodule", "foreach", "--recursive",
		"git lfs pull")
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func init() {
	RegisterCommand("clone", cloneCommand, func(cmd *cobra.Command) {
		cmd.PreRun = nil

		// Mirror all git clone flags
		cmd.Flags().StringVarP(&cloneFlags.TemplateDirectory, "template", "", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Local, "local", "l", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Shared, "shared", "s", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.NoHardlinks, "no-hardlinks", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Quiet, "quiet", "q", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.NoCheckout, "no-checkout", "n", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Progress, "progress", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Bare, "bare", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Mirror, "mirror", "", false, "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Origin, "origin", "o", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Branch, "branch", "b", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Upload, "upload-pack", "u", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Reference, "reference", "", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.ReferenceIfAble, "reference-if-able", "", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Dissociate, "dissociate", "", false, "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.SeparateGit, "separate-git-dir", "", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Depth, "depth", "", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Recursive, "recursive", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.RecurseSubmodules, "recurse-submodules", "", false, "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Config, "config", "c", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.SingleBranch, "single-branch", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.NoSingleBranch, "no-single-branch", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Verbose, "verbose", "v", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Ipv4, "ipv4", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Ipv6, "ipv6", "", false, "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.ShallowSince, "shallow-since", "", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.ShallowExclude, "shallow-exclude", "", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.ShallowSubmodules, "shallow-submodules", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.NoShallowSubmodules, "no-shallow-submodules", "", false, "See 'git clone --help'")
		cmd.Flags().Int64VarP(&cloneFlags.Jobs, "jobs", "j", -1, "See 'git clone --help'")

		cmd.Flags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
		cmd.Flags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")

		cmd.Flags().BoolVar(&cloneSkipRepoInstall, "skip-repo", false, "Skip LFS repo setup")
	})
}
<commit_msg>nevermind the message<commit_after>package commands

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

	"github.com/git-lfs/git-lfs/lfs"
	"github.com/git-lfs/git-lfs/localstorage"
	"github.com/git-lfs/git-lfs/subprocess"

	"github.com/git-lfs/git-lfs/git"
	"github.com/git-lfs/git-lfs/tools"
	"github.com/spf13/cobra"
)

var (
	cloneFlags git.CloneFlags

	cloneSkipRepoInstall bool
)

func cloneCommand(cmd *cobra.Command, args []string) {
	requireGitVersion()

	if git.Config.IsGitVersionAtLeast("2.15.0") {
		msg := []string{
			"WARNING: 'git lfs clone' is deprecated and will not be updated",
			"          with new flags from 'git clone'",
			"",
			"'git clone' has been updated in upstream Git to have comparable",
			"speeds to 'git lfs clone'.",
		}

		fmt.Fprintln(os.Stderr, strings.Join(msg, "\n"))
	}

	// We pass all args to git clone
	err := git.CloneWithoutFilters(cloneFlags, args)
	if err != nil {
		Exit("Error(s) during clone:\n%v", err)
	}

	// now execute pull (need to be inside dir)
	cwd, err := tools.Getwd()
	if err != nil {
		Exit("Unable to derive current working dir: %v", err)
	}

	// Either the last argument was a relative or local dir, or we have to
	// derive it from the clone URL
	clonedir, err := filepath.Abs(args[len(args)-1])
	if err != nil || !tools.DirExists(clonedir) {
		// Derive from clone URL instead
		base := path.Base(args[len(args)-1])
		if strings.HasSuffix(base, ".git") {
			base = base[:len(base)-4]
		}
		clonedir, _ = filepath.Abs(base)
		if !tools.DirExists(clonedir) {
			Exit("Unable to find clone dir at %q", clonedir)
		}
	}

	err = os.Chdir(clonedir)
	if err != nil {
		Exit("Unable to change directory to clone dir %q: %v", clonedir, err)
	}

	// Make sure we pop back to dir we started in at the end
	defer os.Chdir(cwd)

	// Also need to derive dirs now
	localstorage.ResolveDirs()
	requireInRepo()

	// Now just call pull with default args
	// Support --origin option to clone
	var remote string
	if len(cloneFlags.Origin) > 0 {
		remote = cloneFlags.Origin
	} else {
		remote = "origin"
	}

	ref, err := git.CurrentRef()

	if ref != nil {
		includeArg, excludeArg := getIncludeExcludeArgs(cmd)
		filter := buildFilepathFilter(cfg, includeArg, excludeArg)
		if cloneFlags.NoCheckout || cloneFlags.Bare {
			// If --no-checkout or --bare then we shouldn't check out, just fetch instead
			cfg.CurrentRemote = remote
			fetchRef(ref.Name, filter)
		} else {
			pull(remote, filter)
			err := postCloneSubmodules(args)
			if err != nil {
				Exit("Error performing 'git lfs pull' for submodules: %v", err)
			}
		}
	}

	if !cloneSkipRepoInstall {
		// If --skip-repo wasn't given, install repo-level hooks while
		// we're still in the checkout directory.

		if err := lfs.InstallHooks(false); err != nil {
			ExitWithError(err)
		}
	}
}

func postCloneSubmodules(args []string) error {
	// In git 2.9+ the filter option will have been passed through to submodules
	// So we need to lfs pull inside each
	if !git.Config.IsGitVersionAtLeast("2.9.0") {
		// In earlier versions submodules would have used smudge filter
		return nil
	}
	// Also we only do this if --recursive or --recurse-submodules was provided
	if !cloneFlags.Recursive && !cloneFlags.RecurseSubmodules {
		return nil
	}

	// Use `git submodule foreach --recursive` to cascade into nested submodules
	// Also good to call a new instance of git-lfs rather than do things
	// inside this instance, since that way we get a clean env in that subrepo
	cmd := subprocess.ExecCommand("git", "submodule", "foreach", "--recursive",
		"git lfs pull")
	cmd.Stderr = os.Stderr
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	return cmd.Run()
}

func init() {
	RegisterCommand("clone", cloneCommand, func(cmd *cobra.Command) {
		cmd.PreRun = nil

		// Mirror all git clone flags
		cmd.Flags().StringVarP(&cloneFlags.TemplateDirectory, "template", "", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Local, "local", "l", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Shared, "shared", "s", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.NoHardlinks, "no-hardlinks", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Quiet, "quiet", "q", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.NoCheckout, "no-checkout", "n", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Progress, "progress", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Bare, "bare", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Mirror, "mirror", "", false, "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Origin, "origin", "o", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Branch, "branch", "b", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Upload, "upload-pack", "u", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Reference, "reference", "", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.ReferenceIfAble, "reference-if-able", "", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Dissociate, "dissociate", "", false, "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.SeparateGit, "separate-git-dir", "", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Depth, "depth", "", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Recursive, "recursive", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.RecurseSubmodules, "recurse-submodules", "", false, "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.Config, "config", "c", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.SingleBranch, "single-branch", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.NoSingleBranch, "no-single-branch", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Verbose, "verbose", "v", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Ipv4, "ipv4", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.Ipv6, "ipv6", "", false, "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.ShallowSince, "shallow-since", "", "", "See 'git clone --help'")
		cmd.Flags().StringVarP(&cloneFlags.ShallowExclude, "shallow-exclude", "", "", "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.ShallowSubmodules, "shallow-submodules", "", false, "See 'git clone --help'")
		cmd.Flags().BoolVarP(&cloneFlags.NoShallowSubmodules, "no-shallow-submodules", "", false, "See 'git clone --help'")
		cmd.Flags().Int64VarP(&cloneFlags.Jobs, "jobs", "j", -1, "See 'git clone --help'")

		cmd.Flags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
		cmd.Flags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")

		cmd.Flags().BoolVar(&cloneSkipRepoInstall, "skip-repo", false, "Skip LFS repo setup")
	})
}
<|endoftext|>


<commit_before>// Package tgutils provides extra functions to make certain tasks easier.
package tgutils

import (
	"github.com/syfaro/telegram-bot-api"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"sync"
	"time"
)

var rand uint32
var randmu sync.Mutex

func reseed() uint32 {
	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
}

func nextSuffix() string {
	randmu.Lock()
	r := rand
	if r == 0 {
		r = reseed()
	}
	r = r*1664525 + 1013904223 // constants from Numerical Recipes
	rand = r
	randmu.Unlock()
	return strconv.Itoa(int(1e9 + r%1e9))[1:]
}

// this function ripped from ioutils.TempFile, except with a suffix, instead of prefix.
func tempFileWithSuffix(dir, suffix string) (f *os.File, err error) {
	if dir == "" {
		dir = os.TempDir()
	}

	nconflict := 0
	for i := 0; i < 10000; i++ {
		name := filepath.Join(dir, nextSuffix()+suffix)
		f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
		if os.IsExist(err) {
			if nconflict++; nconflict > 10 {
				randmu.Lock()
				rand = reseed()
				randmu.Unlock()
			}
			continue
		}
		break
	}
	return
}

// EncodeAudio takes a file and attempts to convert it to a .ogg for Telegram.
// It then returns an AudioConfig.
//
// This function requires ffmpeg and opusenc to be installed on the system!
func EncodeAudio(audio *tgbotapi.AudioConfig) error {
	f, err := tempFileWithSuffix(os.TempDir(), "_tgutils.ogg")
	if err != nil {
		return err
	}
	defer f.Close()

	log.Println(f.Name())

	ffmpegArgs := []string{
		"-i",
		audio.FilePath,
		"-f",
		"wav",
		"-",
	}

	opusArgs := []string{
		"--bitrate",
		"256",
		"-",
		f.Name(),
	}

	c1 := exec.Command("ffmpeg", ffmpegArgs...)
	c2 := exec.Command("opusenc", opusArgs...)

	c2.Stdin, _ = c1.StdoutPipe()
	c2.Stdout = os.Stdout
	c2.Start()
	c1.Run()
	c2.Wait()

	return nil
}
<commit_msg>fix docs in encodeaudio, remove log<commit_after>// Package tgutils provides extra functions to make certain tasks easier.
package tgutils

import (
	"github.com/syfaro/telegram-bot-api"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"sync"
	"time"
)

var rand uint32
var randmu sync.Mutex

func reseed() uint32 {
	return uint32(time.Now().UnixNano() + int64(os.Getpid()))
}

func nextSuffix() string {
	randmu.Lock()
	r := rand
	if r == 0 {
		r = reseed()
	}
	r = r*1664525 + 1013904223 // constants from Numerical Recipes
	rand = r
	randmu.Unlock()
	return strconv.Itoa(int(1e9 + r%1e9))[1:]
}

// this function ripped from ioutils.TempFile, except with a suffix, instead of prefix.
func tempFileWithSuffix(dir, suffix string) (f *os.File, err error) {
	if dir == "" {
		dir = os.TempDir()
	}

	nconflict := 0
	for i := 0; i < 10000; i++ {
		name := filepath.Join(dir, nextSuffix()+suffix)
		f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
		if os.IsExist(err) {
			if nconflict++; nconflict > 10 {
				randmu.Lock()
				rand = reseed()
				randmu.Unlock()
			}
			continue
		}
		break
	}
	return
}

// EncodeAudio takes a file and attempts to convert it to a .ogg for Telegram.
// It then updates the path to the audio file in the AudioConfig.
//
// This function requires ffmpeg and opusenc to be installed on the system!
func EncodeAudio(audio *tgbotapi.AudioConfig) error {
	f, err := tempFileWithSuffix(os.TempDir(), "_tgutils.ogg")
	if err != nil {
		return err
	}
	defer f.Close()

	ffmpegArgs := []string{
		"-i",
		audio.FilePath,
		"-f",
		"wav",
		"-",
	}

	opusArgs := []string{
		"--bitrate",
		"256",
		"-",
		f.Name(),
	}

	c1 := exec.Command("ffmpeg", ffmpegArgs...)
	c2 := exec.Command("opusenc", opusArgs...)

	c2.Stdin, _ = c1.StdoutPipe()
	c2.Stdout = os.Stdout
	c2.Start()
	c1.Run()
	c2.Wait()

	return nil
}
<|endoftext|>


<commit_before>package transport

import (
	nsq "github.com/bitly/go-nsq"
	log "github.com/cihub/seelog"

	"github.com/mattheath/phosphor/util"
)

// NewNSQTransport initialises a Transport over NSQ
func NewNSQTransport(topic string, nsqdTCPAddrs util.StringArray) (Transport, error) {

	// Currently using default config
	cfg := nsq.NewConfig()

	// Create a producer for each nsqd node provided
	producers := make(map[string]*nsq.Producer)
	for _, addr := range nsqdTCPAddrs {
		producer, err := nsq.NewProducer(addr, cfg)
		if err != nil {
			log.Warnf("failed to create nsq.Producer - %s", err)
		}
		producers[addr] = producer
	}

	return &NSQPublisher{
		topic:     topic,
		producers: producers,
	}, nil
}

type NSQPublisher struct {
	topic     string
	producers map[string]*nsq.Producer
}

func (p *NSQPublisher) MultiPublish(body [][]byte) error {
	return nil
}
<commit_msg>Attempt to publish to nsqd nodes until we succeed, or run out of nodes<commit_after>package transport

import (
	"errors"
	"math/rand"

	nsq "github.com/bitly/go-nsq"
	log "github.com/cihub/seelog"

	"github.com/mattheath/phosphor/util"
)

var ErrPublishFailure = errors.New("Failed to publish to NSQD")

// NewNSQTransport initialises a Transport over NSQ
func NewNSQTransport(topic string, nsqdTCPAddrs util.StringArray) (Transport, error) {

	// Currently using default config
	cfg := nsq.NewConfig()

	// Create a producer for each nsqd node provided
	producers := make(map[string]*nsq.Producer)
	for _, addr := range nsqdTCPAddrs {
		producer, err := nsq.NewProducer(addr, cfg)
		if err != nil {
			log.Warnf("failed to create nsq.Producer - %s", err)
		}
		producers[addr] = producer
	}

	return &NSQPublisher{
		topic:     topic,
		producers: producers,
	}, nil
}

type NSQPublisher struct {
	topic     string
	producers map[string]*nsq.Producer
}

func (p *NSQPublisher) MultiPublish(body [][]byte) error {

	// Round robin, from a random starting position
	i := rand.Intn(len(p.producers)) - 1

	// Attempt up to our number of configured nodes
	for attempt := 0; attempt < len(p.producers); attempt++ {
		pd := p.producers[i]
		if err := pd.MultiPublish(p.topic, body); err == nil {
			// success!
			return nil
		}

		// Move to next host, or cycle back around
		i++
		if i >= len(p.producers) {
			i = 0
		}
	}

	// We've run out of nodes, and not managed to publish
	return ErrPublishFailure
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/artonge/Tamalou/HPO"
	"github.com/artonge/Tamalou/Models"
	"github.com/artonge/Tamalou/Omim"
	"github.com/artonge/Tamalou/Orpha"
	"github.com/artonge/Tamalou/Queries"
)

func main() {
	// startCLI()
	startServer()
}

func fetchDiseases(query Queries.ITamalouQuery) ([]*Models.Disease, error) {
	// Fetch diseases
	// HPO
	resultsHPO, err := HPO.QueryHPO(query)
	if err != nil {
		return nil, err
	}
	// ORPHA
	resultsOrpha, err := orpha.Query(query)
	if err != nil {
		return nil, err
	}
	// OMIM
	resultsOMIM, err := Omim.QueryOmimIndex(query)
	if err != nil {
		return nil, err
	}
	// Orpha and OMIM from HPO
	var orphaIDs []float64
	var omimIDs []string
	for _, d := range resultsHPO {
		if d.OMIMID != "" {
			omimIDs = append(omimIDs, d.OMIMID)
		}
		if d.OrphaID != 0 {
			orphaIDs = append(orphaIDs, d.OrphaID)
		}
	}
	resultsOrphaFromHPO, err := orpha.GetDiseasesFromIDs(orphaIDs)
	if err != nil {
		return nil, err
	}
	resultsOMIMFromHPO, err := Omim.DiseasesFromIDs(omimIDs)
	if err != nil {
		return nil, err
	}

	// Merge results
	results := Models.Merge(resultsOrpha, resultsHPO, "or")
	results = Models.Merge(results, resultsOMIM, "or")
	results = Models.Merge(results, resultsOrphaFromHPO, "or")
	results = Models.Merge(results, resultsOMIMFromHPO, "or")

	// Return filtered results (remove double apparition)
	return filterDiseases(results), nil
}

func fetchDrugs(query Queries.ITamalouQuery) ([]*Models.Drug, error) {
	// Fetch drugs
	results := make([]*Models.Drug, 0)

	return results, nil
}

func filterDiseases(diseaseArray []*Models.Disease) []*Models.Disease {
	var filteredDiseases []*Models.Disease

	// Loop throught the diseaseArray
	for _, d := range diseaseArray {
		// Check that filteredDiseases doesn't contains the current disease
		contains := false
		for _, df := range filteredDiseases {
			if (d.OMIMID != "" && d.OMIMID == df.OMIMID) || (d.OrphaID != 0 && d.OrphaID == df.OrphaID) {
				// Increment Score of the disease
				// ==> better score when the results comes from multiple sources
				df.Score++
				df.Sources = append(df.Sources, d.Sources...)
				contains = true
				break
			}
		}

		// If filteredDiseases doesn't contains the disease, add it
		if !contains {
			d.Score = 1
			filteredDiseases = append(filteredDiseases, d)
		}
	}

	return filteredDiseases
}
<commit_msg>Default to empty array when no answer for diseases<commit_after>package main

import (
	"github.com/artonge/Tamalou/HPO"
	"github.com/artonge/Tamalou/Models"
	"github.com/artonge/Tamalou/Omim"
	"github.com/artonge/Tamalou/Orpha"
	"github.com/artonge/Tamalou/Queries"
)

func main() {
	// startCLI()
	startServer()
}

func fetchDiseases(query Queries.ITamalouQuery) ([]*Models.Disease, error) {
	// Fetch diseases
	// HPO
	resultsHPO, err := HPO.QueryHPO(query)
	if err != nil {
		return nil, err
	}
	// ORPHA
	resultsOrpha, err := orpha.Query(query)
	if err != nil {
		return nil, err
	}
	// OMIM
	resultsOMIM, err := Omim.QueryOmimIndex(query)
	if err != nil {
		return nil, err
	}
	// Orpha and OMIM from HPO
	var orphaIDs []float64
	var omimIDs []string
	for _, d := range resultsHPO {
		if d.OMIMID != "" {
			omimIDs = append(omimIDs, d.OMIMID)
		}
		if d.OrphaID != 0 {
			orphaIDs = append(orphaIDs, d.OrphaID)
		}
	}
	resultsOrphaFromHPO, err := orpha.GetDiseasesFromIDs(orphaIDs)
	if err != nil {
		return nil, err
	}
	resultsOMIMFromHPO, err := Omim.DiseasesFromIDs(omimIDs)
	if err != nil {
		return nil, err
	}

	results := make([]*Models.Disease, 0)
	// Merge results
	results = Models.Merge(results, resultsOrpha, "or")
	results = Models.Merge(results, resultsHPO, "or")
	results = Models.Merge(results, resultsOMIM, "or")
	results = Models.Merge(results, resultsOrphaFromHPO, "or")
	results = Models.Merge(results, resultsOMIMFromHPO, "or")

	// Return filtered results (remove double apparition)
	return filterDiseases(results), nil
}

func fetchDrugs(query Queries.ITamalouQuery) ([]*Models.Drug, error) {
	// Fetch drugs
	results := make([]*Models.Drug, 0)

	return results, nil
}

func filterDiseases(diseaseArray []*Models.Disease) []*Models.Disease {
	var filteredDiseases []*Models.Disease

	// Loop throught the diseaseArray
	for _, d := range diseaseArray {
		// Check that filteredDiseases doesn't contains the current disease
		contains := false
		for _, df := range filteredDiseases {
			if (d.OMIMID != "" && d.OMIMID == df.OMIMID) || (d.OrphaID != 0 && d.OrphaID == df.OrphaID) {
				// Increment Score of the disease
				// ==> better score when the results comes from multiple sources
				df.Score++
				df.Sources = append(df.Sources, d.Sources...)
				contains = true
				break
			}
		}

		// If filteredDiseases doesn't contains the disease, add it
		if !contains {
			d.Score = 1
			filteredDiseases = append(filteredDiseases, d)
		}
	}

	return filteredDiseases
}
<|endoftext|>


<commit_before>/*
The MIT License (MIT)

Copyright (c) 2016 Nick Potts

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package main

import (
	"bufio"
	"fmt"
	"github.com/alecthomas/kingpin"
	"github.com/jmoiron/sqlx"
	_ "github.com/lib/pq"
	"github.com/pkg/errors"
	"github.com/tarm/serial"
	"os"
	"strings"
)

var (
	create = "CREATE TABLE IF NOT EXISTS %s (id SERIAL, timestamp TIMESTAMP DEFAULT now(), pressure FLOAT, tempa FLOAT, tempb FLOAT, humidity FLOAT, ptemp FLOAT, htemp FLOAT, battery FLOAT, indx INT)"

	app            = kingpin.New("wxProxy", "Shovel data from an arduino into a postgres/cockroachdb")
	dataSourceName = app.Flag("dataSource", "Where should we connect to and yelp at (usually a string like 'postgres://user:password@server/database?sslmode=disable')").Short('s').Default("postgres://wx:wx@pika/wx?sslmode=disable").String()
	table          = app.Flag("table", "The database table to fire into").Short('t').Default("raw").String()
	device         = app.Flag("device", "The RS232 serial device to read from (at 57600 baud)").Short('D').Default("/dev/ttyUSB0").String()
)

type inserter struct {
	db  *sqlx.DB
	ser *serial.Port
}

func getPort() *serial.Port {
	port, err := serial.OpenPort(&serial.Config{Name: *device, Baud: 57600, Size: 8, Parity: serial.ParityNone, StopBits: 1})
	if err != nil {
		panic(errors.Wrap(err, "Unable to open serial device"))
	}
	return port
}

func new() *inserter {
	return &inserter{
		db:  sqlx.MustConnect("postgres", *dataSourceName),
		ser: getPort(),
	}
}

//poll forever will look for newlines and assume whatever it got was a full on SQL query worthy of executing.
func (ins *inserter) poll() {
	ins.db.MustExec(fmt.Sprintf(create, *table))
	rdr := bufio.NewReader(ins.ser)
	lines := 0
	for {
		line, err := rdr.ReadString('\n')
		if err != nil {
			fmt.Println(err)
		}
		lines++
		fmt.Printf("%d lines ingested\r", lines)
		if strings.Contains(line, "INSERT INTO") {
			go ins.insert(line)
		}
	}
}

func (ins *inserter) insert(data string) {
	data = fmt.Sprintf(data, *table)
	if _, err := ins.db.Exec(data); err != nil {
		fmt.Println(data)
		fmt.Println(errors.Wrap(err, "Unable to insert"))
		return
	}
}

func main() {
	app.Parse(os.Args[1:])
	i := new()
	i.poll()
}
<commit_msg>Write to JSON construct directly<commit_after>/*
The MIT License (MIT)

Copyright (c) 2016 Nick Potts

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"github.com/alecthomas/kingpin"
	"github.com/jmoiron/sqlx"
	"github.com/pkg/errors"
	"github.com/tarm/serial"
	"os"

	_ "github.com/lib/pq"
	"github.com/npotts/arduino/WxShield2"
)

var (
	create = "CREATE TABLE IF NOT EXISTS %s (id SERIAL, timestamp TIMESTAMP DEFAULT now(), pressure FLOAT, tempa FLOAT, tempb FLOAT, humidity FLOAT, ptemp FLOAT, htemp FLOAT, battery FLOAT, indx INT)"

	app            = kingpin.New("wxProxy", "Shovel data from an arduino into a postgres/cockroachdb")
	dataSourceName = app.Flag("dataSource", "Where should we connect to and yelp at (usually a string like 'postgres://user:password@server/database?sslmode=disable')").Short('s').Default("postgres://wx:wx@pika/wx?sslmode=disable").String()
	table          = app.Flag("table", "The database table to fire into").Short('t').Default("raw").String()
	device         = app.Flag("device", "The RS232 serial device to read from (at 57600 baud)").Short('D').Default("/dev/ttyUSB0").String()
)

type inserter struct {
	db  *sqlx.DB
	ser *serial.Port
}

func getPort() *serial.Port {
	fmt.Printf("Attempting to open %s: ", *device)
	port, err := serial.OpenPort(&serial.Config{Name: *device, Baud: 57600, Size: 8, Parity: serial.ParityNone, StopBits: 1})
	if err != nil {
		fmt.Println(errors.Wrap(err, "Unable to open serial device"))
		os.Exit(1)
	}
	fmt.Println("done")
	return port
}

func new() *inserter {
	return &inserter{
		db:  sqlx.MustConnect("postgres", *dataSourceName),
		ser: getPort(),
	}
}

//poll forever will look for newlines and assume whatever it got was a full on SQL query worthy of executing.
func (ins *inserter) poll() {
	ins.db.MustExec(fmt.Sprintf(create, *table))
	rdr := bufio.NewReader(ins.ser)
	lines := 0
	fmt.Println("Entering Polling Loop")
	for {
		line, err := rdr.ReadBytes('\n')
		if err != nil {
			fmt.Println(err)
			continue
		}
		packet := &wxshield2.Packet{}
		err = json.Unmarshal(line, packet.Jsonable())
		if err == nil {
			go ins.insert(*packet)
			lines++
			fmt.Printf("\r%d lines ingested", lines)
		}
	}
}

/*insert exec*/
func (ins *inserter) insert(packet wxshield2.Packet) {
	sql := packet.InsertNamed(*table)
	if _, err := ins.db.NamedExec(sql, packet); err != nil {
		fmt.Println(errors.Wrapf(err, "Unable to insert: %q", sql))
		return
	}
}

func main() {
	app.Parse(os.Args[1:])
	i := new()
	i.poll()
}
<|endoftext|>


<commit_before>package freetds

import (
	"errors"
	"fmt"
	"reflect"
)

type Result struct {
	Columns      []*ResultColumn
	Rows         [][]interface{}
	ReturnValue  int
	RowsAffected int
	Message      string
	currentRow   int
	scanCount    int
}

func NewResult() *Result {
	return &Result{
		Columns:    make([]*ResultColumn, 0),
		Rows:       nil,
		currentRow: -1,
	}
}

func (r *Result) addColumn(name string, dbSize, dbType int) {
	c := new(ResultColumn)
	c.Name = name
	c.DbSize = dbSize
	c.DbType = dbType
	r.Columns = append(r.Columns, c)
}

func (r *Result) addValue(row, col int, value interface{}) {
	if r.Rows == nil {
		r.Rows = make([][]interface{}, 1)
		r.Rows[0] = make([]interface{}, len(r.Columns))
	}
	for rc := len(r.Rows) - 1; rc < row; rc++ {
		r.Rows = append(r.Rows, make([]interface{}, len(r.Columns)))
	}
	r.Rows[row][col] = value
}

type ResultColumn struct {
	Name   string
	DbSize int
	DbType int
	Type   string
}

func (r *Result) Next() bool {
	if len(r.Rows) == 0 {
		return false
	}
	if r.currentRow >= len(r.Rows)-1 {
		return false
	}
	r.currentRow++
	return true
}

//Scan copies the columns in the current row into the values pointed at by dest.
func (r *Result) Scan(dest ...interface{}) error {
	r.scanCount = 0
	if r.currentRow == -1 {
		return errors.New("Scan called without calling Next.")
	}
	for _, d := range dest {
		if !isPointer(d) {
			return errors.New("Destination not a pointer.")
		}
	}
	if len(dest) == 1 {
		if s := asStructPointer(dest[0]); s != nil {
			return r.scanStruct(s)
		}
	}
	err := assignValues(r.Rows[r.currentRow], dest)
	if err == nil {
		r.scanCount = len(dest)
	}
	return err
}

//Must Scan exactly cnt number of values from result.
//Useful when scanning into structure, to know whether are all expected fields filled with values.
//cnt - number of values assigned to fields
func (r *Result) MustScan(cnt int, dest ...interface{}) error {
	if err := r.Scan(dest...); err != nil {
		return err
	}
	if cnt != r.scanCount {
		return errors.New(fmt.Sprintf("Worng scan count, expected %d, actual %d.", cnt, r.scanCount))
	}
	return nil
}

//Copies values for the current row to the structure.
//Struct filed name must match database column name.
func (r *Result) scanStruct(s *reflect.Value) error {
	for i, col := range r.Columns {
		f := s.FieldByName(camelize(col.Name))
		if f.IsValid() {
			if f.CanSet() {
				if err := convertAssign(f.Addr().Interface(), r.Rows[r.currentRow][i]); err != nil {
					//if err := assignValue(r.Rows[r.currentRow][i], f.Addr().Interface());  err != nil {
					return err
				}
				r.scanCount++
			}
		}
	}
	return nil
}

func asStructPointer(p interface{}) *reflect.Value {
	sp := reflect.ValueOf(p)
	if sp.Kind() == reflect.Ptr {
		s := sp.Elem()
		if s.Kind() == reflect.Struct {
			return &s
		}
	}
	return nil
}

func isPointer(p interface{}) bool {
	sp := reflect.ValueOf(p)
	return sp.Kind() == reflect.Ptr
}

//assignValues copies to dest values in src
//dest should be a pointer type
//error is returned if types don't match and conversion failed
func assignValues(src, dest []interface{}) error {
	if len(dest) > len(src) {
		return errors.New(fmt.Sprintf("More dest values %d than src values %d.", len(dest), len(src)))
	}
	for i, d := range dest {
		err := convertAssign(d, src[i])
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Clean unused commented line<commit_after>package freetds

import (
	"errors"
	"fmt"
	"reflect"
)

type Result struct {
	Columns      []*ResultColumn
	Rows         [][]interface{}
	ReturnValue  int
	RowsAffected int
	Message      string
	currentRow   int
	scanCount    int
}

func NewResult() *Result {
	return &Result{
		Columns:    make([]*ResultColumn, 0),
		Rows:       nil,
		currentRow: -1,
	}
}

func (r *Result) addColumn(name string, dbSize, dbType int) {
	c := new(ResultColumn)
	c.Name = name
	c.DbSize = dbSize
	c.DbType = dbType
	r.Columns = append(r.Columns, c)
}

func (r *Result) addValue(row, col int, value interface{}) {
	if r.Rows == nil {
		r.Rows = make([][]interface{}, 1)
		r.Rows[0] = make([]interface{}, len(r.Columns))
	}
	for rc := len(r.Rows) - 1; rc < row; rc++ {
		r.Rows = append(r.Rows, make([]interface{}, len(r.Columns)))
	}
	r.Rows[row][col] = value
}

type ResultColumn struct {
	Name   string
	DbSize int
	DbType int
	Type   string
}

func (r *Result) Next() bool {
	if len(r.Rows) == 0 {
		return false
	}
	if r.currentRow >= len(r.Rows)-1 {
		return false
	}
	r.currentRow++
	return true
}

//Scan copies the columns in the current row into the values pointed at by dest.
func (r *Result) Scan(dest ...interface{}) error {
	r.scanCount = 0
	if r.currentRow == -1 {
		return errors.New("Scan called without calling Next.")
	}
	for _, d := range dest {
		if !isPointer(d) {
			return errors.New("Destination not a pointer.")
		}
	}
	if len(dest) == 1 {
		if s := asStructPointer(dest[0]); s != nil {
			return r.scanStruct(s)
		}
	}
	err := assignValues(r.Rows[r.currentRow], dest)
	if err == nil {
		r.scanCount = len(dest)
	}
	return err
}

//Must Scan exactly cnt number of values from result.
//Useful when scanning into structure, to know whether are all expected fields filled with values.
//cnt - number of values assigned to fields
func (r *Result) MustScan(cnt int, dest ...interface{}) error {
	if err := r.Scan(dest...); err != nil {
		return err
	}
	if cnt != r.scanCount {
		return errors.New(fmt.Sprintf("Worng scan count, expected %d, actual %d.", cnt, r.scanCount))
	}
	return nil
}

//Copies values for the current row to the structure.
//Struct filed name must match database column name.
func (r *Result) scanStruct(s *reflect.Value) error {
	for i, col := range r.Columns {
		f := s.FieldByName(camelize(col.Name))
		if f.IsValid() {
			if f.CanSet() {
				if err := convertAssign(f.Addr().Interface(), r.Rows[r.currentRow][i]); err != nil {
					return err
				}
				r.scanCount++
			}
		}
	}
	return nil
}

func asStructPointer(p interface{}) *reflect.Value {
	sp := reflect.ValueOf(p)
	if sp.Kind() == reflect.Ptr {
		s := sp.Elem()
		if s.Kind() == reflect.Struct {
			return &s
		}
	}
	return nil
}

func isPointer(p interface{}) bool {
	sp := reflect.ValueOf(p)
	return sp.Kind() == reflect.Ptr
}

//assignValues copies to dest values in src
//dest should be a pointer type
//error is returned if types don't match and conversion failed
func assignValues(src, dest []interface{}) error {
	if len(dest) > len(src) {
		return errors.New(fmt.Sprintf("More dest values %d than src values %d.", len(dest), len(src)))
	}
	for i, d := range dest {
		err := convertAssign(d, src[i])
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package generator

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"socialapi/config"
	"socialapi/workers/helper"
	"socialapi/workers/sitemap/common"
	"socialapi/workers/sitemap/models"

	"github.com/garyburd/redigo/redis"
	"github.com/koding/logging"
	"github.com/robfig/cron"
)

type Controller struct {
	log          logging.Logger
	fileSelector FileSelector
	fileName     string
}

const (
	SCHEDULE = "0 0-59/30 * * * *"
)

var (
	cronJob *cron.Cron
)

func New(log logging.Logger) (*Controller, error) {
	c := &Controller{
		log:          log,
		fileSelector: CachedFileSelector{},
	}

	return c, c.initCron()
}

func (c *Controller) initCron() error {
	cronJob = cron.New()
	if err := cronJob.AddFunc(SCHEDULE, c.generate); err != nil {
		return err
	}
	cronJob.Start()

	return nil
}

func (c *Controller) Shutdown() {
	cronJob.Stop()
}

func (c *Controller) generate() {
	c.log.Info("Sitemap update started")
	for {
		name, err := c.fileSelector.Select()
		if err == redis.ErrNil {
			return
		}

		if err != nil {
			c.log.Error("Could not fetch file name: %s", err)
			return
		}
		c.log.Notice("Updating sitemap: %s", name)
		// there is not any waiting sitemap updates
		if name == "" {
			return
		}

		c.fileName = name

		els, err := c.fetchElements()
		if err != nil {
			c.log.Error("Could not fetch updated elements: %s", err)
			return
		}

		container := c.buildContainer(els)

		s, err := c.getCurrentSet()
		if err != nil {
			c.log.Error("Could not get current set: %s", err)
			return
		}

		if err := c.updateFile(container, s); err != nil {
			c.log.Error("Could not update file: %s", err)
		}

		if err := new(models.SitemapFile).Upsert(name); err != nil {
			c.log.Error("Could not update file meta: %s", err)
		}

	}
}

func (c *Controller) fetchElements() ([]*models.SitemapItem, error) {
	key := common.PrepareFileCacheKey(c.fileName)
	redisConn := helper.MustGetRedisConn()
	els := make([]*models.SitemapItem, 0)

	for {
		item, err := redisConn.PopSetMember(key)
		if err != nil && err != redis.ErrNil {
			return els, err
		}

		if item == "" {
			return els, nil
		}

		i := &models.SitemapItem{}

		if err := i.Populate(item); err != nil {
			c.log.Error("Could not update item %s: %s", item, err)
			continue
		}

		els = append(els, i)
	}
}

func (c *Controller) getCurrentSet() (*models.ItemSet, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, err
	}
	// check if this is a new sitemap file or not
	n := fmt.Sprintf("%s.xml", c.fileName)
	n = path.Join(wd, config.Get().Sitemap.XMLRoot, n)
	if _, err := os.Stat(n); os.IsNotExist(err) {
		return models.NewItemSet(), nil
	}
	input, err := ioutil.ReadFile(n)
	if err != nil {
		return nil, err
	}

	s := models.NewItemSet()
	if err := xml.Unmarshal(input, s); err != nil {
		return nil, err
	}

	return s, nil
}

func (c *Controller) buildContainer(items []*models.SitemapItem) *models.ItemContainer {
	container := models.NewItemContainer()
	for _, v := range items {
		item := v.Definition(config.Get().Uri)
		switch v.Status {
		case models.STATUS_ADD:
			container.Add = append(container.Add, item)
		case models.STATUS_DELETE:
			container.Delete = append(container.Delete, item)
		case models.STATUS_UPDATE:
			container.Update = append(container.Update, item)
		}
	}

	return container
}

func (c *Controller) updateFile(container *models.ItemContainer, set *models.ItemSet) error {
	set.Populate(container)

	return common.XML(set, c.fileName)
}
<commit_msg>Sitemap: Add element length defensive check for sitemap generation<commit_after>package generator

import (
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"socialapi/config"
	"socialapi/workers/helper"
	"socialapi/workers/sitemap/common"
	"socialapi/workers/sitemap/models"

	"github.com/garyburd/redigo/redis"
	"github.com/koding/logging"
	"github.com/robfig/cron"
)

type Controller struct {
	log          logging.Logger
	fileSelector FileSelector
	fileName     string
}

const (
	// before sending this interval, beware that you have to change
	// TIMERANGE in cache key file
	SCHEDULE = "0 0-59/30 * * * *"
)

var (
	cronJob *cron.Cron
)

func New(log logging.Logger) (*Controller, error) {
	c := &Controller{
		log:          log,
		fileSelector: CachedFileSelector{},
	}

	return c, c.initCron()
}

func (c *Controller) initCron() error {
	cronJob = cron.New()
	if err := cronJob.AddFunc(SCHEDULE, c.generate); err != nil {
		return err
	}
	cronJob.Start()

	return nil
}

func (c *Controller) Shutdown() {
	cronJob.Stop()
}

func (c *Controller) generate() {
	c.log.Info("Sitemap update started")
	for {
		name, err := c.fileSelector.Select()
		if err == redis.ErrNil {
			return
		}

		if err != nil {
			c.log.Error("Could not fetch file name: %s", err)
			return
		}
		c.log.Notice("Updating sitemap: %s", name)
		// there is not any waiting sitemap updates
		if name == "" {
			return
		}

		c.fileName = name

		els, err := c.fetchElements()
		if err != nil {
			c.log.Error("Could not fetch updated elements: %s", err)
			return
		}

		if len(els) == 0 {
			c.log.Notice("Items are already added")
			return
		}

		container := c.buildContainer(els)

		s, err := c.getCurrentSet()
		if err != nil {
			c.log.Error("Could not get current set: %s", err)
			return
		}

		if err := c.updateFile(container, s); err != nil {
			c.log.Error("Could not update file: %s", err)
		}

		if err := new(models.SitemapFile).Upsert(name); err != nil {
			c.log.Error("Could not update file meta: %s", err)
		}

	}
}

func (c *Controller) fetchElements() ([]*models.SitemapItem, error) {
	key := common.PrepareFileCacheKey(c.fileName)
	redisConn := helper.MustGetRedisConn()
	els := make([]*models.SitemapItem, 0)

	for {
		item, err := redisConn.PopSetMember(key)
		if err != nil && err != redis.ErrNil {
			return els, err
		}

		if item == "" {
			return els, nil
		}

		i := &models.SitemapItem{}

		if err := i.Populate(item); err != nil {
			c.log.Error("Could not update item %s: %s", item, err)
			continue
		}

		els = append(els, i)
	}
}

func (c *Controller) getCurrentSet() (*models.ItemSet, error) {
	wd, err := os.Getwd()
	if err != nil {
		return nil, err
	}
	// check if this is a new sitemap file or not
	n := fmt.Sprintf("%s.xml", c.fileName)
	n = path.Join(wd, config.Get().Sitemap.XMLRoot, n)
	if _, err := os.Stat(n); os.IsNotExist(err) {
		return models.NewItemSet(), nil
	}
	input, err := ioutil.ReadFile(n)
	if err != nil {
		return nil, err
	}

	s := models.NewItemSet()
	if err := xml.Unmarshal(input, s); err != nil {
		return nil, err
	}

	return s, nil
}

func (c *Controller) buildContainer(items []*models.SitemapItem) *models.ItemContainer {
	container := models.NewItemContainer()
	for _, v := range items {
		item := v.Definition(config.Get().Uri)
		switch v.Status {
		case models.STATUS_ADD:
			container.Add = append(container.Add, item)
		case models.STATUS_DELETE:
			container.Delete = append(container.Delete, item)
		case models.STATUS_UPDATE:
			container.Update = append(container.Update, item)
		}
	}

	return container
}

func (c *Controller) updateFile(container *models.ItemContainer, set *models.ItemSet) error {
	set.Populate(container)

	return common.XML(set, c.fileName)
}
<|endoftext|>


<commit_before>package servicerouter

import (
	"errors"
	"golang.org/x/net/context"
	"regexp"
	"strings"
	"sync"
)

const (
	//RouteKey Context value key for provided path
	RouteKey = "sr.Route:Key"

	//RouteName Context value key for provided path
	RouteName = "sr.Route:Name"
)

type routeMatcher interface {
	match(string) (string, bool)
}

// ErrRouteNotFound route was not found
var ErrRouteNotFound = errors.New("Route Not Found")

// Route holds a match
type Route struct {
	mu      sync.Mutex
	name    string
	matcher routeMatcher
	sub     []*Route
	h       RouteHandler
}

// RouteHandler callback on matched route
type RouteHandler interface {
	Handle(context.Context, interface{}) (interface{}, error)
}

// Router : Service Router
type Router struct {
	rw       sync.RWMutex
	rootPath string
	routes   []*Route
}

// RouteHandlerFunc simplified Handler interface
type RouteHandlerFunc func(context.Context, interface{}) (interface{}, error)

// Handle implementation of RoutedHandler
func (f RouteHandlerFunc) Handle(ctx context.Context, req interface{}) (r interface{}, e error) {
	r, e = f(ctx, req)
	return
}

// NewRouter Create new router
func NewRouter() *Router {
	return &Router{
		rootPath: "",
		routes:   make([]*Route, 0, 1),
	}
}

// SetRootPrefix set base route of the all path matched
func (r *Router) SetRootPrefix(rootPrefix string) {
	r.rootPath = rootPrefix
}

// ExecPath route the specified path
func (r *Router) ExecPath(path string, req interface{}) (interface{}, error) {
	return r.Exec(context.Background(), path, req)
}

// Exec execute routing
func (r *Router) Exec(ctx context.Context, path string, req interface{}) (interface{}, error) {
	r.rw.RLock()
	defer r.rw.RUnlock()

	if strings.HasPrefix(path, r.rootPath) {
		strippedPath := strings.TrimPrefix(path, r.rootPath)
		for _, route := range r.routes {
			matched, isrouted := route.matchRoute(strippedPath)
			if isrouted {
				if ctx == nil {
					ctx = context.Background()
				}

				ctx = context.WithValue(ctx, RouteName, matched.Name())
				ctx = context.WithValue(ctx, RouteKey, strippedPath)

				rz, err := matched.h.Handle(ctx, req)
				return rz, err
			}
		}
	}

	return nil, ErrRouteNotFound
}

// Clear remove all configured routes
func (r *Router) Clear() *Router {
	r.routes = make([]*Route, 0, 1)
	return r
}

// SimpleRoute litral string matching ie: home.matching == home.matching
func (r *Router) SimpleRoute(path string) *Route {
	return r.newRoute().matchSimple(path)
}

// PrefixRoute string prefix matching home. == home.matching
func (r *Router) PrefixRoute(prefix string) *Route {
	return r.newRoute().matchPrefix(prefix)
}

// RegExpRoute regular expression based matching
func (r *Router) RegExpRoute(re *regexp.Regexp) *Route {
	return r.newRoute().matchRegExp(re)
}

func (r *Router) newRoute() *Route {
	r.rw.Lock()
	defer r.rw.Unlock()

	nroute := &Route{
		name: "Unknown Route",
		sub:  make([]*Route, 0),
	}

	r.routes = append(r.routes, nroute)
	return nroute
}

// Name name of route. just for logging and debuging
func (r *Route) Name() string {
	return r.name
}

// SetName name of route. just for logging and debuging
func (r *Route) SetName(name string) *Route {
	r.name = name
	return r
}

// Handler callback if route matches
func (r *Route) Handler(f RouteHandler) *Route {
	r.h = f
	return r
}

// HandlerFunc callback if route matches
func (r *Route) HandlerFunc(f RouteHandlerFunc) *Route {
	return r.Handler(f)
}

// SimpleSubRoute litral string matching ie: home.matching == home.matching
func (r *Route) SimpleSubRoute(path string) *Route {
	return r.subRoute().matchSimple(path)
}

// PrefixSubRoute string prefix matching home. == home.matching
func (r *Route) PrefixSubRoute(prefix string) *Route {
	return r.subRoute().matchPrefix(prefix)
}

// RegExpSubRoute regular expression based matching
func (r *Route) RegExpSubRoute(re *regexp.Regexp) *Route {
	return r.subRoute().matchRegExp(re)
}

func (r *Route) matchPrefix(prefix string) *Route {
	r.matcher = simplePrefixMatcher(prefix)
	return r
}

func (r *Route) matchSimple(path string) *Route {
	r.matcher = simpleMatcher(path)
	return r
}

func (r *Route) matchRegExp(rx *regexp.Regexp) *Route {
	r.matcher = regexpMatcher(rx.Copy())
	return r
}

func (r *Route) subRoute() *Route {
	r.mu.Lock()
	defer r.mu.Unlock()

	s := &Route{
		name: "Unknown SubRoute",
		sub:  make([]*Route, 0),
	}

	r.sub = append(r.sub, s)
	return s
}

func (r *Route) matchRoute(path string) (*Route, bool) {
	r.mu.Lock()
	defer r.mu.Unlock()

	if r.matcher == nil || path == "" {
		return nil, false // this route would never match anything
	}

	if extra, matched := r.matcher.match(path); matched {
		if r.sub != nil && extra != "" {
			for _, sroute := range r.sub {
				if nroute, ok := sroute.matchRoute(extra); ok {
					return nroute, true
				}
			}
		}

		if r.h != nil {
			return r, true
		}
	}
	return nil, false
}

type routeMatcherFunc func(string) (string, bool)

func (f routeMatcherFunc) match(p string) (string, bool) {
	r, e := f(p)
	return r, e
}

func simplePrefixMatcher(prefix string) routeMatcherFunc {
	return func(path string) (string, bool) {
		nprefix := strings.TrimPrefix(path, prefix)
		return nprefix, path != nprefix
	}
}

func simpleMatcher(patten string) routeMatcherFunc {
	return func(path string) (string, bool) {
		return "", patten == path
	}
}

func regexpMatcher(re *regexp.Regexp) routeMatcherFunc {
	return func(path string) (string, bool) {
		if idx := re.FindStringIndex(path); idx != nil {
			return path[idx[1]:], true
		}

		return "", false
	}
}
<commit_msg>make chainable<commit_after>package servicerouter

import (
	"errors"
	"golang.org/x/net/context"
	"regexp"
	"strings"
	"sync"
)

const (
	//RouteKey Context value key for provided path
	RouteKey = "sr.Route:Key"

	//RouteName Context value key for provided path
	RouteName = "sr.Route:Name"
)

type routeMatcher interface {
	match(string) (string, bool)
}

// ErrRouteNotFound route was not found
var ErrRouteNotFound = errors.New("Route Not Found")

// Route holds a match
type Route struct {
	mu      sync.Mutex
	name    string
	matcher routeMatcher
	sub     []*Route
	h       RouteHandler
}

// RouteHandler callback on matched route
type RouteHandler interface {
	Handle(context.Context, interface{}) (interface{}, error)
}

// Router : Service Router
type Router struct {
	rw       sync.RWMutex
	rootPath string
	routes   []*Route
}

// RouteHandlerFunc simplified Handler interface
type RouteHandlerFunc func(context.Context, interface{}) (interface{}, error)

// Handle implementation of RoutedHandler
func (f RouteHandlerFunc) Handle(ctx context.Context, req interface{}) (r interface{}, e error) {
	r, e = f(ctx, req)
	return
}

// NewRouter Create new router
func NewRouter() *Router {
	return &Router{
		rootPath: "",
		routes:   make([]*Route, 0, 1),
	}
}

// SetRootPrefix set base route of the all path matched
func (r *Router) SetRootPrefix(rootPrefix string) *Router {
	r.rootPath = rootPrefix
	return r
}

// ExecPath route the specified path
func (r *Router) ExecPath(path string, req interface{}) (interface{}, error) {
	return r.Exec(context.Background(), path, req)
}

// Exec execute routing
func (r *Router) Exec(ctx context.Context, path string, req interface{}) (interface{}, error) {
	r.rw.RLock()
	defer r.rw.RUnlock()

	if strings.HasPrefix(path, r.rootPath) {
		strippedPath := strings.TrimPrefix(path, r.rootPath)
		for _, route := range r.routes {
			matched, isrouted := route.matchRoute(strippedPath)
			if isrouted {
				if ctx == nil {
					ctx = context.Background()
				}

				ctx = context.WithValue(ctx, RouteName, matched.Name())
				ctx = context.WithValue(ctx, RouteKey, strippedPath)

				rz, err := matched.h.Handle(ctx, req)
				return rz, err
			}
		}
	}

	return nil, ErrRouteNotFound
}

// Clear remove all configured routes
func (r *Router) Clear() *Router {
	r.routes = make([]*Route, 0, 1)
	return r
}

// SimpleRoute litral string matching ie: home.matching == home.matching
func (r *Router) SimpleRoute(path string) *Route {
	return r.newRoute().matchSimple(path)
}

// PrefixRoute string prefix matching home. == home.matching
func (r *Router) PrefixRoute(prefix string) *Route {
	return r.newRoute().matchPrefix(prefix)
}

// RegExpRoute regular expression based matching
func (r *Router) RegExpRoute(re *regexp.Regexp) *Route {
	return r.newRoute().matchRegExp(re)
}

func (r *Router) newRoute() *Route {
	r.rw.Lock()
	defer r.rw.Unlock()

	nroute := &Route{
		name: "Unknown Route",
		sub:  make([]*Route, 0),
	}

	r.routes = append(r.routes, nroute)
	return nroute
}

// Name name of route. just for logging and debuging
func (r *Route) Name() string {
	return r.name
}

// SetName name of route. just for logging and debuging
func (r *Route) SetName(name string) *Route {
	r.name = name
	return r
}

// Handler callback if route matches
func (r *Route) Handler(f RouteHandler) *Route {
	r.h = f
	return r
}

// HandlerFunc callback if route matches
func (r *Route) HandlerFunc(f RouteHandlerFunc) *Route {
	return r.Handler(f)
}

// SimpleSubRoute litral string matching ie: home.matching == home.matching
func (r *Route) SimpleSubRoute(path string) *Route {
	return r.subRoute().matchSimple(path)
}

// PrefixSubRoute string prefix matching home. == home.matching
func (r *Route) PrefixSubRoute(prefix string) *Route {
	return r.subRoute().matchPrefix(prefix)
}

// RegExpSubRoute regular expression based matching
func (r *Route) RegExpSubRoute(re *regexp.Regexp) *Route {
	return r.subRoute().matchRegExp(re)
}

func (r *Route) matchPrefix(prefix string) *Route {
	r.matcher = simplePrefixMatcher(prefix)
	return r
}

func (r *Route) matchSimple(path string) *Route {
	r.matcher = simpleMatcher(path)
	return r
}

func (r *Route) matchRegExp(rx *regexp.Regexp) *Route {
	r.matcher = regexpMatcher(rx.Copy())
	return r
}

func (r *Route) subRoute() *Route {
	r.mu.Lock()
	defer r.mu.Unlock()

	s := &Route{
		name: "Unknown SubRoute",
		sub:  make([]*Route, 0),
	}

	r.sub = append(r.sub, s)
	return s
}

func (r *Route) matchRoute(path string) (*Route, bool) {
	r.mu.Lock()
	defer r.mu.Unlock()

	if r.matcher == nil || path == "" {
		return nil, false // this route would never match anything
	}

	if extra, matched := r.matcher.match(path); matched {
		if r.sub != nil && extra != "" {
			for _, sroute := range r.sub {
				if nroute, ok := sroute.matchRoute(extra); ok {
					return nroute, true
				}
			}
		}

		if r.h != nil {
			return r, true
		}
	}
	return nil, false
}

type routeMatcherFunc func(string) (string, bool)

func (f routeMatcherFunc) match(p string) (string, bool) {
	r, e := f(p)
	return r, e
}

func simplePrefixMatcher(prefix string) routeMatcherFunc {
	return func(path string) (string, bool) {
		nprefix := strings.TrimPrefix(path, prefix)
		return nprefix, path != nprefix
	}
}

func simpleMatcher(patten string) routeMatcherFunc {
	return func(path string) (string, bool) {
		return "", patten == path
	}
}

func regexpMatcher(re *regexp.Regexp) routeMatcherFunc {
	return func(path string) (string, bool) {
		if idx := re.FindStringIndex(path); idx != nil {
			return path[idx[1]:], true
		}

		return "", false
	}
}
<|endoftext|>