<commit_before>// Copyright 2016 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.

// Command dep is a prototype dependency management tool.
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"text/tabwriter"

	"github.com/golang/dep"
)

type command interface {
	Name() string           // "foobar"
	Args() string           // "<baz> [quux...]"
	ShortHelp() string      // "Foo the first bar"
	LongHelp() string       // "Foo the first bar meeting the following conditions..."
	Register(*flag.FlagSet) // command-specific flags
	Hidden() bool           // indicates whether the command should be hidden from help output
	Run(*dep.Ctx, []string) error
}

func main() {
	wd, err := os.Getwd()
	if err != nil {
		fmt.Fprintln(os.Stderr, "failed to get working directory", err)
		os.Exit(1)
	}
	c := &Config{
		Args:       os.Args,
		Stdout:     os.Stdout,
		Stderr:     os.Stderr,
		WorkingDir: wd,
		Env:        os.Environ(),
	}
	os.Exit(c.Run())
}

// A Config specifies a full configuration for a dep execution.
type Config struct {
	WorkingDir     string    // Where to execute
	Args           []string  // Command-line arguments, starting with the program name.
	Env            []string  // Environment variables
	Stdout, Stderr io.Writer // Log output
}

// Run executes a configuration and returns an exit code.
func (c *Config) Run() (exitCode int) {
	// Build the list of available commands.
	commands := []command{
		&initCommand{},
		&statusCommand{},
		&ensureCommand{},
		&hashinCommand{},
		&pruneCommand{},
	}

	examples := [][2]string{
		{
			"dep init",
			"set up a new project",
		},
		{
			"dep ensure",
			"install the project's dependencies",
		},
		{
			"dep ensure -update",
			"update the locked versions of all dependencies",
		},
		{
			"dep ensure github.com/pkg/errors",
			"add a dependency to the project",
		},
	}

	outLogger := log.New(c.Stdout, "", 0)
	errLogger := log.New(c.Stderr, "", 0)

	usage := func() {
		errLogger.Println("dep is a tool for managing dependencies for Go projects")
		errLogger.Println()
		errLogger.Println("Usage: dep <command>")
		errLogger.Println()
		errLogger.Println("Commands:")
		errLogger.Println()
		w := tabwriter.NewWriter(c.Stderr, 0, 4, 2, ' ', 0)
		for _, cmd := range commands {
			if !cmd.Hidden() {
				fmt.Fprintf(w, "\t%s\t%s\n", cmd.Name(), cmd.ShortHelp())
			}
		}
		w.Flush()
		errLogger.Println()
		errLogger.Println("Examples:")
		for _, example := range examples {
			fmt.Fprintf(w, "\t%s\t%s\n", example[0], example[1])
		}
		w.Flush()
		errLogger.Println()
		errLogger.Println("Use \"dep help [command]\" for more information about a command.")
	}

	cmdName, printCommandHelp, exit := parseArgs(c.Args)
	if exit {
		usage()
		exitCode = 1
		return
	}

	for _, cmd := range commands {
		if cmd.Name() == cmdName {
			// Build flag set with global flags in there.
			fs := flag.NewFlagSet(cmdName, flag.ContinueOnError)
			fs.SetOutput(c.Stderr)
			verbose := fs.Bool("v", false, "enable verbose logging")

			// Register the subcommand flags in there, too.
			cmd.Register(fs)

			// Override the usage text to something nicer.
			resetUsage(errLogger, fs, cmdName, cmd.Args(), cmd.LongHelp())

			if printCommandHelp {
				fs.Usage()
				exitCode = 1
				return
			}

			// Parse the flags the user gave us.
			// flag package automatically prints usage and error message in err != nil
			// or if '-h' flag provided
			if err := fs.Parse(c.Args[2:]); err != nil {
				exitCode = 1
				return
			}

			// Set up dep context.
			ctx := &dep.Ctx{
				Out:     outLogger,
				Err:     errLogger,
				Verbose: *verbose,
			}

			GOPATHS := filepath.SplitList(getEnv(c.Env, "GOPATH"))
			ctx.SetPaths(c.WorkingDir, GOPATHS...)

			// Run the command with the post-flag-processing args.
			if err := cmd.Run(ctx, fs.Args()); err != nil {
				errLogger.Printf("%v\n", err)
				exitCode = 1
				return
			}

			// Easy peasy livin' breezy.
			return
		}
	}

	errLogger.Printf("dep: %s: no such command\n", cmdName)
	usage()
	exitCode = 1
	return
}

func resetUsage(logger *log.Logger, fs *flag.FlagSet, name, args, longHelp string) {
	var (
		hasFlags   bool
		flagBlock  bytes.Buffer
		flagWriter = tabwriter.NewWriter(&flagBlock, 0, 4, 2, ' ', 0)
	)
	fs.VisitAll(func(f *flag.Flag) {
		hasFlags = true
		// Default-empty string vars should read "(default: <none>)"
		// rather than the comparatively ugly "(default: )".
		defValue := f.DefValue
		if defValue == "" {
			defValue = "<none>"
		}
		fmt.Fprintf(flagWriter, "\t-%s\t%s (default: %s)\n", f.Name, f.Usage, defValue)
	})
	flagWriter.Flush()
	fs.Usage = func() {
		logger.Printf("Usage: dep %s %s\n", name, args)
		logger.Println()
		logger.Println(strings.TrimSpace(longHelp))
		logger.Println()
		if hasFlags {
			logger.Println("Flags:")
			logger.Println()
			logger.Println(flagBlock.String())
		}
	}
}

// parseArgs determines the name of the dep command and whether the user asked for
// help to be printed.
func parseArgs(args []string) (cmdName string, printCmdUsage bool, exit bool) {
	isHelpArg := func() bool {
		return strings.Contains(strings.ToLower(args[1]), "help") || strings.ToLower(args[1]) == "-h"
	}

	switch len(args) {
	case 0, 1:
		exit = true
	case 2:
		if isHelpArg() {
			exit = true
		}
		cmdName = args[1]
	default:
		if isHelpArg() {
			cmdName = args[2]
			printCmdUsage = true
		} else {
			cmdName = args[1]
		}
	}
	return cmdName, printCmdUsage, exit
}

// getEnv returns the last instance of an environment variable.
func getEnv(env []string, key string) string {
	for i := len(env) - 1; i >= 0; i-- {
		v := env[i]
		kv := strings.SplitN(v, "=", 2)
		if kv[0] == key {
			if len(kv) > 1 {
				return kv[1]
			}
			return ""
		}
	}
	return ""
}
<commit_msg>fixes #951<commit_after>// Copyright 2016 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.

// Command dep is a prototype dependency management tool.
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"path/filepath"
	"strings"
	"text/tabwriter"

	"github.com/golang/dep"
)

type command interface {
	Name() string           // "foobar"
	Args() string           // "<baz> [quux...]"
	ShortHelp() string      // "Foo the first bar"
	LongHelp() string       // "Foo the first bar meeting the following conditions..."
	Register(*flag.FlagSet) // command-specific flags
	Hidden() bool           // indicates whether the command should be hidden from help output
	Run(*dep.Ctx, []string) error
}

func main() {
	wd, err := os.Getwd()
	if err != nil {
		fmt.Fprintln(os.Stderr, "failed to get working directory", err)
		os.Exit(1)
	}
	c := &Config{
		Args:       os.Args,
		Stdout:     os.Stdout,
		Stderr:     os.Stderr,
		WorkingDir: wd,
		Env:        os.Environ(),
	}
	os.Exit(c.Run())
}

// A Config specifies a full configuration for a dep execution.
type Config struct {
	WorkingDir     string    // Where to execute
	Args           []string  // Command-line arguments, starting with the program name.
	Env            []string  // Environment variables
	Stdout, Stderr io.Writer // Log output
}

// Run executes a configuration and returns an exit code.
func (c *Config) Run() (exitCode int) {
	// Build the list of available commands.
	commands := []command{
		&initCommand{},
		&statusCommand{},
		&ensureCommand{},
		&hashinCommand{},
		&pruneCommand{},
	}

	examples := [][2]string{
		{
			"dep init",
			"set up a new project",
		},
		{
			"dep ensure",
			"install the project's dependencies",
		},
		{
			"dep ensure -update",
			"update the locked versions of all dependencies",
		},
		{
			"dep ensure -add github.com/pkg/errors",
			"add a dependency to the project",
		},
	}

	outLogger := log.New(c.Stdout, "", 0)
	errLogger := log.New(c.Stderr, "", 0)

	usage := func() {
		errLogger.Println("dep is a tool for managing dependencies for Go projects")
		errLogger.Println()
		errLogger.Println("Usage: dep <command>")
		errLogger.Println()
		errLogger.Println("Commands:")
		errLogger.Println()
		w := tabwriter.NewWriter(c.Stderr, 0, 4, 2, ' ', 0)
		for _, cmd := range commands {
			if !cmd.Hidden() {
				fmt.Fprintf(w, "\t%s\t%s\n", cmd.Name(), cmd.ShortHelp())
			}
		}
		w.Flush()
		errLogger.Println()
		errLogger.Println("Examples:")
		for _, example := range examples {
			fmt.Fprintf(w, "\t%s\t%s\n", example[0], example[1])
		}
		w.Flush()
		errLogger.Println()
		errLogger.Println("Use \"dep help [command]\" for more information about a command.")
	}

	cmdName, printCommandHelp, exit := parseArgs(c.Args)
	if exit {
		usage()
		exitCode = 1
		return
	}

	for _, cmd := range commands {
		if cmd.Name() == cmdName {
			// Build flag set with global flags in there.
			fs := flag.NewFlagSet(cmdName, flag.ContinueOnError)
			fs.SetOutput(c.Stderr)
			verbose := fs.Bool("v", false, "enable verbose logging")

			// Register the subcommand flags in there, too.
			cmd.Register(fs)

			// Override the usage text to something nicer.
			resetUsage(errLogger, fs, cmdName, cmd.Args(), cmd.LongHelp())

			if printCommandHelp {
				fs.Usage()
				exitCode = 1
				return
			}

			// Parse the flags the user gave us.
			// flag package automatically prints usage and error message in err != nil
			// or if '-h' flag provided
			if err := fs.Parse(c.Args[2:]); err != nil {
				exitCode = 1
				return
			}

			// Set up dep context.
			ctx := &dep.Ctx{
				Out:     outLogger,
				Err:     errLogger,
				Verbose: *verbose,
			}

			GOPATHS := filepath.SplitList(getEnv(c.Env, "GOPATH"))
			ctx.SetPaths(c.WorkingDir, GOPATHS...)

			// Run the command with the post-flag-processing args.
			if err := cmd.Run(ctx, fs.Args()); err != nil {
				errLogger.Printf("%v\n", err)
				exitCode = 1
				return
			}

			// Easy peasy livin' breezy.
			return
		}
	}

	errLogger.Printf("dep: %s: no such command\n", cmdName)
	usage()
	exitCode = 1
	return
}

func resetUsage(logger *log.Logger, fs *flag.FlagSet, name, args, longHelp string) {
	var (
		hasFlags   bool
		flagBlock  bytes.Buffer
		flagWriter = tabwriter.NewWriter(&flagBlock, 0, 4, 2, ' ', 0)
	)
	fs.VisitAll(func(f *flag.Flag) {
		hasFlags = true
		// Default-empty string vars should read "(default: <none>)"
		// rather than the comparatively ugly "(default: )".
		defValue := f.DefValue
		if defValue == "" {
			defValue = "<none>"
		}
		fmt.Fprintf(flagWriter, "\t-%s\t%s (default: %s)\n", f.Name, f.Usage, defValue)
	})
	flagWriter.Flush()
	fs.Usage = func() {
		logger.Printf("Usage: dep %s %s\n", name, args)
		logger.Println()
		logger.Println(strings.TrimSpace(longHelp))
		logger.Println()
		if hasFlags {
			logger.Println("Flags:")
			logger.Println()
			logger.Println(flagBlock.String())
		}
	}
}

// parseArgs determines the name of the dep command and whether the user asked for
// help to be printed.
func parseArgs(args []string) (cmdName string, printCmdUsage bool, exit bool) {
	isHelpArg := func() bool {
		return strings.Contains(strings.ToLower(args[1]), "help") || strings.ToLower(args[1]) == "-h"
	}

	switch len(args) {
	case 0, 1:
		exit = true
	case 2:
		if isHelpArg() {
			exit = true
		}
		cmdName = args[1]
	default:
		if isHelpArg() {
			cmdName = args[2]
			printCmdUsage = true
		} else {
			cmdName = args[1]
		}
	}
	return cmdName, printCmdUsage, exit
}

// getEnv returns the last instance of an environment variable.
func getEnv(env []string, key string) string {
	for i := len(env) - 1; i >= 0; i-- {
		v := env[i]
		kv := strings.SplitN(v, "=", 2)
		if kv[0] == key {
			if len(kv) > 1 {
				return kv[1]
			}
			return ""
		}
	}
	return ""
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strconv"
	"strings"

	sys "golang.org/x/sys/unix"

	"github.com/derekparker/delve/config"
	"github.com/derekparker/delve/service"
	"github.com/derekparker/delve/service/api"
	"github.com/derekparker/delve/service/rpc"
	"github.com/derekparker/delve/terminal"

	"github.com/spf13/cobra"
)

const version string = "0.10.0-alpha"

var (
	Log      bool
	Headless bool
	Addr     string
	InitFile string
)

