<commit_before>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/coreos/go-systemd/dbus"
	"github.com/coreos/go-systemd/unit"
	"github.com/coreos/torus"
	"github.com/coreos/torus/internal/nbd"
	godbus "github.com/godbus/dbus"
	"github.com/kardianos/osext"
	"github.com/spf13/cobra"
)

type VolumeData struct {
	VolumeName     string `json:"volume"`
	Trim           bool   `json:"trim"`
	Etcd           string `json:"etcd"`
	FSType         string `json:"kubernetes.io/fsType"`
	ReadWrite      string `json:"kubernetes.io/readwrite"`
	WriteLevel     string `json:"writeLevel"`
	WriteCacheSize string `json:"writeCacheSize"`
}

type Response struct {
	// Status of the callout. One of "Success" or "Failure".
	Status string `json:"status"`
	// Message is the reason for failure.
	Message string `json:"message,omitempty"`
	// Device assigned by the driver.
	Device string `json:"device,omitempty"`
}

var initCommand = &cobra.Command{
	Use:   "init",
	Short: "flex: init",
	Run:   initAction,
}

var attachCommand = &cobra.Command{
	Use:   "attach",
	Short: "flex: attach",
	Run:   attachAction,
}

var mountCommand = &cobra.Command{
	Use:   "mount",
	Short: "flex: mount",
	Run:   mountAction,
}

var unmountCommand = &cobra.Command{
	Use:   "unmount",
	Short: "flex: unmount",
	Run:   unmountAction,
}

var detachCommand = &cobra.Command{
	Use:   "detach",
	Short: "flex: detach",
	Run:   detachAction,
}

var flexprepvolCommand = &cobra.Command{
	Use:   "flexprepvol",
	Short: "flex: prepvol",
	Run:   flexprepvolAction,
}

func initAction(cmd *cobra.Command, args []string) {
	writeResponse(Response{
		Status: "Success",
	})
}

func devToUnitName(dev string) string {
	return "torus-" + unit.UnitNamePathEscape(dev) + ".service"
}

type systemd struct {
	*dbus.Conn
	evChan  <-chan map[string]*dbus.UnitStatus
	errChan <-chan error
}

func connectSystemd() systemd {
	var sysd systemd
	conn, err := dbus.New()
	if err != nil {
		onErr(err)
	}
	err = conn.Subscribe()
	if err != nil {
		onErr(err)
	}

	err = conn.Unsubscribe()
	if err != nil {
		onErr(err)
	}
	sysd.Conn = conn
	sysd.evChan, sysd.errChan = conn.SubscribeUnits(time.Second)
	return sysd
}

func (s systemd) wait(svc string) string {
	for {
		select {
		case changes := <-s.evChan:
			tCh, ok := changes[svc]

			// Just continue until we see our event.
			if !ok {
				continue
			}
			return tCh.ActiveState
		case err := <-s.errChan:
			onErr(err)
		}
	}
}

func parseJSONArg(s string) VolumeData {
	var vol VolumeData
	err := json.Unmarshal([]byte(s), &vol)
	if err != nil {
		onErr(err)
	}
	if vol.FSType == "" {
		vol.FSType = "ext4"
	}
	if vol.Etcd == "" {
		vol.Etcd = "127.0.0.1:2379"
	}
	return vol
}

//{"kubernetes.io/fsType":"ext4","kubernetes.io/readwrite":"rw","volume":"block1"}
func attachAction(cmd *cobra.Command, args []string) {
	if len(args) != 1 {
		onErr(errors.New("unexpected number of arguments"))
	}
	vol := parseJSONArg(args[0])

	dev, err := nbd.FindDevice()
	if err != nil {
		onErr(err)
	}

	sysd := connectSystemd()

	svc := devToUnitName(dev)

	me, err := osext.Executable()
	if err != nil {
		onErr(err)
	}

	cmdList := []string{
		me,
		"-C",
		vol.Etcd,
		"nbd",
		vol.VolumeName,
		dev,
	}
	if vol.WriteLevel != "" {
		_, err := torus.ParseWriteLevel(vol.WriteLevel)
		if err != nil {
			onErr(err)
		}
		cmdList = append(cmdList, []string{"--write-level", vol.WriteLevel}...)
	}
	if vol.WriteCacheSize != "" {
		cmdList = append(cmdList, []string{"--write-cache-size", vol.WriteCacheSize}...)
	}

	ch := make(chan string)

	sysd.ResetFailedUnit(svc)
	_, err = sysd.StartTransientUnit(svc, "fail", []dbus.Property{
		dbus.PropExecStart(cmdList, false),
	}, ch)
	if err != nil {
		onErr(err)
	}
	<-ch
	status := sysd.wait(svc)
	if status == "failed" {
		onErr(errors.New("Couldn't attach"))
	} else if status == "active" {
		writeResponse(Response{
			Status: "Success",
			Device: dev,
		})
	} else {
		onErr(errors.New(status))
	}
	os.Exit(0)
}

func mountAction(cmd *cobra.Command, args []string) {
	if len(args) != 3 {
		onErr(errors.New("unexpected number of arguments"))
	}

	vol := parseJSONArg(args[2])

	mountdir := args[0]
	mountdev := args[1]
	oneshotsvc := devToUnitName(mountdir)
	// mountsvc := pathToMountName(mountdir)

	me, err := osext.Executable()
	if err != nil {
		onErr(err)
	}

	flags := "noatime"
	if vol.Trim {
		flags = "noatime,discard"
	}

	ch := make(chan string)
	// ch2 := make(chan string)

	sysd := connectSystemd()

	sysd.ResetFailedUnit(oneshotsvc)
	_, err = sysd.StartTransientUnit(oneshotsvc, "fail", []dbus.Property{
		dbus.Property{
			Name:  "Type",
			Value: godbus.MakeVariant("oneshot"),
		},
		dbus.PropExecStart([]string{
			me,
			"flexprepvol",
			mountdev,
			vol.FSType,
		}, false),
	}, ch)
	if err != nil {
		onErr(err)
	}
	s := <-ch
	if s == "failed" {
		onErr(errors.New(s))
	}
	// _, err = sysd.StartTransientUnit(mountsvc, "fail", []dbus.Property{
	// 	dbus.Property{
	// 		Name:  "What",
	// 		Value: godbus.MakeVariant(mountdev),
	// 	},
	// 	dbus.Property{
	// 		Name:  "Where",
	// 		Value: godbus.MakeVariant(mountdir),
	// 	},
	// 	dbus.Property{
	// 		Name:  "Type",
	// 		Value: godbus.MakeVariant(vol.FSType),
	// 	},
	// 	dbus.Property{
	// 		Name:  "Options",
	// 		Value: godbus.MakeVariant(flags),
	// 	},
	// }, ch2)
	// if err != nil {
	// 	onErr(err)
	// }
	// status := sysd.wait(mountsvc)
	// if status == "failed" {
	// 	onErr(errors.New("Couldn't attach"))
	// } else if status == "active" {
	// 	writeResponse(Response{
	// 		Status: "Success",
	// 		Device: mountdev,
	// 	})
	// }
	os.MkdirAll(mountdir, os.ModeDir|0555)
	ex := exec.Command("mount", "-t", vol.FSType, "-o", flags, mountdev, mountdir)
	_, err = ex.CombinedOutput()
	if err != nil {
		onErr(err)
		os.Exit(1)
	}
	writeResponse(Response{
		Status: "Success",
		Device: mountdev,
	})
	os.Exit(0)
}

func unmountAction(cmd *cobra.Command, args []string) {
	if len(args) != 1 {
		onErr(errors.New("unexpected number of arguments"))
	}
	mountdir := args[0]
	// svc := pathToMountName(mountdir)
	// sysd := connectSystemd()
	// ch := make(chan string)
	// sysd.StopUnit(svc, "fail", ch)
	// <-ch

	_, err := exec.Command("umount", mountdir).Output()
	if err != nil {
		onErr(err)
		os.Exit(1)
	}
	writeResponse(Response{
		Status: "Success",
	})
	os.Exit(0)
}

func detachAction(cmd *cobra.Command, args []string) {
	if len(args) != 1 {
		onErr(errors.New("unexpected number of arguments"))
	}
	dev := args[0]
	svc := devToUnitName(dev)
	sysd := connectSystemd()
	sysd.KillUnit(svc, 2)
	sysd.ResetFailedUnit(svc)
	writeResponse(Response{
		Status: "Success",
		Device: dev,
	})
	os.Exit(0)
}

func flexprepvolAction(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		onErr(errors.New("unexpected number of arguments"))
	}
	dev := args[0]
	fstype := args[1]
	out, err := exec.Command("blkid", "-p", dev).Output()
	if err != nil {
		// Not formatted
		out, err := exec.Command("mkfs", "-t", fstype, dev).CombinedOutput()
		if err != nil {
			fmt.Println(string(out))
			os.Exit(1)
		}
	} else {
		if !strings.Contains(string(out), fstype) {
			// wrong FS type, this is bad
			fmt.Println("unexpected FS Type")
			os.Exit(1)
		}
	}
	os.Exit(0)
}

func writeResponse(resp Response) {
	b, err := json.Marshal(resp)
	if err != nil {
		fmt.Println([]byte(err.Error()))
		os.Exit(2)
	}
	fmt.Println(string(b))
}

func onErr(err error) {
	writeResponse(Response{
		Status:  "Failure",
		Message: err.Error(),
	})
	os.Exit(1)
}
<commit_msg>torusblk.flex: fix wrong line break<commit_after>package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/coreos/go-systemd/dbus"
	"github.com/coreos/go-systemd/unit"
	"github.com/coreos/torus"
	"github.com/coreos/torus/internal/nbd"
	godbus "github.com/godbus/dbus"
	"github.com/kardianos/osext"
	"github.com/spf13/cobra"
)

type VolumeData struct {
	VolumeName     string `json:"volume"`
	Trim           bool   `json:"trim"`
	Etcd           string `json:"etcd"`
	FSType         string `json:"kubernetes.io/fsType"`
	ReadWrite      string `json:"kubernetes.io/readwrite"`
	WriteLevel     string `json:"writeLevel"`
	WriteCacheSize string `json:"writeCacheSize"`
}

type Response struct {
	// Status of the callout. One of "Success" or "Failure".
	Status string `json:"status"`
	// Message is the reason for failure.
	Message string `json:"message,omitempty"`
	// Device assigned by the driver.
	Device string `json:"device,omitempty"`
}

var initCommand = &cobra.Command{
	Use:   "init",
	Short: "flex: init",
	Run:   initAction,
}

var attachCommand = &cobra.Command{
	Use:   "attach",
	Short: "flex: attach",
	Run:   attachAction,
}

var mountCommand = &cobra.Command{
	Use:   "mount",
	Short: "flex: mount",
	Run:   mountAction,
}

var unmountCommand = &cobra.Command{
	Use:   "unmount",
	Short: "flex: unmount",
	Run:   unmountAction,
}

var detachCommand = &cobra.Command{
	Use:   "detach",
	Short: "flex: detach",
	Run:   detachAction,
}

var flexprepvolCommand = &cobra.Command{
	Use:   "flexprepvol",
	Short: "flex: prepvol",
	Run:   flexprepvolAction,
}

func initAction(cmd *cobra.Command, args []string) {
	writeResponse(Response{
		Status: "Success",
	})
}

func devToUnitName(dev string) string {
	return "torus-" + unit.UnitNamePathEscape(dev) + ".service"
}

type systemd struct {
	*dbus.Conn
	evChan  <-chan map[string]*dbus.UnitStatus
	errChan <-chan error
}

