<commit_before>package main

import (
	"context"
	"fmt"

	"github.com/urfave/cli"

	"github.com/manifoldco/go-manifold"
	"github.com/manifoldco/manifold-cli/clients"
	"github.com/manifoldco/manifold-cli/config"
	"github.com/manifoldco/manifold-cli/errs"
	"github.com/manifoldco/manifold-cli/generated/marketplace/client"
	resClient "github.com/manifoldco/manifold-cli/generated/marketplace/client/resource"
	"github.com/manifoldco/manifold-cli/generated/marketplace/models"
	"github.com/manifoldco/manifold-cli/prompts"
)

func init() {
	appCmd := cli.Command{
		Name:  "app",
		Usage: "Manages an App in Manifold",
		Subcommands: []cli.Command{
			{
				Name:      "add",
				ArgsUsage: "[label]",
				Usage:     "Add a resource to an app in Manifold.",
				Flags: []cli.Flag{
					appFlag(),
				},
				Action: chain(ensureSession, loadDirPrefs, appAddCmd),
			},
			{
				Name:      "delete",
				ArgsUsage: "[label]",
				Usage:     "Removes a resource from an app in Manifold.",
				Flags: []cli.Flag{
					appFlag(),
				},
				Action: chain(ensureSession, deleteAppCmd),
			},
		},
	}

	cmds = append(cmds, appCmd)
}

func appAddCmd(cliCtx *cli.Context) error {
	ctx := context.Background()

	appName := cliCtx.String("app")
	if appName != "" {
		n := manifold.Name(appName)
		if err := n.Validate(nil); err != nil {
			return errs.NewUsageExitError(cliCtx, errs.ErrInvalidAppName)
		}
	}

	cfg, err := config.Load()
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Could not load configuration: %s", err), -1)
	}

	marketplaceClient, err := clients.NewMarketplace(cfg)
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Failed to create Marketplace client: %s", err), -1)
	}

	resource, res, err := getResource(ctx, cliCtx, cfg, marketplaceClient)
	if err != nil {
		return cli.NewExitError(err, -1)
	}

	if appName == "" {
		apps := fetchUniqueAppNames(res)
		_, appName, err = prompts.SelectCreateAppName(apps, appName, false)
		if err != nil {
			return prompts.HandleSelectError(err, "Could not select app")
		}
	}

	err = updateResourceApp(ctx, cfg, resource, marketplaceClient, appName)
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Failed to add app to resource: %s", err), -1)
	}

	fmt.Printf("Your resource \"%s\" has been added to the app \"%s\"\n", resource.Body.Label, appName)

	return nil
}

func deleteAppCmd(cliCtx *cli.Context) error {
	ctx := context.Background()

	cfg, err := config.Load()
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Could not load configuration: %s", err), -1)
	}

	marketplaceClient, err := clients.NewMarketplace(cfg)
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Failed to create Marketplace client: %s", err), -1)
	}

	resource, _, err := getResource(ctx, cliCtx, cfg, marketplaceClient)
	if err != nil {
		return cli.NewExitError(err, -1)
	}

	err = updateResourceApp(ctx, cfg, resource, marketplaceClient, "")
	if err != nil {
		return cli.NewExitError(
			fmt.Sprintf("Failed to remove app from resource \"%s\": %s", resource.Body.Label, err), -1)
	}

	fmt.Printf("Your resource \"%s\" has been removed from the app \"%s\"\n", resource.Body.Label,
		resource.Body.AppName)

	return nil
}

func getResource(ctx context.Context, cliCtx *cli.Context, cfg *config.Config,
	marketplaceClient *client.Marketplace,
) (*models.Resource, []*models.Resource, error) {
	args := cliCtx.Args()

	resourceLabel := ""
	if len(args) > 1 {
		return nil, nil, errs.NewUsageExitError(cliCtx, errs.ErrTooManyArgs)
	}
	if len(args) > 0 {
		resourceLabel = args[0]
		l := manifold.Label(resourceLabel)
		if err := l.Validate(nil); err != nil {
			return nil, nil, errs.NewUsageExitError(cliCtx, errs.ErrInvalidResourceName)
		}
	}

	res, err := clients.FetchResources(ctx, marketplaceClient)
	if err != nil {
		return nil, nil, cli.NewExitError(
			fmt.Sprintf("Failed to fetch the list of provisioned resources: %s", err), -1)
	}

	res, err = filterResourcesWithApp(res)
	if err != nil {
		return nil, nil, err
	}

	resourceIdx, _, err := prompts.SelectResource(res, resourceLabel)
	if err != nil {
		return nil, nil, prompts.HandleSelectError(err, "Could not select Resource")
	}

	return res[resourceIdx], res, nil
}

func updateResourceApp(ctx context.Context, cfg *config.Config, resource *models.Resource,
	marketplaceClient *client.Marketplace, appName string,
) error {
	appAdd := &models.PublicUpdateResource{
		Body: &models.PublicUpdateResourceBody{
			AppName: &appName,
		},
	}

	c := resClient.NewPatchResourcesIDParamsWithContext(ctx)
	c.SetBody(appAdd)
	c.SetID(resource.ID.String())

	_, err := marketplaceClient.Resource.PatchResourcesID(c, nil)
	if err != nil {
		switch e := err.(type) {
		case *resClient.PatchResourcesIDBadRequest:
			return e.Payload
		case *resClient.PatchResourcesIDUnauthorized:
			return e.Payload
		case *resClient.PatchResourcesIDInternalServerError:
			return errs.ErrSomethingWentHorriblyWrong
		}
	}

	return nil
}

func filterResourcesWithApp(resources []*models.Resource) ([]*models.Resource, error) {
	var rs []*models.Resource

	for _, r := range resources {
		if r.Body.AppName != "" {
			rs = append(rs, r)
		}
	}

	if len(rs) == 0 {
		return nil, errs.ErrNoApps
	}

	return rs, nil
}
<commit_msg>Don't filter resources with apps for add<commit_after>package main

import (
	"context"
	"fmt"

	"github.com/urfave/cli"

	"github.com/manifoldco/go-manifold"
	"github.com/manifoldco/manifold-cli/clients"
	"github.com/manifoldco/manifold-cli/config"
	"github.com/manifoldco/manifold-cli/errs"
	"github.com/manifoldco/manifold-cli/generated/marketplace/client"
	resClient "github.com/manifoldco/manifold-cli/generated/marketplace/client/resource"
	"github.com/manifoldco/manifold-cli/generated/marketplace/models"
	"github.com/manifoldco/manifold-cli/prompts"
)

func init() {
	appCmd := cli.Command{
		Name:  "app",
		Usage: "Manages an App in Manifold",
		Subcommands: []cli.Command{
			{
				Name:      "add",
				ArgsUsage: "[label]",
				Usage:     "Add a resource to an app in Manifold.",
				Flags: []cli.Flag{
					appFlag(),
				},
				Action: chain(ensureSession, loadDirPrefs, appAddCmd),
			},
			{
				Name:      "delete",
				ArgsUsage: "[label]",
				Usage:     "Removes a resource from an app in Manifold.",
				Flags: []cli.Flag{
					appFlag(),
				},
				Action: chain(ensureSession, deleteAppCmd),
			},
		},
	}

	cmds = append(cmds, appCmd)
}

func appAddCmd(cliCtx *cli.Context) error {
	ctx := context.Background()

	appName := cliCtx.String("app")
	if appName != "" {
		n := manifold.Name(appName)
		if err := n.Validate(nil); err != nil {
			return errs.NewUsageExitError(cliCtx, errs.ErrInvalidAppName)
		}
	}

	cfg, err := config.Load()
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Could not load configuration: %s", err), -1)
	}

	marketplaceClient, err := clients.NewMarketplace(cfg)
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Failed to create Marketplace client: %s", err), -1)
	}

	resource, res, err := getResource(ctx, cliCtx, cfg, marketplaceClient, false)
	if err != nil {
		return cli.NewExitError(err, -1)
	}

	if appName == "" {
		apps := fetchUniqueAppNames(res)
		_, appName, err = prompts.SelectCreateAppName(apps, appName, false)
		if err != nil {
			return prompts.HandleSelectError(err, "Could not select app")
		}
	}

	err = updateResourceApp(ctx, cfg, resource, marketplaceClient, appName)
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Failed to add app to resource: %s", err), -1)
	}

	fmt.Printf("Your resource \"%s\" has been added to the app \"%s\"\n", resource.Body.Label, appName)

	return nil
}

func deleteAppCmd(cliCtx *cli.Context) error {
	ctx := context.Background()

	cfg, err := config.Load()
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Could not load configuration: %s", err), -1)
	}

	marketplaceClient, err := clients.NewMarketplace(cfg)
	if err != nil {
		return cli.NewExitError(fmt.Sprintf("Failed to create Marketplace client: %s", err), -1)
	}

	resource, _, err := getResource(ctx, cliCtx, cfg, marketplaceClient, true)
	if err != nil {
		return cli.NewExitError(err, -1)
	}

	err = updateResourceApp(ctx, cfg, resource, marketplaceClient, "")
	if err != nil {
		return cli.NewExitError(
			fmt.Sprintf("Failed to remove app from resource \"%s\": %s", resource.Body.Label, err), -1)
	}

	fmt.Printf("Your resource \"%s\" has been removed from the app \"%s\"\n", resource.Body.Label,
		resource.Body.AppName)

	return nil
}

func getResource(ctx context.Context, cliCtx *cli.Context, cfg *config.Config,
	marketplaceClient *client.Marketplace, withAppsOnly bool,
) (*models.Resource, []*models.Resource, error) {
	args := cliCtx.Args()

	resourceLabel := ""
	if len(args) > 1 {
		return nil, nil, errs.NewUsageExitError(cliCtx, errs.ErrTooManyArgs)
	}
	if len(args) > 0 {
		resourceLabel = args[0]
		l := manifold.Label(resourceLabel)
		if err := l.Validate(nil); err != nil {
			return nil, nil, errs.NewUsageExitError(cliCtx, errs.ErrInvalidResourceName)
		}
	}

	res, err := clients.FetchResources(ctx, marketplaceClient)
	if err != nil {
		return nil, nil, cli.NewExitError(
			fmt.Sprintf("Failed to fetch the list of provisioned resources: %s", err), -1)
	}

	if withAppsOnly {
		res, err = filterResourcesWithApp(res)
		if err != nil {
			return nil, nil, err
		}
	}

	resourceIdx, _, err := prompts.SelectResource(res, resourceLabel)
	if err != nil {
		return nil, nil, prompts.HandleSelectError(err, "Could not select Resource")
	}

	return res[resourceIdx], res, nil
}

func updateResourceApp(ctx context.Context, cfg *config.Config, resource *models.Resource,
	marketplaceClient *client.Marketplace, appName string,
) error {
	appAdd := &models.PublicUpdateResource{
		Body: &models.PublicUpdateResourceBody{
			AppName: &appName,
		},
	}

	c := resClient.NewPatchResourcesIDParamsWithContext(ctx)
	c.SetBody(appAdd)
	c.SetID(resource.ID.String())

	_, err := marketplaceClient.Resource.PatchResourcesID(c, nil)
	if err != nil {
		switch e := err.(type) {
		case *resClient.PatchResourcesIDBadRequest:
			return e.Payload
		case *resClient.PatchResourcesIDUnauthorized:
			return e.Payload
		case *resClient.PatchResourcesIDInternalServerError:
			return errs.ErrSomethingWentHorriblyWrong
		}
	}

	return nil
}

func filterResourcesWithApp(resources []*models.Resource) ([]*models.Resource, error) {
	var rs []*models.Resource

	for _, r := range resources {
		if r.Body.AppName != "" {
			rs = append(rs, r)
		}
	}

	if len(rs) == 0 {
		return nil, errs.ErrNoApps
	}

	return rs, nil
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"

	"github.com/github/hub/ui"
	"github.com/github/hub/utils"
	"github.com/kballard/go-shellquote"
)

type Cmd struct {
	Name string
	Args []string
}

func (cmd Cmd) String() string {
	return fmt.Sprintf("%s %s", cmd.Name, strings.Join(cmd.Args, " "))
}

func (cmd *Cmd) WithArg(arg string) *Cmd {
	cmd.Args = append(cmd.Args, arg)

	return cmd
}

func (cmd *Cmd) WithArgs(args ...string) *Cmd {
	for _, arg := range args {
		cmd.WithArg(arg)
	}

	return cmd
}

func (cmd *Cmd) CombinedOutput() (string, error) {
	verboseLog(cmd)
	output, err := exec.Command(cmd.Name, cmd.Args...).CombinedOutput()

	return string(output), err
}

func (cmd *Cmd) Success() bool {
	verboseLog(cmd)
	err := exec.Command(cmd.Name, cmd.Args...).Run()
	return err == nil
}

// Run runs command with `Exec` on platforms except Windows
// which only supports `Spawn`
func (cmd *Cmd) Run() error {
	if runtime.GOOS == "windows" {
		return cmd.Spawn()
	} else {
		return cmd.Exec()
	}
}

// Spawn runs command with spawn(3)
func (cmd *Cmd) Spawn() error {
	verboseLog(cmd)
	c := exec.Command(cmd.Name, cmd.Args...)
	c.Stdin = os.Stdin
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	return c.Run()
}