func main() {
	// Config setup and load.
	conf := config.LoadConfig()

	// Main dlv root command.
	rootCommand := &cobra.Command{
		Use:   "dlv",
		Short: "Delve is a debugger for the Go programming language.",
		Long: `Delve is a source level debugger for Go programs.

Delve enables you to interact with your program by controlling the execution of the process,
evaluating variables, and providing information of thread / goroutine state, CPU register state and more.

The goal of this tool is to provide a simple yet powerful interface for debugging Go programs.
`,
	}
	rootCommand.PersistentFlags().StringVarP(&Addr, "listen", "l", "localhost:0", "Debugging server listen address.")
	rootCommand.PersistentFlags().BoolVarP(&Log, "log", "", false, "Enable debugging server logging.")
	rootCommand.PersistentFlags().BoolVarP(&Headless, "headless", "", false, "Run debug server only, in headless mode.")
	rootCommand.PersistentFlags().StringVar(&InitFile, "init", "", "Init file, executed by the terminal client")

	// 'version' subcommand.
	versionCommand := &cobra.Command{
		Use:   "version",
		Short: "Prints version.",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Delve version: " + version)
		},
	}
	rootCommand.AddCommand(versionCommand)

	// Deprecated 'run' subcommand.
	runCommand := &cobra.Command{
		Use:   "run",
		Short: "Deprecated command. Use 'debug' instead.",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("This command is deprecated, please use 'debug' instead.")
			os.Exit(0)
		},
	}
	rootCommand.AddCommand(runCommand)

	// 'debug' subcommand.
	debugCommand := &cobra.Command{
		Use:   "debug",
		Short: "Compile and begin debugging program.",
		Long: `Compiles your program with optimizations disabled,
starts and attaches to it, and enables you to immediately begin debugging your program.`,
		Run: func(cmd *cobra.Command, args []string) {
			status := func() int {
				const debugname = "debug"
				goBuild := exec.Command("go", "build", "-o", debugname, "-gcflags", "-N -l")
				goBuild.Stderr = os.Stderr
				err := goBuild.Run()
				if err != nil {
					return 1
				}
				fp, err := filepath.Abs("./" + debugname)
				if err != nil {
					fmt.Fprintf(os.Stderr, err.Error())
					return 1
				}
				defer os.Remove(fp)

				processArgs := append([]string{"./" + debugname}, args...)
				return execute(0, processArgs, conf)
			}()
			os.Exit(status)
		},
	}
	rootCommand.AddCommand(debugCommand)

	// 'exec' subcommand.
	execCommand := &cobra.Command{
		Use:   "exec [./path/to/binary]",
		Short: "Runs precompiled binary, attaches and begins debug session.",
		Run: func(cmd *cobra.Command, args []string) {
			os.Exit(execute(0, args, conf))
		},
	}
	rootCommand.AddCommand(execCommand)

	// 'trace' subcommand.
	var traceAttachPid int
	traceCommand := &cobra.Command{
		Use:   "trace [regexp]",
		Short: "Compile and begin tracing program.",
		Long:  "Trace program execution. Will set a tracepoint on every function matching [regexp] and output information when tracepoint is hit.",
		Run: func(cmd *cobra.Command, args []string) {
			status := func() int {
				const debugname = "debug"
				var processArgs []string
				if traceAttachPid == 0 {
					goBuild := exec.Command("go", "build", "-o", debugname, "-gcflags", "-N -l")
					goBuild.Stderr = os.Stderr
					err := goBuild.Run()
					if err != nil {
						return 1
					}
					fp, err := filepath.Abs("./" + debugname)
					if err != nil {
						fmt.Fprintf(os.Stderr, err.Error())
						return 1
					}
					defer os.Remove(fp)

					processArgs = append([]string{"./" + debugname}, args...)
				}
				// Make a TCP listener
				listener, err := net.Listen("tcp", Addr)
				if err != nil {
					fmt.Printf("couldn't start listener: %s\n", err)
					return 1
				}
				defer listener.Close()

				// Create and start a debugger server
				server := rpc.NewServer(&service.Config{
					Listener:    listener,
					ProcessArgs: processArgs,
					AttachPid:   traceAttachPid,
				}, Log)
				if err := server.Run(); err != nil {
					fmt.Fprintln(os.Stderr, err)
					return 1
				}
				sigChan := make(chan os.Signal)
				signal.Notify(sigChan, sys.SIGINT)
				client := rpc.NewClient(listener.Addr().String())
				funcs, err := client.ListFunctions(args[0])
				if err != nil {
					fmt.Fprintln(os.Stderr, err)
					return 1
				}
				for i := range funcs {
					_, err := client.CreateBreakpoint(&api.Breakpoint{FunctionName: funcs[i], Tracepoint: true})
					if err != nil {
						fmt.Fprintln(os.Stderr, err)
						return 1
					}
				}
				stateChan := client.Continue()
				for {
					select {
					case state := <-stateChan:
						if state.Err != nil {
							fmt.Fprintln(os.Stderr, state.Err)
							return 0
						}
						var args []string
						var fname string
						if state.CurrentThread != nil && state.CurrentThread.Function != nil {
							fname = state.CurrentThread.Function.Name
						}
						if state.BreakpointInfo != nil {
							for _, arg := range state.BreakpointInfo.Arguments {
								args = append(args, arg.Value)
							}
						}
						fmt.Printf("%s(%s) %s:%d\n", fname, strings.Join(args, ", "), state.CurrentThread.File, state.CurrentThread.Line)
					case <-sigChan:
						server.Stop(traceAttachPid == 0)
						return 1
					}
				}
				return 0
			}()
			os.Exit(status)
		},
	}
	traceCommand.Flags().IntVarP(&traceAttachPid, "pid", "p", 0, "Pid to attach to.")
	rootCommand.AddCommand(traceCommand)

	// 'test' subcommand.
	testCommand := &cobra.Command{
		Use:   "test",
		Short: "Compile test binary and begin debugging program.",
		Long: `Compiles a test binary with optimizations disabled,
starts and attaches to it, and enable you to immediately begin debugging your program.`,
		Run: func(cmd *cobra.Command, args []string) {
			status := func() int {
				wd, err := os.Getwd()
				if err != nil {
					fmt.Fprintf(os.Stderr, err.Error())
					return 1
				}
				base := filepath.Base(wd)
				goTest := exec.Command("go", "test", "-c", "-gcflags", "-N -l")
				goTest.Stderr = os.Stderr
				err = goTest.Run()
				if err != nil {
					return 1
				}
				debugname := "./" + base + ".test"
				defer os.Remove(debugname)
				processArgs := append([]string{debugname}, args...)

				return execute(0, processArgs, conf)
			}()
			os.Exit(status)
		},
	}
	rootCommand.AddCommand(testCommand)

	// 'attach' subcommand.
	attachCommand := &cobra.Command{
		Use:   "attach [pid]",
		Short: "Attach to running process and begin debugging.",
		Long:  "Attach to running process and begin debugging.",
		Run: func(cmd *cobra.Command, args []string) {
			pid, err := strconv.Atoi(args[0])
			if err != nil {
				fmt.Fprintf(os.Stderr, "Invalid pid: %s\n", args[0])
				os.Exit(1)
			}
			os.Exit(execute(pid, nil, conf))
		},
	}
	rootCommand.AddCommand(attachCommand)

	// 'connect' subcommand.
	connectCommand := &cobra.Command{
		Use:   "connect [addr]",
		Short: "Connect to a headless debug server.",
		Long:  "Connect to a headless debug server.",
		Run: func(cmd *cobra.Command, args []string) {
			if len(args) == 0 {
				fmt.Fprintf(os.Stderr, "An address was not provided. You must provide an address as the first argument.\n")
				os.Exit(1)
			}
			addr := args[0]
			if addr == "" {
				fmt.Fprintf(os.Stderr, "An empty address was provided. You must provide an address as the first argument.\n")
				os.Exit(1)
			}
			os.Exit(connect(addr, conf))
		},
	}
	rootCommand.AddCommand(connectCommand)

	rootCommand.Execute()
}

func connect(addr string, conf *config.Config) int {
	// Create and start a terminal - attach to running instance
	var client service.Client
	client = rpc.NewClient(addr)
	term := terminal.New(client, conf)
	err, status := term.Run()
	if err != nil {
		fmt.Println(err)
	}
	return status
}

func execute(attachPid int, processArgs []string, conf *config.Config) int {
	// Make a TCP listener
	listener, err := net.Listen("tcp", Addr)
	if err != nil {
		fmt.Printf("couldn't start listener: %s\n", err)
		return 1
	}
	defer listener.Close()

	if Headless && (InitFile != "") {
		fmt.Fprintf(os.Stderr, "Warning: init file ignored\n")
	}

	// Create and start a debugger server
	server := rpc.NewServer(&service.Config{
		Listener:    listener,
		ProcessArgs: processArgs,
		AttachPid:   attachPid,
	}, Log)
	if err := server.Run(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	var status int
	if !Headless {
		// Create and start a terminal
		var client service.Client
		client = rpc.NewClient(listener.Addr().String())
		term := terminal.New(client, conf)
		term.InitFile = InitFile
		err, status = term.Run()
	} else {
		ch := make(chan os.Signal)
		signal.Notify(ch, sys.SIGINT)
		<-ch
		err = server.Stop(true)
	}

	if err != nil {
		fmt.Println(err)
	}

	return status
}
<commit_msg>Fix 2 x panic: runtime error: index out of range<commit_after>package main

import (
	"errors"
	"fmt"
	"net"
	"os"
	"os/exec"
	"os/signal"
	"path/filepath"
	"strconv"
	"strings"

	sys "golang.org/x/sys/unix"

	"github.com/derekparker/delve/config"
	"github.com/derekparker/delve/service"
	"github.com/derekparker/delve/service/api"
	"github.com/derekparker/delve/service/rpc"
	"github.com/derekparker/delve/terminal"

	"github.com/spf13/cobra"
)

const version string = "0.10.0-alpha"

var (
	Log      bool
	Headless bool
	Addr     string
	InitFile string
)

func main() {
	// Config setup and load.
	conf := config.LoadConfig()

	// Main dlv root command.
	rootCommand := &cobra.Command{
		Use:   "dlv",
		Short: "Delve is a debugger for the Go programming language.",
		Long: `Delve is a source level debugger for Go programs.

Delve enables you to interact with your program by controlling the execution of the process,
evaluating variables, and providing information of thread / goroutine state, CPU register state and more.

The goal of this tool is to provide a simple yet powerful interface for debugging Go programs.
`,
	}
	rootCommand.PersistentFlags().StringVarP(&Addr, "listen", "l", "localhost:0", "Debugging server listen address.")
	rootCommand.PersistentFlags().BoolVarP(&Log, "log", "", false, "Enable debugging server logging.")
	rootCommand.PersistentFlags().BoolVarP(&Headless, "headless", "", false, "Run debug server only, in headless mode.")
	rootCommand.PersistentFlags().StringVar(&InitFile, "init", "", "Init file, executed by the terminal client")

	// 'version' subcommand.
	versionCommand := &cobra.Command{
		Use:   "version",
		Short: "Prints version.",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("Delve version: " + version)
		},
	}
	rootCommand.AddCommand(versionCommand)

	// Deprecated 'run' subcommand.
	runCommand := &cobra.Command{
		Use:   "run",
		Short: "Deprecated command. Use 'debug' instead.",
		Run: func(cmd *cobra.Command, args []string) {
			fmt.Println("This command is deprecated, please use 'debug' instead.")
			os.Exit(0)
		},
	}
	rootCommand.AddCommand(runCommand)

	// 'debug' subcommand.
	debugCommand := &cobra.Command{
		Use:   "debug",
		Short: "Compile and begin debugging program.",
		Long: `Compiles your program with optimizations disabled,
starts and attaches to it, and enables you to immediately begin debugging your program.`,
		Run: func(cmd *cobra.Command, args []string) {
			status := func() int {
				const debugname = "debug"
				goBuild := exec.Command("go", "build", "-o", debugname, "-gcflags", "-N -l")
				goBuild.Stderr = os.Stderr
				err := goBuild.Run()
				if err != nil {
					return 1
				}
				fp, err := filepath.Abs("./" + debugname)
				if err != nil {
					fmt.Fprintf(os.Stderr, err.Error())
					return 1
				}
				defer os.Remove(fp)

				processArgs := append([]string{"./" + debugname}, args...)
				return execute(0, processArgs, conf)
			}()
			os.Exit(status)
		},
	}
	rootCommand.AddCommand(debugCommand)

	// 'exec' subcommand.
	execCommand := &cobra.Command{
		Use:   "exec [./path/to/binary]",
		Short: "Runs precompiled binary, attaches and begins debug session.",
		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			if len(args) == 0 {
				return errors.New("you must provide a path to a binary")
			}
			return nil
		},
		Run: func(cmd *cobra.Command, args []string) {
			os.Exit(execute(0, args, conf))
		},
	}
	rootCommand.AddCommand(execCommand)

	// 'trace' subcommand.
	var traceAttachPid int
	traceCommand := &cobra.Command{
		Use:   "trace [regexp]",
		Short: "Compile and begin tracing program.",
		Long:  "Trace program execution. Will set a tracepoint on every function matching [regexp] and output information when tracepoint is hit.",
		Run: func(cmd *cobra.Command, args []string) {
			status := func() int {
				const debugname = "debug"
				var processArgs []string
				if traceAttachPid == 0 {
					goBuild := exec.Command("go", "build", "-o", debugname, "-gcflags", "-N -l")
					goBuild.Stderr = os.Stderr
					err := goBuild.Run()
					if err != nil {
						return 1
					}
					fp, err := filepath.Abs("./" + debugname)
					if err != nil {
						fmt.Fprintf(os.Stderr, err.Error())
						return 1
					}
					defer os.Remove(fp)

					processArgs = append([]string{"./" + debugname}, args...)
				}
				// Make a TCP listener
				listener, err := net.Listen("tcp", Addr)
				if err != nil {
					fmt.Printf("couldn't start listener: %s\n", err)
					return 1
				}
				defer listener.Close()

				// Create and start a debugger server
				server := rpc.NewServer(&service.Config{
					Listener:    listener,
					ProcessArgs: processArgs,
					AttachPid:   traceAttachPid,
				}, Log)
				if err := server.Run(); err != nil {
					fmt.Fprintln(os.Stderr, err)
					return 1
				}
				sigChan := make(chan os.Signal)
				signal.Notify(sigChan, sys.SIGINT)
				client := rpc.NewClient(listener.Addr().String())
				funcs, err := client.ListFunctions(args[0])
				if err != nil {
					fmt.Fprintln(os.Stderr, err)
					return 1
				}
				for i := range funcs {
					_, err := client.CreateBreakpoint(&api.Breakpoint{FunctionName: funcs[i], Tracepoint: true})
					if err != nil {
						fmt.Fprintln(os.Stderr, err)
						return 1
					}
				}
				stateChan := client.Continue()
				for {
					select {
					case state := <-stateChan:
						if state.Err != nil {
							fmt.Fprintln(os.Stderr, state.Err)
							return 0
						}
						var args []string
						var fname string
						if state.CurrentThread != nil && state.CurrentThread.Function != nil {
							fname = state.CurrentThread.Function.Name
						}
						if state.BreakpointInfo != nil {
							for _, arg := range state.BreakpointInfo.Arguments {
								args = append(args, arg.Value)
							}
						}
						fmt.Printf("%s(%s) %s:%d\n", fname, strings.Join(args, ", "), state.CurrentThread.File, state.CurrentThread.Line)
					case <-sigChan:
						server.Stop(traceAttachPid == 0)
						return 1
					}
				}
				return 0
			}()
			os.Exit(status)
		},
	}
	traceCommand.Flags().IntVarP(&traceAttachPid, "pid", "p", 0, "Pid to attach to.")
	rootCommand.AddCommand(traceCommand)

	// 'test' subcommand.
	testCommand := &cobra.Command{
		Use:   "test",
		Short: "Compile test binary and begin debugging program.",
		Long: `Compiles a test binary with optimizations disabled,
starts and attaches to it, and enable you to immediately begin debugging your program.`,
		Run: func(cmd *cobra.Command, args []string) {
			status := func() int {
				wd, err := os.Getwd()
				if err != nil {
					fmt.Fprintf(os.Stderr, err.Error())
					return 1
				}
				base := filepath.Base(wd)
				goTest := exec.Command("go", "test", "-c", "-gcflags", "-N -l")
				goTest.Stderr = os.Stderr
				err = goTest.Run()
				if err != nil {
					return 1
				}
				debugname := "./" + base + ".test"
				defer os.Remove(debugname)
				processArgs := append([]string{debugname}, args...)

				return execute(0, processArgs, conf)
			}()
			os.Exit(status)
		},
	}
	rootCommand.AddCommand(testCommand)

	// 'attach' subcommand.
	attachCommand := &cobra.Command{
		Use:   "attach [pid]",
		Short: "Attach to running process and begin debugging.",
		Long:  "Attach to running process and begin debugging.",
		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
			if len(args) == 0 {
				return errors.New("you must provide a PID")
			}
			return nil
		},
		Run: func(cmd *cobra.Command, args []string) {
			pid, err := strconv.Atoi(args[0])
			if err != nil {
				fmt.Fprintf(os.Stderr, "Invalid pid: %s\n", args[0])
				os.Exit(1)
			}
			os.Exit(execute(pid, nil, conf))
		},
	}
	rootCommand.AddCommand(attachCommand)

	// 'connect' subcommand.
	connectCommand := &cobra.Command{
		Use:   "connect [addr]",
		Short: "Connect to a headless debug server.",
		Long:  "Connect to a headless debug server.",
		Run: func(cmd *cobra.Command, args []string) {
			if len(args) == 0 {
				fmt.Fprintf(os.Stderr, "An address was not provided. You must provide an address as the first argument.\n")
				os.Exit(1)
			}
			addr := args[0]
			if addr == "" {
				fmt.Fprintf(os.Stderr, "An empty address was provided. You must provide an address as the first argument.\n")
				os.Exit(1)
			}
			os.Exit(connect(addr, conf))
		},
	}
	rootCommand.AddCommand(connectCommand)

	rootCommand.Execute()
}