func connectSystemd() systemd {
	var sysd systemd
	conn, err := dbus.New()
	if err != nil {
		onErr(err)
	}
	err = conn.Subscribe()
	if err != nil {
		onErr(err)
	}

	err = conn.Unsubscribe()
	if err != nil {
		onErr(err)
	}
	sysd.Conn = conn
	sysd.evChan, sysd.errChan = conn.SubscribeUnits(time.Second)
	return sysd
}

func (s systemd) wait(svc string) string {
	for {
		select {
		case changes := <-s.evChan:
			tCh, ok := changes[svc]

			// Just continue until we see our event.
			if !ok {
				continue
			}
			return tCh.ActiveState
		case err := <-s.errChan:
			onErr(err)
		}
	}
}

func parseJSONArg(s string) VolumeData {
	var vol VolumeData
	err := json.Unmarshal([]byte(s), &vol)
	if err != nil {
		onErr(err)
	}
	if vol.FSType == "" {
		vol.FSType = "ext4"
	}
	if vol.Etcd == "" {
		vol.Etcd = "127.0.0.1:2379"
	}
	return vol
}

//{"kubernetes.io/fsType":"ext4","kubernetes.io/readwrite":"rw","volume":"block1"}
func attachAction(cmd *cobra.Command, args []string) {
	if len(args) != 1 {
		onErr(errors.New("unexpected number of arguments"))
	}
	vol := parseJSONArg(args[0])

	dev, err := nbd.FindDevice()
	if err != nil {
		onErr(err)
	}

	sysd := connectSystemd()

	svc := devToUnitName(dev)

	me, err := osext.Executable()
	if err != nil {
		onErr(err)
	}

	cmdList := []string{
		me,
		"-C",
		vol.Etcd,
		"nbd",
		vol.VolumeName,
		dev,
	}
	if vol.WriteLevel != "" {
		_, err := torus.ParseWriteLevel(vol.WriteLevel)
		if err != nil {
			onErr(err)
		}
		cmdList = append(cmdList, []string{"--write-level", vol.WriteLevel}...)
	}
	if vol.WriteCacheSize != "" {
		cmdList = append(cmdList, []string{"--write-cache-size", vol.WriteCacheSize}...)
	}

	ch := make(chan string)

	sysd.ResetFailedUnit(svc)
	_, err = sysd.StartTransientUnit(svc, "fail", []dbus.Property{
		dbus.PropExecStart(cmdList, false),
	}, ch)
	if err != nil {
		onErr(err)
	}
	<-ch
	status := sysd.wait(svc)
	if status == "failed" {
		onErr(errors.New("Couldn't attach"))
	} else if status == "active" {
		writeResponse(Response{
			Status: "Success",
			Device: dev,
		})
	} else {
		onErr(errors.New(status))
	}
	os.Exit(0)
}

func mountAction(cmd *cobra.Command, args []string) {
	if len(args) != 3 {
		onErr(errors.New("unexpected number of arguments"))
	}

	vol := parseJSONArg(args[2])

	mountdir := args[0]
	mountdev := args[1]
	oneshotsvc := devToUnitName(mountdir)
	// mountsvc := pathToMountName(mountdir)

	me, err := osext.Executable()
	if err != nil {
		onErr(err)
	}

	flags := "noatime"
	if vol.Trim {
		flags = "noatime,discard"
	}

	ch := make(chan string)
	// ch2 := make(chan string)

	sysd := connectSystemd()

	sysd.ResetFailedUnit(oneshotsvc)
	_, err = sysd.StartTransientUnit(oneshotsvc, "fail", []dbus.Property{
		dbus.Property{
			Name:  "Type",
			Value: godbus.MakeVariant("oneshot"),
		},
		dbus.PropExecStart([]string{
			me,
			"flexprepvol",
			mountdev,
			vol.FSType,
		}, false),
	}, ch)
	if err != nil {
		onErr(err)
	}
	s := <-ch
	if s == "failed" {
		onErr(errors.New(s))
	}
	// _, err = sysd.StartTransientUnit(mountsvc, "fail", []dbus.Property{
	// 	dbus.Property{
	// 		Name:  "What",
	// 		Value: godbus.MakeVariant(mountdev),
	// 	},
	// 	dbus.Property{
	// 		Name:  "Where",
	// 		Value: godbus.MakeVariant(mountdir),
	// 	},
	// 	dbus.Property{
	// 		Name:  "Type",
	// 		Value: godbus.MakeVariant(vol.FSType),
	// 	},
	// 	dbus.Property{
	// 		Name:  "Options",
	// 		Value: godbus.MakeVariant(flags),
	// 	},
	// }, ch2)
	// if err != nil {
	// 	onErr(err)
	// }
	// status := sysd.wait(mountsvc)
	// if status == "failed" {
	// 	onErr(errors.New("Couldn't attach"))
	// } else if status == "active" {
	// 	writeResponse(Response{
	// 		Status: "Success",
	// 		Device: mountdev,
	// 	})
	// }
	os.MkdirAll(mountdir, os.ModeDir|0555)
	ex := exec.Command("mount", "-t", vol.FSType, "-o", flags, mountdev, mountdir)
	_, err = ex.CombinedOutput()
	if err != nil {
		onErr(err)
		os.Exit(1)
	}
	writeResponse(Response{
		Status: "Success",
		Device: mountdev,
	})
	os.Exit(0)
}

func unmountAction(cmd *cobra.Command, args []string) {
	if len(args) != 1 {
		onErr(errors.New("unexpected number of arguments"))
	}
	mountdir := args[0]
	// svc := pathToMountName(mountdir)
	// sysd := connectSystemd()
	// ch := make(chan string)
	// sysd.StopUnit(svc, "fail", ch)
	// <-ch

	_, err := exec.Command("umount", mountdir).Output()
	if err != nil {
		onErr(err)
		os.Exit(1)
	}
	writeResponse(Response{
		Status: "Success",
	})
	os.Exit(0)
}

func detachAction(cmd *cobra.Command, args []string) {
	if len(args) != 1 {
		onErr(errors.New("unexpected number of arguments"))
	}
	dev := args[0]
	svc := devToUnitName(dev)
	sysd := connectSystemd()
	sysd.KillUnit(svc, 2)
	sysd.ResetFailedUnit(svc)
	writeResponse(Response{
		Status: "Success",
		Device: dev,
	})
	os.Exit(0)
}

func flexprepvolAction(cmd *cobra.Command, args []string) {
	if len(args) != 2 {
		onErr(errors.New("unexpected number of arguments"))
	}
	dev := args[0]
	fstype := args[1]
	out, err := exec.Command("blkid", "-p", dev).Output()
	if err != nil {
		// Not formatted
		out, err := exec.Command("mkfs", "-t", fstype, dev).CombinedOutput()
		if err != nil {
			fmt.Println(string(out))
			os.Exit(1)
		}
	} else {
		if !strings.Contains(string(out), fstype) {
			// wrong FS type, this is bad
			fmt.Println("unexpected FS Type")
			os.Exit(1)
		}
	}
	os.Exit(0)
}

func writeResponse(resp Response) {
	b, err := json.Marshal(resp)
	if err != nil {
		fmt.Println([]byte(err.Error()))
		os.Exit(2)
	}
	fmt.Print(string(b))
}

func onErr(err error) {
	writeResponse(Response{
		Status:  "Failure",
		Message: err.Error(),
	})
	os.Exit(1)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io"

	"github.com/hackebrot/turtle"
	"github.com/spf13/cobra"
)

var indent string
var prefix string

// Create a new turtle command with the given output
func newTurtleCmd(w io.Writer) *cobra.Command {
	turtleCmd := &cobra.Command{
		Use:     "turtle",
		Version: turtle.Version,
		Short:   "Print the emoji with the specified name identifier",
		Long:    "Print the emoji with the specified name identifier",
		RunE: func(cmd *cobra.Command, args []string) error {
			return runTurtle(w, args[0])
		},
		Args: func(cmd *cobra.Command, args []string) error {
			if len(args) != 1 {
				return fmt.Errorf("require one emoji name")
			}
			return nil
		},
	}

	turtleCmd.PersistentFlags().StringVarP(&indent, "indent", "i", "", "indent for JSON output")
	turtleCmd.PersistentFlags().StringVarP(&prefix, "prefix", "p", "", "prefix for JSON output")

	turtleCmd.SetVersionTemplate("{{with .Name}}{{printf \"%s \" .}}{{end}}{{printf \"%s\" .Version}}\n")

	turtleCmd.AddCommand(newCharCmd(w))
	turtleCmd.AddCommand(newCategoryCmd(w))
	turtleCmd.AddCommand(newKeywordCmd(w))
	turtleCmd.AddCommand(newSearchCmd(w))
	turtleCmd.AddCommand(newListCmd(w))
	turtleCmd.AddCommand(newRandomCmd(w))

	return turtleCmd
}

func runTurtle(w io.Writer, name string) error {

	e, ok := turtle.Emojis[name]

	if !ok {
		return fmt.Errorf("cannot find emoji with name %q", name)
	}

	j, err := NewJSONWriter(w, WithIndent(prefix, indent))

	if err != nil {
		return fmt.Errorf("error creating JSONWriter: %v", err)
	}

	return j.WriteEmoji(e)
}
<commit_msg>Update Use and Args for turtle cmd<commit_after>package main

import (
	"fmt"
	"io"

	"github.com/hackebrot/turtle"
	"github.com/spf13/cobra"
)

var indent string
var prefix string

// Create a new turtle command with the given output
func newTurtleCmd(w io.Writer) *cobra.Command {
	turtleCmd := &cobra.Command{
		Use:   "turtle [NAME]",
		Short: "Print the emoji with the specified name identifier",
		Long:  "Print the emoji with the specified name identifier",
		Args:  cobra.ExactArgs(1),
		RunE: func(cmd *cobra.Command, args []string) error {
			return runTurtle(w, args[0])
		},
		Version: turtle.Version,
	}

	turtleCmd.PersistentFlags().StringVarP(&indent, "indent", "i", "", "indent for JSON output")
	turtleCmd.PersistentFlags().StringVarP(&prefix, "prefix", "p", "", "prefix for JSON output")

	turtleCmd.SetVersionTemplate("{{with .Name}}{{printf \"%s \" .}}{{end}}{{printf \"%s\" .Version}}\n")

	turtleCmd.AddCommand(newCharCmd(w))
	turtleCmd.AddCommand(newCategoryCmd(w))
	turtleCmd.AddCommand(newKeywordCmd(w))
	turtleCmd.AddCommand(newSearchCmd(w))
	turtleCmd.AddCommand(newListCmd(w))
	turtleCmd.AddCommand(newRandomCmd(w))

	return turtleCmd
}

func runTurtle(w io.Writer, name string) error {

	e, ok := turtle.Emojis[name]

	if !ok {
		return fmt.Errorf("cannot find emoji with name %q", name)
	}

	j, err := NewJSONWriter(w, WithIndent(prefix, indent))

	if err != nil {
		return fmt.Errorf("error creating JSONWriter: %v", err)
	}

	return j.WriteEmoji(e)
}
<|endoftext|>


<commit_before>package newedit

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"sync"

	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/eval/vals"
	"github.com/elves/elvish/eval/vars"
	"github.com/elves/elvish/newedit/core"
	"github.com/elves/elvish/newedit/prompt"
	"github.com/elves/elvish/styled"
	"github.com/elves/elvish/util"
)

func makePrompt(nt notifier, ev *eval.Evaler, ns eval.Ns, computeInit eval.Callable, name string) core.Prompt {
	compute := computeInit
	ns[name] = vars.FromPtr(&compute)
	return prompt.New(func() styled.Text {
		return callPrompt(nt, ev, compute)
	})
}

var defaultPrompt, defaultRPrompt eval.Callable