// Exec runs command with exec(3)
// Note that Windows doesn't support exec(3): http://golang.org/src/pkg/syscall/exec_windows.go#L339
func (cmd *Cmd) Exec() error {
	binary, err := exec.LookPath(cmd.Name)
	if err != nil {
		return fmt.Errorf("command not found: %s", cmd.Name)
	}

	args := []string{binary}
	args = append(args, cmd.Args...)

	verboseLog(cmd)
	return syscall.Exec(binary, args, os.Environ())
}

func New(cmd string) *Cmd {
	cmds, err := shellquote.Split(cmd)
	utils.Check(err)

	name := cmds[0]
	args := make([]string, 0)
	for _, arg := range cmds[1:] {
		args = append(args, arg)
	}
	return &Cmd{Name: name, Args: args}
}

func NewWithArray(cmd []string) *Cmd {
	return &Cmd{Name: cmd[0], Args: cmd[1:]}
}

func verboseLog(cmd *Cmd) {
	if os.Getenv("HUB_VERBOSE") != "" {
		msg := fmt.Sprintf("$ %s %s", cmd.Name, strings.Join(cmd.Args, " "))
		if ui.IsTerminal(os.Stderr) {
			msg = fmt.Sprintf("\033[35m%s\033[0m", msg)
		}
		ui.Errorln(msg)
	}
}
<commit_msg>Ensure that verbose logging always happens in `Exec()`<commit_after>package cmd

import (
	"fmt"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"

	"github.com/github/hub/ui"
	"github.com/github/hub/utils"
	"github.com/kballard/go-shellquote"
)

type Cmd struct {
	Name string
	Args []string
}

func (cmd Cmd) String() string {
	return fmt.Sprintf("%s %s", cmd.Name, strings.Join(cmd.Args, " "))
}

func (cmd *Cmd) WithArg(arg string) *Cmd {
	cmd.Args = append(cmd.Args, arg)

	return cmd
}

func (cmd *Cmd) WithArgs(args ...string) *Cmd {
	for _, arg := range args {
		cmd.WithArg(arg)
	}

	return cmd
}

func (cmd *Cmd) CombinedOutput() (string, error) {
	verboseLog(cmd)
	output, err := exec.Command(cmd.Name, cmd.Args...).CombinedOutput()

	return string(output), err
}

func (cmd *Cmd) Success() bool {
	verboseLog(cmd)
	err := exec.Command(cmd.Name, cmd.Args...).Run()
	return err == nil
}

// Run runs command with `Exec` on platforms except Windows
// which only supports `Spawn`
func (cmd *Cmd) Run() error {
	if runtime.GOOS == "windows" {
		return cmd.Spawn()
	} else {
		return cmd.Exec()
	}
}

// Spawn runs command with spawn(3)
func (cmd *Cmd) Spawn() error {
	verboseLog(cmd)
	c := exec.Command(cmd.Name, cmd.Args...)
	c.Stdin = os.Stdin
	c.Stdout = os.Stdout
	c.Stderr = os.Stderr

	return c.Run()
}

// Exec runs command with exec(3)
// Note that Windows doesn't support exec(3): http://golang.org/src/pkg/syscall/exec_windows.go#L339
func (cmd *Cmd) Exec() error {
	verboseLog(cmd)

	binary, err := exec.LookPath(cmd.Name)
	if err != nil {
		return fmt.Errorf("command not found: %s", cmd.Name)
	}

	args := []string{binary}
	args = append(args, cmd.Args...)

	return syscall.Exec(binary, args, os.Environ())
}

func New(cmd string) *Cmd {
	cmds, err := shellquote.Split(cmd)
	utils.Check(err)

	name := cmds[0]
	args := make([]string, 0)
	for _, arg := range cmds[1:] {
		args = append(args, arg)
	}
	return &Cmd{Name: name, Args: args}
}

func NewWithArray(cmd []string) *Cmd {
	return &Cmd{Name: cmd[0], Args: cmd[1:]}
}

func verboseLog(cmd *Cmd) {
	if os.Getenv("HUB_VERBOSE") != "" {
		msg := fmt.Sprintf("$ %s %s", cmd.Name, strings.Join(cmd.Args, " "))
		if ui.IsTerminal(os.Stderr) {
			msg = fmt.Sprintf("\033[35m%s\033[0m", msg)
		}
		ui.Errorln(msg)
	}
}
<|endoftext|>


<commit_before>// Copyright 2017 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package cmd

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

	"github.com/open-policy-agent/opa/format"

	"github.com/spf13/cobra"
)

var (
	overwrite bool
	list      bool
	diff      bool
)

var formatCommand = &cobra.Command{
	Use:   "fmt",
	Short: "Format Rego source code",
	Long: `Format Rego source code.

The 'fmt' command takes a Rego source file and outputs a reformatted version.
The format of the output is not defined specifically; whatever this tool outputs
is considered correct format (with the exception of bugs).

If the '-w' option is supplied, the 'fmt' command with overwrite the source file
instead of printing to stdout.

If the '-d' option is supplied, the 'fmt' command will output a diff between the
original and formatted source.

If the '-l' option is suppled, the 'fmt' command will output the names of files
that would change if formatted. The '-l' option will suppress any other output
to stdout from the 'fmt' command.`,
	Run: func(cmd *cobra.Command, args []string) {
		os.Exit(opaFmt(args))
	},
}

func opaFmt(args []string) int {
	for _, filename := range args {
		if err := filepath.Walk(filename, formatFile); err != nil {
			switch err := err.(type) {
			case fmtError:
				fmt.Fprintln(os.Stderr, err.msg)
				return err.code
			default:
				fmt.Fprintln(os.Stderr, err.Error())
				return 1
			}
		}
	}

	return 0
}

func formatFile(filename string, info os.FileInfo, err error) error {
	if info.IsDir() {
		return nil
	}

	if filepath.Ext(filename) != ".rego" {
		return nil
	}

	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return newError("failed to open file: %v", err)
	}

	formatted, err := format.Source(filename, contents)
	if err != nil {
		return newError("failed to parse Rego source file: %v", err)
	}

	if bytes.Equal(formatted, contents) {
		return nil
	}

	var out io.Writer = os.Stdout
	if list {
		fmt.Fprintln(out, filename)
		out = ioutil.Discard
	}

	if diff {
		stdout, stderr, err := doDiff(contents, formatted)
		if err != nil && stdout.Len() == 0 {
			fmt.Fprintln(os.Stderr, stderr.String())
			return newError("failed to diff formatting: %v", err)
		}

		fmt.Fprintln(out, stdout.String())

		// If we called diff, we shouldn't output to stdout.
		out = ioutil.Discard
	}

	if overwrite {
		backupName := filename + ".bak"
		if _, err := os.Stat(backupName); err == nil || !os.IsNotExist(err) {
			backupName, err = requestBackupName(backupName)
			if err != nil {
				return newError("failed to read user input: %v", err)
			}
		}

		bak, err := os.OpenFile(backupName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, info.Mode().Perm())
		if err != nil {
			return newError("failed to open backup file for writing: %v", err)
		}
		defer bak.Close()

		if _, err := bak.Write(contents); err != nil {
			return newError("failed to write to backup file: %v", err)
		}

		outfile, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, info.Mode().Perm())
		if err != nil {
			return newError("failed to open file for writing: %v", err)
		}
		defer outfile.Close()
		out = outfile
	}

	_, err = out.Write(formatted)
	if err != nil {
		return newError("failed writing formatted contents: %v", err)
	}

	return nil
}

func requestBackupName(old string) (string, error) {
	r := bufio.NewReader(os.Stdin)
	fmt.Printf("Backup file (%s) already exists. Enter a name for the backup file (or blank to overwrite): ", old)
	resp, err := r.ReadString('\n')
	if err != nil {
		return "", err
	}

	resp = strings.TrimSpace(resp)
	if resp == "" {
		return old, nil
	}
	return resp, nil
}

func doDiff(old, new []byte) (stdout, stderr bytes.Buffer, err error) {
	o, err := ioutil.TempFile("", ".opafmt")
	if err != nil {
		return stdout, stderr, err
	}
	n, err := ioutil.TempFile("", ".opafmt")
	if err != nil {
		return stdout, stderr, err
	}

	o.Write(old)
	n.Write(new)

	cmd := exec.Command("diff", "-u", o.Name(), n.Name())
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	return stdout, stderr, cmd.Run()
}

type fmtError struct {
	msg  string
	code int
}

func (e fmtError) Error() string {
	return fmt.Sprintf("%s (%d)", e.msg, e.code)
}

func newError(msg string, a ...interface{}) fmtError {
	return fmtError{
		msg:  fmt.Sprintf(msg, a...),
		code: 2,
	}
}

func init() {
	formatCommand.Flags().BoolVarP(&overwrite, "write", "w", false, "overwrite the original source file")
	formatCommand.Flags().BoolVarP(&list, "list", "l", false, "list all files who would change when formatted")
	formatCommand.Flags().BoolVarP(&diff, "diff", "d", false, "only display a diff of the changes")
	RootCommand.AddCommand(formatCommand)
}
<commit_msg>Correct `opa fmt` panic on missing files<commit_after>// Copyright 2017 The OPA Authors.  All rights reserved.
// Use of this source code is governed by an Apache2
// license that can be found in the LICENSE file.

package cmd

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

	"github.com/open-policy-agent/opa/format"

	"github.com/spf13/cobra"
)

var (
	overwrite bool
	list      bool
	diff      bool
)

var formatCommand = &cobra.Command{
	Use:   "fmt",
	Short: "Format Rego source code",
	Long: `Format Rego source code.

The 'fmt' command takes a Rego source file and outputs a reformatted version.
The format of the output is not defined specifically; whatever this tool outputs
is considered correct format (with the exception of bugs).

If the '-w' option is supplied, the 'fmt' command with overwrite the source file
instead of printing to stdout.

If the '-d' option is supplied, the 'fmt' command will output a diff between the
original and formatted source.

If the '-l' option is suppled, the 'fmt' command will output the names of files
that would change if formatted. The '-l' option will suppress any other output
to stdout from the 'fmt' command.`,
	Run: func(cmd *cobra.Command, args []string) {
		os.Exit(opaFmt(args))
	},
}

func opaFmt(args []string) int {
	for _, filename := range args {
		if err := filepath.Walk(filename, formatFile); err != nil {
			switch err := err.(type) {
			case fmtError:
				fmt.Fprintln(os.Stderr, err.msg)
				return err.code
			default:
				fmt.Fprintln(os.Stderr, err.Error())
				return 1
			}
		}
	}

	return 0
}

func formatFile(filename string, info os.FileInfo, err error) error {
	if err != nil {
		return err
	}

	if info.IsDir() {
		return nil
	}

	if filepath.Ext(filename) != ".rego" {
		return nil
	}

	contents, err := ioutil.ReadFile(filename)
	if err != nil {
		return newError("failed to open file: %v", err)
	}

	formatted, err := format.Source(filename, contents)
	if err != nil {
		return newError("failed to parse Rego source file: %v", err)
	}

	if bytes.Equal(formatted, contents) {
		return nil
	}

	var out io.Writer = os.Stdout
	if list {
		fmt.Fprintln(out, filename)
		out = ioutil.Discard
	}

	if diff {
		stdout, stderr, err := doDiff(contents, formatted)
		if err != nil && stdout.Len() == 0 {
			fmt.Fprintln(os.Stderr, stderr.String())
			return newError("failed to diff formatting: %v", err)
		}

		fmt.Fprintln(out, stdout.String())

		// If we called diff, we shouldn't output to stdout.
		out = ioutil.Discard
	}

	if overwrite {
		backupName := filename + ".bak"
		if _, err := os.Stat(backupName); err == nil || !os.IsNotExist(err) {
			backupName, err = requestBackupName(backupName)
			if err != nil {
				return newError("failed to read user input: %v", err)
			}
		}

		bak, err := os.OpenFile(backupName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, info.Mode().Perm())
		if err != nil {
			return newError("failed to open backup file for writing: %v", err)
		}
		defer bak.Close()

		if _, err := bak.Write(contents); err != nil {
			return newError("failed to write to backup file: %v", err)
		}

		outfile, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, info.Mode().Perm())
		if err != nil {
			return newError("failed to open file for writing: %v", err)
		}
		defer outfile.Close()
		out = outfile
	}

	_, err = out.Write(formatted)
	if err != nil {
		return newError("failed writing formatted contents: %v", err)
	}

	return nil
}

func requestBackupName(old string) (string, error) {
	r := bufio.NewReader(os.Stdin)
	fmt.Printf("Backup file (%s) already exists. Enter a name for the backup file (or blank to overwrite): ", old)
	resp, err := r.ReadString('\n')
	if err != nil {
		return "", err
	}

	resp = strings.TrimSpace(resp)
	if resp == "" {
		return old, nil
	}
	return resp, nil
}

func doDiff(old, new []byte) (stdout, stderr bytes.Buffer, err error) {
	o, err := ioutil.TempFile("", ".opafmt")
	if err != nil {
		return stdout, stderr, err
	}
	n, err := ioutil.TempFile("", ".opafmt")
	if err != nil {
		return stdout, stderr, err
	}

	o.Write(old)
	n.Write(new)

	cmd := exec.Command("diff", "-u", o.Name(), n.Name())
	cmd.Stdout = &stdout
	cmd.Stderr = &stderr
	return stdout, stderr, cmd.Run()
}