func connect(addr string, conf *config.Config) int {
	// Create and start a terminal - attach to running instance
	var client service.Client
	client = rpc.NewClient(addr)
	term := terminal.New(client, conf)
	err, status := term.Run()
	if err != nil {
		fmt.Println(err)
	}
	return status
}

func execute(attachPid int, processArgs []string, conf *config.Config) int {
	// Make a TCP listener
	listener, err := net.Listen("tcp", Addr)
	if err != nil {
		fmt.Printf("couldn't start listener: %s\n", err)
		return 1
	}
	defer listener.Close()

	if Headless && (InitFile != "") {
		fmt.Fprintf(os.Stderr, "Warning: init file ignored\n")
	}

	// Create and start a debugger server
	server := rpc.NewServer(&service.Config{
		Listener:    listener,
		ProcessArgs: processArgs,
		AttachPid:   attachPid,
	}, Log)
	if err := server.Run(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		return 1
	}

	var status int
	if !Headless {
		// Create and start a terminal
		var client service.Client
		client = rpc.NewClient(listener.Addr().String())
		term := terminal.New(client, conf)
		term.InitFile = InitFile
		err, status = term.Run()
	} else {
		ch := make(chan os.Signal)
		signal.Notify(ch, sys.SIGINT)
		<-ch
		err = server.Stop(true)
	}

	if err != nil {
		fmt.Println(err)
	}

	return status
}
<|endoftext|>


<commit_before>package rpc2

import (
	"bufio"
	"encoding/json"
	"time"
	"unicode"
	"unicode/utf8"

	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git"
	"github.com/bitly/go-simplejson"
	"github.com/ninjasphere/go-ninja/logger"
)

type mqttJsonRpcConnection struct {
	log            *logger.Logger
	incomingTopic  string
	outgoingTopic  string
	mqttConn       *mqtt.MqttClient
	bufferedReader *bufio.Reader
}

type rpcRequestResponse struct {
	Params   *json.RawMessage `json:"params,omitEmpty"`
	Method   *string          `json:"method,omitEmpty"`
	Time     *int64           `json:"time,omitEmpty"`
	Version  *string          `json:"jsonrpc,omitEmpty"`
	ID       *json.RawMessage `json:"id,omitEmpty"`
	Result   *json.RawMessage `json:"result,omitEmpty"`
	Response *json.RawMessage `json:"response,omitEmpty"`
	Error    *json.RawMessage `json:"error,omitEmpty"`
}

func upperFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToUpper(r)) + s[n:]
}

func lowerFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToLower(r)) + s[n:]
}

func NewMqttJsonRpcConnection(serving bool, mqttConn *mqtt.MqttClient, topic string, log *logger.Logger) (*mqttJsonRpcConnection, error) {

	fake := &fakeReader{
		incomingData: make(chan []byte),
	}

	c := &mqttJsonRpcConnection{
		mqttConn:       mqttConn,
		incomingTopic:  topic,
		outgoingTopic:  topic + "/reply",
		log:            log,
		bufferedReader: bufio.NewReaderSize(fake, 512*1024), // TODO: Fix this
	}

	if !serving {
		c.incomingTopic, c.outgoingTopic = c.outgoingTopic, c.incomingTopic
	}

	fake.incomingTopic = c.incomingTopic

	filter, err := mqtt.NewTopicFilter(c.incomingTopic, 0)
	if err != nil {
		return nil, err
	}

	receipt, err := c.mqttConn.StartSubscription(func(client *mqtt.MqttClient, message mqtt.Message) {
		fake.incomingData <- message.Payload()
	}, filter)

	if err != nil {
		return nil, err
	}

	<-receipt

	return c, nil
}

func (c *mqttJsonRpcConnection) SendEvent(event string, payload interface{}) error {
	jsonPayload, err := json.Marshal(payload)
	if err != nil {
		return err
	}

	log.Debugf("Sending event: %s payload: %s", event, jsonPayload)

	pubReceipt := c.mqttConn.Publish(mqtt.QoS(0), c.incomingTopic+"/event/"+event, jsonPayload)
	<-pubReceipt
	return nil
}

func (c *mqttJsonRpcConnection) Read(p []byte) (n int, err error) {
	return c.bufferedReader.Read(p)
}

type fakeReader struct {
	incomingData  chan []byte
	incomingTopic string
}

var result = json.RawMessage([]byte("true"))

func (c *fakeReader) Read(p []byte) (n int, err error) {
	msg := <-c.incomingData

	//log.Infof("< Incoming (%s) (unaltered) %s", c.incomingTopic, msg)

	r := &rpcRequestResponse{}

	err = json.Unmarshal(msg, r)

	if err != nil {
		log.Errorf("Failed to parse incoming json-rpc message %s : %s", err, msg)
		return 0, err
	}

	if r.Method != nil {
		method := "service." + upperFirst(*r.Method)
		r.Method = &method
	}

	r.Result = r.Response
	r.Response = nil
	r.Time = nil
	r.Version = nil

	if r.Result == nil && r.Error == nil {
		r.Result = &result
	}

	data, err := json.Marshal(r)

	//log.Infof("< Incoming (%s) (altered)   %s", c.incomingTopic, data)

	if err != nil {
		log.Errorf("Failed to re-marshal incoming json-rpc message %s:", err)
		return 0, err
	}

	return copy(p[0:], data), nil
}

const blank = "[]"
const version = "2.0"

func (c *mqttJsonRpcConnection) Write(p []byte) (n int, err error) {

	//log.Infof("< Outgoing (%s) (unaltered) %s", c.outgoingTopic, p)

	var version = "2.0"
	var now = time.Now().Unix() / 10000

	req, err := simplejson.NewJson(p)

	if err != nil {
		return 0, err
	}

	req.Set("jsonrpc", version)
	req.Set("time", now)
	req.Set("response", req.Get("result"))
	req.Del("result")
	/*error := req.Get("error").MustString()
	log.Infof("outgoing error %s", error)
	if error == "" {
		req.Del("error")
	}*/
	/*
		if req.Params != nil && string(*req.Params) == "[null]" {
			blank := json.RawMessage([]byte("[]"))
			req.Params = &blank
		}*/

	payload, err := req.MarshalJSON()

	//log.Infof("< Outgoing (%s) (altered)   %s", c.outgoingTopic, payload)

	_ /*pubReceipt :*/ = c.mqttConn.Publish(mqtt.QoS(0), c.outgoingTopic, payload)
	//<-pubReceipt
	return len(p), nil
}

func (c *mqttJsonRpcConnection) Close() error {
	log.Infof("mqttjson: Closing")
	return nil
}
<commit_msg>Fix clients getting each others replies<commit_after>package rpc2

import (
	"bufio"
	"bytes"

	"encoding/binary"
	"encoding/json"
	"fmt"
	"math/rand"
	"strconv"
	"strings"
	"time"
	"unicode"
	"unicode/utf8"

	"git.eclipse.org/gitroot/paho/org.eclipse.paho.mqtt.golang.git"
	"github.com/ninjasphere/go-ninja/logger"
)

type mqttJsonRpcConnection struct {
	log            *logger.Logger
	incomingTopic  string
	outgoingTopic  string
	mqttConn       *mqtt.MqttClient
	bufferedReader *bufio.Reader
	connectionId   string
	server         bool
}

type rpcRequestResponse struct {
	Params   *json.RawMessage `json:"params,omitEmpty"`
	Method   *string          `json:"method,omitEmpty"`
	Time     *int64           `json:"time,omitEmpty"`
	Version  *string          `json:"jsonrpc,omitEmpty"`
	ID       *json.RawMessage `json:"id,omitEmpty"`
	Result   *json.RawMessage `json:"result,omitEmpty"`
	Response *json.RawMessage `json:"response,omitEmpty"`
	Error    *json.RawMessage `json:"error,omitEmpty"`
}

func upperFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToUpper(r)) + s[n:]
}

func lowerFirst(s string) string {
	if s == "" {
		return ""
	}
	r, n := utf8.DecodeRuneInString(s)
	return string(unicode.ToLower(r)) + s[n:]
}

func NewMqttJsonRpcConnection(serving bool, mqttConn *mqtt.MqttClient, topic string, log *logger.Logger) (*mqttJsonRpcConnection, error) {

	fake := &fakeReader{
		incomingData: make(chan []byte),
	}

	id := rand.Intn(999999)

	c := &mqttJsonRpcConnection{
		mqttConn:       mqttConn,
		incomingTopic:  topic,
		outgoingTopic:  topic + "/reply",
		log:            log,
		bufferedReader: bufio.NewReaderSize(fake, 512*1024), // TODO: Fix this
		connectionId:   fmt.Sprintf("gorpc%d", id),
		server:         serving,
	}

	if !serving {
		c.incomingTopic, c.outgoingTopic = c.outgoingTopic, c.incomingTopic
	}

	fake.conn = c

	filter, err := mqtt.NewTopicFilter(c.incomingTopic, 0)
	if err != nil {
		return nil, err
	}

	receipt, err := c.mqttConn.StartSubscription(func(client *mqtt.MqttClient, message mqtt.Message) {
		fake.incomingData <- message.Payload()
	}, filter)

	if err != nil {
		return nil, err
	}

	<-receipt

	return c, nil
}

func (c *mqttJsonRpcConnection) SendEvent(event string, payload interface{}) error {
	jsonPayload, err := json.Marshal(payload)
	if err != nil {
		return err
	}

	log.Debugf("Sending event: %s payload: %s", event, jsonPayload)

	pubReceipt := c.mqttConn.Publish(mqtt.QoS(0), c.incomingTopic+"/event/"+event, jsonPayload)
	<-pubReceipt
	return nil
}

func (c *mqttJsonRpcConnection) Read(p []byte) (n int, err error) {
	return c.bufferedReader.Read(p)
}

type fakeReader struct {
	incomingData chan []byte
	conn         *mqttJsonRpcConnection
}

var result = json.RawMessage([]byte("true"))