func init() {
	user, userErr := user.Current()
	isRoot := userErr == nil && user.Uid == "0"

	defaultPrompt = getDefaultPrompt(isRoot)

	username := "???"
	if userErr == nil {
		username = user.Name
	}
	hostname, err := os.Hostname()
	if err != nil {
		hostname = "???"
	}

	defaultRPrompt = getDefaultRPrompt(username, hostname)
}

func getDefaultPrompt(isRoot bool) eval.Callable {
	p := styled.Unstyled("> ")
	if isRoot {
		p = styled.Transform(styled.Unstyled("# "), "red")
	}
	return eval.NewBuiltinFn("default prompt", func(fm *eval.Frame) {
		out := fm.OutputChan()
		out <- string(util.Getwd())
		out <- p
	})
}

func getDefaultRPrompt(username, hostname string) eval.Callable {
	rp := styled.Transform(styled.Unstyled(username+"@"+hostname), "inverse")
	return eval.NewBuiltinFn("default rprompt", func(fm *eval.Frame) {
		fm.OutputChan() <- rp
	})
}

// callPrompt calls a function with no arguments and closed input, and converts
// its outputs to styled objects. Used to call prompt callbacks.
func callPrompt(nt notifier, ev *eval.Evaler, fn eval.Callable) styled.Text {
	ports := []*eval.Port{
		eval.DevNullClosedChan,
		{}, // Will be replaced when capturing output
		{File: os.Stderr},
	}

	return callForStyledText(nt, ev, fn, ports)
}

func callForStyledText(nt notifier, ev *eval.Evaler, fn eval.Callable, ports []*eval.Port) styled.Text {

	var (
		result      styled.Text
		resultMutex sync.Mutex
	)
	add := func(v interface{}) {
		resultMutex.Lock()
		defer resultMutex.Unlock()
		newResult, err := result.Concat(v)
		if err != nil {
			nt.Notify(fmt.Sprintf(
				"invalid output type from prompt: %s", vals.Kind(v)))
		} else {
			result = newResult.(styled.Text)
		}
	}

	// Value outputs are concatenated.
	valuesCb := func(ch <-chan interface{}) {
		for v := range ch {
			add(v)
		}
	}
	// Byte output is added to the prompt as a single unstyled text.
	bytesCb := func(r *os.File) {
		allBytes, err := ioutil.ReadAll(r)
		if err != nil {
			nt.Notify(fmt.Sprintf("error reading prompt byte output: %v", err))
		}
		if len(allBytes) > 0 {
			add(string(allBytes))
		}
	}

	// XXX There is no source to pass to NewTopEvalCtx.
	fm := eval.NewTopFrame(ev, eval.NewInternalSource("[prompt]"), ports)
	err := fm.CallWithOutputCallback(fn, nil, eval.NoOpts, valuesCb, bytesCb)

	if err != nil {
		nt.Notify(fmt.Sprintf("prompt function error: %v", err))
		return nil
	}

	return result
}
<commit_msg>newedit: Use username, not name, in default rprompt.<commit_after>package newedit

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"sync"

	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/eval/vals"
	"github.com/elves/elvish/eval/vars"
	"github.com/elves/elvish/newedit/core"
	"github.com/elves/elvish/newedit/prompt"
	"github.com/elves/elvish/styled"
	"github.com/elves/elvish/util"
)

func makePrompt(nt notifier, ev *eval.Evaler, ns eval.Ns, computeInit eval.Callable, name string) core.Prompt {
	compute := computeInit
	ns[name] = vars.FromPtr(&compute)
	return prompt.New(func() styled.Text {
		return callPrompt(nt, ev, compute)
	})
}

var defaultPrompt, defaultRPrompt eval.Callable

func init() {
	user, userErr := user.Current()
	isRoot := userErr == nil && user.Uid == "0"

	defaultPrompt = getDefaultPrompt(isRoot)

	username := "???"
	if userErr == nil {
		username = user.Username
	}
	hostname, err := os.Hostname()
	if err != nil {
		hostname = "???"
	}

	defaultRPrompt = getDefaultRPrompt(username, hostname)
}

func getDefaultPrompt(isRoot bool) eval.Callable {
	p := styled.Unstyled("> ")
	if isRoot {
		p = styled.Transform(styled.Unstyled("# "), "red")
	}
	return eval.NewBuiltinFn("default prompt", func(fm *eval.Frame) {
		out := fm.OutputChan()
		out <- string(util.Getwd())
		out <- p
	})
}

func getDefaultRPrompt(username, hostname string) eval.Callable {
	rp := styled.Transform(styled.Unstyled(username+"@"+hostname), "inverse")
	return eval.NewBuiltinFn("default rprompt", func(fm *eval.Frame) {
		fm.OutputChan() <- rp
	})
}

// callPrompt calls a function with no arguments and closed input, and converts
// its outputs to styled objects. Used to call prompt callbacks.
func callPrompt(nt notifier, ev *eval.Evaler, fn eval.Callable) styled.Text {
	ports := []*eval.Port{
		eval.DevNullClosedChan,
		{}, // Will be replaced when capturing output
		{File: os.Stderr},
	}

	return callForStyledText(nt, ev, fn, ports)
}

func callForStyledText(nt notifier, ev *eval.Evaler, fn eval.Callable, ports []*eval.Port) styled.Text {

	var (
		result      styled.Text
		resultMutex sync.Mutex
	)
	add := func(v interface{}) {
		resultMutex.Lock()
		defer resultMutex.Unlock()
		newResult, err := result.Concat(v)
		if err != nil {
			nt.Notify(fmt.Sprintf(
				"invalid output type from prompt: %s", vals.Kind(v)))
		} else {
			result = newResult.(styled.Text)
		}
	}

	// Value outputs are concatenated.
	valuesCb := func(ch <-chan interface{}) {
		for v := range ch {
			add(v)
		}
	}
	// Byte output is added to the prompt as a single unstyled text.
	bytesCb := func(r *os.File) {
		allBytes, err := ioutil.ReadAll(r)
		if err != nil {
			nt.Notify(fmt.Sprintf("error reading prompt byte output: %v", err))
		}
		if len(allBytes) > 0 {
			add(string(allBytes))
		}
	}

	// XXX There is no source to pass to NewTopEvalCtx.
	fm := eval.NewTopFrame(ev, eval.NewInternalSource("[prompt]"), ports)
	err := fm.CallWithOutputCallback(fn, nil, eval.NoOpts, valuesCb, bytesCb)

	if err != nil {
		nt.Notify(fmt.Sprintf("prompt function error: %v", err))
		return nil
	}

	return result
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/kelseyhightower/terminus/facts"
	"golang.org/x/sys/unix"
)

// SystemFacts holds the system facts.
type SystemFacts struct {
	Architecture string
	BootID       string
	Date         Date
	Domainname   string
	Hostname     string
	Network      Network
	Kernel       Kernel
	MachineID    string
	Memory       Memory
	OSRelease    OSRelease
	Swap         Swap
	Uptime       int64
	LoadAverage  LoadAverage
	FileSystems  FileSystems

	mu sync.Mutex
}

// Holds the load average facts.
type LoadAverage struct {
	One  uint64
	Five uint64
	Ten  uint64
}

// Date holds the date facts.
type Date struct {
	Unix int64
	UTC  string
}

// Swap holds the swap facts.
type Swap struct {
	Total uint64
	Free  uint64
}

// OSRelease holds the OS release facts.
type OSRelease struct {
	Name       string
	ID         string
	PrettyName string
	Version    string
	VersionID  string
}

// Kernel holds the kernel facts.
type Kernel struct {
	Name    string
	Release string
	Version string
}

// Memory holds the memory facts.
type Memory struct {
	Total    uint64
	Free     uint64
	Shared   uint64
	Buffered uint64
}

// Network holds the network facts.
type Network struct {
	Interfaces Interfaces
}

// Interfaces holds the interface facts.
type Interfaces map[string]Interface

// Interface holds facts for a single interface.
type Interface struct {
	Name         string
	Index        int
	HardwareAddr string
	IpAddresses  []string
	Ip4Addresses []Ip4Address
	Ip6Addresses []Ip6Address
}

type Ip4Address struct {
	CIDR    string
	Ip      string
	Netmask string
}

type Ip6Address struct {
	CIDR   string
	Ip     string
	Prefix int
}

// FileSystems holds the Filesystem facts.
type FileSystems map[string]FileSystem

// FileSystem holds facts for a filesystem (man fstab).
type FileSystem struct {
	Device     string
	MountPoint string
	Type       string
	Options    []string
	DumpFreq   uint64
	PassNo     uint64
}

func getFacts() *facts.Facts {
	f := facts.New()
	systemFacts := getSystemFacts()
	f.Add("System", systemFacts)
	processExternalFacts(externalFactsDir, f)
	return f
}

func getSystemFacts() *SystemFacts {
	facts := new(SystemFacts)
	var wg sync.WaitGroup

	wg.Add(8)
	go facts.getOSRelease(&wg)
	go facts.getInterfaces(&wg)
	go facts.getBootID(&wg)
	go facts.getMachineID(&wg)
	go facts.getUname(&wg)
	go facts.getSysInfo(&wg)
	go facts.getDate(&wg)
	go facts.getFileSystems(&wg)

	wg.Wait()
	return facts
}

func (f *SystemFacts) getDate(wg *sync.WaitGroup) {
	defer wg.Done()

	now := time.Now()
	f.Date.Unix = now.Unix()
	f.Date.UTC = now.UTC().String()

	return
}

func (f *SystemFacts) getSysInfo(wg *sync.WaitGroup) {
	defer wg.Done()

	var info unix.Sysinfo_t
	if err := unix.Sysinfo(&info); err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	f.Memory.Total = info.Totalram
	f.Memory.Free = info.Freeram
	f.Memory.Shared = info.Sharedram
	f.Memory.Buffered = info.Bufferram

	f.Swap.Total = info.Totalswap
	f.Swap.Free = info.Freeswap

	f.Uptime = info.Uptime

	f.LoadAverage.One = info.Loads[0]
	f.LoadAverage.Five = info.Loads[1]
	f.LoadAverage.Ten = info.Loads[2]

	return
}

func (f *SystemFacts) getOSRelease(wg *sync.WaitGroup) {
	defer wg.Done()
	osReleaseFile, err := os.Open("/etc/os-release")
	if err != nil {
		log.Println(err.Error())
		return
	}
	defer osReleaseFile.Close()

	f.mu.Lock()
	defer f.mu.Unlock()
	scanner := bufio.NewScanner(osReleaseFile)
	for scanner.Scan() {
		columns := strings.Split(scanner.Text(), "=")
		if len(columns) > 1 {
			key := columns[0]
			value := strings.Trim(strings.TrimSpace(columns[1]), `"`)
			switch key {
			case "NAME":
				f.OSRelease.Name = value
			case "ID":
				f.OSRelease.ID = value
			case "PRETTY_NAME":
				f.OSRelease.PrettyName = value
			case "VERSION":
				f.OSRelease.Version = value
			case "VERSION_ID":
				f.OSRelease.VersionID = value
			}
		}
	}
	return
}

func (f *SystemFacts) getMachineID(wg *sync.WaitGroup) {
	defer wg.Done()
	machineIDFile, err := os.Open("/etc/machine-id")
	if err != nil {
		log.Println(err.Error())
		return
	}
	defer machineIDFile.Close()
	data, err := ioutil.ReadAll(machineIDFile)
	if err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	f.MachineID = strings.TrimSpace(string(data))
	return
}

func (f *SystemFacts) getBootID(wg *sync.WaitGroup) {
	defer wg.Done()
	bootIDFile, err := os.Open("/proc/sys/kernel/random/boot_id")
	if err != nil {
		log.Println(err.Error())
		return
	}
	defer bootIDFile.Close()
	data, err := ioutil.ReadAll(bootIDFile)
	if err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	f.BootID = strings.TrimSpace(string(data))
	return
}