type fmtError struct {
	msg  string
	code int
}

func (e fmtError) Error() string {
	return fmt.Sprintf("%s (%d)", e.msg, e.code)
}

func newError(msg string, a ...interface{}) fmtError {
	return fmtError{
		msg:  fmt.Sprintf(msg, a...),
		code: 2,
	}
}

func init() {
	formatCommand.Flags().BoolVarP(&overwrite, "write", "w", false, "overwrite the original source file")
	formatCommand.Flags().BoolVarP(&list, "list", "l", false, "list all files who would change when formatted")
	formatCommand.Flags().BoolVarP(&diff, "diff", "d", false, "only display a diff of the changes")
	RootCommand.AddCommand(formatCommand)
}
<|endoftext|>


<commit_before>package raft

import (
	"os"
	"testing"

	"github.com/barrucadu/logdb"

	"github.com/hashicorp/raft"
	"github.com/hashicorp/raft/bench"
)

func BenchmarkFirstIndex(b *testing.B) {
	db := assertCreateForBench(b, "first_index")
	defer assertClose(b, db)

	raftbench.FirstIndex(b, db)
}

func BenchmarkLastIndex(b *testing.B) {
	db := assertCreateForBench(b, "last_index")
	defer assertClose(b, db)

	raftbench.LastIndex(b, db)
}

func BenchmarkGetLog(b *testing.B) {
	db := assertCreateForBench(b, "get_log")
	defer assertClose(b, db)

	raftbench.GetLog(b, db)
}

func BenchmarkStoreLog(b *testing.B) {
	db := assertCreateForBench(b, "store_log")
	defer assertClose(b, db)

	// raftbench.StoreLog(b, db)

	// This is the hashicorp benchmark, modified to use 1-based indecing for log entries.
	for n := 0; n < b.N; n++ {
		log := &raft.Log{Index: uint64(n) + 1, Data: []byte("data")}
		if err := db.StoreLog(log); err != nil {
			b.Fatalf("err: %s", err)
		}
	}
}

func BenchmarkStoreLogs(b *testing.B) {
	db := assertCreateForBench(b, "store_logs")
	defer assertClose(b, db)

	raftbench.StoreLogs(b, db)
}

func BenchmarkDeleteRange(b *testing.B) {
	db := assertCreateForBench(b, "delete_range")
	defer assertClose(b, db)

	// raftbench.DeleteRange(b, db)

	// This is the hashicorp benchmark, modified to not have gaps.
	var logs []*raft.Log
	for n := 0; n < b.N; n++ {
		for i := 0; i < 10; i++ {
			logs = append(logs, &raft.Log{Index: uint64(n*10 + i + 1), Data: []byte("data")})
		}
	}
	if err := db.StoreLogs(logs); err != nil {
		b.Fatalf("err: %s", err)
	}
	b.ResetTimer()

	// Delete a range of the data
	for n := 0; n < b.N; n++ {
		offset := 10 * n
		if err := db.DeleteRange(uint64(offset), uint64(offset+9)); err != nil {
			b.Fatalf("err: %s", err)
		}
	}
}

/// HELPERS

func assertCreateForBench(b *testing.B, benchName string) *LogStore {
	_ = os.RemoveAll("../test_db/raft-bench/" + benchName)
	db, err := logdb.Open("../test_db/raft-bench/"+benchName, 1024*1024, true)
	if err != nil {
		b.Fatal(err)
	}
	ldb, err := New(db)
	if err != nil {
		b.Fatal(err)
	}
	return ldb
}
<commit_msg>Rename Raft benchmarks to be in line with others.<commit_after>package raft

import (
	"os"
	"testing"

	"github.com/barrucadu/logdb"

	"github.com/hashicorp/raft"
	"github.com/hashicorp/raft/bench"
)

func BenchmarkLogDB_FirstIndex(b *testing.B) {
	db := assertCreateForBench(b, "first_index")
	defer assertClose(b, db)

	raftbench.FirstIndex(b, db)
}

func BenchmarkLogDB_LastIndex(b *testing.B) {
	db := assertCreateForBench(b, "last_index")
	defer assertClose(b, db)

	raftbench.LastIndex(b, db)
}

func BenchmarkLogDB_GetLog(b *testing.B) {
	db := assertCreateForBench(b, "get_log")
	defer assertClose(b, db)

	raftbench.GetLog(b, db)
}

func BenchmarkLogDB_StoreLog(b *testing.B) {
	db := assertCreateForBench(b, "store_log")
	defer assertClose(b, db)

	// raftbench.StoreLog(b, db)

	// This is the hashicorp benchmark, modified to use 1-based indecing for log entries.
	for n := 0; n < b.N; n++ {
		log := &raft.Log{Index: uint64(n) + 1, Data: []byte("data")}
		if err := db.StoreLog(log); err != nil {
			b.Fatalf("err: %s", err)
		}
	}
}

func BenchmarkLogDB_StoreLogs(b *testing.B) {
	db := assertCreateForBench(b, "store_logs")
	defer assertClose(b, db)

	raftbench.StoreLogs(b, db)
}

func BenchmarkLogDB_DeleteRange(b *testing.B) {
	db := assertCreateForBench(b, "delete_range")
	defer assertClose(b, db)

	// raftbench.DeleteRange(b, db)

	// This is the hashicorp benchmark, modified to not have gaps.
	var logs []*raft.Log
	for n := 0; n < b.N; n++ {
		for i := 0; i < 10; i++ {
			logs = append(logs, &raft.Log{Index: uint64(n*10 + i + 1), Data: []byte("data")})
		}
	}
	if err := db.StoreLogs(logs); err != nil {
		b.Fatalf("err: %s", err)
	}
	b.ResetTimer()

	// Delete a range of the data
	for n := 0; n < b.N; n++ {
		offset := 10 * n
		if err := db.DeleteRange(uint64(offset), uint64(offset+9)); err != nil {
			b.Fatalf("err: %s", err)
		}
	}
}

/// HELPERS

func assertCreateForBench(b *testing.B, benchName string) *LogStore {
	_ = os.RemoveAll("../test_db/raft-bench/" + benchName)
	db, err := logdb.Open("../test_db/raft-bench/"+benchName, 1024*1024, true)
	if err != nil {
		b.Fatal(err)
	}
	ldb, err := New(db)
	if err != nil {
		b.Fatal(err)
	}
	return ldb
}
<|endoftext|>


<commit_before>// Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-ego/ego/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package cmd

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

	"github.com/go-ego/e/log"
)

var cmdNew = &Command{
	UsageLine: "new [appname]",
	Short:     "auto-generate code for the ego app, Creates a ego API application",
	Long: `

`, Run: createDir,
}

func createDir(cmd *Command, args []string) int {
	gopath := GetGOPATHs()
	fmt.Println(gopath)
	githubsrc := gopath[0] + "/src/github.com/go-ego/e/gen/"
	if runtime.GOOS == "windows" {
		githubsrc = strings.Replace(githubsrc, "/", "\\", -1)
	}
	// fmt.Println("githubsrc--------", githubsrc)

	afile, err := WalkFile(githubsrc, "")
	if err != nil {
		fmt.Println(err)
	}
	// fmt.Println(afile)

	if len(args) != 1 {
		logger.Fatal("Argument [appname] is missing")
	}

	apppath, packpath, err := checkEnv(args[0])
	if err != nil {
		logger.Fatalf("%s", err)
	}

	if isExist(apppath) {
		logger.Errorf(log.Bold("Application '%s' already exists"), apppath)
		logger.Warn(log.Bold("Do you want to overwrite it? [Yes|No] "))
		if !askForConfirmation() {
			os.Exit(2)
		}
	}

	logger.Info("Creating application... " + packpath)

	for i := 0; i < len(afile); i++ {

		tfile := strings.Replace(afile[i], githubsrc, "", -1)
		name := apppath + "/" + tfile

		CopyFile(afile[i], name)
	}

	return 0
}

func CopyFile(src, dst string) (w int64, err error) {
	srcFile, err := os.Open(src)
	if err != nil {
		return
	}
	defer srcFile.Close()
	// if fileExist(dst) != true {
	if !fileExist(dst) {
		Wirtefile("", dst)
	}
	dstFile, err := os.Create(dst)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer dstFile.Close()
	return io.Copy(dstFile, srcFile)
}

func fileExist(filename string) bool {
	_, err := os.Stat(filename)
	return err == nil || os.IsExist(err)
}

func Wirtefile(wirtestr string, userFile string) {

	fmt.Println(log.Blue("Create:::"), log.Yellow(userFile))

	os.MkdirAll(path.Dir(userFile), os.ModePerm)

	fout, err := os.Create(userFile)
	defer fout.Close()
	if err != nil {
		fmt.Println(userFile, err)
		return
	}

	fout.WriteString(wirtestr)

}

func WalkFile(dirPth, suffix string) (files []string, err error) {
	files = make([]string, 0, 30)
	suffix = strings.ToUpper(suffix)
	err = filepath.Walk(dirPth, func(filename string, fi os.FileInfo, err error) error {

		if fi.IsDir() { // dir
			return nil
		}

		if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) {
			files = append(files, filename)
		}
		return nil
	})
	return files, err
}
<commit_msg>Update Windows path<commit_after>// Copyright 2016 The go-ego Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// https://github.com/go-ego/ego/blob/master/LICENSE
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

package cmd

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

	"github.com/go-ego/e/log"
)

var cmdNew = &Command{
	UsageLine: "new [appname]",
	Short:     "auto-generate code for the ego app, Creates a ego API application",
	Long: `

`, Run: createDir,
}

func createDir(cmd *Command, args []string) int {
	gopath := GetGOPATHs()
	fmt.Println(gopath)
	githubsrc := gopath[0] + "/src/github.com/go-ego/e/gen/"
	if runtime.GOOS == "windows" {
		githubsrc = strings.Replace(githubsrc, "/", "\\", -1)
	}
	// fmt.Println("githubsrc--------", githubsrc)

	afilesrc, err := WalkFile(githubsrc, "")
	if err != nil {
		fmt.Println(err)
	}
	// fmt.Println(afilesrc)

	if len(args) != 1 {
		logger.Fatal("Argument [appname] is missing")
	}

	apppath, packpath, err := checkEnv(args[0])
	if err != nil {
		logger.Fatalf("%s", err)
	}

	if isExist(apppath) {
		logger.Errorf(log.Bold("Application '%s' already exists"), apppath)
		logger.Warn(log.Bold("Do you want to overwrite it? [Yes|No] "))
		if !askForConfirmation() {
			os.Exit(2)
		}
	}

	logger.Info("Creating application... " + packpath)

	for i := 0; i < len(afilesrc); i++ {
		if runtime.GOOS == "windows" {
			afilesrc[i] = strings.Replace(afilesrc[i], "/", "\\", -1)
		}
		tfile := strings.Replace(afilesrc[i], githubsrc, "", -1)
		name := apppath + "/" + tfile
		CopyFile(afilesrc[i], name)
	}

	return 0
}

func CopyFile(src, dst string) (w int64, err error) {
	srcFile, err := os.Open(src)
	if err != nil {
		return
	}
	defer srcFile.Close()
	// if fileExist(dst) != true {
	if !fileExist(dst) {
		Wirtefile("", dst)
	}
	dstFile, err := os.Create(dst)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer dstFile.Close()
	return io.Copy(dstFile, srcFile)
}

func fileExist(filename string) bool {
	_, err := os.Stat(filename)
	return err == nil || os.IsExist(err)
}

func Wirtefile(wirtestr string, userFile string) {

	fmt.Println(log.Blue("Create:::"), log.Yellow(userFile))

	os.MkdirAll(path.Dir(userFile), os.ModePerm)

	fout, err := os.Create(userFile)
	defer fout.Close()
	if err != nil {
		fmt.Println(userFile, err)
		return
	}

	fout.WriteString(wirtestr)

}

func WalkFile(dirPth, suffix string) (files []string, err error) {
	files = make([]string, 0, 30)
	suffix = strings.ToUpper(suffix)
	err = filepath.Walk(dirPth, func(filename string, fi os.FileInfo, err error) error {

		if fi.IsDir() { // dir
			return nil
		}

		if strings.HasSuffix(strings.ToUpper(fi.Name()), suffix) {
			files = append(files, filename)
		}
		return nil
	})
	return files, err
}
<|endoftext|>


<commit_before>package cmd

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/atotto/clipboard"
	"github.com/b4b4r07/gist/config"
	"github.com/b4b4r07/gist/gist"
	"github.com/b4b4r07/gist/util"
	"github.com/fatih/color"
	"github.com/spf13/cobra"

	"golang.org/x/crypto/ssh/terminal"
)

var newCmd = &cobra.Command{
	Use:   "new [FILE/DIR]",
	Short: "Create a new gist",
	Long:  `Create a new gist. If you pass file/dir paths, upload those files`,
	RunE:  new,
}

type gistItem struct {
	files gist.Files
	desc  string
}