func (c *fakeReader) Read(p []byte) (n int, err error) {
	msg := <-c.incomingData

	//log.Infof("< Incoming (%s) (unaltered) %s", c.incomingTopic, msg)

	r := &rpcRequestResponse{}

	err = json.Unmarshal(msg, r)

	if err != nil {
		log.Errorf("Failed to parse incoming json-rpc message %s : %s", err, msg)
		return 0, err
	}

	if r.ID != nil {
		if !c.conn.server {
			// The id must have out connection Id at the front

			var stringID string

			err := json.Unmarshal(*r.ID, &stringID)

			if err != nil {
				log.Infof("Failed to unmarshall id: %s", err)
				return 0, err
			}

			log.Infof("Incoming ID %s", stringID)

			if !strings.Contains(stringID, c.conn.connectionId) {
				log.Infof("Not for us!")
				return 0, nil
			}

			intID, err := strconv.ParseUint(strings.TrimPrefix(stringID, c.conn.connectionId+"-"), 10, 64)

			log.Infof("Converted ID %d - %s", intID, err)

			buf := new(bytes.Buffer)
			err = binary.Write(buf, binary.LittleEndian, intID)
			if err != nil {
				log.Infof("Failed to write int id: %s", err)
				return 0, nil
			}

			fixedID := json.RawMessage(fmt.Sprintf("%d", intID))
			r.ID = &fixedID
		}
	}

	if r.Method != nil {
		method := "service." + upperFirst(*r.Method)
		r.Method = &method
	}

	r.Result = r.Response
	r.Response = nil
	r.Time = nil
	r.Version = nil

	if r.Result == nil && r.Error == nil {
		r.Result = &result
	}

	data, err := json.Marshal(r)

	//log.Infof("< Incoming (%s) (altered)   %s", c.incomingTopic, data)

	if err != nil {
		log.Errorf("Failed to re-marshal incoming json-rpc message %s:", err)
		return 0, err
	}

	return copy(p[0:], data), nil
}

const blank = "[]"
const version = "2.0"

func (c *mqttJsonRpcConnection) Write(p []byte) (n int, err error) {

	log.Infof("> Outgoing (%s) (unaltered) %s", c.outgoingTopic, p)

	r := &rpcRequestResponse{}

	err = json.Unmarshal(p, r)

	var version = "2.0"
	var now = time.Now().Unix()

	r.Version = &version
	r.Time = &now

	if r.Result != nil {
		r.Response = r.Result
	}

	if r.ID != nil {
		if !c.server {
			var id uint64
			err := json.Unmarshal(*r.ID, &id)

			if err != nil {
				log.Infof("Failed to unmarshall id: %s", err)
				return 0, err
			}
			log.Infof("Outgoing id : %d", id)
			// The id needs to be changed, we need to add our connection id to it
			stringID := json.RawMessage(fmt.Sprintf(`"%s-%d"`, c.connectionId, id))
			r.ID = &stringID
		}
	}

	/*error := req.Get("error").MustString()
	log.Infof("outgoing error %s", error)
	if error == "" {
		req.Del("error")
	}*/
	/*
		if req.Params != nil && string(*req.Params) == "[null]" {
			blank := json.RawMessage([]byte("[]"))
			req.Params = &blank
		}*/

	payload, err := json.Marshal(r)

	log.Infof("> Outgoing (%s) (altered)   %s", c.outgoingTopic, payload)

	_ /*pubReceipt :*/ = c.mqttConn.Publish(mqtt.QoS(0), c.outgoingTopic, payload)
	//<-pubReceipt
	return len(p), nil
}

func (c *mqttJsonRpcConnection) Close() error {
	log.Infof("mqttjson: Closing")
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2016-2017 The psh Authors. All rights reserved.

package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/repejota/psh"
)

var (
	// Version is the latest release number.
	//
	// This number is the latest tag from the git repository.
	Version string

	// Build is the lastest build string.
	//
	// This string is the branch name and the commit hash (short format)
	Build string

	versionFlag        bool
	colortestFlag      bool
	backgroundtestFlag bool
	segmentsFlag       string
)

func init() {
	flag.BoolVar(&versionFlag, "version", false, "Show version information")
	flag.BoolVar(&colortestFlag, "colortest", false, "Show available colors on the terminazl.")
	flag.BoolVar(&backgroundtestFlag, "backgroundtest", false, "Show available backgrounds on the terminal.")
	flag.StringVar(&segmentsFlag, "segments", psh.DefaultSegments, "Segments to show on the propmt.")
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("psh: ")

	flag.Parse()
	if versionFlag {
		versionInfo := showVersion()
		fmt.Println(versionInfo)
		os.Exit(0)
	}
	if colortestFlag {
		ColorTest()
		os.Exit(0)
	}
	if backgroundtestFlag {
		BackgroundTest()
		os.Exit(0)
	}

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

// doPSH builds the prompt decoupled from main function to easy tests.
func doPSH() error {
	// Create a prompt instance
	prompt := psh.NewPrompt(segmentsFlag)

	// Compile prompt (all of its segments)
	err := prompt.Compile()
	if err != nil {
		return err
	}

	// Render prompt
	result, err := prompt.Render()
	if err != nil {
		return err
	}

	fmt.Printf("%s", result)
	return nil
}

// showVersion prints the current version information.
func showVersion() string {
	versionInfo := fmt.Sprintf("psh : Version %s Build %s", Version, Build)
	return versionInfo
}

// ColorTest executes a foreground color test.
func ColorTest() {
	escape := "\x1b"
	for c := 0; c < 256; c++ {
		color := fmt.Sprintf("%s[38;5;%dm", escape, c)
		fmt.Printf("%s%d\n", color, c)
	}
	fmt.Printf("%s[0m", escape)
}

// BackgroundTest executes a backgtound color test.
func BackgroundTest() {
	escape := "\x1b"
	for c := 0; c < 256; c++ {
		background := fmt.Sprintf("%s[48;5;%dm", escape, c)
		fmt.Printf("%s%d\n", background, c)
	}
	fmt.Printf("%s[0m", escape)
}
<commit_msg>Refactor flags, remove global state variables<commit_after>// Copyright 2016-2017 The psh Authors. All rights reserved.

package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/repejota/psh"
)

var (
	// Version is the latest release number.
	//
	// This number is the latest tag from the git repository.
	Version string

	// Build is the lastest build string.
	//
	// This string is the branch name and the commit hash (short format)
	Build string
)

func main() {
	log.SetFlags(0)
	log.SetPrefix("psh: ")

	var (
		// Define CLI flags.
		versionFlag        = flag.Bool("version", false, "Show version information")
		colortestFlag      = flag.Bool("colortest", false, "Show available colors on the terminazl.")
		backgroundtestFlag = flag.Bool("backgroundtest", false, "Show available backgrounds on the terminal.")
		segmentsFlag       = flag.String("segments", psh.DefaultSegments, "Segments to show on the propmt.")
	)
	flag.Parse()
	if *versionFlag {
		versionInfo := showVersion()
		fmt.Println(versionInfo)
		os.Exit(0)
	}
	if *colortestFlag {
		ColorTest()
		os.Exit(0)
	}
	if *backgroundtestFlag {
		BackgroundTest()
		os.Exit(0)
	}
	err := doPSH(*segmentsFlag)
	if err != nil {
		log.Fatal(err)
	}
}

// doPSH compiles and renders the prompt.
func doPSH(segmentsFlag string) error {
	// Create a prompt instance
	prompt := psh.NewPrompt(segmentsFlag)

	// Compile prompt
	err := prompt.Compile()
	if err != nil {
		return err
	}

	// Render prompt
	result, err := prompt.Render()
	if err != nil {
		return err
	}

	fmt.Printf("%s", result)
	return nil
}

// showVersion prints the current version information.
func showVersion() string {
	versionInfo := fmt.Sprintf("psh : Version %s Build %s", Version, Build)
	return versionInfo
}

// ColorTest executes a foreground color test.
func ColorTest() {
	escape := "\x1b"
	for c := 0; c < 256; c++ {
		color := fmt.Sprintf("%s[38;5;%dm", escape, c)
		fmt.Printf("%s%d\n", color, c)
	}
	fmt.Printf("%s[0m", escape)
}

// BackgroundTest executes a backgtound color test.
func BackgroundTest() {
	escape := "\x1b"
	for c := 0; c < 256; c++ {
		background := fmt.Sprintf("%s[48;5;%dm", escape, c)
		fmt.Printf("%s%d\n", background, c)
	}
	fmt.Printf("%s[0m", escape)
}
<|endoftext|>


<commit_before>// Copyright (c) 2019 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import (
	"math/bits"
)

const idAllocRangeLen = 16384

func makeIdAllocator(limit int) (<-chan int16, chan<- int16) {
	if true {
		c := makeIdAllocatorImpl1(limit)
		return c, c
	} else {
		return makeIdAllocatorImpl2(limit)
	}
}

func makeIdAllocatorImpl1(limit int) chan int16 {
	c := make(chan int16, limit)
	for i := 0; i < limit; i++ {
		c <- int16(i)
	}
	return c
}

func makeIdAllocatorImpl2(limit int) (<-chan int16, chan<- int16) {
	alloc := make(chan int16, 128)
	free := make(chan int16, 128)
	go serveIdAllocations(alloc, free, limit)
	return alloc, free
}

func serveIdAllocations(alloc chan<- int16, free <-chan int16, limit int) {
	defer close(alloc)

	var ar idAllocator
	ar.init(limit)

	allocatedId := int16(-1)

	for {
		if allocatedId < 0 {
			allocatedId = ar.alloc()
			if allocatedId < 0 {
				id, ok := <-free
				if !ok {
					return
				}
				ar.free(id)
			}
		}

		select {
		case alloc <- allocatedId:
			allocatedId = -1

		case id, ok := <-free:
			if !ok {
				return
			}
			ar.free(id)
		}
	}
}

// idAllocator allocates ids in range [2,32767] in arbitrary order.
type idAllocator struct {
	level3 [512]uint64
	level2 [8]uint64
	level1 uint8
	minId  int16
}

func (ar *idAllocator) init(limit int) {
	for i := 0; i < len(ar.level3); i++ {
		ar.level3[i] = ^uint64(0)
	}
	for i := 0; i < len(ar.level2); i++ {
		ar.level2[i] = ^uint64(0)
	}
	ar.level1 = ^uint8(0)
	ar.minId = int16(16384 - limit)
}

func (ar *idAllocator) alloc() int16 {
	bit1 := uint(bits.Len8(ar.level1)) - 1
	bit2 := uint(bits.Len64(ar.level2[bit1])) - 1
	bit3 := uint(bits.Len64(ar.level3[bit1<<6|bit2])) - 1
	id := int16(bit1<<12 | bit2<<6 | bit3)
	if id < ar.minId {
		return -1
	}

	ar.level3[bit1<<6|bit2] ^= 1 << bit3
	if ar.level3[bit1<<6|bit2] == 0 {
		ar.level2[bit1] ^= 1 << bit2
		if ar.level2[bit1] == 0 {
			ar.level1 ^= 1 << bit1
		}
	}

	return id
}

func (ar *idAllocator) free(id int16) {
	bit1 := uint(id >> 12)
	bit2 := uint(id>>6) & 63
	bit3 := uint(id) & 63

	ar.level3[bit1<<6|bit2] |= 1 << bit3
	ar.level2[bit1] |= 1 << bit2
	ar.level1 |= 1 << bit1
}
<commit_msg>runtime: fix alternative id allocator<commit_after>// Copyright (c) 2019 Timo Savola. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import (
	"math/bits"
)

const idAllocRangeLen = 16384

func makeIdAllocator(limit int) (<-chan int16, chan<- int16) {
	if true {
		c := makeIdAllocatorImpl1(limit)
		return c, c
	} else {
		return makeIdAllocatorImpl2(limit)
	}
}

func makeIdAllocatorImpl1(limit int) chan int16 {
	c := make(chan int16, limit)
	for i := 0; i < limit; i++ {
		c <- int16(i)
	}
	return c
}

func makeIdAllocatorImpl2(limit int) (<-chan int16, chan<- int16) {
	alloc := make(chan int16, 128)
	free := make(chan int16, 128)
	go serveIdAllocations(alloc, free, limit)
	return alloc, free
}

func serveIdAllocations(alloc chan<- int16, free <-chan int16, limit int) {
	defer close(alloc)

	var ar idAllocator
	ar.init(limit)

	allocatedId := int16(-1)

	for {
		if allocatedId < 0 {
			allocatedId = ar.alloc()
			if allocatedId < 0 {
				id, ok := <-free
				if !ok {
					return
				}
				ar.free(id)
			}
		}

		select {
		case alloc <- allocatedId:
			allocatedId = -1

		case id, ok := <-free:
			if !ok {
				return
			}
			ar.free(id)
		}
	}
}

type idAllocator struct {
	level3 [256]uint64
	level2 [8]uint32
	level1 uint8
	minId  int16
}

func (ar *idAllocator) init(limit int) {
	for i := 0; i < len(ar.level3); i++ {
		ar.level3[i] = ^uint64(0)
	}
	for i := 0; i < len(ar.level2); i++ {
		ar.level2[i] = ^uint32(0)
	}
	ar.level1 = ^uint8(0)
	ar.minId = int16(16384 - limit)
}

func (ar *idAllocator) alloc() int16 {
	bit1 := uint(bits.Len8(ar.level1)) - 1
	bit2 := uint(bits.Len32(ar.level2[bit1])) - 1
	bit3 := uint(bits.Len64(ar.level3[bit1<<5|bit2])) - 1
	id := int16(bit1<<11 | bit2<<6 | bit3)
	if id < ar.minId {
		return -1
	}

	ar.level3[bit1<<5|bit2] ^= 1 << bit3
	if ar.level3[bit1<<5|bit2] == 0 {
		ar.level2[bit1] ^= 1 << bit2
		if ar.level2[bit1] == 0 {
			ar.level1 ^= 1 << bit1
		}
	}

	return id
}

func (ar *idAllocator) free(id int16) {
	bit1 := uint(id >> 11)
	bit2 := uint(id>>6) & 31
	bit3 := uint(id) & 63

	ar.level3[bit1<<5|bit2] |= 1 << bit3
	ar.level2[bit1] |= 1 << bit2
	ar.level1 |= 1 << bit1
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.

package gnmi

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"path"
	"strconv"

	pb "github.com/openconfig/gnmi/proto/gnmi"
	"google.golang.org/grpc/codes"
)