func (f *SystemFacts) getInterfaces(wg *sync.WaitGroup) {
	defer wg.Done()
	ls, err := net.Interfaces()
	if err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	m := make(Interfaces)
	for _, i := range ls {
		ipaddreses := make([]string, 0)
		ip4addrs := make([]Ip4Address, 0)
		ip6addrs := make([]Ip6Address, 0)

		addrs, err := i.Addrs()
		if err != nil {
			log.Println(err.Error())
			return
		}
		for _, ip := range addrs {
			cidr := ip.String()
			ipaddreses = append(ipaddreses, cidr)
			ip, ipnet, _ := net.ParseCIDR(cidr)
			if ip.To4() != nil {
				ip4addrs = append(ip4addrs, Ip4Address{cidr, ip.String(), toNetmask(ipnet.Mask)})
				continue
			}
			if ip.To16() != nil {
				ones, _ := ipnet.Mask.Size()
				ip6addrs = append(ip6addrs, Ip6Address{cidr, ip.String(), ones})
			}
		}
		m[i.Name] = Interface{
			Name:         i.Name,
			Index:        i.Index,
			HardwareAddr: i.HardwareAddr.String(),
			IpAddresses:  ipaddreses,
			Ip4Addresses: ip4addrs,
			Ip6Addresses: ip6addrs,
		}
	}
	f.Network.Interfaces = m
	return
}

func toNetmask(m net.IPMask) string {
	return fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3])
}

func (f *SystemFacts) getUname(wg *sync.WaitGroup) {
	defer wg.Done()

	var buf unix.Utsname
	err := unix.Uname(&buf)
	if err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	f.Domainname = charsToString(buf.Domainname)
	f.Architecture = charsToString(buf.Machine)
	f.Hostname = charsToString(buf.Nodename)
	f.Kernel.Name = charsToString(buf.Sysname)
	f.Kernel.Release = charsToString(buf.Release)
	f.Kernel.Version = charsToString(buf.Version)
	return
}

func (f *SystemFacts) getFileSystems(wg *sync.WaitGroup) {
	defer wg.Done()

	mtab, err := ioutil.ReadFile("/etc/mtab")
	if err != nil {
		log.Println(err.Error())
		return
	}

	fsMap := make(FileSystems)

	f.mu.Lock()
	defer f.mu.Unlock()

	s := bufio.NewScanner(bytes.NewBuffer(mtab))
	for s.Scan() {
		line := s.Text()
		if string(line[0]) == "#" {
			continue
		}
		fields := strings.Fields(s.Text())
		fs := FileSystem{}
		fs.Device = fields[0]
		fs.MountPoint = fields[1]
		fs.Type = fields[2]
		fs.Options = strings.Split(fields[3], ",")
		dumpFreq, err := strconv.ParseUint(fields[4], 10, 64)
		if err != nil {
			log.Println(err.Error())
			return
		}
		fs.DumpFreq = dumpFreq

		passNo, err := strconv.ParseUint(fields[4], 10, 64)
		if err != nil {
			log.Println(err.Error())
			return
		}
		fs.PassNo = passNo

		fsMap[fs.Device] = fs
	}

	f.FileSystems = fsMap
	return
}

func processExternalFacts(dir string, f *facts.Facts) {
	d, err := os.Open(dir)
	if err != nil {
		log.Println(err)
		return
	}
	defer d.Close()

	files, err := d.Readdir(0)
	if err != nil {
		log.Println(err)
		return
	}

	executableFacts := make([]string, 0)
	staticFacts := make([]string, 0)

	for _, fi := range files {
		name := filepath.Join(dir, fi.Name())
		if isExecutable(fi) {
			executableFacts = append(executableFacts, name)
			continue
		}
		if strings.HasSuffix(name, ".json") {
			staticFacts = append(staticFacts, name)
		}
	}

	var wg sync.WaitGroup
	for _, p := range staticFacts {
		p := p
		wg.Add(1)
		go factsFromFile(p, f, &wg)
	}
	for _, p := range executableFacts {
		p := p
		wg.Add(1)
		go factsFromExec(p, f, &wg)
	}
	wg.Wait()
}

func factsFromFile(path string, f *facts.Facts, wg *sync.WaitGroup) {
	defer wg.Done()
	data, err := ioutil.ReadFile(path)
	if err != nil {
		log.Println(err)
		return
	}
	var result interface{}
	err = json.Unmarshal(data, &result)
	if err != nil {
		log.Println(err)
		return
	}
	f.Add(strings.TrimSuffix(filepath.Base(path), ".json"), result)
}

func factsFromExec(path string, f *facts.Facts, wg *sync.WaitGroup) {
	defer wg.Done()
	out, err := exec.Command(path).Output()
	if err != nil {
		log.Println(err)
		return
	}
	var result interface{}
	err = json.Unmarshal(out, &result)
	if err != nil {
		log.Println(err)
		return
	}
	f.Add(filepath.Base(path), result)
}

func isExecutable(fi os.FileInfo) bool {
	if m := fi.Mode(); !m.IsDir() && m&0111 != 0 {
		return true
	}
	return false
}

func charsToString(ca [65]int8) string {
	s := make([]byte, len(ca))
	var lens int
	for ; lens < len(ca); lens++ {
		if ca[lens] == 0 {
			break
		}
		s[lens] = uint8(ca[lens])
	}
	return string(s[0:lens])
}
<commit_msg>Adding Timezone to facts<commit_after>package main

import (
	"bufio"
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/kelseyhightower/terminus/facts"
	"golang.org/x/sys/unix"
)

// SystemFacts holds the system facts.
type SystemFacts struct {
	Architecture string
	BootID       string
	Date         Date
	Domainname   string
	Hostname     string
	Network      Network
	Kernel       Kernel
	MachineID    string
	Memory       Memory
	OSRelease    OSRelease
	Swap         Swap
	Uptime       int64
	LoadAverage  LoadAverage
	FileSystems  FileSystems

	mu sync.Mutex
}

// Holds the load average facts.
type LoadAverage struct {
	One  uint64
	Five uint64
	Ten  uint64
}

// Date holds the date facts.
type Date struct {
	Unix     int64
	UTC      string
	Timezone string
	Offset   int
}

// Swap holds the swap facts.
type Swap struct {
	Total uint64
	Free  uint64
}

// OSRelease holds the OS release facts.
type OSRelease struct {
	Name       string
	ID         string
	PrettyName string
	Version    string
	VersionID  string
}

// Kernel holds the kernel facts.
type Kernel struct {
	Name    string
	Release string
	Version string
}

// Memory holds the memory facts.
type Memory struct {
	Total    uint64
	Free     uint64
	Shared   uint64
	Buffered uint64
}

// Network holds the network facts.
type Network struct {
	Interfaces Interfaces
}

// Interfaces holds the interface facts.
type Interfaces map[string]Interface

// Interface holds facts for a single interface.
type Interface struct {
	Name         string
	Index        int
	HardwareAddr string
	IpAddresses  []string
	Ip4Addresses []Ip4Address
	Ip6Addresses []Ip6Address
}

type Ip4Address struct {
	CIDR    string
	Ip      string
	Netmask string
}

type Ip6Address struct {
	CIDR   string
	Ip     string
	Prefix int
}

// FileSystems holds the Filesystem facts.
type FileSystems map[string]FileSystem

// FileSystem holds facts for a filesystem (man fstab).
type FileSystem struct {
	Device     string
	MountPoint string
	Type       string
	Options    []string
	DumpFreq   uint64
	PassNo     uint64
}

func getFacts() *facts.Facts {
	f := facts.New()
	systemFacts := getSystemFacts()
	f.Add("System", systemFacts)
	processExternalFacts(externalFactsDir, f)
	return f
}

func getSystemFacts() *SystemFacts {
	facts := new(SystemFacts)
	var wg sync.WaitGroup

	wg.Add(8)
	go facts.getOSRelease(&wg)
	go facts.getInterfaces(&wg)
	go facts.getBootID(&wg)
	go facts.getMachineID(&wg)
	go facts.getUname(&wg)
	go facts.getSysInfo(&wg)
	go facts.getDate(&wg)
	go facts.getFileSystems(&wg)

	wg.Wait()
	return facts
}

func (f *SystemFacts) getDate(wg *sync.WaitGroup) {
	defer wg.Done()

	now := time.Now()
	f.Date.Unix = now.Unix()
	f.Date.UTC = now.UTC().String()
	f.Date.Timezone, f.Date.Offset = now.Zone()

	return
}

func (f *SystemFacts) getSysInfo(wg *sync.WaitGroup) {
	defer wg.Done()

	var info unix.Sysinfo_t
	if err := unix.Sysinfo(&info); err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	f.Memory.Total = info.Totalram
	f.Memory.Free = info.Freeram
	f.Memory.Shared = info.Sharedram
	f.Memory.Buffered = info.Bufferram

	f.Swap.Total = info.Totalswap
	f.Swap.Free = info.Freeswap

	f.Uptime = info.Uptime

	f.LoadAverage.One = info.Loads[0]
	f.LoadAverage.Five = info.Loads[1]
	f.LoadAverage.Ten = info.Loads[2]

	return
}

func (f *SystemFacts) getOSRelease(wg *sync.WaitGroup) {
	defer wg.Done()
	osReleaseFile, err := os.Open("/etc/os-release")
	if err != nil {
		log.Println(err.Error())
		return
	}
	defer osReleaseFile.Close()

	f.mu.Lock()
	defer f.mu.Unlock()
	scanner := bufio.NewScanner(osReleaseFile)
	for scanner.Scan() {
		columns := strings.Split(scanner.Text(), "=")
		if len(columns) > 1 {
			key := columns[0]
			value := strings.Trim(strings.TrimSpace(columns[1]), `"`)
			switch key {
			case "NAME":
				f.OSRelease.Name = value
			case "ID":
				f.OSRelease.ID = value
			case "PRETTY_NAME":
				f.OSRelease.PrettyName = value
			case "VERSION":
				f.OSRelease.Version = value
			case "VERSION_ID":
				f.OSRelease.VersionID = value
			}
		}
	}
	return
}

func (f *SystemFacts) getMachineID(wg *sync.WaitGroup) {
	defer wg.Done()
	machineIDFile, err := os.Open("/etc/machine-id")
	if err != nil {
		log.Println(err.Error())
		return
	}
	defer machineIDFile.Close()
	data, err := ioutil.ReadAll(machineIDFile)
	if err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	f.MachineID = strings.TrimSpace(string(data))
	return
}

func (f *SystemFacts) getBootID(wg *sync.WaitGroup) {
	defer wg.Done()
	bootIDFile, err := os.Open("/proc/sys/kernel/random/boot_id")
	if err != nil {
		log.Println(err.Error())
		return
	}
	defer bootIDFile.Close()
	data, err := ioutil.ReadAll(bootIDFile)
	if err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	f.BootID = strings.TrimSpace(string(data))
	return
}

func (f *SystemFacts) getInterfaces(wg *sync.WaitGroup) {
	defer wg.Done()
	ls, err := net.Interfaces()
	if err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	m := make(Interfaces)
	for _, i := range ls {
		ipaddreses := make([]string, 0)
		ip4addrs := make([]Ip4Address, 0)
		ip6addrs := make([]Ip6Address, 0)

		addrs, err := i.Addrs()
		if err != nil {
			log.Println(err.Error())
			return
		}
		for _, ip := range addrs {
			cidr := ip.String()
			ipaddreses = append(ipaddreses, cidr)
			ip, ipnet, _ := net.ParseCIDR(cidr)
			if ip.To4() != nil {
				ip4addrs = append(ip4addrs, Ip4Address{cidr, ip.String(), toNetmask(ipnet.Mask)})
				continue
			}
			if ip.To16() != nil {
				ones, _ := ipnet.Mask.Size()
				ip6addrs = append(ip6addrs, Ip6Address{cidr, ip.String(), ones})
			}
		}
		m[i.Name] = Interface{
			Name:         i.Name,
			Index:        i.Index,
			HardwareAddr: i.HardwareAddr.String(),
			IpAddresses:  ipaddreses,
			Ip4Addresses: ip4addrs,
			Ip6Addresses: ip6addrs,
		}
	}
	f.Network.Interfaces = m
	return
}