func new(cmd *cobra.Command, args []string) error {
	var err error
	var gi gistItem

	gist_, err := gist.New(config.Conf.Gist.Token)
	if err != nil {
		return err
	}

	// Make Gist from various conditions
	switch {
	case config.Conf.Flag.FromClipboard:
		gi, err = makeFromClipboard()
	case !terminal.IsTerminal(0):
		gi, err = makeFromStdin()
	case len(args) > 0:
		gi, err = makeFromArguments(args)
	case len(args) == 0:
		gi, err = makeFromEditor()
	}

	if err != nil {
		return err
	}

	url, err := gist_.Create(gi.files, gi.desc)
	if err != nil {
		return err
	}
	util.Underline("Created", url)

	if config.Conf.Flag.OpenURL {
		util.Open(url)
	}
	return nil
}

func makeFromClipboard() (gi gistItem, err error) {
	content, err := clipboard.ReadAll()
	if err != nil {
		return
	}
	if content == "" {
		return gi, errors.New("clipboard is empty")
	}
	filename, err := util.Scan(color.YellowString("Filename> "), !util.ScanAllowEmpty)
	if err != nil {
		return
	}
	desc, err := util.Scan(color.GreenString("Description> "), util.ScanAllowEmpty)
	if err != nil {
		return
	}
	return gistItem{
		files: gist.Files{gist.File{
			Filename: filename,
			Content:  content,
		}},
		desc: desc,
	}, nil
}

func makeFromStdin() (gi gistItem, err error) {
	body, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		return
	}
	return gistItem{
		files: gist.Files{gist.File{
			Filename: "stdin",
			Content:  string(body),
		}},
		desc: "",
	}, nil
}

func makeFromEditor() (gi gistItem, err error) {
	filename, err := util.Scan(color.YellowString("Filename> "), !util.ScanAllowEmpty)
	if err != nil {
		return
	}
	f, err := util.TempFile(filename)
	defer os.Remove(f.Name())
	err = util.RunCommand(config.Conf.Core.Editor, f.Name())
	if err != nil {
		return
	}
	desc, err := util.Scan(color.GreenString("Description> "), util.ScanAllowEmpty)
	if err != nil {
		return
	}
	return gistItem{
		files: gist.Files{gist.File{
			Filename: filename,
			Content:  util.FileContent(f.Name()),
		}},
		desc: desc,
	}, nil
}

func makeFromArguments(args []string) (gi gistItem, err error) {
	var gistFiles gist.Files
	target := args[0]
	files := []string{}
	err = filepath.Walk(target, func(path string, info os.FileInfo, err error) error {
		if strings.HasPrefix(path, ".") {
			return nil
		}
		if info.IsDir() {
			return nil
		}
		files = append(files, path)
		return nil
	})
	if err != nil {
		return
	}
	if len(files) == 0 {
		return gi, fmt.Errorf("%s: no files", target)
	}
	for _, file := range files {
		fmt.Fprintf(color.Output, "%s %s\n", color.YellowString("Filename>"), file)
		gistFiles = append(gistFiles, gist.File{
			Filename: filepath.Base(file),
			Content:  util.FileContent(file),
		})
	}
	desc, err := util.Scan(color.GreenString("Description> "), util.ScanAllowEmpty)
	if err != nil {
		return
	}
	return gistItem{
		files: gistFiles,
		desc:  desc,
	}, nil
}

func init() {
	RootCmd.AddCommand(newCmd)
	newCmd.Flags().BoolVarP(&config.Conf.Flag.OpenURL, "open", "o", false, "Open with the default browser")
	newCmd.Flags().BoolVarP(&config.Conf.Flag.Private, "private", "p", false, "Create as private gist")
	newCmd.Flags().BoolVarP(&config.Conf.Flag.FromClipboard, "from-clipboard", "c", false, "Create gist from clipboard")
}
<commit_msg>Improve makeFromArguments()<commit_after>package cmd

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"github.com/atotto/clipboard"
	"github.com/b4b4r07/gist/config"
	"github.com/b4b4r07/gist/gist"
	"github.com/b4b4r07/gist/util"
	"github.com/fatih/color"
	"github.com/spf13/cobra"

	"golang.org/x/crypto/ssh/terminal"
)

var newCmd = &cobra.Command{
	Use:   "new [FILE/DIR]",
	Short: "Create a new gist",
	Long:  `Create a new gist. If you pass file/dir paths, upload those files`,
	RunE:  new,
}

type gistItem struct {
	files gist.Files
	desc  string
}

func new(cmd *cobra.Command, args []string) error {
	var err error
	var gi gistItem

	gist_, err := gist.New(config.Conf.Gist.Token)
	if err != nil {
		return err
	}

	// Make Gist from various conditions
	switch {
	case config.Conf.Flag.FromClipboard:
		gi, err = makeFromClipboard()
	case !terminal.IsTerminal(0):
		gi, err = makeFromStdin()
	case len(args) > 0:
		gi, err = makeFromArguments(args)
	case len(args) == 0:
		gi, err = makeFromEditor()
	}

	if err != nil {
		return err
	}

	url, err := gist_.Create(gi.files, gi.desc)
	if err != nil {
		return err
	}
	util.Underline("Created", url)

	if config.Conf.Flag.OpenURL {
		util.Open(url)
	}
	return nil
}

func makeFromClipboard() (gi gistItem, err error) {
	content, err := clipboard.ReadAll()
	if err != nil {
		return
	}
	if content == "" {
		return gi, errors.New("clipboard is empty")
	}
	filename, err := util.Scan(color.YellowString("Filename> "), !util.ScanAllowEmpty)
	if err != nil {
		return
	}
	desc, err := util.Scan(color.GreenString("Description> "), util.ScanAllowEmpty)
	if err != nil {
		return
	}
	return gistItem{
		files: gist.Files{gist.File{
			Filename: filename,
			Content:  content,
		}},
		desc: desc,
	}, nil
}

func makeFromStdin() (gi gistItem, err error) {
	body, err := ioutil.ReadAll(os.Stdin)
	if err != nil {
		return
	}
	return gistItem{
		files: gist.Files{gist.File{
			Filename: "stdin",
			Content:  string(body),
		}},
		desc: "",
	}, nil
}

func makeFromEditor() (gi gistItem, err error) {
	filename, err := util.Scan(color.YellowString("Filename> "), !util.ScanAllowEmpty)
	if err != nil {
		return
	}
	f, err := util.TempFile(filename)
	defer os.Remove(f.Name())
	err = util.RunCommand(config.Conf.Core.Editor, f.Name())
	if err != nil {
		return
	}
	desc, err := util.Scan(color.GreenString("Description> "), util.ScanAllowEmpty)
	if err != nil {
		return
	}
	return gistItem{
		files: gist.Files{gist.File{
			Filename: filename,
			Content:  util.FileContent(f.Name()),
		}},
		desc: desc,
	}, nil
}

func makeFromArguments(args []string) (gi gistItem, err error) {
	var (
		gistFiles gist.Files
		files     []string
	)

	// Check if the path is directory
	isdir := func(path string) bool {
		if stat, err := os.Stat(path); err == nil && stat.IsDir() {
			return true
		}
		return false
	}

	for _, arg := range args {
		// if the arg is dir, walk within the dir and add them to slice
		// otherwise (regular file), just add it to slice
		if isdir(arg) {
			err = filepath.Walk(arg, func(arg string, info os.FileInfo, err error) error {
				if strings.HasPrefix(arg, ".") {
					return nil
				}
				if info.IsDir() {
					return nil
				}
				files = append(files, arg)
				return nil
			})
			if err != nil {
				return
			}
		} else {
			files = append(files, arg)
		}
	}

	if len(files) == 0 {
		return gi, errors.New("no files to be able create")
	}

	for _, file := range files {
		fmt.Fprintf(color.Output, "%s %s\n", color.YellowString("Filename>"), file)
		gistFiles = append(gistFiles, gist.File{
			Filename: filepath.Base(file),
			Content:  util.FileContent(file),
		})
	}

	desc, err := util.Scan(color.GreenString("Description> "), util.ScanAllowEmpty)
	if err != nil {
		return
	}

	return gistItem{
		files: gistFiles,
		desc:  desc,
	}, nil
}

func init() {
	RootCmd.AddCommand(newCmd)
	newCmd.Flags().BoolVarP(&config.Conf.Flag.OpenURL, "open", "o", false, "Open with the default browser")
	newCmd.Flags().BoolVarP(&config.Conf.Flag.Private, "private", "p", false, "Create as private gist")
	newCmd.Flags().BoolVarP(&config.Conf.Flag.FromClipboard, "from-clipboard", "c", false, "Create gist from clipboard")
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"errors"
	"github.com/conformal/btcchain"
	"github.com/conformal/btcdb"
	_ "github.com/conformal/btcdb/ldb"
	"github.com/conformal/btcec"
	"github.com/conformal/btclog"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcwire"
	"github.com/conformal/go-flags"
	"github.com/davecgh/go-spew/spew"
	// "math/big"
	"os"
	"path/filepath"
)

type ShaHash btcwire.ShaHash

type config struct {
	DataDir  string `long:"datadir" description:"Directory to store data"`
	DbType   string `long:"dbtype" description:"Database backend"`
	TestNet3 bool   `long:"testnet" description:"Use the test network"`
	// Height   int64  `short:"b" description:"Block height to process" required:"true"`
}

var (
	btcdHomeDir    = btcutil.AppDataDir("btcd", false)
	defaultDataDir = filepath.Join(btcdHomeDir, "data")
	log            btclog.Logger
)

const (
	ArgSha = iota
	ArgHeight
)

var rValuesMap = make(map[string]int64)
var duplicates = make(map[string][]int64)

func main() {
	cfg := config{
		DbType:  "leveldb",
		DataDir: defaultDataDir,
	}
	parser := flags.NewParser(&cfg, flags.Default)
	_, err := parser.Parse()
	if err != nil {
		if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
			parser.WriteHelp(os.Stderr)
		}
		return
	}

	backendLogger := btclog.NewDefaultBackendLogger()
	defer backendLogger.Flush()
	log = btclog.NewSubsystemLogger(backendLogger, "")
	btcdb.UseLogger(log)

	var testnet string
	if cfg.TestNet3 {
		testnet = "testnet"
	} else {
		testnet = "mainnet"
	}

	cfg.DataDir = filepath.Join(cfg.DataDir, testnet)

	blockDbNamePrefix := "blocks"
	dbName := blockDbNamePrefix + "_" + cfg.DbType
	if cfg.DbType == "sqlite" {
		dbName = dbName + ".db"
	}
	dbPath := filepath.Join(cfg.DataDir, dbName)

	log.Infof("loading db %v", cfg.DbType)
	db, err := btcdb.OpenDB(cfg.DbType, dbPath)
	if err != nil {
		log.Warnf("db open failed: %v", err)
		return
	}
	defer db.Close()
	log.Infof("db load complete")

	_, max_heigth, err := db.NewestSha()
	if err != nil {
		log.Warnf("db NewestSha failed: %v", err)
		return
	}
	log.Infof("max_heigth: %v", max_heigth)

	for h := int64(0); h < max_heigth; h++ {
		err = DumpBlock(db, h)
		if err != nil {
			log.Warnf("Failed to dump block %v, err %v", h, err)
		}
	}

	log.Info(spew.Sdump(duplicates))
}

var notDataError = errors.New("the first opcode is not a data push")

func parseData(SignatureScript []uint8) ([]uint8, error) {
	opcode := SignatureScript[0]

	if opcode >= 1 && opcode <= 75 {
		sigStr := SignatureScript[1 : opcode+1]
		return sigStr, nil
	}

	// TODO: OP_PUSHDATA1 OP_PUSHDATA2 OP_PUSHDATA3

	return nil, notDataError
}

func DumpBlock(db btcdb.Db, height int64) error {
	sha, err := db.FetchBlockShaByHeight(height)
	if err != nil {
		return err
	}
	blk, err := db.FetchBlockBySha(sha)
	if err != nil {
		return err
	}
	rblk, err := blk.Bytes()
	if err != nil {
		return err
	}
	blkid := blk.Height()
	if blkid != height {
		return errors.New("WHAT!?")
	}

	log.Infof("Block %v depth %v", sha, blkid)

	log.Debugf("Block %v depth %v %v", sha, blkid, spew.Sdump(rblk))
	mblk := blk.MsgBlock()
	log.Debugf("Block %v depth %v %v", sha, blkid, spew.Sdump(mblk))

	log.Infof("Num transactions %v", len(mblk.Transactions))
	for i, tx := range mblk.Transactions {

		txsha, err := tx.TxSha()
		if err != nil {
			log.Warnf("Block %v (%v)", blkid, sha)
			log.Warnf("tx %v (%v)", i, &txsha)
			log.Warnf("Error: %v", err)
			continue
		}

		log.Infof("tx %v: %v", i, &txsha)

		if btcchain.IsCoinBase(btcutil.NewTx(tx)) {
			log.Infof("tx %v: skipping (coinbase)", i)
			continue
		}

		for t, txin := range tx.TxIn {
			log.Debugf("tx %v: TxIn %v: SignatureScript: %v", i, t, spew.Sdump(txin.SignatureScript))

			sigStr, err := parseData(txin.SignatureScript)
			if err != nil {
				log.Warnf("Block %v (%v)", blkid, sha)
				log.Warnf("tx %v (%v)", i, &txsha)
				log.Warnf("txin %v (parseData)", t)
				log.Warnf("Error: %v", err)
				continue
			}
			log.Debugf("tx %v: TxIn %v: sigStr: %v", i, t, spew.Sdump(sigStr))

			signature, err := btcec.ParseSignature(sigStr, btcec.S256())
			if err != nil {
				log.Warnf("Block %v (%v)", blkid, sha)
				log.Warnf("tx %v (%v)", i, &txsha)
				log.Warnf("txin %v (ParseSignature)", t)
				log.Warnf("Error: %v", err)
				continue

			}
			log.Infof("tx %v: TxIn %v: signature: %v", i, t, spew.Sdump(signature))

			signatureString := signature.R.String()
			if rValuesMap[signatureString] != int64(0) {
				log.Infof("DUPLICATE FOUND: %v", rValuesMap[signatureString])
				if len(duplicates[signatureString]) == 0 {
					duplicates[signatureString] = append(duplicates[signatureString], rValuesMap[signatureString])
				}
				duplicates[signatureString] = append(duplicates[signatureString], blkid)
			} else {
				rValuesMap[signatureString] = blkid
			}

		}

	}

	return nil
}
<commit_msg>Update Copyright note<commit_after>// Copyright (c) 2013 Conformal Systems LLC.
// Copyright (c) 2014 Filippo Valsorda
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.