// Get sents a GetRequest to the given client.
func Get(ctx context.Context, client pb.GNMIClient, paths [][]string) error {
	req, err := NewGetRequest(paths)
	if err != nil {
		return err
	}
	resp, err := client.Get(ctx, req)
	if err != nil {
		return err
	}
	for _, notif := range resp.Notification {
		for _, update := range notif.Update {
			fmt.Printf("%s:\n", StrPath(update.Path))
			fmt.Println(strUpdateVal(update))
		}
	}
	return nil
}

// Capabilities retuns the capabilities of the client.
func Capabilities(ctx context.Context, client pb.GNMIClient) error {
	resp, err := client.Capabilities(ctx, &pb.CapabilityRequest{})
	if err != nil {
		return err
	}
	fmt.Printf("Version: %s\n", resp.GNMIVersion)
	for _, mod := range resp.SupportedModels {
		fmt.Printf("SupportedModel: %s\n", mod)
	}
	for _, enc := range resp.SupportedEncodings {
		fmt.Printf("SupportedEncoding: %s\n", enc)
	}
	return nil
}

// val may be a path to a file or it may be json. First see if it is a
// file, if so return its contents, otherwise return val
func extractJSON(val string) []byte {
	jsonBytes, err := ioutil.ReadFile(val)
	if err != nil {
		jsonBytes = []byte(val)
	}
	return jsonBytes
}

// strUpdateVal will return a string representing the value within the supplied update
func strUpdateVal(u *pb.Update) string {
	if u.Value != nil {
		return string(u.Value.Value) // Backwards compatibility with pre-v0.4 gnmi
	}
	return strVal(u.Val)
}

// strVal will return a string representing the supplied value
func strVal(val *pb.TypedValue) string {
	switch v := val.GetValue().(type) {
	case *pb.TypedValue_StringVal:
		return v.StringVal
	case *pb.TypedValue_JsonIetfVal:
		return strJSON(v.JsonIetfVal)
	case *pb.TypedValue_JsonVal:
		return strJSON(v.JsonVal)
	case *pb.TypedValue_IntVal:
		return strconv.FormatInt(v.IntVal, 10)
	case *pb.TypedValue_UintVal:
		return strconv.FormatUint(v.UintVal, 10)
	case *pb.TypedValue_BoolVal:
		return strconv.FormatBool(v.BoolVal)
	case *pb.TypedValue_BytesVal:
		return base64.StdEncoding.EncodeToString(v.BytesVal)
	case *pb.TypedValue_DecimalVal:
		return strDecimal64(v.DecimalVal)
	case *pb.TypedValue_FloatVal:
		return strconv.FormatFloat(float64(v.FloatVal), 'g', -1, 32)
	case *pb.TypedValue_LeaflistVal:
		return strLeaflist(v.LeaflistVal)
	case *pb.TypedValue_AsciiVal:
		return v.AsciiVal
	case *pb.TypedValue_AnyVal:
		return v.AnyVal.String()
	default:
		panic(v)
	}
}

func strJSON(inJSON []byte) string {
	var out bytes.Buffer
	err := json.Indent(&out, inJSON, "", "  ")
	if err != nil {
		return fmt.Sprintf("(error unmarshalling json: %s)\n", err) + string(inJSON)
	}
	return out.String()
}

func strDecimal64(d *pb.Decimal64) string {
	var i, frac uint64
	if d.Precision > 0 {
		div := uint64(10)
		it := d.Precision - 1
		for it > 0 {
			div *= 10
			it--
		}
		i = d.Digits / div
		frac = d.Digits % div
	} else {
		i = d.Digits
	}
	return fmt.Sprintf("%d.%d", i, frac)
}

// strLeafList builds a human-readable form of a leaf-list. e.g. [1,2,3] or [a,b,c]
func strLeaflist(v *pb.ScalarArray) string {
	s := make([]string, 0, len(v.Element))
	sz := 2 // []

	// convert arbitrary TypedValues to string form
	for _, elm := range v.Element {
		str := strVal(elm)
		s = append(s, str)
		sz += len(str) + 1 // %v + ,
	}

	b := make([]byte, sz)
	buf := bytes.NewBuffer(b)

	buf.WriteRune('[')
	for i := range v.Element {
		buf.WriteString(s[i])
		if i < len(v.Element)-1 {
			buf.WriteRune(',')
		}
	}
	buf.WriteRune(']')
	return buf.String()
}

func update(p *pb.Path, val string) *pb.Update {
	var v *pb.TypedValue
	switch p.Origin {
	case "":
		v = &pb.TypedValue{
			Value: &pb.TypedValue_JsonIetfVal{JsonIetfVal: extractJSON(val)}}
	case "cli":
		v = &pb.TypedValue{
			Value: &pb.TypedValue_AsciiVal{AsciiVal: val}}
	default:
		panic(fmt.Errorf("unexpected origin: %q", p.Origin))
	}

	return &pb.Update{Path: p, Val: v}
}

// Operation describes an gNMI operation.
type Operation struct {
	Type string
	Path []string
	Val  string
}

func newSetRequest(setOps []*Operation) (*pb.SetRequest, error) {
	req := &pb.SetRequest{}
	for _, op := range setOps {
		p, err := ParseGNMIElements(op.Path)
		if err != nil {
			return nil, err
		}

		switch op.Type {
		case "delete":
			req.Delete = append(req.Delete, p)
		case "update":
			req.Update = append(req.Update, update(p, op.Val))
		case "replace":
			req.Replace = append(req.Replace, update(p, op.Val))
		}
	}
	return req, nil
}

// Set sends a SetRequest to the given client.
func Set(ctx context.Context, client pb.GNMIClient, setOps []*Operation) error {
	req, err := newSetRequest(setOps)
	if err != nil {
		return err
	}
	resp, err := client.Set(ctx, req)
	if err != nil {
		return err
	}
	if resp.Message != nil && codes.Code(resp.Message.Code) != codes.OK {
		return errors.New(resp.Message.Message)
	}
	// TODO: Iterate over SetResponse.Response for more detailed error message?

	return nil
}

// Subscribe sends a SubscribeRequest to the given client.
func Subscribe(ctx context.Context, client pb.GNMIClient, paths [][]string,
	respChan chan<- *pb.SubscribeResponse, errChan chan<- error) {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	stream, err := client.Subscribe(ctx)
	if err != nil {
		errChan <- err
		return
	}
	req, err := NewSubscribeRequest(paths)
	if err != nil {
		errChan <- err
		return
	}
	if err := stream.Send(req); err != nil {
		errChan <- err
		return
	}

	for {
		resp, err := stream.Recv()
		if err != nil {
			if err == io.EOF {
				return
			}
			errChan <- err
			return
		}
		respChan <- resp
	}
}

// LogSubscribeResponse logs update responses to stderr.
func LogSubscribeResponse(response *pb.SubscribeResponse) error {
	switch resp := response.Response.(type) {
	case *pb.SubscribeResponse_Error:
		return errors.New(resp.Error.Message)
	case *pb.SubscribeResponse_SyncResponse:
		if !resp.SyncResponse {
			return errors.New("initial sync failed")
		}
	case *pb.SubscribeResponse_Update:
		prefix := StrPath(resp.Update.Prefix)
		for _, update := range resp.Update.Update {
			fmt.Printf("%s = %s\n", path.Join(prefix, StrPath(update.Path)),
				strUpdateVal(update))
		}
	}
	return nil
}
<commit_msg>gnmi: Pretty-print pre-gnmi v0.4 values<commit_after>// Copyright (c) 2017 Arista Networks, Inc.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the COPYING file.

package gnmi

import (
	"bytes"
	"context"
	"encoding/base64"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"path"
	"strconv"

	pb "github.com/openconfig/gnmi/proto/gnmi"
	"google.golang.org/grpc/codes"
)

// Get sents a GetRequest to the given client.
func Get(ctx context.Context, client pb.GNMIClient, paths [][]string) error {
	req, err := NewGetRequest(paths)
	if err != nil {
		return err
	}
	resp, err := client.Get(ctx, req)
	if err != nil {
		return err
	}
	for _, notif := range resp.Notification {
		for _, update := range notif.Update {
			fmt.Printf("%s:\n", StrPath(update.Path))
			fmt.Println(strUpdateVal(update))
		}
	}
	return nil
}

// Capabilities retuns the capabilities of the client.
func Capabilities(ctx context.Context, client pb.GNMIClient) error {
	resp, err := client.Capabilities(ctx, &pb.CapabilityRequest{})
	if err != nil {
		return err
	}
	fmt.Printf("Version: %s\n", resp.GNMIVersion)
	for _, mod := range resp.SupportedModels {
		fmt.Printf("SupportedModel: %s\n", mod)
	}
	for _, enc := range resp.SupportedEncodings {
		fmt.Printf("SupportedEncoding: %s\n", enc)
	}
	return nil
}

// val may be a path to a file or it may be json. First see if it is a
// file, if so return its contents, otherwise return val
func extractJSON(val string) []byte {
	jsonBytes, err := ioutil.ReadFile(val)
	if err != nil {
		jsonBytes = []byte(val)
	}
	return jsonBytes
}

// strUpdateVal will return a string representing the value within the supplied update
func strUpdateVal(u *pb.Update) string {
	if u.Value != nil {
		// Backwards compatibility with pre-v0.4 gnmi
		switch u.Value.Type {
		case pb.Encoding_JSON, pb.Encoding_JSON_IETF:
			return strJSON(u.Value.Value)
		case pb.Encoding_BYTES, pb.Encoding_PROTO:
			base64.StdEncoding.EncodeToString(u.Value.Value)
		case pb.Encoding_ASCII:
			return string(u.Value.Value)
		default:
			return string(u.Value.Value)
		}
	}
	return strVal(u.Val)
}

// strVal will return a string representing the supplied value
func strVal(val *pb.TypedValue) string {
	switch v := val.GetValue().(type) {
	case *pb.TypedValue_StringVal:
		return v.StringVal
	case *pb.TypedValue_JsonIetfVal:
		return strJSON(v.JsonIetfVal)
	case *pb.TypedValue_JsonVal:
		return strJSON(v.JsonVal)
	case *pb.TypedValue_IntVal:
		return strconv.FormatInt(v.IntVal, 10)
	case *pb.TypedValue_UintVal:
		return strconv.FormatUint(v.UintVal, 10)
	case *pb.TypedValue_BoolVal:
		return strconv.FormatBool(v.BoolVal)
	case *pb.TypedValue_BytesVal:
		return base64.StdEncoding.EncodeToString(v.BytesVal)
	case *pb.TypedValue_DecimalVal:
		return strDecimal64(v.DecimalVal)
	case *pb.TypedValue_FloatVal:
		return strconv.FormatFloat(float64(v.FloatVal), 'g', -1, 32)
	case *pb.TypedValue_LeaflistVal:
		return strLeaflist(v.LeaflistVal)
	case *pb.TypedValue_AsciiVal:
		return v.AsciiVal
	case *pb.TypedValue_AnyVal:
		return v.AnyVal.String()
	default:
		panic(v)
	}
}

func strJSON(inJSON []byte) string {
	var out bytes.Buffer
	err := json.Indent(&out, inJSON, "", "  ")
	if err != nil {
		return fmt.Sprintf("(error unmarshalling json: %s)\n", err) + string(inJSON)
	}
	return out.String()
}

func strDecimal64(d *pb.Decimal64) string {
	var i, frac uint64
	if d.Precision > 0 {
		div := uint64(10)
		it := d.Precision - 1
		for it > 0 {
			div *= 10
			it--
		}
		i = d.Digits / div
		frac = d.Digits % div
	} else {
		i = d.Digits
	}
	return fmt.Sprintf("%d.%d", i, frac)
}

// strLeafList builds a human-readable form of a leaf-list. e.g. [1,2,3] or [a,b,c]
func strLeaflist(v *pb.ScalarArray) string {
	s := make([]string, 0, len(v.Element))
	sz := 2 // []

	// convert arbitrary TypedValues to string form
	for _, elm := range v.Element {
		str := strVal(elm)
		s = append(s, str)
		sz += len(str) + 1 // %v + ,
	}

	b := make([]byte, sz)
	buf := bytes.NewBuffer(b)

	buf.WriteRune('[')
	for i := range v.Element {
		buf.WriteString(s[i])
		if i < len(v.Element)-1 {
			buf.WriteRune(',')
		}
	}
	buf.WriteRune(']')
	return buf.String()
}

func update(p *pb.Path, val string) *pb.Update {
	var v *pb.TypedValue
	switch p.Origin {
	case "":
		v = &pb.TypedValue{
			Value: &pb.TypedValue_JsonIetfVal{JsonIetfVal: extractJSON(val)}}
	case "cli":
		v = &pb.TypedValue{
			Value: &pb.TypedValue_AsciiVal{AsciiVal: val}}
	default:
		panic(fmt.Errorf("unexpected origin: %q", p.Origin))
	}

	return &pb.Update{Path: p, Val: v}
}

// Operation describes an gNMI operation.
type Operation struct {
	Type string
	Path []string
	Val  string
}

func newSetRequest(setOps []*Operation) (*pb.SetRequest, error) {
	req := &pb.SetRequest{}
	for _, op := range setOps {
		p, err := ParseGNMIElements(op.Path)
		if err != nil {
			return nil, err
		}

		switch op.Type {
		case "delete":
			req.Delete = append(req.Delete, p)
		case "update":
			req.Update = append(req.Update, update(p, op.Val))
		case "replace":
			req.Replace = append(req.Replace, update(p, op.Val))
		}
	}
	return req, nil
}

// Set sends a SetRequest to the given client.
func Set(ctx context.Context, client pb.GNMIClient, setOps []*Operation) error {
	req, err := newSetRequest(setOps)
	if err != nil {
		return err
	}
	resp, err := client.Set(ctx, req)
	if err != nil {
		return err
	}
	if resp.Message != nil && codes.Code(resp.Message.Code) != codes.OK {
		return errors.New(resp.Message.Message)
	}
	// TODO: Iterate over SetResponse.Response for more detailed error message?

	return nil
}