func toNetmask(m net.IPMask) string {
	return fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3])
}

func (f *SystemFacts) getUname(wg *sync.WaitGroup) {
	defer wg.Done()

	var buf unix.Utsname
	err := unix.Uname(&buf)
	if err != nil {
		log.Println(err.Error())
		return
	}

	f.mu.Lock()
	defer f.mu.Unlock()

	f.Domainname = charsToString(buf.Domainname)
	f.Architecture = charsToString(buf.Machine)
	f.Hostname = charsToString(buf.Nodename)
	f.Kernel.Name = charsToString(buf.Sysname)
	f.Kernel.Release = charsToString(buf.Release)
	f.Kernel.Version = charsToString(buf.Version)
	return
}

func (f *SystemFacts) getFileSystems(wg *sync.WaitGroup) {
	defer wg.Done()

	mtab, err := ioutil.ReadFile("/etc/mtab")
	if err != nil {
		log.Println(err.Error())
		return
	}

	fsMap := make(FileSystems)

	f.mu.Lock()
	defer f.mu.Unlock()

	s := bufio.NewScanner(bytes.NewBuffer(mtab))
	for s.Scan() {
		line := s.Text()
		if string(line[0]) == "#" {
			continue
		}
		fields := strings.Fields(s.Text())
		fs := FileSystem{}
		fs.Device = fields[0]
		fs.MountPoint = fields[1]
		fs.Type = fields[2]
		fs.Options = strings.Split(fields[3], ",")
		dumpFreq, err := strconv.ParseUint(fields[4], 10, 64)
		if err != nil {
			log.Println(err.Error())
			return
		}
		fs.DumpFreq = dumpFreq

		passNo, err := strconv.ParseUint(fields[4], 10, 64)
		if err != nil {
			log.Println(err.Error())
			return
		}
		fs.PassNo = passNo

		fsMap[fs.Device] = fs
	}

	f.FileSystems = fsMap
	return
}

func processExternalFacts(dir string, f *facts.Facts) {
	d, err := os.Open(dir)
	if err != nil {
		log.Println(err)
		return
	}
	defer d.Close()

	files, err := d.Readdir(0)
	if err != nil {
		log.Println(err)
		return
	}

	executableFacts := make([]string, 0)
	staticFacts := make([]string, 0)

	for _, fi := range files {
		name := filepath.Join(dir, fi.Name())
		if isExecutable(fi) {
			executableFacts = append(executableFacts, name)
			continue
		}
		if strings.HasSuffix(name, ".json") {
			staticFacts = append(staticFacts, name)
		}
	}

	var wg sync.WaitGroup
	for _, p := range staticFacts {
		p := p
		wg.Add(1)
		go factsFromFile(p, f, &wg)
	}
	for _, p := range executableFacts {
		p := p
		wg.Add(1)
		go factsFromExec(p, f, &wg)
	}
	wg.Wait()
}

func factsFromFile(path string, f *facts.Facts, wg *sync.WaitGroup) {
	defer wg.Done()
	data, err := ioutil.ReadFile(path)
	if err != nil {
		log.Println(err)
		return
	}
	var result interface{}
	err = json.Unmarshal(data, &result)
	if err != nil {
		log.Println(err)
		return
	}
	f.Add(strings.TrimSuffix(filepath.Base(path), ".json"), result)
}

func factsFromExec(path string, f *facts.Facts, wg *sync.WaitGroup) {
	defer wg.Done()
	out, err := exec.Command(path).Output()
	if err != nil {
		log.Println(err)
		return
	}
	var result interface{}
	err = json.Unmarshal(out, &result)
	if err != nil {
		log.Println(err)
		return
	}
	f.Add(filepath.Base(path), result)
}

func isExecutable(fi os.FileInfo) bool {
	if m := fi.Mode(); !m.IsDir() && m&0111 != 0 {
		return true
	}
	return false
}

func charsToString(ca [65]int8) string {
	s := make([]byte, len(ca))
	var lens int
	for ; lens < len(ca); lens++ {
		if ca[lens] == 0 {
			break
		}
		s[lens] = uint8(ca[lens])
	}
	return string(s[0:lens])
}
<|endoftext|>


<commit_before>// A fullscreen clock with some hardware data.
package main

import (
	"fmt"
	"log"
	"os/exec"
	"time"

	"openvg"
)

func main() {
	width, height := openvg.Init()
	dim := fmt.Sprintf("w=%d h=%d", width, height)

	w2 := float32(width / 2)
	h2 := float32(height / 2)
	w := float32(width)

	for {
		openvg.Start(width, height)
		openvg.BackgroundColor("black")

		openvg.FillRGB(44, 100, 232, 1) // blue 1/2 circle
		openvg.Circle(w2, 0, w)
		//openvg.Circle(w2, h2, h2*2)

		openvg.FillColor("white")
		l1, l2, l3 := clock()
		openvg.TextMid(w2, h2+h2/2, l1, "serif", width/15)
		openvg.TextMid(w2, h2, l2, "serif", width/7)
		openvg.TextMid(w2, h2-h2/2+100, l3, "serif", width/15)
		openvg.TextMid(w2, h2-h2/2-20, dim, "serif", width/30)

		l4 := hwinfo()
		openvg.TextMid(w2, h2-h2/2-100, l4, "serif", width/30)

		l5 := cpuTemperature()
		openvg.TextMid(w2, h2-h2/2-180, l5, "serif", width/30)

		openvg.End()
		time.Sleep(1000 * time.Millisecond)
	}
	//TODO catch keys or signals
	openvg.Finish()
}

func clock() (string, string, string) {
	t := time.Now()
	return t.Local().Format("Mon 2006-01-02"),
		t.Local().Format("15:04:05"),
		t.Local().Format("-0700 MST")
}

// Read the CPU/GPU clock frequence.
func hwinfo() string {
	b1, err := exec.Command("vcgencmd", "measure_clock", "arm").Output()
	if err != nil {
		log.Println(err)
	}
	b2, err := exec.Command("vcgencmd", "measure_clock", "core").Output()
	if err != nil {
		log.Println(err)
	}
	if len(b1) < 17 || len(b2) < 17 {
		return "bad len"
	}
	return fmt.Sprintf("arm=%sMhz core=%sMHz", b1[14:17], b2[13:16])
}

// Read the CPU temperature.
func cpuTemperature() string {
	b, err := exec.Command("vcgencmd", "measure_temp").Output()
	if err != nil {
		log.Println(err)
	}
	return string(b)
}

// Just a test.
func k_clk() string {
	// XXX set perms and read would be better
	b, err := exec.Command("sudo", "cat", "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq").Output()
	if err != nil {
		log.Println(err)
	}
	return string(b)
}
<commit_msg>Display a better error message.<commit_after>// A fullscreen clock with some hardware data.
package main

import (
	"fmt"
	"log"
	"os/exec"
	"time"

	"openvg"
)

func main() {
	width, height := openvg.Init()
	dim := fmt.Sprintf("w=%d h=%d", width, height)

	w2 := float32(width / 2)
	h2 := float32(height / 2)
	w := float32(width)

	for {
		openvg.Start(width, height)
		openvg.BackgroundColor("black")

		openvg.FillRGB(44, 100, 232, 1) // blue 1/2 circle
		openvg.Circle(w2, 0, w)
		//openvg.Circle(w2, h2, h2*2)

		openvg.FillColor("white")
		l1, l2, l3 := clock()
		openvg.TextMid(w2, h2+h2/2, l1, "serif", width/15)
		openvg.TextMid(w2, h2, l2, "serif", width/7)
		openvg.TextMid(w2, h2-h2/2+100, l3, "serif", width/15)
		openvg.TextMid(w2, h2-h2/2-20, dim, "serif", width/30)

		l4 := hwinfo()
		openvg.TextMid(w2, h2-h2/2-100, l4, "serif", width/30)

		l5 := cpuTemperature()
		openvg.TextMid(w2, h2-h2/2-180, l5, "serif", width/30)

		openvg.End()
		time.Sleep(1000 * time.Millisecond)
	}
	//TODO catch keys or signals
	openvg.Finish()
}

func clock() (string, string, string) {
	t := time.Now()
	return t.Local().Format("Mon 2006-01-02"),
		t.Local().Format("15:04:05"),
		t.Local().Format("-0700 MST")
}

// Read the CPU/GPU clock frequence.
func hwinfo() string {
	b1, err := exec.Command("vcgencmd", "measure_clock", "arm").Output()
	if err != nil {
		log.Println(err)
	}
	b2, err := exec.Command("vcgencmd", "measure_clock", "core").Output()
	if err != nil {
		log.Println(err)
	}
	if len(b1) < 17 || len(b2) < 17 {
		return "error: parse hw data"
	}
	return fmt.Sprintf("arm=%sMhz core=%sMHz", b1[14:17], b2[13:16])
}

// Read the CPU temperature.
func cpuTemperature() string {
	b, err := exec.Command("vcgencmd", "measure_temp").Output()
	if err != nil {
		log.Println(err)
	}
	return string(b)
}

// Just for testing, is insecure and slow.
func k_clk() string {
	b, err := exec.Command("sudo", "cat", "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq").Output()
	if err != nil {
		log.Println(err)
	}
	return string(b)
}
<|endoftext|>


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

package main

import (
	"bufio"
	"encoding/json"
	"io"
	"os"
	"text/template"
)

var cmdList = &Command{
	UsageLine: "list [-e] [-f format] [-json] [packages]",
	Short:     "list packages",
	Long: `
List lists the packages named by the import paths, one per line.

The default output shows the package import path:

    code.google.com/p/google-api-go-client/books/v1
    code.google.com/p/goauth2/oauth
    code.google.com/p/sqlite

The -f flag specifies an alternate format for the list,
using the syntax of package template.  The default output
is equivalent to -f '{{.ImportPath}}'.  The struct
being passed to the template is:

    type Package struct {
        Dir        string // directory containing package sources
        ImportPath string // import path of package in dir
        Name       string // package name
        Doc        string // package documentation string
        Target     string // install path
        Goroot     bool   // is this package in the Go root?
        Standard   bool   // is this package part of the standard Go library?
        Stale      bool   // would 'go install' do anything for this package?
        Root       string // Go root or Go path dir containing this package

        // Source files
        GoFiles  []string     // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
        CgoFiles []string     // .go sources files that import "C"
        CFiles   []string     // .c source files
        HFiles   []string     // .h source files
        SFiles   []string     // .s source files
        SysoFiles []string    // .syso object files to add to archive
        SwigFiles []string    // .swig files
        SwigCXXFiles []string // .swigcxx files

        // Cgo directives
        CgoCFLAGS    []string // cgo: flags for C compiler
        CgoLDFLAGS   []string // cgo: flags for linker
        CgoPkgConfig []string // cgo: pkg-config names

        // Dependency information
        Imports []string // import paths used by this package
        Deps    []string // all (recursively) imported dependencies

        // Error information
        Incomplete bool            // this package or a dependency has an error
        Error      *PackageError   // error loading package
        DepsErrors []*PackageError // errors loading dependencies

        TestGoFiles  []string // _test.go files in package
        TestImports  []string // imports from TestGoFiles
        XTestGoFiles []string // _test.go files outside package
        XTestImports []string // imports from XTestGoFiles
    }

The -json flag causes the package data to be printed in JSON format
instead of using the template format.

The -e flag changes the handling of erroneous packages, those that
cannot be found or are malformed.  By default, the list command
prints an error to standard error for each erroneous package and
omits the packages from consideration during the usual printing.
With the -e flag, the list command never prints errors to standard
error and instead processes the erroneous packages with the usual
printing.  Erroneous packages will have a non-empty ImportPath and
a non-nil Error field; other information may or may not be missing
(zeroed).

For more about specifying packages, see 'go help packages'.
	`,
}