package main

import (
	"errors"
	"github.com/conformal/btcchain"
	"github.com/conformal/btcdb"
	_ "github.com/conformal/btcdb/ldb"
	"github.com/conformal/btcec"
	"github.com/conformal/btclog"
	"github.com/conformal/btcutil"
	"github.com/conformal/btcwire"
	"github.com/conformal/go-flags"
	"github.com/davecgh/go-spew/spew"
	// "math/big"
	"os"
	"path/filepath"
)

type ShaHash btcwire.ShaHash

type config struct {
	DataDir  string `long:"datadir" description:"Directory to store data"`
	DbType   string `long:"dbtype" description:"Database backend"`
	TestNet3 bool   `long:"testnet" description:"Use the test network"`
	// Height   int64  `short:"b" description:"Block height to process" required:"true"`
}

var (
	btcdHomeDir    = btcutil.AppDataDir("btcd", false)
	defaultDataDir = filepath.Join(btcdHomeDir, "data")
	log            btclog.Logger
)

const (
	ArgSha = iota
	ArgHeight
)

var rValuesMap = make(map[string]int64)
var duplicates = make(map[string][]int64)

func main() {
	cfg := config{
		DbType:  "leveldb",
		DataDir: defaultDataDir,
	}
	parser := flags.NewParser(&cfg, flags.Default)
	_, err := parser.Parse()
	if err != nil {
		if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
			parser.WriteHelp(os.Stderr)
		}
		return
	}

	backendLogger := btclog.NewDefaultBackendLogger()
	defer backendLogger.Flush()
	log = btclog.NewSubsystemLogger(backendLogger, "")
	btcdb.UseLogger(log)

	var testnet string
	if cfg.TestNet3 {
		testnet = "testnet"
	} else {
		testnet = "mainnet"
	}

	cfg.DataDir = filepath.Join(cfg.DataDir, testnet)

	blockDbNamePrefix := "blocks"
	dbName := blockDbNamePrefix + "_" + cfg.DbType
	if cfg.DbType == "sqlite" {
		dbName = dbName + ".db"
	}
	dbPath := filepath.Join(cfg.DataDir, dbName)

	log.Infof("loading db %v", cfg.DbType)
	db, err := btcdb.OpenDB(cfg.DbType, dbPath)
	if err != nil {
		log.Warnf("db open failed: %v", err)
		return
	}
	defer db.Close()
	log.Infof("db load complete")

	_, max_heigth, err := db.NewestSha()
	if err != nil {
		log.Warnf("db NewestSha failed: %v", err)
		return
	}
	log.Infof("max_heigth: %v", max_heigth)

	for h := int64(0); h < max_heigth; h++ {
		err = DumpBlock(db, h)
		if err != nil {
			log.Warnf("Failed to dump block %v, err %v", h, err)
		}
	}

	log.Info(spew.Sdump(duplicates))
}

var notDataError = errors.New("the first opcode is not a data push")

func parseData(SignatureScript []uint8) ([]uint8, error) {
	opcode := SignatureScript[0]

	if opcode >= 1 && opcode <= 75 {
		sigStr := SignatureScript[1 : opcode+1]
		return sigStr, nil
	}

	// TODO: OP_PUSHDATA1 OP_PUSHDATA2 OP_PUSHDATA3

	return nil, notDataError
}

func DumpBlock(db btcdb.Db, height int64) error {
	sha, err := db.FetchBlockShaByHeight(height)
	if err != nil {
		return err
	}
	blk, err := db.FetchBlockBySha(sha)
	if err != nil {
		return err
	}
	rblk, err := blk.Bytes()
	if err != nil {
		return err
	}
	blkid := blk.Height()
	if blkid != height {
		return errors.New("WHAT!?")
	}

	log.Infof("Block %v depth %v", sha, blkid)

	log.Debugf("Block %v depth %v %v", sha, blkid, spew.Sdump(rblk))
	mblk := blk.MsgBlock()
	log.Debugf("Block %v depth %v %v", sha, blkid, spew.Sdump(mblk))

	log.Infof("Num transactions %v", len(mblk.Transactions))
	for i, tx := range mblk.Transactions {

		txsha, err := tx.TxSha()
		if err != nil {
			log.Warnf("Block %v (%v)", blkid, sha)
			log.Warnf("tx %v (%v)", i, &txsha)
			log.Warnf("Error: %v", err)
			continue
		}

		log.Infof("tx %v: %v", i, &txsha)

		if btcchain.IsCoinBase(btcutil.NewTx(tx)) {
			log.Infof("tx %v: skipping (coinbase)", i)
			continue
		}

		for t, txin := range tx.TxIn {
			log.Debugf("tx %v: TxIn %v: SignatureScript: %v", i, t, spew.Sdump(txin.SignatureScript))

			sigStr, err := parseData(txin.SignatureScript)
			if err != nil {
				log.Warnf("Block %v (%v)", blkid, sha)
				log.Warnf("tx %v (%v)", i, &txsha)
				log.Warnf("txin %v (parseData)", t)
				log.Warnf("Error: %v", err)
				continue
			}
			log.Debugf("tx %v: TxIn %v: sigStr: %v", i, t, spew.Sdump(sigStr))

			signature, err := btcec.ParseSignature(sigStr, btcec.S256())
			if err != nil {
				log.Warnf("Block %v (%v)", blkid, sha)
				log.Warnf("tx %v (%v)", i, &txsha)
				log.Warnf("txin %v (ParseSignature)", t)
				log.Warnf("Error: %v", err)
				continue

			}
			log.Infof("tx %v: TxIn %v: signature: %v", i, t, spew.Sdump(signature))

			signatureString := signature.R.String()
			if rValuesMap[signatureString] != int64(0) {
				log.Infof("DUPLICATE FOUND: %v", rValuesMap[signatureString])
				if len(duplicates[signatureString]) == 0 {
					duplicates[signatureString] = append(duplicates[signatureString], rValuesMap[signatureString])
				}
				duplicates[signatureString] = append(duplicates[signatureString], blkid)
			} else {
				rValuesMap[signatureString] = blkid
			}

		}

	}

	return nil
}
<|endoftext|>


<commit_before>package goblin

import (
	"flag"
	"fmt"
	"regexp"
	"runtime"
	"sync"
	"testing"
	"time"
)

type Done func(error ...interface{})

type Runnable interface {
	run(*G) bool
}

func (g *G) Describe(name string, h func()) {
	d := &Describe{name: name, h: h, parent: g.parent}

	if d.parent != nil {
		d.parent.children = append(d.parent.children, Runnable(d))
	}

	g.parent = d

	h()

	g.parent = d.parent

	if g.parent == nil && d.hasTests {
		g.reporter.begin()
		if d.run(g) {
			g.t.Fail()
		}
		g.reporter.end()
	}
}

type Describe struct {
	name       string
	h          func()
	children   []Runnable
	befores    []func()
	afters     []func()
	afterEach  []func()
	beforeEach []func()
	hasTests   bool
	parent     *Describe
}

func (d *Describe) runBeforeEach() {
	if d.parent != nil {
		d.parent.runBeforeEach()
	}

	for _, b := range d.beforeEach {
		b()
	}
}

func (d *Describe) runAfterEach() {

	if d.parent != nil {
		d.parent.runAfterEach()
	}

	for _, a := range d.afterEach {
		a()
	}
}

func (d *Describe) run(g *G) bool {
	g.reporter.beginDescribe(d.name)

	failed := ""

	if d.hasTests {
		for _, b := range d.befores {
			b()
		}
	}

	for _, r := range d.children {
		if r.run(g) {
			failed = "true"
		}
	}

	if d.hasTests {
		for _, a := range d.afters {
			a()
		}
	}

	g.reporter.endDescribe()

	return failed != ""
}

type Failure struct {
	stack    []string
	testName string
	message  string
}

type It struct {
	h        interface{}
	name     string
	parent   *Describe
	failure  *Failure
	reporter Reporter
	isAsync  bool
}

func (it *It) run(g *G) bool {
	g.currentIt = it

	if it.h == nil {
		g.reporter.itIsPending(it.name)
		return false
	}
	//TODO: should handle errors for beforeEach
	it.parent.runBeforeEach()

	runIt(g, it.h)

	it.parent.runAfterEach()

	failed := false
	if it.failure != nil {
		failed = true
	}

	if failed {
		g.reporter.itFailed(it.name)
		g.reporter.failure(it.failure)
	} else {
		g.reporter.itPassed(it.name)
	}
	return failed
}

func (it *It) failed(msg string, stack []string) {
	it.failure = &Failure{stack: stack, message: msg, testName: it.parent.name + " " + it.name}
}

func parseFlags() {
	//Flag parsing
	flag.Parse()
	if *regexParam != "" {
		runRegex = regexp.MustCompile(*regexParam)
	} else {
		runRegex = nil
	}
}

var timeout = flag.Duration("goblin.timeout", 5*time.Second, "Sets default timeouts for all tests")
var isTty = flag.Bool("goblin.tty", true, "Sets the default output format (color / monochrome)")
var regexParam = flag.String("goblin.run", "", "Runs only tests which match the supplied regex")
var runRegex *regexp.Regexp

func init() {
	parseFlags()
}

func Goblin(t *testing.T, arguments ...string) *G {
	g := &G{t: t, timeout: *timeout}
	var fancy TextFancier
	if *isTty {
		fancy = &TerminalFancier{}
	} else {
		fancy = &Monochrome{}
	}

	g.reporter = Reporter(&DetailedReporter{fancy: fancy})
	return g
}

func runIt(g *G, h interface{}) {
	defer timeTrack(time.Now(), g)
	g.mutex.Lock()
	g.timedOut = false
	g.mutex.Unlock()
	g.shouldContinue = make(chan bool)
	if call, ok := h.(func()); ok {
		// the test is synchronous
		go func(c chan bool) { call(); c <- true }(g.shouldContinue)
	} else if call, ok := h.(func(Done)); ok {
		doneCalled := 0
		go func(c chan bool) {
			call(func(msg ...interface{}) {
				if len(msg) > 0 {
					g.Fail(msg)
				} else {
					doneCalled++
					if doneCalled > 1 {
						g.Fail("Done called multiple times")
					}
					c <- true
				}
			})
		}(g.shouldContinue)
	} else {
		panic("Not implemented.")
	}
	select {
	case <-g.shouldContinue:
	case <-time.After(g.timeout):
		//Set to nil as it shouldn't continue
		g.shouldContinue = nil
		g.timedOut = true
		g.Fail("Test exceeded " + fmt.Sprintf("%s", g.timeout))
	}
}

type G struct {
	t              *testing.T
	parent         *Describe
	currentIt      *It
	timeout        time.Duration
	reporter       Reporter
	timedOut       bool
	shouldContinue chan bool
	mutex          sync.Mutex
}

func (g *G) SetReporter(r Reporter) {
	g.reporter = r
}

func (g *G) It(name string, h ...interface{}) {
	if matchesRegex(name) {
		it := &It{name: name, parent: g.parent, reporter: g.reporter}
		notifyParents(g.parent)
		if len(h) > 0 {
			it.h = h[0]
		}
		g.parent.children = append(g.parent.children, Runnable(it))
	}
}

func matchesRegex(value string) bool {
	if runRegex != nil {
		return runRegex.MatchString(value)
	}
	return true
}

func notifyParents(d *Describe) {
	d.hasTests = true
	if d.parent != nil {
		notifyParents(d.parent)
	}
}

func (g *G) Before(h func()) {
	g.parent.befores = append(g.parent.befores, h)
}

func (g *G) BeforeEach(h func()) {
	g.parent.beforeEach = append(g.parent.beforeEach, h)
}

func (g *G) After(h func()) {
	g.parent.afters = append(g.parent.afters, h)
}

func (g *G) AfterEach(h func()) {
	g.parent.afterEach = append(g.parent.afterEach, h)
}

func (g *G) Assert(src interface{}) *Assertion {
	return &Assertion{src: src, fail: g.Fail}
}

func timeTrack(start time.Time, g *G) {
	g.reporter.itTook(time.Since(start))
}

func (g *G) Fail(error interface{}) {
	//Skips 7 stacks due to the functions between the stack and the test
	stack := ResolveStack(4)
	message := fmt.Sprintf("%v", error)
	g.currentIt.failed(message, stack)
	if g.shouldContinue != nil {
		g.shouldContinue <- true
	}
	g.mutex.Lock()
	defer g.mutex.Unlock()
	if !g.timedOut {
		//Stop test function execution
		runtime.Goexit()
	}

}
<commit_msg>Don't show describe block names if tests are filtered out<commit_after>package goblin