// Subscribe sends a SubscribeRequest to the given client.
func Subscribe(ctx context.Context, client pb.GNMIClient, paths [][]string,
	respChan chan<- *pb.SubscribeResponse, errChan chan<- error) {
	ctx, cancel := context.WithCancel(ctx)
	defer cancel()
	stream, err := client.Subscribe(ctx)
	if err != nil {
		errChan <- err
		return
	}
	req, err := NewSubscribeRequest(paths)
	if err != nil {
		errChan <- err
		return
	}
	if err := stream.Send(req); err != nil {
		errChan <- err
		return
	}

	for {
		resp, err := stream.Recv()
		if err != nil {
			if err == io.EOF {
				return
			}
			errChan <- err
			return
		}
		respChan <- resp
	}
}

// LogSubscribeResponse logs update responses to stderr.
func LogSubscribeResponse(response *pb.SubscribeResponse) error {
	switch resp := response.Response.(type) {
	case *pb.SubscribeResponse_Error:
		return errors.New(resp.Error.Message)
	case *pb.SubscribeResponse_SyncResponse:
		if !resp.SyncResponse {
			return errors.New("initial sync failed")
		}
	case *pb.SubscribeResponse_Update:
		prefix := StrPath(resp.Update.Prefix)
		for _, update := range resp.Update.Update {
			fmt.Printf("%s = %s\n", path.Join(prefix, StrPath(update.Path)),
				strUpdateVal(update))
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package fs

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

var ErrSpaceNotEnough = fmt.Errorf("buffer space is not enough")

type Cobuffer struct {
	buffer        []byte
	offset        int32
	rw            sync.RWMutex
	maxSize       int
	flushChan     chan struct{}
	flushChanSent int32
	wantFlushTime time.Time

	writeChan     chan struct{}
	writeChanSent int32
	writeTime     time.Time
	waiter        sync.WaitGroup
}

func NewCobuffer(n int, maxSize int) *Cobuffer {
	return &Cobuffer{
		buffer:    make([]byte, n),
		maxSize:   maxSize,
		flushChan: make(chan struct{}, 1),
		writeChan: make(chan struct{}, 1),
	}
}

func (c *Cobuffer) isWantFlush() bool {
	return atomic.LoadInt32(&c.flushChanSent) == 1
}

func (c *Cobuffer) grow() bool {
	success := false
	c.rw.Lock()
	if len(c.buffer) >= c.maxSize {
		goto exit
	}
	c.buffer = append(c.buffer, 0)
	c.buffer = c.buffer[:cap(c.buffer)]
	success = true

exit:
	c.rw.Unlock()
	return success
}

func (c *Cobuffer) Flush() {
	if !atomic.CompareAndSwapInt32(&c.flushChanSent, 0, 1) {
		return
	}
	c.wantFlushTime = time.Now()
	select {
	case c.flushChan <- struct{}{}:
	default:
	}
	c.waiter.Add(1)
}

func (c *Cobuffer) IsWritten() <-chan struct{} {
	return c.writeChan
}

func (c *Cobuffer) IsFlush() <-chan struct{} {
	return c.flushChan
}

func (c *Cobuffer) GetData(buffer []byte) int {
	now := time.Now()
	c.rw.Lock()
	Stat.Cobuffer.GetDataLock.AddNow(now)
	now = time.Now()
	n := int(c.offset)
	if len(buffer) < n {
		c.rw.Unlock()
		return n
	}

	copy(buffer[:n], c.buffer)
	c.offset = 0

	Stat.Cobuffer.GetData.AddNow(now)
	Stat.Cobuffer.FlushDelay.AddNow(c.wantFlushTime)
	c.wantFlushTime = time.Now()

	atomic.StoreInt32(&c.writeChanSent, 0)
	if atomic.SwapInt32(&c.flushChanSent, 0) == 1 {
		c.waiter.Done()
	}
	c.rw.Unlock()
	return n
}

func (c *Cobuffer) WriteData(b []byte) {
	tryTime := 0
	for {
		if c.writeData(b) {
			Stat.Cobuffer.Trytime.HitN(tryTime)
			return
		}
		tryTime++
		if !c.grow() {
			c.Flush()
			c.waiter.Wait()
		}
	}
}

func (c *Cobuffer) writeData(b []byte) bool {
	success := false
	now := time.Now()

	c.rw.RLock()

	newOff := atomic.AddInt32(&c.offset, int32(len(b)))
	if newOff >= int32(len(c.buffer)) {
		atomic.AddInt32(&c.offset, -int32(len(b)))
		goto exit
	}

	copy(c.buffer[newOff-int32(len(b)):newOff], b)
	success = true

	if atomic.CompareAndSwapInt32(&c.writeChanSent, 0, 1) {
		c.writeTime = time.Now()
		select {
		case c.writeChan <- struct{}{}:
		default:
		}
	}

	if int(newOff) > c.maxSize/2 {
		if !c.isWantFlush() {
			Stat.Cobuffer.NotifyFlushByWrite.Hit()
			Stat.Cobuffer.FullTime.AddNow(c.writeTime)
		}
		c.Flush()
	} else {
		Stat.Cobuffer.NotifyFlushByWrite.Miss()
	}

exit:
	c.rw.RUnlock()
	Stat.Cobuffer.WriteTime.AddNow(now)
	return success
}

func (c *Cobuffer) Close() {
	close(c.flushChan)
	close(c.writeChan)
}
<commit_msg>[fs] cobuffer: remote all goto/label<commit_after>package fs

import (
	"fmt"
	"sync"
	"sync/atomic"
	"time"
)

var ErrSpaceNotEnough = fmt.Errorf("buffer space is not enough")

type Cobuffer struct {
	buffer        []byte
	offset        int32
	rw            sync.RWMutex
	maxSize       int
	flushChan     chan struct{}
	flushChanSent int32
	wantFlushTime time.Time

	writeChan     chan struct{}
	writeChanSent int32
	writeTime     time.Time
	waiter        sync.WaitGroup
}

func NewCobuffer(n int, maxSize int) *Cobuffer {
	return &Cobuffer{
		buffer:    make([]byte, n),
		maxSize:   maxSize,
		flushChan: make(chan struct{}, 1),
		writeChan: make(chan struct{}, 1),
	}
}

func (c *Cobuffer) isWantFlush() bool {
	return atomic.LoadInt32(&c.flushChanSent) == 1
}

func (c *Cobuffer) grow() bool {
	if c.isWantFlush() {
		return false
	}

	c.rw.Lock()
	if len(c.buffer) >= c.maxSize {
		c.rw.Unlock()
		return false
	}
	c.buffer = append(c.buffer, 0)
	c.buffer = c.buffer[:cap(c.buffer)]
	c.rw.Unlock()
	return true
}

func (c *Cobuffer) Flush() {
	if !atomic.CompareAndSwapInt32(&c.flushChanSent, 0, 1) {
		return
	}
	c.wantFlushTime = time.Now()
	select {
	case c.flushChan <- struct{}{}:
	default:
	}
	c.waiter.Add(1)
}

func (c *Cobuffer) IsWritten() <-chan struct{} {
	return c.writeChan
}

func (c *Cobuffer) IsFlush() <-chan struct{} {
	return c.flushChan
}

func (c *Cobuffer) GetData(buffer []byte) int {
	now := time.Now()
	c.rw.Lock()
	Stat.Cobuffer.GetData.Lock.AddNow(now)
	n := int(c.offset)
	if len(buffer) < n {
		c.rw.Unlock()
		return n
	}

	now = time.Now()
	copy(buffer[:n], c.buffer)
	c.offset = 0
	Stat.Cobuffer.GetData.Copy.AddNow(now)
	Stat.Cobuffer.GetData.Size.Add(int64(n))

	Stat.Cobuffer.FlushDelay.AddNow(c.wantFlushTime)
	c.wantFlushTime = time.Now()

	atomic.StoreInt32(&c.writeChanSent, 0)
	if atomic.SwapInt32(&c.flushChanSent, 0) == 1 {
		c.waiter.Done()
	}
	c.rw.Unlock()
	return n
}

func (c *Cobuffer) WriteData(b []byte) {
	tryTime := 0
	for {
		if c.writeData(b) {
			Stat.Cobuffer.Trytime.HitN(tryTime)
			return
		}
		tryTime++
		if !c.grow() {
			c.Flush()
			c.waiter.Wait()
		}
	}
}

func (c *Cobuffer) writeData(b []byte) bool {
	if c.isWantFlush() {
		return false
	}

	now := time.Now()

	c.rw.RLock()

	newOff := atomic.AddInt32(&c.offset, int32(len(b)))
	if newOff >= int32(len(c.buffer)) {
		atomic.AddInt32(&c.offset, -int32(len(b)))
		c.rw.RUnlock()
		return false
	}

	copy(c.buffer[newOff-int32(len(b)):newOff], b)

	if atomic.CompareAndSwapInt32(&c.writeChanSent, 0, 1) {
		c.writeTime = time.Now()
		select {
		case c.writeChan <- struct{}{}:
		default:
		}
	}

	if int(newOff) > c.maxSize/2 {
		if !c.isWantFlush() {
			Stat.Cobuffer.NotifyFlushByWrite.Hit()
			Stat.Cobuffer.FullTime.AddNow(c.writeTime)
		}
		c.Flush()
	} else {
		Stat.Cobuffer.NotifyFlushByWrite.Miss()
	}

	c.rw.RUnlock()
	Stat.Cobuffer.WriteTime.AddNow(now)
	return true
}

func (c *Cobuffer) Close() {
	close(c.flushChan)
	close(c.writeChan)
}
<|endoftext|>


<commit_before>// Copyright 2013 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.

//go:build darwin || dragonfly || freebsd || netbsd || openbsd

package runtime

// Integrated network poller (kqueue-based implementation).

import (
	"runtime/internal/atomic"
	"unsafe"
)

var (
	kq int32 = -1

	netpollBreakRd, netpollBreakWr uintptr // for netpollBreak

	netpollWakeSig uint32 // used to avoid duplicate calls of netpollBreak
)

func netpollinit() {
	kq = kqueue()
	if kq < 0 {
		println("runtime: kqueue failed with", -kq)
		throw("runtime: netpollinit failed")
	}
	closeonexec(kq)
	r, w, errno := nonblockingPipe()
	if errno != 0 {
		println("runtime: pipe failed with", -errno)
		throw("runtime: pipe failed")
	}
	ev := keventt{
		filter: _EVFILT_READ,
		flags:  _EV_ADD,
	}
	*(*uintptr)(unsafe.Pointer(&ev.ident)) = uintptr(r)
	n := kevent(kq, &ev, 1, nil, 0, nil)
	if n < 0 {
		println("runtime: kevent failed with", -n)
		throw("runtime: kevent failed")
	}
	netpollBreakRd = uintptr(r)
	netpollBreakWr = uintptr(w)
}

func netpollIsPollDescriptor(fd uintptr) bool {
	return fd == uintptr(kq) || fd == netpollBreakRd || fd == netpollBreakWr
}

func netpollopen(fd uintptr, pd *pollDesc) int32 {
	// Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
	// for the whole fd lifetime. The notifications are automatically unregistered
	// when fd is closed.
	var ev [2]keventt
	*(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd
	ev[0].filter = _EVFILT_READ
	ev[0].flags = _EV_ADD | _EV_CLEAR
	ev[0].fflags = 0
	ev[0].data = 0
	ev[0].udata = (*byte)(unsafe.Pointer(pd))
	ev[1] = ev[0]
	ev[1].filter = _EVFILT_WRITE
	n := kevent(kq, &ev[0], 2, nil, 0, nil)
	if n < 0 {
		return -n
	}
	return 0
}

func netpollclose(fd uintptr) int32 {
	// Don't need to unregister because calling close()
	// on fd will remove any kevents that reference the descriptor.
	return 0
}

func netpollarm(pd *pollDesc, mode int) {
	throw("runtime: unused")
}

// netpollBreak interrupts a kevent.
func netpollBreak() {
	// Failing to cas indicates there is an in-flight wakeup, so we're done here.
	if !atomic.Cas(&netpollWakeSig, 0, 1) {
		return
	}

	for {
		var b byte
		n := write(netpollBreakWr, unsafe.Pointer(&b), 1)
		if n == 1 || n == -_EAGAIN {
			break
		}
		if n == -_EINTR {
			continue
		}
		println("runtime: netpollBreak write failed with", -n)
		throw("runtime: netpollBreak write failed")
	}
}

// netpoll checks for ready network connections.
// Returns list of goroutines that become runnable.
// delay < 0: blocks indefinitely
// delay == 0: does not block, just polls
// delay > 0: block for up to that many nanoseconds
func netpoll(delay int64) gList {
	if kq == -1 {
		return gList{}
	}
	var tp *timespec
	var ts timespec
	if delay < 0 {
		tp = nil
	} else if delay == 0 {
		tp = &ts
	} else {
		ts.setNsec(delay)
		if ts.tv_sec > 1e6 {
			// Darwin returns EINVAL if the sleep time is too long.
			ts.tv_sec = 1e6
		}
		tp = &ts
	}
	var events [64]keventt
retry:
	n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp)
	if n < 0 {
		if n != -_EINTR {
			println("runtime: kevent on fd", kq, "failed with", -n)
			throw("runtime: netpoll failed")
		}
		// If a timed sleep was interrupted, just return to
		// recalculate how long we should sleep now.
		if delay > 0 {
			return gList{}
		}
		goto retry
	}
	var toRun gList
	for i := 0; i < int(n); i++ {
		ev := &events[i]

		if uintptr(ev.ident) == netpollBreakRd {
			if ev.filter != _EVFILT_READ {
				println("runtime: netpoll: break fd ready for", ev.filter)
				throw("runtime: netpoll: break fd ready for something unexpected")
			}
			if delay != 0 {
				// netpollBreak could be picked up by a
				// nonblocking poll. Only read the byte
				// if blocking.
				var tmp [16]byte
				read(int32(netpollBreakRd), noescape(unsafe.Pointer(&tmp[0])), int32(len(tmp)))
				atomic.Store(&netpollWakeSig, 0)
			}
			continue
		}

		var mode int32
		switch ev.filter {
		case _EVFILT_READ:
			mode += 'r'

			// On some systems when the read end of a pipe
			// is closed the write end will not get a
			// _EVFILT_WRITE event, but will get a
			// _EVFILT_READ event with EV_EOF set.
			// Note that setting 'w' here just means that we
			// will wake up a goroutine waiting to write;
			// that goroutine will try the write again,
			// and the appropriate thing will happen based
			// on what that write returns (success, EPIPE, EAGAIN).
			if ev.flags&_EV_EOF != 0 {
				mode += 'w'
			}
		case _EVFILT_WRITE:
			mode += 'w'
		}
		if mode != 0 {
			pd := (*pollDesc)(unsafe.Pointer(ev.udata))
			pd.setEventErr(ev.flags == _EV_ERROR)
			netpollready(&toRun, pd, mode)
		}
	}
	return toRun
}
<commit_msg>runtime: convert kqueue netpollWakeSig to atomic type<commit_after>// Copyright 2013 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.

//go:build darwin || dragonfly || freebsd || netbsd || openbsd

package runtime

// Integrated network poller (kqueue-based implementation).

import (
	"runtime/internal/atomic"
	"unsafe"
)

var (
	kq int32 = -1

	netpollBreakRd, netpollBreakWr uintptr // for netpollBreak

	netpollWakeSig atomic.Uint32 // used to avoid duplicate calls of netpollBreak
)

func netpollinit() {
	kq = kqueue()
	if kq < 0 {
		println("runtime: kqueue failed with", -kq)
		throw("runtime: netpollinit failed")
	}
	closeonexec(kq)
	r, w, errno := nonblockingPipe()
	if errno != 0 {
		println("runtime: pipe failed with", -errno)
		throw("runtime: pipe failed")
	}
	ev := keventt{
		filter: _EVFILT_READ,
		flags:  _EV_ADD,
	}
	*(*uintptr)(unsafe.Pointer(&ev.ident)) = uintptr(r)
	n := kevent(kq, &ev, 1, nil, 0, nil)
	if n < 0 {
		println("runtime: kevent failed with", -n)
		throw("runtime: kevent failed")
	}
	netpollBreakRd = uintptr(r)
	netpollBreakWr = uintptr(w)
}

func netpollIsPollDescriptor(fd uintptr) bool {
	return fd == uintptr(kq) || fd == netpollBreakRd || fd == netpollBreakWr
}

func netpollopen(fd uintptr, pd *pollDesc) int32 {
	// Arm both EVFILT_READ and EVFILT_WRITE in edge-triggered mode (EV_CLEAR)
	// for the whole fd lifetime. The notifications are automatically unregistered
	// when fd is closed.
	var ev [2]keventt
	*(*uintptr)(unsafe.Pointer(&ev[0].ident)) = fd
	ev[0].filter = _EVFILT_READ
	ev[0].flags = _EV_ADD | _EV_CLEAR
	ev[0].fflags = 0
	ev[0].data = 0
	ev[0].udata = (*byte)(unsafe.Pointer(pd))
	ev[1] = ev[0]
	ev[1].filter = _EVFILT_WRITE
	n := kevent(kq, &ev[0], 2, nil, 0, nil)
	if n < 0 {
		return -n
	}
	return 0
}

func netpollclose(fd uintptr) int32 {
	// Don't need to unregister because calling close()
	// on fd will remove any kevents that reference the descriptor.
	return 0
}

func netpollarm(pd *pollDesc, mode int) {
	throw("runtime: unused")
}

// netpollBreak interrupts a kevent.
func netpollBreak() {
	// Failing to cas indicates there is an in-flight wakeup, so we're done here.
	if !netpollWakeSig.CompareAndSwap(0, 1) {
		return
	}

	for {
		var b byte
		n := write(netpollBreakWr, unsafe.Pointer(&b), 1)
		if n == 1 || n == -_EAGAIN {
			break
		}
		if n == -_EINTR {
			continue
		}
		println("runtime: netpollBreak write failed with", -n)
		throw("runtime: netpollBreak write failed")
	}
}

// netpoll checks for ready network connections.
// Returns list of goroutines that become runnable.
// delay < 0: blocks indefinitely
// delay == 0: does not block, just polls
// delay > 0: block for up to that many nanoseconds
func netpoll(delay int64) gList {
	if kq == -1 {
		return gList{}
	}
	var tp *timespec
	var ts timespec
	if delay < 0 {
		tp = nil
	} else if delay == 0 {
		tp = &ts
	} else {
		ts.setNsec(delay)
		if ts.tv_sec > 1e6 {
			// Darwin returns EINVAL if the sleep time is too long.
			ts.tv_sec = 1e6
		}
		tp = &ts
	}
	var events [64]keventt
retry:
	n := kevent(kq, nil, 0, &events[0], int32(len(events)), tp)
	if n < 0 {
		if n != -_EINTR {
			println("runtime: kevent on fd", kq, "failed with", -n)
			throw("runtime: netpoll failed")
		}
		// If a timed sleep was interrupted, just return to
		// recalculate how long we should sleep now.
		if delay > 0 {
			return gList{}
		}
		goto retry
	}
	var toRun gList
	for i := 0; i < int(n); i++ {
		ev := &events[i]

		if uintptr(ev.ident) == netpollBreakRd {
			if ev.filter != _EVFILT_READ {
				println("runtime: netpoll: break fd ready for", ev.filter)
				throw("runtime: netpoll: break fd ready for something unexpected")
			}
			if delay != 0 {
				// netpollBreak could be picked up by a
				// nonblocking poll. Only read the byte
				// if blocking.
				var tmp [16]byte
				read(int32(netpollBreakRd), noescape(unsafe.Pointer(&tmp[0])), int32(len(tmp)))
				netpollWakeSig.Store(0)
			}
			continue
		}

		var mode int32
		switch ev.filter {
		case _EVFILT_READ:
			mode += 'r'

			// On some systems when the read end of a pipe
			// is closed the write end will not get a
			// _EVFILT_WRITE event, but will get a
			// _EVFILT_READ event with EV_EOF set.
			// Note that setting 'w' here just means that we
			// will wake up a goroutine waiting to write;
			// that goroutine will try the write again,
			// and the appropriate thing will happen based
			// on what that write returns (success, EPIPE, EAGAIN).
			if ev.flags&_EV_EOF != 0 {
				mode += 'w'
			}
		case _EVFILT_WRITE:
			mode += 'w'
		}
		if mode != 0 {
			pd := (*pollDesc)(unsafe.Pointer(ev.udata))
			pd.setEventErr(ev.flags == _EV_ERROR)
			netpollready(&toRun, pd, mode)
		}
	}
	return toRun
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Matthew Collins
 *
 * 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 thinkbot

type Event interface{}

type Stop struct{}

type Connected struct{}<commit_msg>/: go fmt<commit_after>/*
 * Copyright 2015 Matthew Collins
 *
 * 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 thinkbot

type Event interface{}

type Stop struct{}

type Connected struct{}
<|endoftext|>


<commit_before>package main

/**
 * Disk Usage
 */

import (
	"fmt"
	"log"
	"sort"
	"syscall"
	"time"

	linuxproc "github.com/c9s/goprocinfo/linux"
	ui "github.com/gizak/termui"
	set "gopkg.in/fatih/set.v0"
)

////////////////////////////////////////////
// Utility: Disk Usage
////////////////////////////////////////////

type DiskUsage struct {
	MountPoint           string
	FSType               string
	TotalSizeInBytes     uint64
	AvailableSizeInBytes uint64
	FreePercentage       float64
	InodesInUse          uint64
	TotalInodes          uint64
	FreeInodesPercentage float64
}

var IgnoreFilesystemTypes = set.New(
	"sysfs", "proc", "udev", "devpts", "tmpfs", "cgroup", "systemd-1",
	"mqueue", "debugfs", "hugetlbfs", "fusectl", "tracefs", "binfmt_misc",
	"devtmpfs", "securityfs", "pstore", "autofs", "fuse.jetbrains-toolbox",
	"fuse.gvfsd-fuse", "fuse.lxcfs")

func loadDiskUsage() map[string]DiskUsage {
	diskUsageData := make(map[string]DiskUsage, 0)

	// Load mount points
	mounts, mountsErr := linuxproc.ReadMounts("/proc/mounts")

	if mountsErr != nil {
		log.Printf("Error loading mounts: %v", mountsErr)
	} else {
		for _, mnt := range mounts.Mounts {

			if IgnoreFilesystemTypes.Has(mnt.FSType) {
				// Skip it
				continue
			}

			// Also skip these docker fs, since it's a dup of root
			if "/var/lib/docker/aufs" == mnt.MountPoint || "/var/lib/docker/devicemapper" == mnt.MountPoint {
				// Skip it
				continue
			}

			statfs := syscall.Statfs_t{}
			statErr := syscall.Statfs(mnt.MountPoint, &statfs)

			if statErr != nil {
				log.Printf("Error statfs-ing mount: %v", mnt.MountPoint)
			} else {
				var totalBytes uint64 = 0
				var availBytes uint64 = 0
				var bytesFreePercent float64 = 0
				var totalInodes uint64 = 0
				var freeInodes uint64 = 0
				var inodesFreePercent float64 = 0

				var blocksize uint64 = 0
				if statfs.Bsize > 0 {
					blocksize = uint64(statfs.Bsize)
				} else {
					blocksize = 1 // bad guess
					log.Printf("Bad block size: %v", statfs.Bsize)
				}

				totalBytes = statfs.Blocks * blocksize
				availBytes = statfs.Bavail * blocksize
				if totalBytes > 0 {
					bytesFreePercent = float64(availBytes) / float64(totalBytes)
				} else {
					log.Printf("Bad total bytes: %v", totalBytes)
				}

				totalInodes = statfs.Files
				freeInodes = statfs.Ffree
				if totalInodes > 0 {
					inodesFreePercent = float64(freeInodes) / float64(totalInodes)
				} else {
					log.Printf("Bad total inodes: %v", totalInodes)
				}

				usage := DiskUsage{
					MountPoint:           mnt.MountPoint,
					FSType:               mnt.FSType,
					TotalSizeInBytes:     totalBytes,
					AvailableSizeInBytes: availBytes,
					FreePercentage:       bytesFreePercent,
					TotalInodes:          totalInodes,
					InodesInUse:          totalInodes - freeInodes,
					FreeInodesPercentage: inodesFreePercent,
				}

				diskUsageData[mnt.MountPoint] = usage
			}
		}
	}

	return diskUsageData
}

const DiskUsageUpdateInterval = 30 * time.Second

type CachedDiskUsage struct {
	LastUsage   map[string]DiskUsage
	lastUpdated *time.Time
}

func (w *CachedDiskUsage) getUpdateInterval() time.Duration {
	return DiskUsageUpdateInterval
}

func (w *CachedDiskUsage) getLastUpdated() *time.Time {
	return w.lastUpdated
}

func (w *CachedDiskUsage) setLastUpdated(t time.Time) {
	w.lastUpdated = &t
}

func (w *CachedDiskUsage) update() {
	if shouldUpdate(w) {
		w.LastUsage = loadDiskUsage()
	}
}

func NewCachedDiskUsage() *CachedDiskUsage {
	// Build it
	w := &CachedDiskUsage{}

	w.update()

	return w
}

var cachedDiskUsage = NewCachedDiskUsage()

////////////////////////////////////////////
// Widget: Disk
////////////////////////////////////////////

const DiskHeaderText = "--- Disks ---"

type DiskColumn struct {
	column  *ui.Row
	header  *ui.Par
	widgets []*ui.Gauge
}

func NewDiskColumn(span int, offset int) *DiskColumn {
	c := ui.NewCol(span, offset)

	h := ui.NewPar(DiskHeaderText)
	h.Border = false
	h.TextFgColor = ui.ColorGreen
	h.Height = 1

	column := &DiskColumn{
		column:  c,
		header:  h,
		widgets: make([]*ui.Gauge, 0),
	}

	column.update()

	return column
}

func (w *DiskColumn) getGridWidget() ui.GridBufferer {
	return w.column
}

func (w *DiskColumn) getColumn() *ui.Row {
	return w.column
}

func (w *DiskColumn) update() {
	w.header.Text = centerString(w.header.Width, DiskHeaderText)
	//w.header.Text = DiskHeaderText

	gauges := make([]*ui.Gauge, 0)

	for _, d := range cachedDiskUsage.LastUsage {
		gauges = append(gauges, NewDiskGauge(d))
	}

	sort.Sort(ByMountPoint(gauges))

	w.column.Cols = []*ui.Row{}
	ir := w.column

	for _, widget := range gauges {
		nr := &ui.Row{Span: 12, Widget: widget}
		ir.Cols = []*ui.Row{nr}
		ir = nr
	}
}

func (w *DiskColumn) resize() {
	// Do nothing
}

func NewDiskGauge(usage DiskUsage) *ui.Gauge {
	free := int(100 * usage.FreePercentage)
	g := ui.NewGauge()
	g.BorderLabel = usage.MountPoint
	g.Height = 3
	g.Percent = free
	g.Label = fmt.Sprintf("Free: %s/%s (%d%%)",
		prettyPrintBytes(usage.AvailableSizeInBytes), prettyPrintBytes(usage.TotalSizeInBytes), free)
	g.PercentColor = ui.ColorWhite | ui.AttrBold

	g.BarColor = percentToAttribute(free, 0, 100, false)

	return g
}

type ByMountPoint []*ui.Gauge

func (a ByMountPoint) Len() int           { return len(a) }
func (a ByMountPoint) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByMountPoint) Less(i, j int) bool { return a[i].BorderLabel < a[j].BorderLabel }
<commit_msg>Updating to new set version for some dumb reason.<commit_after>package main

/**
 * Disk Usage
 */

import (
	"fmt"
	"log"
	"sort"
	"syscall"
	"time"

	linuxproc "github.com/c9s/goprocinfo/linux"
	ui "github.com/gizak/termui"
	set "github.com/fatih/set"
)

////////////////////////////////////////////
// Utility: Disk Usage
////////////////////////////////////////////

type DiskUsage struct {
	MountPoint           string
	FSType               string
	TotalSizeInBytes     uint64
	AvailableSizeInBytes uint64
	FreePercentage       float64
	InodesInUse          uint64
	TotalInodes          uint64
	FreeInodesPercentage float64
}

var IgnoreFilesystemTypes = buildIgnoreSet()

func buildIgnoreSet() set.Interface{
    ignore := set.New(set.NonThreadSafe)
    ignore.Add("sysfs", "proc", "udev", "devpts", "tmpfs", "cgroup", "systemd-1",
	"mqueue", "debugfs", "hugetlbfs", "fusectl", "tracefs", "binfmt_misc",
	"devtmpfs", "securityfs", "pstore", "autofs", "fuse.jetbrains-toolbox",
	"fuse.gvfsd-fuse", "fuse.lxcfs")
    return ignore
}

func loadDiskUsage() map[string]DiskUsage {
	diskUsageData := make(map[string]DiskUsage, 0)

	// Load mount points
	mounts, mountsErr := linuxproc.ReadMounts("/proc/mounts")

	if mountsErr != nil {
		log.Printf("Error loading mounts: %v", mountsErr)
	} else {
		for _, mnt := range mounts.Mounts {

			if IgnoreFilesystemTypes.Has(mnt.FSType) {
				// Skip it
				continue
			}

			// Also skip these docker fs, since it's a dup of root
			if "/var/lib/docker/aufs" == mnt.MountPoint || "/var/lib/docker/devicemapper" == mnt.MountPoint {
				// Skip it
				continue
			}

			statfs := syscall.Statfs_t{}
			statErr := syscall.Statfs(mnt.MountPoint, &statfs)

			if statErr != nil {
				log.Printf("Error statfs-ing mount: %v", mnt.MountPoint)
			} else {
				var totalBytes uint64 = 0
				var availBytes uint64 = 0
				var bytesFreePercent float64 = 0
				var totalInodes uint64 = 0
				var freeInodes uint64 = 0
				var inodesFreePercent float64 = 0

				var blocksize uint64 = 0
				if statfs.Bsize > 0 {
					blocksize = uint64(statfs.Bsize)
				} else {
					blocksize = 1 // bad guess
					log.Printf("Bad block size: %v", statfs.Bsize)
				}

				totalBytes = statfs.Blocks * blocksize
				availBytes = statfs.Bavail * blocksize
				if totalBytes > 0 {
					bytesFreePercent = float64(availBytes) / float64(totalBytes)
				} else {
					log.Printf("Bad total bytes: %v", totalBytes)
				}

				totalInodes = statfs.Files
				freeInodes = statfs.Ffree
				if totalInodes > 0 {
					inodesFreePercent = float64(freeInodes) / float64(totalInodes)
				} else {
					log.Printf("Bad total inodes: %v", totalInodes)
				}

				usage := DiskUsage{
					MountPoint:           mnt.MountPoint,
					FSType:               mnt.FSType,
					TotalSizeInBytes:     totalBytes,
					AvailableSizeInBytes: availBytes,
					FreePercentage:       bytesFreePercent,
					TotalInodes:          totalInodes,
					InodesInUse:          totalInodes - freeInodes,
					FreeInodesPercentage: inodesFreePercent,
				}

				diskUsageData[mnt.MountPoint] = usage
			}
		}
	}

	return diskUsageData
}

const DiskUsageUpdateInterval = 30 * time.Second

type CachedDiskUsage struct {
	LastUsage   map[string]DiskUsage
	lastUpdated *time.Time
}

func (w *CachedDiskUsage) getUpdateInterval() time.Duration {
	return DiskUsageUpdateInterval
}

func (w *CachedDiskUsage) getLastUpdated() *time.Time {
	return w.lastUpdated
}

func (w *CachedDiskUsage) setLastUpdated(t time.Time) {
	w.lastUpdated = &t
}

func (w *CachedDiskUsage) update() {
	if shouldUpdate(w) {
		w.LastUsage = loadDiskUsage()
	}
}

func NewCachedDiskUsage() *CachedDiskUsage {
	// Build it
	w := &CachedDiskUsage{}

	w.update()

	return w
}

var cachedDiskUsage = NewCachedDiskUsage()

////////////////////////////////////////////
// Widget: Disk
////////////////////////////////////////////

const DiskHeaderText = "--- Disks ---"

type DiskColumn struct {
	column  *ui.Row
	header  *ui.Par
	widgets []*ui.Gauge
}

func NewDiskColumn(span int, offset int) *DiskColumn {
	c := ui.NewCol(span, offset)

	h := ui.NewPar(DiskHeaderText)
	h.Border = false
	h.TextFgColor = ui.ColorGreen
	h.Height = 1

	column := &DiskColumn{
		column:  c,
		header:  h,
		widgets: make([]*ui.Gauge, 0),
	}

	column.update()

	return column
}

func (w *DiskColumn) getGridWidget() ui.GridBufferer {
	return w.column
}

func (w *DiskColumn) getColumn() *ui.Row {
	return w.column
}

func (w *DiskColumn) update() {
	w.header.Text = centerString(w.header.Width, DiskHeaderText)
	//w.header.Text = DiskHeaderText

	gauges := make([]*ui.Gauge, 0)

	for _, d := range cachedDiskUsage.LastUsage {
		gauges = append(gauges, NewDiskGauge(d))
	}

	sort.Sort(ByMountPoint(gauges))

	w.column.Cols = []*ui.Row{}
	ir := w.column

	for _, widget := range gauges {
		nr := &ui.Row{Span: 12, Widget: widget}
		ir.Cols = []*ui.Row{nr}
		ir = nr
	}
}

func (w *DiskColumn) resize() {
	// Do nothing
}

func NewDiskGauge(usage DiskUsage) *ui.Gauge {
	free := int(100 * usage.FreePercentage)
	g := ui.NewGauge()
	g.BorderLabel = usage.MountPoint
	g.Height = 3
	g.Percent = free
	g.Label = fmt.Sprintf("Free: %s/%s (%d%%)",
		prettyPrintBytes(usage.AvailableSizeInBytes), prettyPrintBytes(usage.TotalSizeInBytes), free)
	g.PercentColor = ui.ColorWhite | ui.AttrBold

	g.BarColor = percentToAttribute(free, 0, 100, false)

	return g
}

type ByMountPoint []*ui.Gauge

func (a ByMountPoint) Len() int           { return len(a) }
func (a ByMountPoint) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a ByMountPoint) Less(i, j int) bool { return a[i].BorderLabel < a[j].BorderLabel }
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"
	"path"
)

func NewTempEditBuffer(gs *GlobalState, prefix string) *EditBuffer {
	// TODO: this.
	e := NewEditBuffer(gs, prefix)
	e.temp = true
	return e
}

func OpenBuffer(gs *GlobalState, pathname string) (Buffer, os.Error) {
	wd, e := os.Getwd()
	if e != nil {
		return nil, e
	}
	if !path.IsAbs(pathname) {
		pathname = path.Join(wd, pathname)
	}

	f, e := os.Open(pathname)
	if st, e := f.Stat(); e == nil {
		if st.IsRegular() {
			eb := NewEditBuffer(gs, pathname)
			if _, e = eb.readFile(f, 0); e == nil {
				return eb, nil
			}
		} else if st.IsDirectory() {
			eb := NewDirBuffer(gs, pathname)
			return eb, nil
		} else {
			e = &DviError{fmt.Sprintf("%s: can't deal with this filetype", pathname)}
		}
	}
	return nil, e
}
<commit_msg>close file in openbuffer<commit_after>package main

import (
	"fmt"
	"os"
	"path"
)

func NewTempEditBuffer(gs *GlobalState, prefix string) *EditBuffer {
	// TODO: this.
	e := NewEditBuffer(gs, prefix)
	e.temp = true
	return e
}

func OpenBuffer(gs *GlobalState, pathname string) (Buffer, os.Error) {
	wd, e := os.Getwd()
	if e != nil {
		return nil, e
	}
	if !path.IsAbs(pathname) {
		pathname = path.Join(wd, pathname)
	}

	f, e := os.Open(pathname)
	if e != nil {
		return nil, e
	}
	defer f.Close()

	if st, e := f.Stat(); e == nil {
		if st.IsRegular() {
			eb := NewEditBuffer(gs, pathname)
			if _, e = eb.readFile(f, 0); e == nil {
				return eb, nil
			}
		} else if st.IsDirectory() {
			eb := NewDirBuffer(gs, pathname)
			return eb, nil
		} else {
			e = &DviError{fmt.Sprintf("%s: can't deal with this filetype", pathname)}
		}
	}
	return nil, e
}
<|endoftext|>


<commit_before>package sol

import (
	"fmt"

	"github.com/aodin/sol/dialect"
)

// DropStmt is the internal representation of an DROP TABLE statement.
type DropStmt struct {
	table    *TableElem
	ifExists bool
}

// IfExists adds the IF EXISTS modifier to a DROP TABLE statement.
func (stmt DropStmt) IfExists() DropStmt {
	stmt.ifExists = true
	return stmt
}

// String outputs the parameter-less CREATE TABLE statement in a neutral
// dialect.
func (stmt DropStmt) String() string {
	c, _ := stmt.Compile(&defaultDialect{}, Params())
	return c
}

// Compile outputs the DROP TABLE statement using the given dialect and
// parameters.
func (stmt DropStmt) Compile(d dialect.Dialect, p *Parameters) (string, error) {
	if stmt.ifExists {
		return fmt.Sprintf(`DROP TABLE IF EXISTS "%s"`, stmt.table.Name()), nil
	}
	return fmt.Sprintf(`DROP TABLE "%s"`, stmt.table.Name()), nil
}
<commit_msg>Removed duplicate double quotes in drop statement<commit_after>package sol

import (
	"fmt"

	"github.com/aodin/sol/dialect"
)

// DropStmt is the internal representation of an DROP TABLE statement.
type DropStmt struct {
	table    *TableElem
	ifExists bool
}

// IfExists adds the IF EXISTS modifier to a DROP TABLE statement.
func (stmt DropStmt) IfExists() DropStmt {
	stmt.ifExists = true
	return stmt
}

// String outputs the parameter-less CREATE TABLE statement in a neutral
// dialect.
func (stmt DropStmt) String() string {
	c, _ := stmt.Compile(&defaultDialect{}, Params())
	return c
}

// Compile outputs the DROP TABLE statement using the given dialect and
// parameters.
func (stmt DropStmt) Compile(d dialect.Dialect, p *Parameters) (string, error) {
	if stmt.ifExists {
		return fmt.Sprintf(`DROP TABLE IF EXISTS %s`, stmt.table.Name()), nil
	}
	return fmt.Sprintf(`DROP TABLE %s`, stmt.table.Name()), nil
}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/exec"
	"time"

	"github.com/99designs/aws-vault/keyring"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
)