func init() {
	cmdList.Run = runList // break init cycle
	cmdList.Flag.Var(buildCompiler{}, "compiler", "")
}

var listE = cmdList.Flag.Bool("e", false, "")
var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
var listJson = cmdList.Flag.Bool("json", false, "")
var nl = []byte{'\n'}

func runList(cmd *Command, args []string) {
	out := newCountingWriter(os.Stdout)
	defer out.w.Flush()

	var do func(*Package)
	if *listJson {
		do = func(p *Package) {
			b, err := json.MarshalIndent(p, "", "\t")
			if err != nil {
				out.Flush()
				fatalf("%s", err)
			}
			out.Write(b)
			out.Write(nl)
		}
	} else {
		tmpl, err := template.New("main").Parse(*listFmt)
		if err != nil {
			fatalf("%s", err)
		}
		do = func(p *Package) {
			out.Reset()
			if err := tmpl.Execute(out, p); err != nil {
				out.Flush()
				fatalf("%s", err)
			}
			if out.Count() > 0 {
				out.w.WriteRune('\n')
			}
		}
	}

	load := packages
	if *listE {
		load = packagesAndErrors
	}

	for _, pkg := range load(args) {
		do(pkg)
	}
}

// CountingWriter counts its data, so we can avoid appending a newline
// if there was no actual output.
type CountingWriter struct {
	w     *bufio.Writer
	count int64
}

func newCountingWriter(w io.Writer) *CountingWriter {
	return &CountingWriter{
		w: bufio.NewWriter(w),
	}
}

func (cw *CountingWriter) Write(p []byte) (n int, err error) {
	cw.count += int64(len(p))
	return cw.w.Write(p)
}

func (cw *CountingWriter) Flush() {
	cw.w.Flush()
}

func (cw *CountingWriter) Reset() {
	cw.count = 0
}

func (cw *CountingWriter) Count() int64 {
	return cw.count
}
<commit_msg>cmd/go: add join template function.<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"encoding/json"
	"io"
	"os"
	"strings"
	"text/template"
)

var cmdList = &Command{
	UsageLine: "list [-e] [-f format] [-json] [packages]",
	Short:     "list packages",
	Long: `
List lists the packages named by the import paths, one per line.

The default output shows the package import path:

    code.google.com/p/google-api-go-client/books/v1
    code.google.com/p/goauth2/oauth
    code.google.com/p/sqlite

The -f flag specifies an alternate format for the list, using the
syntax of package template.  The default output is equivalent to -f
'{{.ImportPath}}'.  One extra template function is available, "join",
which calls strings.Join. The struct being passed to the template is:

    type Package struct {
        Dir        string // directory containing package sources
        ImportPath string // import path of package in dir
        Name       string // package name
        Doc        string // package documentation string
        Target     string // install path
        Goroot     bool   // is this package in the Go root?
        Standard   bool   // is this package part of the standard Go library?
        Stale      bool   // would 'go install' do anything for this package?
        Root       string // Go root or Go path dir containing this package

        // Source files
        GoFiles  []string     // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
        CgoFiles []string     // .go sources files that import "C"
        CFiles   []string     // .c source files
        HFiles   []string     // .h source files
        SFiles   []string     // .s source files
        SysoFiles []string    // .syso object files to add to archive
        SwigFiles []string    // .swig files
        SwigCXXFiles []string // .swigcxx files

        // Cgo directives
        CgoCFLAGS    []string // cgo: flags for C compiler
        CgoLDFLAGS   []string // cgo: flags for linker
        CgoPkgConfig []string // cgo: pkg-config names

        // Dependency information
        Imports []string // import paths used by this package
        Deps    []string // all (recursively) imported dependencies

        // Error information
        Incomplete bool            // this package or a dependency has an error
        Error      *PackageError   // error loading package
        DepsErrors []*PackageError // errors loading dependencies

        TestGoFiles  []string // _test.go files in package
        TestImports  []string // imports from TestGoFiles
        XTestGoFiles []string // _test.go files outside package
        XTestImports []string // imports from XTestGoFiles
    }

The -json flag causes the package data to be printed in JSON format
instead of using the template format.

The -e flag changes the handling of erroneous packages, those that
cannot be found or are malformed.  By default, the list command
prints an error to standard error for each erroneous package and
omits the packages from consideration during the usual printing.
With the -e flag, the list command never prints errors to standard
error and instead processes the erroneous packages with the usual
printing.  Erroneous packages will have a non-empty ImportPath and
a non-nil Error field; other information may or may not be missing
(zeroed).

For more about specifying packages, see 'go help packages'.
	`,
}

func init() {
	cmdList.Run = runList // break init cycle
	cmdList.Flag.Var(buildCompiler{}, "compiler", "")
}

var listE = cmdList.Flag.Bool("e", false, "")
var listFmt = cmdList.Flag.String("f", "{{.ImportPath}}", "")
var listJson = cmdList.Flag.Bool("json", false, "")
var nl = []byte{'\n'}

func runList(cmd *Command, args []string) {
	out := newCountingWriter(os.Stdout)
	defer out.w.Flush()

	var do func(*Package)
	if *listJson {
		do = func(p *Package) {
			b, err := json.MarshalIndent(p, "", "\t")
			if err != nil {
				out.Flush()
				fatalf("%s", err)
			}
			out.Write(b)
			out.Write(nl)
		}
	} else {
		tmpl, err := template.New("main").Funcs(template.FuncMap{"join": strings.Join}).Parse(*listFmt)
		if err != nil {
			fatalf("%s", err)
		}
		do = func(p *Package) {
			out.Reset()
			if err := tmpl.Execute(out, p); err != nil {
				out.Flush()
				fatalf("%s", err)
			}
			if out.Count() > 0 {
				out.w.WriteRune('\n')
			}
		}
	}

	load := packages
	if *listE {
		load = packagesAndErrors
	}

	for _, pkg := range load(args) {
		do(pkg)
	}
}

// CountingWriter counts its data, so we can avoid appending a newline
// if there was no actual output.
type CountingWriter struct {
	w     *bufio.Writer
	count int64
}

func newCountingWriter(w io.Writer) *CountingWriter {
	return &CountingWriter{
		w: bufio.NewWriter(w),
	}
}

func (cw *CountingWriter) Write(p []byte) (n int, err error) {
	cw.count += int64(len(p))
	return cw.w.Write(p)
}

func (cw *CountingWriter) Flush() {
	cw.w.Flush()
}

func (cw *CountingWriter) Reset() {
	cw.count = 0
}

func (cw *CountingWriter) Count() int64 {
	return cw.count
}
<|endoftext|>


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

package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/build"
	"io"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"text/template"
	"unicode"
	"unicode/utf8"
)

// A Command is an implementation of a go command
// like go build or go fix.
type Command struct {
	// Run runs the command.
	// The args are the arguments after the command name.
	Run func(cmd *Command, args []string)

	// UsageLine is the one-line usage message.
	// The first word in the line is taken to be the command name.
	UsageLine string

	// Short is the short description shown in the 'go help' output.
	Short string

	// Long is the long message shown in the 'go help <this-command>' output.
	Long string

	// Flag is a set of flags specific to this command.
	Flag flag.FlagSet

	// CustomFlags indicates that the command will do its own
	// flag parsing.
	CustomFlags bool
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.UsageLine
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) Usage() {
	fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
	fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
	os.Exit(2)
}

// Runnable reports whether the command can be run; otherwise
// it is a documentation pseudo-command such as importpath.
func (c *Command) Runnable() bool {
	return c.Run != nil
}

// Commands lists the available commands and help topics.
// The order here is the order in which they are printed by 'go help'.
var commands = []*Command{
	cmdBuild,
	cmdClean,
	cmdDoc,
	cmdFix,
	cmdFmt,
	cmdGet,
	cmdInstall,
	cmdList,
	cmdRun,
	cmdTest,
	cmdTool,
	cmdVersion,
	cmdVet,

	helpGopath,
	helpImportpath,
	helpRemote,
	helpTestflag,
	helpTestfunc,
}

var exitStatus = 0
var exitMu sync.Mutex

func setExitStatus(n int) {
	exitMu.Lock()
	if exitStatus < n {
		exitStatus = n
	}
	exitMu.Unlock()
}

func main() {
	flag.Usage = usage
	flag.Parse()
	log.SetFlags(0)

	args := flag.Args()
	if len(args) < 1 {
		usage()
	}

	if args[0] == "help" {
		help(args[1:])
		return
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] && cmd.Run != nil {
			cmd.Flag.Usage = func() { cmd.Usage() }
			if cmd.CustomFlags {
				args = args[1:]
			} else {
				cmd.Flag.Parse(args[1:])
				args = cmd.Flag.Args()
			}
			cmd.Run(cmd, args)
			exit()
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown command %#q\n\n", args[0])
	usage()
}

var usageTemplate = `Go is a tool for managing Go source code.

Usage: go command [arguments]

The commands are:
{{range .}}{{if .Runnable}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use "go help [command]" for more information about a command.

Additional help topics:
{{range .}}{{if not .Runnable}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use "go help [topic]" for more information about that topic.

`

var helpTemplate = `{{if .Run}}usage: go {{.UsageLine}}

{{end}}{{.Long | trim}}
`

var documentationTemplate = `// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
{{range .}}{{if .Short}}{{.Short | capitalize}}

{{end}}{{if .Run}}Usage:

	go {{.UsageLine}}

{{end}}{{.Long | trim}}

{{end}}*/
package documentation

// NOTE: cmdDoc is in fmt.go.
`

// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) {
	t := template.New("top")
	t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
	template.Must(t.Parse(text))
	if err := t.Execute(w, data); err != nil {
		panic(err)
	}
}

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

func printUsage(w io.Writer) {
	tmpl(w, usageTemplate, commands)
}

func usage() {
	printUsage(os.Stderr)
	os.Exit(2)
}