import (
	"flag"
	"fmt"
	"regexp"
	"runtime"
	"sync"
	"testing"
	"time"
)

type Done func(error ...interface{})

type Runnable interface {
	run(*G) bool
}

func (g *G) Describe(name string, h func()) {
	d := &Describe{name: name, h: h, parent: g.parent}

	if d.parent != nil {
		d.parent.children = append(d.parent.children, Runnable(d))
	}

	g.parent = d

	h()

	g.parent = d.parent

	if g.parent == nil && d.hasTests {
		g.reporter.begin()
		if d.run(g) {
			g.t.Fail()
		}
		g.reporter.end()
	}
}

type Describe struct {
	name       string
	h          func()
	children   []Runnable
	befores    []func()
	afters     []func()
	afterEach  []func()
	beforeEach []func()
	hasTests   bool
	parent     *Describe
}

func (d *Describe) runBeforeEach() {
	if d.parent != nil {
		d.parent.runBeforeEach()
	}

	for _, b := range d.beforeEach {
		b()
	}
}

func (d *Describe) runAfterEach() {

	if d.parent != nil {
		d.parent.runAfterEach()
	}

	for _, a := range d.afterEach {
		a()
	}
}

func (d *Describe) run(g *G) bool {
	failed := false
	if d.hasTests {
		g.reporter.beginDescribe(d.name)

		for _, b := range d.befores {
			b()
		}

		for _, r := range d.children {
			if r.run(g) {
				failed = true
			}
		}

		for _, a := range d.afters {
			a()
		}

		g.reporter.endDescribe()
	}

	return failed
}

type Failure struct {
	stack    []string
	testName string
	message  string
}

type It struct {
	h        interface{}
	name     string
	parent   *Describe
	failure  *Failure
	reporter Reporter
	isAsync  bool
}

func (it *It) run(g *G) bool {
	g.currentIt = it

	if it.h == nil {
		g.reporter.itIsPending(it.name)
		return false
	}
	//TODO: should handle errors for beforeEach
	it.parent.runBeforeEach()

	runIt(g, it.h)

	it.parent.runAfterEach()

	failed := false
	if it.failure != nil {
		failed = true
	}

	if failed {
		g.reporter.itFailed(it.name)
		g.reporter.failure(it.failure)
	} else {
		g.reporter.itPassed(it.name)
	}
	return failed
}

func (it *It) failed(msg string, stack []string) {
	it.failure = &Failure{stack: stack, message: msg, testName: it.parent.name + " " + it.name}
}

func parseFlags() {
	//Flag parsing
	flag.Parse()
	if *regexParam != "" {
		runRegex = regexp.MustCompile(*regexParam)
	} else {
		runRegex = nil
	}
}

var timeout = flag.Duration("goblin.timeout", 5*time.Second, "Sets default timeouts for all tests")
var isTty = flag.Bool("goblin.tty", true, "Sets the default output format (color / monochrome)")
var regexParam = flag.String("goblin.run", "", "Runs only tests which match the supplied regex")
var runRegex *regexp.Regexp

func init() {
	parseFlags()
}

func Goblin(t *testing.T, arguments ...string) *G {
	g := &G{t: t, timeout: *timeout}
	var fancy TextFancier
	if *isTty {
		fancy = &TerminalFancier{}
	} else {
		fancy = &Monochrome{}
	}

	g.reporter = Reporter(&DetailedReporter{fancy: fancy})
	return g
}

func runIt(g *G, h interface{}) {
	defer timeTrack(time.Now(), g)
	g.mutex.Lock()
	g.timedOut = false
	g.mutex.Unlock()
	g.shouldContinue = make(chan bool)
	if call, ok := h.(func()); ok {
		// the test is synchronous
		go func(c chan bool) { call(); c <- true }(g.shouldContinue)
	} else if call, ok := h.(func(Done)); ok {
		doneCalled := 0
		go func(c chan bool) {
			call(func(msg ...interface{}) {
				if len(msg) > 0 {
					g.Fail(msg)
				} else {
					doneCalled++
					if doneCalled > 1 {
						g.Fail("Done called multiple times")
					}
					c <- true
				}
			})
		}(g.shouldContinue)
	} else {
		panic("Not implemented.")
	}
	select {
	case <-g.shouldContinue:
	case <-time.After(g.timeout):
		//Set to nil as it shouldn't continue
		g.shouldContinue = nil
		g.timedOut = true
		g.Fail("Test exceeded " + fmt.Sprintf("%s", g.timeout))
	}
}

type G struct {
	t              *testing.T
	parent         *Describe
	currentIt      *It
	timeout        time.Duration
	reporter       Reporter
	timedOut       bool
	shouldContinue chan bool
	mutex          sync.Mutex
}

func (g *G) SetReporter(r Reporter) {
	g.reporter = r
}

func (g *G) It(name string, h ...interface{}) {
	if matchesRegex(name) {
		it := &It{name: name, parent: g.parent, reporter: g.reporter}
		notifyParents(g.parent)
		if len(h) > 0 {
			it.h = h[0]
		}
		g.parent.children = append(g.parent.children, Runnable(it))
	}
}

func matchesRegex(value string) bool {
	if runRegex != nil {
		return runRegex.MatchString(value)
	}
	return true
}

func notifyParents(d *Describe) {
	d.hasTests = true
	if d.parent != nil {
		notifyParents(d.parent)
	}
}

func (g *G) Before(h func()) {
	g.parent.befores = append(g.parent.befores, h)
}

func (g *G) BeforeEach(h func()) {
	g.parent.beforeEach = append(g.parent.beforeEach, h)
}

func (g *G) After(h func()) {
	g.parent.afters = append(g.parent.afters, h)
}

func (g *G) AfterEach(h func()) {
	g.parent.afterEach = append(g.parent.afterEach, h)
}

func (g *G) Assert(src interface{}) *Assertion {
	return &Assertion{src: src, fail: g.Fail}
}

func timeTrack(start time.Time, g *G) {
	g.reporter.itTook(time.Since(start))
}

func (g *G) Fail(error interface{}) {
	//Skips 7 stacks due to the functions between the stack and the test
	stack := ResolveStack(4)
	message := fmt.Sprintf("%v", error)
	g.currentIt.failed(message, stack)
	if g.shouldContinue != nil {
		g.shouldContinue <- true
	}
	g.mutex.Lock()
	defer g.mutex.Unlock()
	if !g.timedOut {
		//Stop test function execution
		runtime.Goexit()
	}

}
<|endoftext|>


<commit_before>package main
// Author: Robert B Frangioso

import (
	"path/filepath"
	"os"
	"flag"
	"fmt"
	"io/ioutil"
	"sync"
	"os/exec"
	"bytes"
)

type msg_type int

const (
	OUTPUT msg_type = 1 + iota
	ERROR
	CLOSE
)

type output_msg struct {
	mtype	msg_type
	buffer	bytes.Buffer
}

func find(root string, wg *sync.WaitGroup, exp []string, output chan output_msg) {

	defer wg.Done()
	var cmd_out, cmd_err bytes.Buffer
	var msg output_msg

	findargs := append([]string{root}, exp... )
	cmd := exec.Command("find", findargs... )
	cmd.Stdout = &cmd_out
	cmd.Stderr = &cmd_err
	err := cmd.Run()

	if err == nil {
		msg.mtype = OUTPUT
		msg.buffer = cmd_out
		output <- msg
	} else {
		msg.mtype = ERROR
		msg.buffer = cmd_err
		output <- msg
	}

	return
}

func aggregator(wg *sync.WaitGroup, input chan output_msg) {

	defer wg.Done()
	var msg output_msg

	for true {
		msg = <- input
		switch msg.mtype {
		case CLOSE:
			return
		case OUTPUT:
			if msg.buffer.Len() > 0 {
				fmt.Printf("%s", msg.buffer.String())
			}
		case ERROR:
			if msg.buffer.Len() > 0 {
				fmt.Fprintf(os.Stderr, "%s", msg.buffer.String())
			}
		default:
		}
	}

}

func main() {

	var wg, wga sync.WaitGroup
	msg_channel := make(chan output_msg)

	flag.Parse()
	root := flag.Arg(0)
	basedirs, direrr := ioutil.ReadDir(root)
	argslice := flag.Args()

	if(direrr != nil) {
		fmt.Printf("ReadDir err %v \n", direrr)
		fmt.Printf("Usage: gofind rootsearchdir <other-find-args> \n")
		return
	}

	shallowfind := append(append([]string{},[]string{"-maxdepth", "1"}... ), argslice[1:]... )
	wg.Add(1)
	go find(root, &wg, shallowfind, msg_channel)

	for  dir := range basedirs {
		if basedirs[dir].IsDir() {
			wg.Add(1)
			go find(filepath.Join(root, basedirs[dir].Name()), &wg, argslice[1:], msg_channel)
		}
	}

	wga.Add(1)
	go aggregator(&wga, msg_channel)
	wg.Wait()

	msg_channel <- output_msg{CLOSE, bytes.Buffer{}}
	wga.Wait()
}

<commit_msg>add flag handling for osx find flags<commit_after>package main
// Author: Robert B Frangioso

import (
	"path/filepath"
	"os"
	"flag"
	"fmt"
	"io/ioutil"
	"sync"
	"os/exec"
	"bytes"
	"strconv"
)

type msg_type int

const (
	OUTPUT msg_type = 1 + iota
	ERROR
	CLOSE
)

type output_msg struct {
	mtype	msg_type
	buffer	bytes.Buffer
}

func find(root string, wg *sync.WaitGroup, flags []string, args []string, output chan output_msg) {

	defer wg.Done()
	var cmd_out, cmd_err bytes.Buffer
	var msg output_msg

	findstr := append(append(append([]string{}, flags... ), []string{root}... ), args... )
	cmd := exec.Command("find", findstr... )
	cmd.Stdout = &cmd_out
	cmd.Stderr = &cmd_err
	err := cmd.Run()

	if err == nil {
		msg.mtype = OUTPUT
		msg.buffer = cmd_out
		output <- msg
	} else {
		msg.mtype = ERROR
		msg.buffer = cmd_err
		output <- msg
	}

	return
}

func aggregator(wg *sync.WaitGroup, input chan output_msg) {

	defer wg.Done()
	var msg output_msg

	for true {
		msg = <- input
		switch msg.mtype {
		case CLOSE:
			return
		case OUTPUT:
			if msg.buffer.Len() > 0 {
				fmt.Printf("%s", msg.buffer.String())
			}
		case ERROR:
			if msg.buffer.Len() > 0 {
				fmt.Fprintf(os.Stderr, "%s", msg.buffer.String())
			}
		default:
		}
	}

}

func parseflags() []string {

	osx_find_flags := []string{"L", "H", "P", "E", "X", "d", "s", "x"}
	set_flags := []string{}

	for f := range osx_find_flags {
		flag.Bool(osx_find_flags[f], false, "bool")
	}

	flag.Parse()
	for f := range osx_find_flags {
		flag_p := flag.Lookup(osx_find_flags[f])
		val, err := strconv.ParseBool(flag_p.Value.String())
		if err == nil && val == true {
			set_flags = append(set_flags, "-"+flag_p.Name)
		}
	}

	return set_flags
}

func main() {

	var wg, wga sync.WaitGroup
	msg_channel := make(chan output_msg)

	set_flags := parseflags()

	argslice := flag.Args()
	fmt.Printf("flag.Args() %v \n", argslice)
	root := argslice[0]
	basedirs, direrr := ioutil.ReadDir(root)

	if(direrr != nil) {
		fmt.Printf("ReadDir err %v \n", direrr)
		fmt.Printf("Usage: gofind rootsearchdir <other-find-args> \n")
		return
	}

	shallowfind := append(append([]string{},[]string{"-maxdepth", "1"}... ), argslice[1:]... )
	wg.Add(1)
	go find(root, &wg, set_flags, shallowfind, msg_channel)

	for  dir := range basedirs {
		if basedirs[dir].IsDir() {
			wg.Add(1)
			go find(filepath.Join(root, basedirs[dir].Name()), &wg, set_flags, argslice[1:], msg_channel)
		}
	}

	wga.Add(1)
	go aggregator(&wga, msg_channel)
	wg.Wait()

	msg_channel <- output_msg{CLOSE, bytes.Buffer{}}
	wga.Wait()
}

<|endoftext|>


<commit_before>package main

import (
  "net/http"
  "log"
  "io/ioutil"
  "encoding/json"
  "os/exec"
  "flag"
  "strconv"
  "crypto/md5"
  "text/template"
  "bytes"
  "gopkg.in/fsnotify.v1"
)

// A map of repos => (a map of branches => (a list of actions))
// Todo: Idiomatic way of doing this?
type Config map[string]map[string][]string

type HookMsg struct {
  CanonicalUrl string `json:"canon_url"`

  Commits []struct {
    Branch string
  }

  Repository struct {
    AbsoluteUrl string `json:"absolute_url"`
  }
}

type Commit struct {
  Repository string
  Branch string
}

type Job struct {
  Commit Commit
  Action string
}