type ExecCommandInput struct {
	Profile  string
	Command  string
	Args     []string
	Keyring  keyring.Keyring
	Duration time.Duration
}

func ExecCommand(ui Ui, input ExecCommandInput) {
	provider, err := NewVaultProvider(input.Keyring, input.Profile, input.Duration)
	if err != nil {
		ui.Error.Fatal(err)
	}

	creds := credentials.NewCredentials(provider)
	val, err := creds.Get()
	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoCredentialProviders" {
			ui.Error.Fatalf("No credentials found for profile %q", input.Profile)
		} else {
			ui.Error.Fatal(err)
		}
	}

	env := append(os.Environ(),
		"AWS_ACCESS_KEY_ID="+val.AccessKeyID,
		"AWS_SECRET_ACCESS_KEY="+val.SecretAccessKey,
		"AWS_DEFAULT_PROFILE="+input.Profile,
	)

	if val.SessionToken != "" {
		env = append(env, "AWS_SESSION_TOKEN="+val.SessionToken)
	}

	cmd := exec.Command(input.Command, input.Args...)
	cmd.Env = env
	cmd.Stdin = os.Stdin
	cmd.Stdout = &logWriter{ui.Logger}
	cmd.Stderr = &logWriter{ui.Error}

	if err := cmd.Run(); err != nil {
		ui.Error.Fatal(err)
	}
}
<commit_msg>Use exec syscall vs pipes and subprocess<commit_after>package main