// help implements the 'help' command.
func help(args []string) {
	if len(args) == 0 {
		printUsage(os.Stdout)
		// not exit 2: succeeded at 'go help'.
		return
	}
	if len(args) != 1 {
		fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
		os.Exit(2) // failed at 'go help'
	}

	arg := args[0]

	// 'go help documentation' generates doc.go.
	if arg == "documentation" {
		buf := new(bytes.Buffer)
		printUsage(buf)
		usage := &Command{Long: buf.String()}
		tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...))
		return
	}

	for _, cmd := range commands {
		if cmd.Name() == arg {
			tmpl(os.Stdout, helpTemplate, cmd)
			// not exit 2: succeeded at 'go help cmd'.
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown help topic %#q.  Run 'go help'.\n", arg)
	os.Exit(2) // failed at 'go help cmd'
}

// importPaths returns the import paths to use for the given command line.
func importPaths(args []string) []string {
	if len(args) == 0 {
		return []string{"."}
	}
	var out []string
	for _, a := range args {
		if isLocalPath(a) && strings.Contains(a, "...") {
			out = append(out, allPackagesInFS(a)...)
			continue
		}
		if a == "all" || a == "std" || strings.Contains(a, "...") {
			out = append(out, allPackages(a)...)
			continue
		}
		out = append(out, a)
	}
	return out
}

var atexitFuncs []func()

func atexit(f func()) {
	atexitFuncs = append(atexitFuncs, f)
}

func exit() {
	for _, f := range atexitFuncs {
		f()
	}
	os.Exit(exitStatus)
}

func fatalf(format string, args ...interface{}) {
	errorf(format, args...)
	exit()
}

func errorf(format string, args ...interface{}) {
	log.Printf(format, args...)
	setExitStatus(1)
}

var logf = log.Printf

func exitIfErrors() {
	if exitStatus != 0 {
		exit()
	}
}

func run(cmdargs ...interface{}) {
	cmdline := stringList(cmdargs...)
	cmd := exec.Command(cmdline[0], cmdline[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		errorf("%v", err)
	}
}

func runOut(dir string, cmdargs ...interface{}) []byte {
	cmdline := stringList(cmdargs...)
	cmd := exec.Command(cmdline[0], cmdline[1:]...)
	cmd.Dir = dir
	out, err := cmd.CombinedOutput()
	if err != nil {
		os.Stderr.Write(out)
		errorf("%v", err)
		out = nil
	}
	return out
}

// matchPattern(pattern)(name) reports whether
// name matches pattern.  Pattern is a limited glob
// pattern in which '...' means 'any string' and there
// is no other special syntax.
func matchPattern(pattern string) func(name string) bool {
	re := regexp.QuoteMeta(pattern)
	re = strings.Replace(re, `\.\.\.`, `.*`, -1)
	reg := regexp.MustCompile(`^` + re + `$`)
	return func(name string) bool {
		return reg.MatchString(name)
	}
}

// allPackages returns all the packages that can be found
// under the $GOPATH directories and $GOROOT matching pattern.
// The pattern is either "all" (all packages), "std" (standard packages)
// or a path including "...".
func allPackages(pattern string) []string {
	match := func(string) bool { return true }
	if pattern != "all" && pattern != "std" {
		match = matchPattern(pattern)
	}

	have := map[string]bool{
		"builtin": true, // ignore pseudo-package that exists only for documentation
	}
	if !buildContext.CgoEnabled {
		have["runtime/cgo"] = true // ignore during walk
	}
	var pkgs []string

	// Commands
	goroot := build.Path[0].Path
	cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
	filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() || path == cmd {
			return nil
		}
		name := path[len(cmd):]
		// Commands are all in cmd/, not in subdirectories.
		if strings.Contains(name, string(filepath.Separator)) {
			return filepath.SkipDir
		}

		_, err = build.ScanDir(path)
		if err != nil {
			return nil
		}

		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
		name = "cmd/" + name
		if !have[name] {
			have[name] = true
			if match(name) {
				pkgs = append(pkgs, name)
			}
		}
		return nil
	})

	for _, t := range build.Path {
		if pattern == "std" && !t.Goroot {
			continue
		}
		src := t.SrcDir() + string(filepath.Separator)
		filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
			if err != nil || !fi.IsDir() || path == src {
				return nil
			}

			// Avoid .foo, _foo, and testdata directory trees.
			_, elem := filepath.Split(path)
			if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
				return filepath.SkipDir
			}

			name := filepath.ToSlash(path[len(src):])
			if pattern == "std" && strings.Contains(name, ".") {
				return filepath.SkipDir
			}
			if have[name] {
				return nil
			}
			have[name] = true

			_, err = build.ScanDir(path)
			if err != nil && strings.Contains(err.Error(), "no Go source files") {
				return nil
			}

			if match(name) {
				pkgs = append(pkgs, name)
			}

			// Avoid go/build test data.
			// TODO: Move it into a testdata directory.
			if path == filepath.Join(build.Path[0].SrcDir(), "go/build") {
				return filepath.SkipDir
			}

			return nil
		})
	}

	if len(pkgs) == 0 {
		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
	}
	return pkgs
}

// allPackagesInFS is like allPackages but is passed a pattern
// beginning ./ or ../, meaning it should scan the tree rooted
// at the given directory.  There are ... in the pattern too.
func allPackagesInFS(pattern string) []string {
	// Find directory to begin the scan.
	// Could be smarter but this one optimization
	// is enough for now, since ... is usually at the
	// end of a path.
	i := strings.Index(pattern, "...")
	dir, _ := path.Split(pattern[:i])

	// pattern begins with ./ or ../.
	// path.Clean will discard the ./ but not the ../.
	// We need to preserve the ./ for pattern matching
	// and in the returned import paths.
	prefix := ""
	if strings.HasPrefix(pattern, "./") {
		prefix = "./"
	}
	match := matchPattern(pattern)

	var pkgs []string
	filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() || path == dir {
			return nil
		}

		// Avoid .foo, _foo, and testdata directory trees.
		_, elem := filepath.Split(path)
		if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
			return filepath.SkipDir
		}

		name := prefix + filepath.ToSlash(path)
		if !match(name) {
			return nil
		}
		if _, err = build.ScanDir(path); err != nil {
			return nil
		}
		pkgs = append(pkgs, name)
		return nil
	})

	if len(pkgs) == 0 {
		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
	}
	return pkgs
}

// stringList's arguments should be a sequence of string or []string values.
// stringList flattens them into a single []string.
func stringList(args ...interface{}) []string {
	var x []string
	for _, arg := range args {
		switch arg := arg.(type) {
		case []string:
			x = append(x, arg...)
		case string:
			x = append(x, arg)
		default:
			panic("stringList: invalid argument")
		}
	}
	return x
}

// isLocalPath returns true if arg is an import path denoting
// a local file system directory.  That is, it returns true if the
// path begins with ./ or ../ .
func isLocalPath(arg string) bool {
	return arg == "." || arg == ".." || strings.HasPrefix(arg, "./") || strings.HasPrefix(arg, "../")
}
<commit_msg>cmd/go: fix 'go help <command>'<commit_after>// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"bytes"
	"flag"
	"fmt"
	"go/build"
	"io"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"sync"
	"text/template"
	"unicode"
	"unicode/utf8"
)

// A Command is an implementation of a go command
// like go build or go fix.
type Command struct {
	// Run runs the command.
	// The args are the arguments after the command name.
	Run func(cmd *Command, args []string)

	// UsageLine is the one-line usage message.
	// The first word in the line is taken to be the command name.
	UsageLine string

	// Short is the short description shown in the 'go help' output.
	Short string

	// Long is the long message shown in the 'go help <this-command>' output.
	Long string

	// Flag is a set of flags specific to this command.
	Flag flag.FlagSet

	// CustomFlags indicates that the command will do its own
	// flag parsing.
	CustomFlags bool
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.UsageLine
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) Usage() {
	fmt.Fprintf(os.Stderr, "usage: %s\n\n", c.UsageLine)
	fmt.Fprintf(os.Stderr, "%s\n", strings.TrimSpace(c.Long))
	os.Exit(2)
}

// Runnable reports whether the command can be run; otherwise
// it is a documentation pseudo-command such as importpath.
func (c *Command) Runnable() bool {
	return c.Run != nil
}

// Commands lists the available commands and help topics.
// The order here is the order in which they are printed by 'go help'.
var commands = []*Command{
	cmdBuild,
	cmdClean,
	cmdDoc,
	cmdFix,
	cmdFmt,
	cmdGet,
	cmdInstall,
	cmdList,
	cmdRun,
	cmdTest,
	cmdTool,
	cmdVersion,
	cmdVet,

	helpGopath,
	helpImportpath,
	helpRemote,
	helpTestflag,
	helpTestfunc,
}

var exitStatus = 0
var exitMu sync.Mutex

func setExitStatus(n int) {
	exitMu.Lock()
	if exitStatus < n {
		exitStatus = n
	}
	exitMu.Unlock()
}

func main() {
	flag.Usage = usage
	flag.Parse()
	log.SetFlags(0)

	args := flag.Args()
	if len(args) < 1 {
		usage()
	}

	if args[0] == "help" {
		help(args[1:])
		return
	}

	for _, cmd := range commands {
		if cmd.Name() == args[0] && cmd.Run != nil {
			cmd.Flag.Usage = func() { cmd.Usage() }
			if cmd.CustomFlags {
				args = args[1:]
			} else {
				cmd.Flag.Parse(args[1:])
				args = cmd.Flag.Args()
			}
			cmd.Run(cmd, args)
			exit()
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown command %#q\n\n", args[0])
	usage()
}

var usageTemplate = `Go is a tool for managing Go source code.

Usage: go command [arguments]

The commands are:
{{range .}}{{if .Runnable}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use "go help [command]" for more information about a command.

Additional help topics:
{{range .}}{{if not .Runnable}}
    {{.Name | printf "%-11s"}} {{.Short}}{{end}}{{end}}

Use "go help [topic]" for more information about that topic.

`

var helpTemplate = `{{if .Runnable}}usage: go {{.UsageLine}}

{{end}}{{.Long | trim}}
`

var documentationTemplate = `// Copyright 2011 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
{{range .}}{{if .Short}}{{.Short | capitalize}}

{{end}}{{if .Runnable}}Usage:

	go {{.UsageLine}}

{{end}}{{.Long | trim}}

{{end}}*/
package documentation

// NOTE: cmdDoc is in fmt.go.
`

// tmpl executes the given template text on data, writing the result to w.
func tmpl(w io.Writer, text string, data interface{}) {
	t := template.New("top")
	t.Funcs(template.FuncMap{"trim": strings.TrimSpace, "capitalize": capitalize})
	template.Must(t.Parse(text))
	if err := t.Execute(w, data); err != nil {
		panic(err)
	}
}

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

func printUsage(w io.Writer) {
	tmpl(w, usageTemplate, commands)
}

func usage() {
	printUsage(os.Stderr)
	os.Exit(2)
}

// help implements the 'help' command.
func help(args []string) {
	if len(args) == 0 {
		printUsage(os.Stdout)
		// not exit 2: succeeded at 'go help'.
		return
	}
	if len(args) != 1 {
		fmt.Fprintf(os.Stderr, "usage: go help command\n\nToo many arguments given.\n")
		os.Exit(2) // failed at 'go help'
	}

	arg := args[0]

	// 'go help documentation' generates doc.go.
	if arg == "documentation" {
		buf := new(bytes.Buffer)
		printUsage(buf)
		usage := &Command{Long: buf.String()}
		tmpl(os.Stdout, documentationTemplate, append([]*Command{usage}, commands...))
		return
	}

	for _, cmd := range commands {
		if cmd.Name() == arg {
			tmpl(os.Stdout, helpTemplate, cmd)
			// not exit 2: succeeded at 'go help cmd'.
			return
		}
	}

	fmt.Fprintf(os.Stderr, "Unknown help topic %#q.  Run 'go help'.\n", arg)
	os.Exit(2) // failed at 'go help cmd'
}

// importPaths returns the import paths to use for the given command line.
func importPaths(args []string) []string {
	if len(args) == 0 {
		return []string{"."}
	}
	var out []string
	for _, a := range args {
		if isLocalPath(a) && strings.Contains(a, "...") {
			out = append(out, allPackagesInFS(a)...)
			continue
		}
		if a == "all" || a == "std" || strings.Contains(a, "...") {
			out = append(out, allPackages(a)...)
			continue
		}
		out = append(out, a)
	}
	return out
}

var atexitFuncs []func()

func atexit(f func()) {
	atexitFuncs = append(atexitFuncs, f)
}

func exit() {
	for _, f := range atexitFuncs {
		f()
	}
	os.Exit(exitStatus)
}

func fatalf(format string, args ...interface{}) {
	errorf(format, args...)
	exit()
}

func errorf(format string, args ...interface{}) {
	log.Printf(format, args...)
	setExitStatus(1)
}

var logf = log.Printf

func exitIfErrors() {
	if exitStatus != 0 {
		exit()
	}
}

func run(cmdargs ...interface{}) {
	cmdline := stringList(cmdargs...)
	cmd := exec.Command(cmdline[0], cmdline[1:]...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		errorf("%v", err)
	}
}

func runOut(dir string, cmdargs ...interface{}) []byte {
	cmdline := stringList(cmdargs...)
	cmd := exec.Command(cmdline[0], cmdline[1:]...)
	cmd.Dir = dir
	out, err := cmd.CombinedOutput()
	if err != nil {
		os.Stderr.Write(out)
		errorf("%v", err)
		out = nil
	}
	return out
}

// matchPattern(pattern)(name) reports whether
// name matches pattern.  Pattern is a limited glob
// pattern in which '...' means 'any string' and there
// is no other special syntax.
func matchPattern(pattern string) func(name string) bool {
	re := regexp.QuoteMeta(pattern)
	re = strings.Replace(re, `\.\.\.`, `.*`, -1)
	reg := regexp.MustCompile(`^` + re + `$`)
	return func(name string) bool {
		return reg.MatchString(name)
	}
}

// allPackages returns all the packages that can be found
// under the $GOPATH directories and $GOROOT matching pattern.
// The pattern is either "all" (all packages), "std" (standard packages)
// or a path including "...".
func allPackages(pattern string) []string {
	match := func(string) bool { return true }
	if pattern != "all" && pattern != "std" {
		match = matchPattern(pattern)
	}

	have := map[string]bool{
		"builtin": true, // ignore pseudo-package that exists only for documentation
	}
	if !buildContext.CgoEnabled {
		have["runtime/cgo"] = true // ignore during walk
	}
	var pkgs []string

	// Commands
	goroot := build.Path[0].Path
	cmd := filepath.Join(goroot, "src/cmd") + string(filepath.Separator)
	filepath.Walk(cmd, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() || path == cmd {
			return nil
		}
		name := path[len(cmd):]
		// Commands are all in cmd/, not in subdirectories.
		if strings.Contains(name, string(filepath.Separator)) {
			return filepath.SkipDir
		}

		_, err = build.ScanDir(path)
		if err != nil {
			return nil
		}

		// We use, e.g., cmd/gofmt as the pseudo import path for gofmt.
		name = "cmd/" + name
		if !have[name] {
			have[name] = true
			if match(name) {
				pkgs = append(pkgs, name)
			}
		}
		return nil
	})

	for _, t := range build.Path {
		if pattern == "std" && !t.Goroot {
			continue
		}
		src := t.SrcDir() + string(filepath.Separator)
		filepath.Walk(src, func(path string, fi os.FileInfo, err error) error {
			if err != nil || !fi.IsDir() || path == src {
				return nil
			}

			// Avoid .foo, _foo, and testdata directory trees.
			_, elem := filepath.Split(path)
			if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
				return filepath.SkipDir
			}

			name := filepath.ToSlash(path[len(src):])
			if pattern == "std" && strings.Contains(name, ".") {
				return filepath.SkipDir
			}
			if have[name] {
				return nil
			}
			have[name] = true

			_, err = build.ScanDir(path)
			if err != nil && strings.Contains(err.Error(), "no Go source files") {
				return nil
			}

			if match(name) {
				pkgs = append(pkgs, name)
			}

			// Avoid go/build test data.
			// TODO: Move it into a testdata directory.
			if path == filepath.Join(build.Path[0].SrcDir(), "go/build") {
				return filepath.SkipDir
			}

			return nil
		})
	}

	if len(pkgs) == 0 {
		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
	}
	return pkgs
}