var listenPort = flag.Int("port", 8080, "portnumber to listen on")
var configFile = flag.String("config", "golive.json", "the configfile to read")
var verbose = flag.Bool("v", false, "print more output")

var jobTemplates = make(map[[16]byte]template.Template)
var config Config

func main() {
	flag.Parse()

  parseConfig(*configFile)
  go watchConfig(*configFile)

  msgs := make(chan HookMsg, 100)
  commits := make(chan Commit, 100)
  jobs := make(chan Job, 100)
  actions := make(chan string, 100)

  go hookWrangler(msgs, commits)
  go commitWrangler(commits, jobs, config)
  go jobWrangler(jobs, actions)
  go actionRunner(actions)

  log.Print("Starting golive server")

  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    log.Print("Received request")

    payload := r.FormValue("payload")

    var hookmsg HookMsg
    if err := json.Unmarshal([]byte(payload), &hookmsg); err != nil {
      http.Error(w, "Could not decode json", 500)
      log.Fatal(err)
    }

    if *verbose {
      log.Print("Received commit: ", hookmsg)
    }

    msgs <- hookmsg
  })

  log.Fatal(http.ListenAndServe(":" + strconv.Itoa(*listenPort), nil))
}

func watchConfig(configFile string) {
  watcher, err := fsnotify.NewWatcher()
  if err != nil {
    log.Fatal(err)
  }

  log.Print("Watching config file: ", configFile)

  defer watcher.Close()

	done := make(chan bool)

  go func() {
    for {
      select {
        case event := <-watcher.Events:
          if event.Name == "" {
            continue
          }

          if *verbose {
            log.Println(event.Name, event.Op, event)
          }

          // The watching doesn't seem to follow renames, which happen i.e.
          // during Vim editing, so set up a new one
          if event.Op & fsnotify.Rename == fsnotify.Rename {
            addWatcher(watcher, configFile)
          }

          log.Print("Relading config file ", configFile)

          parseConfig(configFile)

        case err := <-watcher.Errors:
          if err == nil {
            continue
          }

          done <- true
          log.Fatal("Error when watching config file: ", err)
      }
    }
  }()

  addWatcher(watcher, configFile)

  <- done
}

func addWatcher(watcher *fsnotify.Watcher, file string) {
  err := watcher.Add(file)
  if err != nil {
    log.Fatal(err)
  }
}

func parseConfig(configFile string) {
    config_raw, err := ioutil.ReadFile(configFile)
    if err != nil {
      log.Fatal(err)
    }

    var newConfig Config
    json.Unmarshal(config_raw, &newConfig)

    config = newConfig

    if *verbose {
      log.Print("Loaded config: ", config)
    }
}

func hookWrangler(msgs <-chan HookMsg, results chan<- Commit) {
  for msg := range msgs {
    repository := msg.CanonicalUrl + msg.Repository.AbsoluteUrl

    for _, commit := range msg.Commits {
      results <- Commit{ repository, commit.Branch}
    }
  }
}

func commitWrangler(commits <-chan Commit, results chan<- Job, config Config) {
  for commit := range commits {
    if commit.Branch == "" || commit.Repository == "" {
      continue
    }

    if branches, ok := config[commit.Repository]; ok {
      if actions, ok := branches[commit.Branch]; ok {
        for _, action := range actions {
          results <- Job{commit, string(action)}
        }
      }
    }
  }
}

func jobWrangler(jobs <-chan Job, actions chan<- string) {
  for job := range jobs {
    if *verbose {
      log.Print("Running job: ", job)
    }

    hash := md5.Sum([]byte(job.Action))

    if _, ok := jobTemplates[hash]; !ok {
      t, err := template.New(string(hash[:])).Parse(job.Action)
      if err != nil {
        log.Fatal("Could not compile template: ", job.Action, " - ", err)
      }

      jobTemplates[hash] = *t
    }

    t := jobTemplates[hash]

    var buff bytes.Buffer
    (&t).Execute(&buff, job.Commit)
    s := buff.String()

    actions <- s
  }
}

func actionRunner(actions <-chan string) {
  for action := range actions {
    command := exec.Command("bash", "-c", action)

    command.Run()
  }
}
<commit_msg>Log 'running job' in the proper place<commit_after>package main

import (
  "net/http"
  "log"
  "io/ioutil"
  "encoding/json"
  "os/exec"
  "flag"
  "strconv"
  "crypto/md5"
  "text/template"
  "bytes"
  "gopkg.in/fsnotify.v1"
)

// A map of repos => (a map of branches => (a list of actions))
// Todo: Idiomatic way of doing this?
type Config map[string]map[string][]string

type HookMsg struct {
  CanonicalUrl string `json:"canon_url"`

  Commits []struct {
    Branch string
  }

  Repository struct {
    AbsoluteUrl string `json:"absolute_url"`
  }
}

type Commit struct {
  Repository string
  Branch string
}

type Job struct {
  Commit Commit
  Action string
}

var listenPort = flag.Int("port", 8080, "portnumber to listen on")
var configFile = flag.String("config", "golive.json", "the configfile to read")
var verbose = flag.Bool("v", false, "print more output")

var jobTemplates = make(map[[16]byte]template.Template)
var config Config

func main() {
	flag.Parse()

  parseConfig(*configFile)
  go watchConfig(*configFile)

  msgs := make(chan HookMsg, 100)
  commits := make(chan Commit, 100)
  jobs := make(chan Job, 100)
  actions := make(chan string, 100)

  go hookWrangler(msgs, commits)
  go commitWrangler(commits, jobs, config)
  go jobWrangler(jobs, actions)
  go actionRunner(actions)

  log.Print("Starting golive server")

  http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    log.Print("Received request")

    payload := r.FormValue("payload")

    var hookmsg HookMsg
    if err := json.Unmarshal([]byte(payload), &hookmsg); err != nil {
      http.Error(w, "Could not decode json", 500)
      log.Fatal(err)
    }

    if *verbose {
      log.Print("Received commit: ", hookmsg)
    }

    msgs <- hookmsg
  })

  log.Fatal(http.ListenAndServe(":" + strconv.Itoa(*listenPort), nil))
}

func watchConfig(configFile string) {
  watcher, err := fsnotify.NewWatcher()
  if err != nil {
    log.Fatal(err)
  }

  log.Print("Watching config file: ", configFile)

  defer watcher.Close()

	done := make(chan bool)

  go func() {
    for {
      select {
        case event := <-watcher.Events:
          if event.Name == "" {
            continue
          }

          if *verbose {
            log.Println(event.Name, event.Op, event)
          }

          // The watching doesn't seem to follow renames, which happen i.e.
          // during Vim editing, so set up a new one
          if event.Op & fsnotify.Rename == fsnotify.Rename {
            addWatcher(watcher, configFile)
          }

          log.Print("Relading config file ", configFile)

          parseConfig(configFile)

        case err := <-watcher.Errors:
          if err == nil {
            continue
          }

          done <- true
          log.Fatal("Error when watching config file: ", err)
      }
    }
  }()

  addWatcher(watcher, configFile)

  <- done
}

func addWatcher(watcher *fsnotify.Watcher, file string) {
  err := watcher.Add(file)
  if err != nil {
    log.Fatal(err)
  }
}

func parseConfig(configFile string) {
    config_raw, err := ioutil.ReadFile(configFile)
    if err != nil {
      log.Fatal(err)
    }

    var newConfig Config
    json.Unmarshal(config_raw, &newConfig)

    config = newConfig

    if *verbose {
      log.Print("Loaded config: ", config)
    }
}

func hookWrangler(msgs <-chan HookMsg, results chan<- Commit) {
  for msg := range msgs {
    repository := msg.CanonicalUrl + msg.Repository.AbsoluteUrl

    for _, commit := range msg.Commits {
      results <- Commit{ repository, commit.Branch}
    }
  }
}

func commitWrangler(commits <-chan Commit, results chan<- Job, config Config) {
  for commit := range commits {
    if commit.Branch == "" || commit.Repository == "" {
      continue
    }

    if branches, ok := config[commit.Repository]; ok {
      if actions, ok := branches[commit.Branch]; ok {
        for _, action := range actions {
          results <- Job{commit, string(action)}
        }
      }
    }
  }
}

func jobWrangler(jobs <-chan Job, actions chan<- string) {
  for job := range jobs {
    hash := md5.Sum([]byte(job.Action))

    if _, ok := jobTemplates[hash]; !ok {
      t, err := template.New(string(hash[:])).Parse(job.Action)
      if err != nil {
        log.Fatal("Could not compile template: ", job.Action, " - ", err)
      }

      jobTemplates[hash] = *t
    }

    t := jobTemplates[hash]

    var buff bytes.Buffer
    (&t).Execute(&buff, job.Commit)
    s := buff.String()

    actions <- s
  }
}

func actionRunner(actions <-chan string) {
  for action := range actions {
    if *verbose {
      log.Print("Running action: ", action)
    }

    command := exec.Command("bash", "-c", action)

    command.Run()
  }
}
<|endoftext|>


<commit_before>package gol

import (
	"fmt"

	"github.com/philchia/gol/adapter"
	"github.com/philchia/gol/internal/stringUtil"
)

type gollog struct {
	level    LogLevel
	option   LogOption
	adapters []adapter.Adapter
	logChan  chan string
}

func (l *gollog) msgPump() {
	for {
		select {
		case msg := <-l.logChan:
			for _, adap := range l.adapters {
				adap.Write([]byte(msg))
			}
		}
	}
}

func (l *gollog) put(msg string) {
	l.logChan <- msg
}

func (l *gollog) generateLog(level LogLevel, msg string) string {
	return stringUtil.JoinStrings("[", level.String(), "] ", msg, "\n")
}