import (
	"os"
	"os/exec"
	"syscall"
	"time"

	"github.com/99designs/aws-vault/keyring"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/credentials"
)

type ExecCommandInput struct {
	Profile  string
	Command  string
	Args     []string
	Keyring  keyring.Keyring
	Duration time.Duration
}

func ExecCommand(ui Ui, input ExecCommandInput) {
	provider, err := NewVaultProvider(input.Keyring, input.Profile, input.Duration)
	if err != nil {
		ui.Error.Fatal(err)
	}

	creds := credentials.NewCredentials(provider)
	val, err := creds.Get()
	if err != nil {
		if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NoCredentialProviders" {
			ui.Error.Fatalf("No credentials found for profile %q", input.Profile)
		} else {
			ui.Error.Fatal(err)
		}
	}

	env := append(os.Environ(),
		"AWS_ACCESS_KEY_ID="+val.AccessKeyID,
		"AWS_SECRET_ACCESS_KEY="+val.SecretAccessKey,
		"AWS_DEFAULT_PROFILE="+input.Profile,
	)

	if val.SessionToken != "" {
		env = append(env, "AWS_SESSION_TOKEN="+val.SessionToken)
	}

	path, err := exec.LookPath(input.Command)
	if err != nil {
		ui.Error.Fatal(err)
	}

	argv := append([]string{input.Command}, input.Args...)

	if err := syscall.Exec(path, argv, env); err != nil {
		ui.Error.Fatal(err)
	}
}
<|endoftext|>