// allPackagesInFS is like allPackages but is passed a pattern
// beginning ./ or ../, meaning it should scan the tree rooted
// at the given directory.  There are ... in the pattern too.
func allPackagesInFS(pattern string) []string {
	// Find directory to begin the scan.
	// Could be smarter but this one optimization
	// is enough for now, since ... is usually at the
	// end of a path.
	i := strings.Index(pattern, "...")
	dir, _ := path.Split(pattern[:i])

	// pattern begins with ./ or ../.
	// path.Clean will discard the ./ but not the ../.
	// We need to preserve the ./ for pattern matching
	// and in the returned import paths.
	prefix := ""
	if strings.HasPrefix(pattern, "./") {
		prefix = "./"
	}
	match := matchPattern(pattern)

	var pkgs []string
	filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
		if err != nil || !fi.IsDir() || path == dir {
			return nil
		}

		// Avoid .foo, _foo, and testdata directory trees.
		_, elem := filepath.Split(path)
		if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
			return filepath.SkipDir
		}

		name := prefix + filepath.ToSlash(path)
		if !match(name) {
			return nil
		}
		if _, err = build.ScanDir(path); err != nil {
			return nil
		}
		pkgs = append(pkgs, name)
		return nil
	})

	if len(pkgs) == 0 {
		fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern)
	}
	return pkgs
}

// stringList's arguments should be a sequence of string or []string values.
// stringList flattens them into a single []string.
func stringList(args ...interface{}) []string {
	var x []string
	for _, arg := range args {
		switch arg := arg.(type) {
		case []string:
			x = append(x, arg...)
		case string:
			x = append(x, arg)
		default:
			panic("stringList: invalid argument")
		}
	}
	return x
}

// isLocalPath returns true if arg is an import path denoting
// a local file system directory.  That is, it returns true if the
// path begins with ./ or ../ .
func isLocalPath(arg string) bool {
	return arg == "." || arg == ".." || strings.HasPrefix(arg, "./") || strings.HasPrefix(arg, "../")
}
<|endoftext|>


<commit_before>package main

import (
	"testing"

	"github.com/mozilla-services/heka/message"
)

func newField(name string, value interface{}) *message.Field {
	field, err := message.NewField(name, value, "")
	if err != nil {
		panic(err)
	}
	return field
}

func newTestMessage() *message.Message {
	msg := &message.Message{}
	msg.SetHostname("srv001")
	msg.SetLogger("foo")
	for k, v := range map[string]interface{}{
		"status": 500,
		"float":  1.6,
		"up":     true,
	} {
		msg.AddField(newField(k, v))
	}
	return msg
}

func TestGetFieldValue(t *testing.T) {
	msg := newTestMessage()
	if expect, got := "srv001", getFieldValue("@hostname", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if expect, got := "foo", getFieldValue("@logger", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if expect, got := int64(500), getFieldValue("status", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if expect, got := 1.6, getFieldValue("float", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if expect, got := true, getFieldValue("up", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
}

var fieldToFloatTests = map[*message.Field]float64{
	newField("", 23.5): 23.5,
	newField("", 5):    5.0,
	newField("", true): 1.0,
}

func TestFieldToFloat(t *testing.T) {
	for field, expect := range fieldToFloatTests {
		got, err := fieldToFloat(field)
		if err != nil {
			t.Fatal("Expected %s but got error: %s", expect, err)
		}
		if expect != got {
			t.Fatal("Expect: %s, Got: %s", expect, got)
		}
	}
}

func TestNewBridge(t *testing.T) {
	bridge, err := newBridge("metrics.sample.json")
	if err != nil {
		t.Fatal(err)
	}
	if expect, got := 5, len(bridge.metrics); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if bridge.metrics[2].gaugeVec == nil {
		t.Fatal("Expected 3rd metric to be gaugeVec")
	}
	if expect, got := "Logger = 'x'", bridge.metrics[2].MetricConfig.Matcher; expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if bridge.metrics[2].matcher == nil {
		t.Fatal("Expected matcher to be setup")
	}
}
<commit_msg>Fix test<commit_after>package main

import (
	"testing"

	"github.com/mozilla-services/heka/message"
)

func newField(name string, value interface{}) *message.Field {
	field, err := message.NewField(name, value, "")
	if err != nil {
		panic(err)
	}
	return field
}

func newTestMessage() *message.Message {
	msg := &message.Message{}
	msg.SetHostname("srv001")
	msg.SetLogger("foo")
	for k, v := range map[string]interface{}{
		"status": 500,
		"float":  1.6,
		"up":     true,
	} {
		msg.AddField(newField(k, v))
	}
	return msg
}

func TestGetFieldValue(t *testing.T) {
	msg := newTestMessage()
	if expect, got := "srv001", getFieldValue("@hostname", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if expect, got := "foo", getFieldValue("@logger", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if expect, got := int64(500), getFieldValue("status", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if expect, got := 1.6, getFieldValue("float", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if expect, got := true, getFieldValue("up", msg); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
}

var fieldToFloatTests = map[*message.Field]float64{
	newField("", 23.5): 23.5,
	newField("", 5):    5.0,
	newField("", true): 1.0,
}

func TestFieldToFloat(t *testing.T) {
	for field, expect := range fieldToFloatTests {
		got, err := fieldToFloat(field)
		if err != nil {
			t.Fatal("Expected %s but got error: %s", expect, err)
		}
		if expect != got {
			t.Fatal("Expect: %s, Got: %s", expect, got)
		}
	}
}

func TestNewBridge(t *testing.T) {
	bridge, err := newBridge("metrics.sample.json")
	if err != nil {
		t.Fatal(err)
	}
	if expect, got := 5, len(bridge.metrics); expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if bridge.metrics[2].gaugeVec == nil {
		t.Fatal("Expected 3rd metric to be gaugeVec")
	}
	if expect, got := "Logger == 'x'", bridge.metrics[2].MetricConfig.Matcher; expect != got {
		t.Fatalf("Expect: %s, Got: %s", expect, got)
	}
	if bridge.metrics[2].matcher == nil {
		t.Fatal("Expected matcher to be setup")
	}
}
<|endoftext|>


<commit_before>package processout

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// Gateways manages the Gateway struct
type Gatewaies struct {
	p *ProcessOut
}

type Gateway struct {
	// ID : ID of the gateway
	ID string `json:"id"`
	// Name : Name of the payment gateway
	Name string `json:"name"`
	// DisplayName : Name of the payment gateway that can be displayed
	DisplayName string `json:"display_name"`
	// LogoURL : Logo URL of the payment gateway
	LogoURL string `json:"logo_url"`
	// URL : URL of the payment gateway
	URL string `json:"url"`
	// Description : Description of the payment gateway
	Description string `json:"description"`
}

// dummyGateway is a dummy function that's only
// here because some files need specific packages and some don't.
// It's easier to include it for every file. In case you couldn't
// tell, everything is generated.
func dummyGateway() {
	type dummy struct {
		a bytes.Buffer
		b json.RawMessage
		c http.File
		d strings.Reader
		e time.Time
		f url.URL
	}
	errors.New("")
}
<commit_msg>Add flows to gateway model<commit_after>package processout

import (
	"bytes"
	"encoding/json"
	"errors"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// Gateways manages the Gateway struct
type Gatewaies struct {
	p *ProcessOut
}

type Gateway struct {
	// ID : ID of the gateway
	ID string `json:"id"`
	// Name : Name of the payment gateway
	Name string `json:"name"`
	// DisplayName : Name of the payment gateway that can be displayed
	DisplayName string `json:"display_name"`
	// LogoURL : Logo URL of the payment gateway
	LogoURL string `json:"logo_url"`
	// URL : URL of the payment gateway
	URL string `json:"url"`
	// Flows : Supported flow by the gateway (one-off, subscription or tokenization)
	Flows []string `json:"flows"`
	// Description : Description of the payment gateway
	Description string `json:"description"`
}

// dummyGateway is a dummy function that's only
// here because some files need specific packages and some don't.
// It's easier to include it for every file. In case you couldn't
// tell, everything is generated.
func dummyGateway() {
	type dummy struct {
		a bytes.Buffer
		b json.RawMessage
		c http.File
		d strings.Reader
		e time.Time
		f url.URL
	}
	errors.New("")
}
<|endoftext|>