func (l *gollog) Debug(i ...interface{}) {
	if l.level > DEBUG {
		return
	}
	msg := l.generateLog(DEBUG, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Debugf(format string, i ...interface{}) {
	if l.level > DEBUG {
		return
	}
	msg := l.generateLog(DEBUG, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) Info(i ...interface{}) {
	if l.level > INFO {
		return
	}
	msg := l.generateLog(INFO, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Infof(format string, i ...interface{}) {
	if l.level > INFO {
		return
	}
	msg := l.generateLog(INFO, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) Warn(i ...interface{}) {
	if l.level > WARN {
		return
	}
	msg := l.generateLog(WARN, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Warnf(format string, i ...interface{}) {
	if l.level > WARN {
		return
	}
	msg := l.generateLog(WARN, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) Error(i ...interface{}) {
	if l.level > ERROR {
		return
	}
	msg := l.generateLog(ERROR, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Errorf(format string, i ...interface{}) {
	if l.level > ERROR {
		return
	}
	msg := l.generateLog(ERROR, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) Critical(i ...interface{}) {
	if l.level > CRITICAL {
		return
	}
	msg := l.generateLog(CRITICAL, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Criticalf(format string, i ...interface{}) {
	if l.level > CRITICAL {
		return
	}
	msg := l.generateLog(CRITICAL, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) SetLevel(level LogLevel) {
	l.level = level
}

func (l *gollog) SetOption(option LogOption) {
	l.option = option
}

func (l *gollog) AddLogAdapter(a adapter.Adapter) {
	if a != nil {
		l.adapters = append(l.adapters, a)
	}
}
<commit_msg>write log in goroutine<commit_after>package gol

import (
	"fmt"

	"github.com/philchia/gol/adapter"
	"github.com/philchia/gol/internal/stringUtil"
)

type gollog struct {
	level    LogLevel
	option   LogOption
	adapters []adapter.Adapter
	logChan  chan string
}

func (l *gollog) msgPump() {
	for {
		select {
		case msg := <-l.logChan:
			for _, adap := range l.adapters {
				go adap.Write([]byte(msg))
			}
		}
	}
}

func (l *gollog) put(msg string) {
	l.logChan <- msg
}

func (l *gollog) generateLog(level LogLevel, msg string) string {
	return stringUtil.JoinStrings("[", level.String(), "] ", msg, "\n")
}

func (l *gollog) Debug(i ...interface{}) {
	if l.level > DEBUG {
		return
	}
	msg := l.generateLog(DEBUG, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Debugf(format string, i ...interface{}) {
	if l.level > DEBUG {
		return
	}
	msg := l.generateLog(DEBUG, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) Info(i ...interface{}) {
	if l.level > INFO {
		return
	}
	msg := l.generateLog(INFO, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Infof(format string, i ...interface{}) {
	if l.level > INFO {
		return
	}
	msg := l.generateLog(INFO, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) Warn(i ...interface{}) {
	if l.level > WARN {
		return
	}
	msg := l.generateLog(WARN, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Warnf(format string, i ...interface{}) {
	if l.level > WARN {
		return
	}
	msg := l.generateLog(WARN, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) Error(i ...interface{}) {
	if l.level > ERROR {
		return
	}
	msg := l.generateLog(ERROR, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Errorf(format string, i ...interface{}) {
	if l.level > ERROR {
		return
	}
	msg := l.generateLog(ERROR, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) Critical(i ...interface{}) {
	if l.level > CRITICAL {
		return
	}
	msg := l.generateLog(CRITICAL, fmt.Sprint(i...))
	l.put(msg)
}

func (l *gollog) Criticalf(format string, i ...interface{}) {
	if l.level > CRITICAL {
		return
	}
	msg := l.generateLog(CRITICAL, fmt.Sprintf(format, i...))
	l.put(msg)
}

func (l *gollog) SetLevel(level LogLevel) {
	l.level = level
}

func (l *gollog) SetOption(option LogOption) {
	l.option = option
}

func (l *gollog) AddLogAdapter(a adapter.Adapter) {
	if a != nil {
		l.adapters = append(l.adapters, a)
	}
}
<|endoftext|>


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

package reddit

import (
	"fmt"
)

// Comment represents a reddit comment.
type Comment struct {
	Author              string  //`json:"author"`
	Body                string  //`json:"body"`
	BodyHTML            string  //`json:"body_html"`
	Subreddit           string  //`json:"subreddit"`
	LinkID              string  //`json:"link_id"`
	ParentID            string  //`json:"parent_id"`
	SubredditID         string  //`json:"subreddit_id"`
	FullID              string  //`json:"name"`
	UpVotes             float64 //`json:"ups"`
	DownVotes           float64 //`json:"downs"`
	Created             float64 //`json:"created_utc"`
	Edited              bool    //`json:"edited"`
	BannedBy            *string //`json:"banned_by"`
	ApprovedBy          *string //`json:"approved_by"`
	AuthorFlairTxt      *string //`json:"author_flair_text"`
	AuthorFlairCSSClass *string //`json:"author_flair_css_class"`
	NumReports          *int    //`json:"num_reports"`
	Likes               *int    //`json:"likes"`
	Replies             []*Comment
}

func (c Comment) voteID() string   { return c.FullID }
func (c Comment) deleteID() string { return c.FullID }
func (c Comment) replyID() string  { return c.FullID }

func (c Comment) String() string {
	return fmt.Sprintf("%s (%d/%d): %s", c.Author, c.UpVotes, c.DownVotes, c.Body)
}

// Does the ugly work of setting the comment fields
func makeComment(cmap map[string]interface{}) *Comment {
	ret := new(Comment)
	ret.Author = cmap["author"].(string)
	ret.Body = cmap["body"].(string)
	ret.BodyHTML = cmap["body_html"].(string)
	ret.Subreddit = cmap["subreddit"].(string)
	ret.LinkID = cmap["link_id"].(string)
	ret.ParentID = cmap["parent_id"].(string)
	ret.SubredditID = cmap["subreddit_id"].(string)
	ret.FullID = cmap["name"].(string)
	ret.UpVotes = cmap["ups"].(float64)
	ret.DownVotes = cmap["downs"].(float64)
	ret.Created = cmap["created_utc"].(float64)

	//These fields commented out because they threw runtime errors in type assertion

	//ret.Edited = cmap["edited"].(bool)
	//ret.BannedBy = cmap["banned_by"].(*string)
	//ret.ApprovedBy = cmap["approved_by"].(*string)
	//ret.AuthorFlairTxt = cmap["author_flair_text"].(*string)
	//ret.AuthorFlairCSSClass = cmap["author_flair_css_class"].(*string)
	//ret.NumReports = cmap["num_reports"].(*int)
	//ret.Likes = cmap["likes"].(*int)

	helper := new(helper)
	helper.buildComments(cmap["replies"])
	ret.Replies = helper.comments

	return ret
}

//Helper struct to keep our interesting stuff
type helper struct {
	comments []*Comment
}

//Recursive function to find the fields we want and build the Comments
//Way too hackish for my likes
func (h *helper) buildComments(inf interface{}) {
	switch tp := inf.(type) {
	case []interface{}: //Maybe array for base comments
		for _, k := range tp {
			h.buildComments(k)
		}
	case map[string]interface{}: //Maybe comment data
		if tp["body"] == nil {
			for _, k := range tp {
				h.buildComments(k)
			}
		} else {
			h.comments = append(h.comments, makeComment(tp))
		}
	}
}
<commit_msg>fix runtime panic setting comments fields<commit_after>// Copyright 2012 Jimmy Zelinskie. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package reddit

import (
	"fmt"
)

// Comment represents a reddit comment.
type Comment struct {
	Author              string  //`json:"author"`
	Body                string  //`json:"body"`
	BodyHTML            string  //`json:"body_html"`
	Subreddit           string  //`json:"subreddit"`
	LinkID              string  //`json:"link_id"`
	ParentID            string  //`json:"parent_id"`
	SubredditID         string  //`json:"subreddit_id"`
	FullID              string  //`json:"name"`
	UpVotes             float64 //`json:"ups"`
	DownVotes           float64 //`json:"downs"`
	Created             float64 //`json:"created_utc"`
	Edited              bool    //`json:"edited"`
	BannedBy            *string //`json:"banned_by"`
	ApprovedBy          *string //`json:"approved_by"`
	AuthorFlairTxt      *string //`json:"author_flair_text"`
	AuthorFlairCSSClass *string //`json:"author_flair_css_class"`
	NumReports          *int    //`json:"num_reports"`
	Likes               *int    //`json:"likes"`
	Replies             []*Comment
}

func (c Comment) voteID() string   { return c.FullID }
func (c Comment) deleteID() string { return c.FullID }
func (c Comment) replyID() string  { return c.FullID }

func (c Comment) String() string {
	return fmt.Sprintf("%s (%d/%d): %s", c.Author, c.UpVotes, c.DownVotes, c.Body)
}

// makeComment tries its best to fill as many fields as possible of a Comment.
func makeComment(cmap map[string]interface{}) *Comment {
	ret := new(Comment)
	ret.Author, _ = cmap["author"].(string)
	ret.Body, _ = cmap["body"].(string)
	ret.BodyHTML, _ = cmap["body_html"].(string)
	ret.Subreddit, _ = cmap["subreddit"].(string)
	ret.LinkID, _ = cmap["link_id"].(string)
	ret.ParentID, _ = cmap["parent_id"].(string)
	ret.SubredditID, _ = cmap["subreddit_id"].(string)
	ret.FullID, _ = cmap["name"].(string)
	ret.UpVotes, _ = cmap["ups"].(float64)
	ret.DownVotes, _ = cmap["downs"].(float64)
	ret.Created, _ = cmap["created_utc"].(float64)
	ret.Edited, _ = cmap["edited"].(bool)
	ret.BannedBy, _ = cmap["banned_by"].(*string)
	ret.ApprovedBy, _ = cmap["approved_by"].(*string)
	ret.AuthorFlairTxt, _ = cmap["author_flair_text"].(*string)
	ret.AuthorFlairCSSClass, _ = cmap["author_flair_css_class"].(*string)
	ret.NumReports, _ = cmap["num_reports"].(*int)
	ret.Likes, _ = cmap["likes"].(*int)

	helper := new(helper)
	helper.buildComments(cmap["replies"])
	ret.Replies = helper.comments

	return ret
}

//Helper struct to keep our interesting stuff
type helper struct {
	comments []*Comment
}

//Recursive function to find the fields we want and build the Comments
//Way too hackish for my likes
func (h *helper) buildComments(inf interface{}) {
	switch tp := inf.(type) {
	case []interface{}: //Maybe array for base comments
		for _, k := range tp {
			h.buildComments(k)
		}
	case map[string]interface{}: //Maybe comment data
		if tp["body"] == nil {
			for _, k := range tp {
				h.buildComments(k)
			}
		} else {
			h.comments = append(h.comments, makeComment(tp))
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/fsouza/go-dockerclient"
)

const TRIES = 10

type Healthcheck struct {
	Result int
	Lines  []string
}

func command(config *docker.HealthConfig) []string {
	switch config.Test[0] {
	case "CMD":
		return config.Test[1:len(config.Test)]
	case "CMD-SHELL":
		return append([]string{"/bin/sh", "-c"}, config.Test[1:len(config.Test)]...)
	default:
		return []string{"echo", "Healthcheck", config.Test[0]}
	}
}

func healthcheck(client *docker.Client, container *docker.Container) (*Healthcheck, error) {
	exec, err := client.CreateExec(docker.CreateExecOptions{
		AttachStdin:  false,
		AttachStdout: true,
		AttachStderr: true,
		Tty:          false,
		Cmd:          command(container.Config.Healthcheck),
		Container:    container.ID,
	})
	if err != nil {
		return nil, err
	}

	var stdout, stderr bytes.Buffer
	err = client.StartExec(exec.ID, docker.StartExecOptions{
		OutputStream: &stdout,
		ErrorStream:  &stderr,
		RawTerminal:  true,
	})
	if err != nil {
		return nil, err
	}

	inspect, err := client.InspectExec(exec.ID)
	if err != nil {
		return nil, err
	}

	return &Healthcheck{Result: inspect.ExitCode, Lines: strings.Split(stdout.String(), "\n")}, nil
}

func wait(client *docker.Client, ID string) error {
	container, err := client.InspectContainer(ID)
	if err != nil {
		return err
	}

	fmt.Printf("  %+v\n", container.Config.Healthcheck)
	if container.Config.Healthcheck == nil || len(container.Config.Healthcheck.Test) == 0 {
		fmt.Printf("  No Healthcheck, assuming container started.\n")
		return nil
	}

	tries := TRIES
	for tries > 0 {
		check, err := healthcheck(client, container)
		fmt.Printf("  %+v.\n", check)
		if err != nil {
			return err
		}

		if check.Result == 0 {
			return nil
		}

		time.Sleep(1 * time.Second)
		tries--
	}
	return fmt.Errorf("Timed out")
}

func main() {
	endpoint := flag.String("endpoint", "unix:///var/run/docker.sock", "Docker socket")

	client, err := docker.NewClient(*endpoint)
	if err != nil {
		fmt.Printf("Error (%s) %s\n", *endpoint, err.Error())
		os.Exit(1)
	}

	events := make(chan *docker.APIEvents)
	client.AddEventListener(events)
	fmt.Println("Listening...")

	for {
		select {
		case event := <-events:
			switch event.Status {
			case "start":
				fmt.Printf("> START %s: %s\n", event.From, event.ID)

				err := wait(client, event.ID)
				if err != nil {
					fmt.Printf("  %s\n", err.Error())
				} else {
					fmt.Printf("  Up and running!\n")
				}

			case "stop":
				fmt.Printf("> STOP %s: %s\n", event.From, event.ID)
			case "die":
				fmt.Printf("> DIE %s: %s\n", event.From, event.ID)
			}
		}
	}
}
<commit_msg>Beautify output<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/fsouza/go-dockerclient"
)

const TRIES = 10

type Healthcheck struct {
	Result int
	Lines  []string
}

func writef(ID, format string, args ...interface{}) {
	fmt.Printf("\033[1;34m"+ID[0:13]+" |\033[0m "+format+"\n", args...)
}

func command(config *docker.HealthConfig) []string {
	switch config.Test[0] {
	case "CMD":
		return config.Test[1:len(config.Test)]
	case "CMD-SHELL":
		return append([]string{"/bin/sh", "-c"}, config.Test[1:len(config.Test)]...)
	default:
		return []string{"echo", "Healthcheck", config.Test[0]}
	}
}

func healthcheck(client *docker.Client, container *docker.Container) (*Healthcheck, error) {
	exec, err := client.CreateExec(docker.CreateExecOptions{
		AttachStdin:  false,
		AttachStdout: true,
		AttachStderr: true,
		Tty:          false,
		Cmd:          command(container.Config.Healthcheck),
		Container:    container.ID,
	})
	if err != nil {
		return nil, err
	}

	var stdout, stderr bytes.Buffer
	err = client.StartExec(exec.ID, docker.StartExecOptions{
		OutputStream: &stdout,
		ErrorStream:  &stderr,
		RawTerminal:  true,
	})
	if err != nil {
		return nil, err
	}

	inspect, err := client.InspectExec(exec.ID)
	if err != nil {
		return nil, err
	}

	return &Healthcheck{Result: inspect.ExitCode, Lines: strings.Split(stdout.String(), "\n")}, nil
}

func wait(client *docker.Client, ID string) error {
	container, err := client.InspectContainer(ID)
	if err != nil {
		return err
	}

	writef(ID, "%+v", container.Config.Healthcheck)
	if container.Config.Healthcheck == nil || len(container.Config.Healthcheck.Test) == 0 {
		writef(ID, "No Healthcheck, assuming container started")
		return nil
	}

	tries := TRIES
	for tries > 0 {
		check, err := healthcheck(client, container)
		writef(ID, "%+v", check)
		if err != nil {
			return err
		}

		if check.Result == 0 {
			return nil
		}

		time.Sleep(1 * time.Second)
		tries--
	}
	return fmt.Errorf("Timed out")
}

func main() {
	endpoint := flag.String("endpoint", "unix:///var/run/docker.sock", "Docker socket")

	client, err := docker.NewClient(*endpoint)
	if err != nil {
		fmt.Printf("Error (%s) %s\n", *endpoint, err.Error())
		os.Exit(1)
	}

	events := make(chan *docker.APIEvents)
	client.AddEventListener(events)
	fmt.Println("Listening...")

	for {
		select {
		case event := <-events:
			switch event.Status {
			case "start":
				writef(event.ID, "Start %s", event.From)

				go func() {
					err := wait(client, event.ID)
					if err != nil {
						writef(event.ID, "Error %s", err.Error())
					} else {
						writef(event.ID, "Up and running!")
					}
				}()

			case "stop":
				writef(event.ID, "Stop %s", event.From)
			case "die":
				writef(event.ID, "Die %s", event.From)
			}
		}
	}
}
<|endoftext|>