<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"os"
	"syscall"

	log "github.com/Sirupsen/logrus"
	cobra "github.com/spf13/cobra"
)

var zfs *os.File

func init() {
	z, err := os.OpenFile("/dev/zfs", os.O_RDWR, 0)
	if err != nil {
		panic(err)
	}
	zfs = z
}

type handler func(*cobra.Command, []string) error

func genCommand(use, short string, fn handler) *cobra.Command {
	run := func(cmd *cobra.Command, args []string) {
		if err := fn(cmd, args); err != nil {
			log.Fatal(err)
		} else {
			log.Info("success")
		}
	}
	return &cobra.Command{
		Use:   use,
		Short: short,
		Run:   run,
	}

}

func main() {
	root := &cobra.Command{
		Use:  "gozfs",
		Long: "gozfs is the cli for testing the go zfs ioctl api",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			if cmd.Use == "gozfs" {
				return
			}
			name, err := cmd.Flags().GetString("name")
			if err != nil {
				log.Fatal(err)
			}
			if name == "" {
				log.Fatal("missing name")
			}
		},
		Run: help,
	}
	root.PersistentFlags().StringP("name", "n", "", "dataset name")

	cmdExists := genCommand("exists", "Test for dataset existence.",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			return exists(name)
		})

	cmdDestroy := genCommand("destroy", "Destroys a dataset or volume.",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			deferFlag, _ := cmd.Flags().GetBool("defer")
			return destroy(name, deferFlag)
		})
	cmdDestroy.Flags().BoolP("defer", "d", false, "defer destroy")

	cmdHolds := genCommand("holds", "Retrieve list of user holds on the specified snapshot.",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			holds, err := holds(name)
			if err == nil {
				fmt.Println(holds)
			}
			return err
		})

	cmdSnapshot := genCommand("snapshot <snap1> <snap2> ...", "Creates a snapshot of a dataset or volume",
		func(cmd *cobra.Command, snaps []string) error {
			zpool, _ := cmd.Flags().GetString("zpool")
			if zpool == "" {
				log.Fatal("zpool required")
			}
			if len(snaps) == 0 {
				log.Fatal("at least one snapshot name required")
			}

			var props map[string]string
			propJSON, _ := cmd.Flags().GetString("props")
			if err := json.Unmarshal([]byte(propJSON), &props); err != nil {
				log.Fatal("bad prop json")
			}

			errlist, err := snapshot(zpool, snaps, props)
			if errlist != nil {
				log.Error(errlist)
			}
			return err
		},
	)
	cmdSnapshot.PersistentPreRun = func(cmd *cobra.Command, args []string) {
		// Use PersistentPreRun here to replace the root one
	}
	cmdSnapshot.Flags().StringP("zpool", "z", "", "zpool")
	cmdSnapshot.Flags().StringP("props", "p", "{}", "snapshot properties")

	cmdRollback := genCommand("rollback", "Rollback this filesystem or volume to its most recent snapshot.",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			result, err := rollback(name)
			if err == nil {
				fmt.Println(result)
			}
			return err
		},
	)

	cmdCreate := genCommand("create", "Create a ZFS dataset or volume",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			createTypeName, _ := cmd.Flags().GetString("type")
			createType, err := getDMUType(createTypeName)
			if err != nil {
				log.Fatal("invalid type")
			}

			propJSON, _ := cmd.Flags().GetString("props")
			var props map[string]interface{}
			if err := json.Unmarshal([]byte(propJSON), &props); err != nil {
				log.Fatal("bad prop json")
			}

			if volsize, ok := props["volsize"]; ok {
				if volsizeFloat, ok := volsize.(float64); ok {
					props["volsize"] = uint64(volsizeFloat)
				}
			}

			if volblocksize, ok := props["volblocksize"]; ok {
				if volblocksizeFloat, ok := volblocksize.(float64); ok {
					props["volblocksize"] = uint64(volblocksizeFloat)
				}
			}

			return create(name, createType, props)
		},
	)
	cmdCreate.Flags().StringP("type", "t", "zfs", "zfs or zvol")
	cmdCreate.Flags().StringP("props", "p", "{}", "create properties")

	cmdSend := genCommand("send", "Generate a send stream from a snapshot",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			largeBlockOK, _ := cmd.Flags().GetBool("largeblock")
			embedOK, _ := cmd.Flags().GetBool("embed")
			fromSnap, _ := cmd.Flags().GetString("fromsnap")

			outputFD := uintptr(syscall.Stdout)
			output, _ := cmd.Flags().GetString("output")
			if output != "" {
				outputFile, err := os.Create(output)
				if err != nil {
					return err
				}
				defer outputFile.Close()

				outputFD = outputFile.Fd()
			} else {
				// If sending on stdout, don't log anything else unless there's
				// an error
				log.SetLevel(log.ErrorLevel)
			}

			return send(name, outputFD, fromSnap, largeBlockOK, embedOK)
		},
	)
	cmdSend.Flags().StringP("output", "o", "", "output file")
	cmdSend.Flags().StringP("fromsnap", "f", "", "full snap name to send incremental from")
	cmdSend.Flags().BoolP("embed", "e", false, "embed data")
	cmdSend.Flags().BoolP("largeblock", "l", false, "large block")

	root.AddCommand(
		cmdExists,
		cmdDestroy,
		cmdHolds,
		cmdSnapshot,
		cmdRollback,
		cmdCreate,
		cmdSend,
	)
	if err := root.Execute(); err != nil {
		log.Fatal("root execute failed:", err)
	}
}

func help(cmd *cobra.Command, _ []string) {
	if err := cmd.Help(); err != nil {
		log.Fatal("help failed:", err)
	}
}
<commit_msg>Use os.Stdout.Fd() instead of uintptr(syscall.Stdout)<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"os"

	log "github.com/Sirupsen/logrus"
	cobra "github.com/spf13/cobra"
)

var zfs *os.File

func init() {
	z, err := os.OpenFile("/dev/zfs", os.O_RDWR, 0)
	if err != nil {
		panic(err)
	}
	zfs = z
}

type handler func(*cobra.Command, []string) error

func genCommand(use, short string, fn handler) *cobra.Command {
	run := func(cmd *cobra.Command, args []string) {
		if err := fn(cmd, args); err != nil {
			log.Fatal(err)
		} else {
			log.Info("success")
		}
	}
	return &cobra.Command{
		Use:   use,
		Short: short,
		Run:   run,
	}

}

func main() {
	root := &cobra.Command{
		Use:  "gozfs",
		Long: "gozfs is the cli for testing the go zfs ioctl api",
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			if cmd.Use == "gozfs" {
				return
			}
			name, err := cmd.Flags().GetString("name")
			if err != nil {
				log.Fatal(err)
			}
			if name == "" {
				log.Fatal("missing name")
			}
		},
		Run: help,
	}
	root.PersistentFlags().StringP("name", "n", "", "dataset name")

	cmdExists := genCommand("exists", "Test for dataset existence.",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			return exists(name)
		})

	cmdDestroy := genCommand("destroy", "Destroys a dataset or volume.",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			deferFlag, _ := cmd.Flags().GetBool("defer")
			return destroy(name, deferFlag)
		})
	cmdDestroy.Flags().BoolP("defer", "d", false, "defer destroy")

	cmdHolds := genCommand("holds", "Retrieve list of user holds on the specified snapshot.",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			holds, err := holds(name)
			if err == nil {
				fmt.Println(holds)
			}
			return err
		})

	cmdSnapshot := genCommand("snapshot <snap1> <snap2> ...", "Creates a snapshot of a dataset or volume",
		func(cmd *cobra.Command, snaps []string) error {
			zpool, _ := cmd.Flags().GetString("zpool")
			if zpool == "" {
				log.Fatal("zpool required")
			}
			if len(snaps) == 0 {
				log.Fatal("at least one snapshot name required")
			}

			var props map[string]string
			propJSON, _ := cmd.Flags().GetString("props")
			if err := json.Unmarshal([]byte(propJSON), &props); err != nil {
				log.Fatal("bad prop json")
			}

			errlist, err := snapshot(zpool, snaps, props)
			if errlist != nil {
				log.Error(errlist)
			}
			return err
		},
	)
	cmdSnapshot.PersistentPreRun = func(cmd *cobra.Command, args []string) {
		// Use PersistentPreRun here to replace the root one
	}
	cmdSnapshot.Flags().StringP("zpool", "z", "", "zpool")
	cmdSnapshot.Flags().StringP("props", "p", "{}", "snapshot properties")

	cmdRollback := genCommand("rollback", "Rollback this filesystem or volume to its most recent snapshot.",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			result, err := rollback(name)
			if err == nil {
				fmt.Println(result)
			}
			return err
		},
	)

	cmdCreate := genCommand("create", "Create a ZFS dataset or volume",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			createTypeName, _ := cmd.Flags().GetString("type")
			createType, err := getDMUType(createTypeName)
			if err != nil {
				log.Fatal("invalid type")
			}

			propJSON, _ := cmd.Flags().GetString("props")
			var props map[string]interface{}
			if err := json.Unmarshal([]byte(propJSON), &props); err != nil {
				log.Fatal("bad prop json")
			}

			if volsize, ok := props["volsize"]; ok {
				if volsizeFloat, ok := volsize.(float64); ok {
					props["volsize"] = uint64(volsizeFloat)
				}
			}

			if volblocksize, ok := props["volblocksize"]; ok {
				if volblocksizeFloat, ok := volblocksize.(float64); ok {
					props["volblocksize"] = uint64(volblocksizeFloat)
				}
			}

			return create(name, createType, props)
		},
	)
	cmdCreate.Flags().StringP("type", "t", "zfs", "zfs or zvol")
	cmdCreate.Flags().StringP("props", "p", "{}", "create properties")

	cmdSend := genCommand("send", "Generate a send stream from a snapshot",
		func(cmd *cobra.Command, args []string) error {
			name, _ := cmd.Flags().GetString("name")
			largeBlockOK, _ := cmd.Flags().GetBool("largeblock")
			embedOK, _ := cmd.Flags().GetBool("embed")
			fromSnap, _ := cmd.Flags().GetString("fromsnap")

			outputFD := os.Stdout.Fd()
			output, _ := cmd.Flags().GetString("output")
			if output != "" {
				outputFile, err := os.Create(output)
				if err != nil {
					return err
				}
				defer outputFile.Close()

				outputFD = outputFile.Fd()
			} else {
				// If sending on stdout, don't log anything else unless there's
				// an error
				log.SetLevel(log.ErrorLevel)
			}

			return send(name, outputFD, fromSnap, largeBlockOK, embedOK)
		},
	)
	cmdSend.Flags().StringP("output", "o", "", "output file")
	cmdSend.Flags().StringP("fromsnap", "f", "", "full snap name to send incremental from")
	cmdSend.Flags().BoolP("embed", "e", false, "embed data")
	cmdSend.Flags().BoolP("largeblock", "l", false, "large block")

	root.AddCommand(
		cmdExists,
		cmdDestroy,
		cmdHolds,
		cmdSnapshot,
		cmdRollback,
		cmdCreate,
		cmdSend,
	)
	if err := root.Execute(); err != nil {
		log.Fatal("root execute failed:", err)
	}
}

func help(cmd *cobra.Command, _ []string) {
	if err := cmd.Help(); err != nil {
		log.Fatal("help failed:", err)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Lennart Espe. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.md file.

// Bench is a file patching system using HTTPS and secure file hashing.
package main

import (
	"flag"
	"fmt"
	"path/filepath"

	"github.com/lnsp/bench/lib"
	"github.com/lnsp/pkginfo"
)

var (
	PatchSource     = flag.String("source", "", "Set patch source")
	TargetDirectory = flag.String("target", ".", "Set custom working directory")
	VerboseOutput   = flag.Bool("verbose", false, "Enable verbose output")
	PkgInfo         = pkginfo.PackageInfo{
		Name: "bench",
		Version: pkginfo.PackageVersion{
			Major:      0,
			Minor:      1,
			Patch:      0,
			Identifier: "rc1",
		},
	}
)

const (
	PatchFilePerm = 0664
	PatchFile     = ".bpatch"
	IgnoreFile    = ".benchignore"
	HelpText      = `USAGE: bench [action]

Available actions:
	generate - Generate patch files from active folder
	version - Print software version information
	fetch - Fetch updated files using file or server origin
	help - Display command overview

Available flags:
	--target - Set custom working directory
	--verbose - Enable verbose output
	--source - Set patch source`
)

func main() {
	flag.Parse()

	lib.SetVerbose(*VerboseOutput)
	workingDir, _ := filepath.Abs(*TargetDirectory)

	command := flag.Arg(0)
	switch command {
	case "generate":
		lib.Generate(workingDir, *PatchSource)
	case "fetch":
		lib.Fetch(workingDir, *PatchSource)
	case "version":
		printVersion()
	case "help":
		fallthrough // to existing help case
	default:
		fmt.Println(HelpText)
	}
}

func printVersion() {
	fmt.Println(PkgInfo)
}
<commit_msg>chore: push version<commit_after>// Copyright 2016 Lennart Espe. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE.md file.

// Bench is a file patching system using HTTPS and secure file hashing.
package main

import (
	"flag"
	"fmt"
	"path/filepath"

	"github.com/lnsp/bench/lib"
	"github.com/lnsp/pkginfo"
)

var (
	PatchSource     = flag.String("source", "", "Set patch source")
	TargetDirectory = flag.String("target", ".", "Set custom working directory")
	VerboseOutput   = flag.Bool("verbose", false, "Enable verbose output")
	PkgInfo         = pkginfo.PackageInfo{
		Name: "bench",
		Version: pkginfo.PackageVersion{
			Major:      0,
			Minor:      1,
			Patch:      0,
			Identifier: "release",
		},
	}
)

const (
	PatchFilePerm = 0664
	PatchFile     = ".bpatch"
	IgnoreFile    = ".benchignore"
	HelpText      = `USAGE: bench [action]

Available actions:
	generate - Generate patch files from active folder
	version - Print software version information
	fetch - Fetch updated files using file or server origin
	help - Display command overview

Available flags:
	--target - Set custom working directory
	--verbose - Enable verbose output
	--source - Set patch source`
)

func main() {
	flag.Parse()

	lib.SetVerbose(*VerboseOutput)
	workingDir, _ := filepath.Abs(*TargetDirectory)

	command := flag.Arg(0)
	switch command {
	case "generate":
		lib.Generate(workingDir, *PatchSource)
	case "fetch":
		lib.Fetch(workingDir, *PatchSource)
	case "version":
		printVersion()
	case "help":
		fallthrough // to existing help case
	default:
		fmt.Println(HelpText)
	}
}

func printVersion() {
	fmt.Println(PkgInfo)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/joho/godotenv"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

var (
	version = "unknown"
)

func main() {
	app := cli.NewApp()
	app.Name = "github-release plugin"
	app.Usage = "github-release plugin"
	app.Action = run
	app.Version = version
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "api-key",
			Usage:  "api key to access github api",
			EnvVar: "PLUGIN_API_KEY,GITHUB_RELEASE_API_KEY,GITHUB_TOKEN",
		},
		cli.StringSliceFlag{
			Name:   "files",
			Usage:  "list of files to upload",
			EnvVar: "PLUGIN_FILES,GITHUB_RELEASE_FILES",
		},
		cli.StringFlag{
			Name:   "file-exists",
			Value:  "overwrite",
			Usage:  "what to do if file already exist",
			EnvVar: "PLUGIN_FILE_EXISTS,GITHUB_RELEASE_FILE_EXISTS",
		},
		cli.StringSliceFlag{
			Name:   "checksum",
			Usage:  "generate specific checksums",
			EnvVar: "PLUGIN_CHECKSUM,GITHUB_RELEASE_CHECKSUM",
		},
		cli.StringFlag{
			Name:   "checksum-file",
			Usage:  "name used for checksum file. \"CHECKSUM\" is replaced with the chosen method",
			EnvVar: "PLUGIN_CHECKSUM_FILE",
			Value:  "CHECKSUMsum.txt",
		},
		cli.BoolFlag{
			Name:   "checksum-flatten",
			Usage:  "include only the basename of the file in the checksum file",
			EnvVar: "PLUGIN_CHECKSUM_FLATTEN",
		},
		cli.BoolFlag{
			Name:   "draft",
			Usage:  "create a draft release",
			EnvVar: "PLUGIN_DRAFT,GITHUB_RELEASE_DRAFT",
		},
		cli.BoolFlag{
			Name:   "prerelease",
			Usage:  "set the release as prerelease",
			EnvVar: "PLUGIN_PRERELEASE,GITHUB_RELEASE_PRERELEASE",
		},
		cli.StringFlag{
			Name:   "base-url",
			Value:  "https://api.github.com/",
			Usage:  "api url, needs to be changed for ghe",
			EnvVar: "PLUGIN_BASE_URL,GITHUB_RELEASE_BASE_URL",
		},
		cli.StringFlag{
			Name:   "upload-url",
			Value:  "https://uploads.github.com/",
			Usage:  "upload url, needs to be changed for ghe",
			EnvVar: "PLUGIN_UPLOAD_URL,GITHUB_RELEASE_UPLOAD_URL",
		},
		cli.StringFlag{
			Name:   "note",
			Value:  "",
			Usage:  "file or string with notes for the release (example: changelog)",
			EnvVar: "PLUGIN_NOTE,GITHUB_RELEASE_NOTE",
		},
		cli.StringFlag{
			Name:   "title",
			Value:  "",
			Usage:  "file or string for the title shown in the github release",
			EnvVar: "PLUGIN_TITLE,GITHUB_RELEASE_TITLE",
		},
		cli.BoolFlag{
			Name:   "overwrite",
			Usage:  "force overwrite existing release informations e.g. title or note",
			EnvVar: "PLUGIN_OVERWRITE,GITHUB_RELEASE_OVERWRIDE",
		},
		cli.StringFlag{
			Name:   "repo.owner",
			Usage:  "repository owner",
			EnvVar: "DRONE_REPO_OWNER",
		},
		cli.StringFlag{
			Name:   "repo.name",
			Usage:  "repository name",
			EnvVar: "DRONE_REPO_NAME",
		},
		cli.StringFlag{
			Name:   "build.event",
			Value:  "push",
			Usage:  "build event",
			EnvVar: "DRONE_BUILD_EVENT",
		},
		cli.StringFlag{
			Name:   "commit.ref",
			Value:  "refs/heads/master",
			Usage:  "git commit ref",
			EnvVar: "DRONE_COMMIT_REF",
		},
		cli.StringFlag{
			Name:  "env-file",
			Usage: "source env file",
		},
	}

	if err := app.Run(os.Args); err != nil {
		logrus.Fatal(err)
	}
}

func run(c *cli.Context) error {
	if c.String("env-file") != "" {
		_ = godotenv.Load(c.String("env-file"))
	}

	plugin := Plugin{
		Repo: Repo{
			Owner: c.String("repo.owner"),
			Name:  c.String("repo.name"),
		},
		Build: Build{
			Event: c.String("build.event"),
		},
		Commit: Commit{
			Ref: c.String("commit.ref"),
		},
		Config: Config{
			APIKey:          c.String("api-key"),
			Files:           c.StringSlice("files"),
			FileExists:      c.String("file-exists"),
			Checksum:        c.StringSlice("checksum"),
			ChecksumFile:    c.String("checksum-file"),
			ChecksumFlatten: c.Bool("checksum-flatten"),
			Draft:           c.Bool("draft"),
			Prerelease:      c.Bool("prerelease"),
			BaseURL:         c.String("base-url"),
			UploadURL:       c.String("upload-url"),
			Title:           c.String("title"),
			Note:            c.String("note"),
			Overwrite:       c.Bool("overwrite"),
		},
	}

	return plugin.Exec()
}
<commit_msg>Drop import of unused fmt package<commit_after>package main

import (
	"os"

	"github.com/joho/godotenv"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli"
)

var (
	version = "unknown"
)

func main() {
	app := cli.NewApp()
	app.Name = "github-release plugin"
	app.Usage = "github-release plugin"
	app.Action = run
	app.Version = version
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "api-key",
			Usage:  "api key to access github api",
			EnvVar: "PLUGIN_API_KEY,GITHUB_RELEASE_API_KEY,GITHUB_TOKEN",
		},
		cli.StringSliceFlag{
			Name:   "files",
			Usage:  "list of files to upload",
			EnvVar: "PLUGIN_FILES,GITHUB_RELEASE_FILES",
		},
		cli.StringFlag{
			Name:   "file-exists",
			Value:  "overwrite",
			Usage:  "what to do if file already exist",
			EnvVar: "PLUGIN_FILE_EXISTS,GITHUB_RELEASE_FILE_EXISTS",
		},
		cli.StringSliceFlag{
			Name:   "checksum",
			Usage:  "generate specific checksums",
			EnvVar: "PLUGIN_CHECKSUM,GITHUB_RELEASE_CHECKSUM",
		},
		cli.StringFlag{
			Name:   "checksum-file",
			Usage:  "name used for checksum file. \"CHECKSUM\" is replaced with the chosen method",
			EnvVar: "PLUGIN_CHECKSUM_FILE",
			Value:  "CHECKSUMsum.txt",
		},
		cli.BoolFlag{
			Name:   "checksum-flatten",
			Usage:  "include only the basename of the file in the checksum file",
			EnvVar: "PLUGIN_CHECKSUM_FLATTEN",
		},
		cli.BoolFlag{
			Name:   "draft",
			Usage:  "create a draft release",
			EnvVar: "PLUGIN_DRAFT,GITHUB_RELEASE_DRAFT",
		},
		cli.BoolFlag{
			Name:   "prerelease",
			Usage:  "set the release as prerelease",
			EnvVar: "PLUGIN_PRERELEASE,GITHUB_RELEASE_PRERELEASE",
		},
		cli.StringFlag{
			Name:   "base-url",
			Value:  "https://api.github.com/",
			Usage:  "api url, needs to be changed for ghe",
			EnvVar: "PLUGIN_BASE_URL,GITHUB_RELEASE_BASE_URL",
		},
		cli.StringFlag{
			Name:   "upload-url",
			Value:  "https://uploads.github.com/",
			Usage:  "upload url, needs to be changed for ghe",
			EnvVar: "PLUGIN_UPLOAD_URL,GITHUB_RELEASE_UPLOAD_URL",
		},
		cli.StringFlag{
			Name:   "note",
			Value:  "",
			Usage:  "file or string with notes for the release (example: changelog)",
			EnvVar: "PLUGIN_NOTE,GITHUB_RELEASE_NOTE",
		},
		cli.StringFlag{
			Name:   "title",
			Value:  "",
			Usage:  "file or string for the title shown in the github release",
			EnvVar: "PLUGIN_TITLE,GITHUB_RELEASE_TITLE",
		},
		cli.BoolFlag{
			Name:   "overwrite",
			Usage:  "force overwrite existing release informations e.g. title or note",
			EnvVar: "PLUGIN_OVERWRITE,GITHUB_RELEASE_OVERWRIDE",
		},
		cli.StringFlag{
			Name:   "repo.owner",
			Usage:  "repository owner",
			EnvVar: "DRONE_REPO_OWNER",
		},
		cli.StringFlag{
			Name:   "repo.name",
			Usage:  "repository name",
			EnvVar: "DRONE_REPO_NAME",
		},
		cli.StringFlag{
			Name:   "build.event",
			Value:  "push",
			Usage:  "build event",
			EnvVar: "DRONE_BUILD_EVENT",
		},
		cli.StringFlag{
			Name:   "commit.ref",
			Value:  "refs/heads/master",
			Usage:  "git commit ref",
			EnvVar: "DRONE_COMMIT_REF",
		},
		cli.StringFlag{
			Name:  "env-file",
			Usage: "source env file",
		},
	}

	if err := app.Run(os.Args); err != nil {
		logrus.Fatal(err)
	}
}

func run(c *cli.Context) error {
	if c.String("env-file") != "" {
		_ = godotenv.Load(c.String("env-file"))
	}

	plugin := Plugin{
		Repo: Repo{
			Owner: c.String("repo.owner"),
			Name:  c.String("repo.name"),
		},
		Build: Build{
			Event: c.String("build.event"),
		},
		Commit: Commit{
			Ref: c.String("commit.ref"),
		},
		Config: Config{
			APIKey:          c.String("api-key"),
			Files:           c.StringSlice("files"),
			FileExists:      c.String("file-exists"),
			Checksum:        c.StringSlice("checksum"),
			ChecksumFile:    c.String("checksum-file"),
			ChecksumFlatten: c.Bool("checksum-flatten"),
			Draft:           c.Bool("draft"),
			Prerelease:      c.Bool("prerelease"),
			BaseURL:         c.String("base-url"),
			UploadURL:       c.String("upload-url"),
			Title:           c.String("title"),
			Note:            c.String("note"),
			Overwrite:       c.Bool("overwrite"),
		},
	}

	return plugin.Exec()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/url"
	"os"

	"github.com/afeld/tangle/models"
)

func startURL() (u *url.URL) {
	rawURL := os.Args[1]
	if len(os.Args) != 2 {
		log.Fatal("Usage:\n\n\tgo run main.go <url>\n\n")
	}

	u, err := url.Parse(rawURL)
	if err != nil {
		log.Fatalln(err)
	}
	if !u.IsAbs() {
		log.Fatalln("Must be an absolute URL.")
	}
	return
}

func main() {
	u := startURL()
	page := models.Page{AbsURL: u}

	fmt.Println("Checking for broken links...")

	links, err := page.GetLinks()
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("Number of links found: %d\n", len(links))

	numBrokenLinks := 0
	for _, link := range links {
		if !link.IsValid() {
			numBrokenLinks++
			dest, _ := link.DestURL()
			fmt.Printf("%s line %d has broken link to %s.\n", u.String(), link.Node.LineNumber(), dest)
		}
	}
	fmt.Printf("Number of broken links: %d\n", numBrokenLinks)
}
<commit_msg>check URLs in parallel<commit_after>package main

import (
	"fmt"
	"log"
	"net/url"
	"os"
	"sync"

	"github.com/afeld/tangle/models"
)

func startURL() (u *url.URL) {
	rawURL := os.Args[1]
	if len(os.Args) != 2 {
		log.Fatal("Usage:\n\n\tgo run main.go <url>\n\n")
	}

	u, err := url.Parse(rawURL)
	if err != nil {
		log.Fatalln(err)
	}
	if !u.IsAbs() {
		log.Fatalln("Must be an absolute URL.")
	}
	return
}

func main() {
	u := startURL()
	page := models.Page{AbsURL: u}

	fmt.Println("Checking for broken links...")

	links, err := page.GetLinks()
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Printf("Number of links found: %d\n", len(links))

	numBrokenLinks := 0
	var counterMx sync.Mutex
	var wg sync.WaitGroup

	for _, link := range links {
		wg.Add(1)
		go func(l models.Link) {
			defer wg.Done()

			if !l.IsValid() {
				counterMx.Lock()
				numBrokenLinks++
				counterMx.Unlock()

				dest, _ := l.DestURL()
				fmt.Printf("%s line %d has broken link to %s.\n", u.String(), l.Node.LineNumber(), dest)
			}
		}(link)
	}
	wg.Wait()

	fmt.Printf("Number of broken links: %d\n", numBrokenLinks)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/benbjohnson/clock"
	"github.com/gorilla/mux"
	"github.com/petergtz/bitsgo/basic_auth_middleware"
	"github.com/petergtz/bitsgo/blobstores/decorator"
	"github.com/petergtz/bitsgo/blobstores/local"
	"github.com/petergtz/bitsgo/blobstores/s3"
	"github.com/petergtz/bitsgo/blobstores/webdav"
	"github.com/petergtz/bitsgo/config"
	log "github.com/petergtz/bitsgo/logger"
	"github.com/petergtz/bitsgo/middlewares"
	"github.com/petergtz/bitsgo/pathsigner"
	"github.com/petergtz/bitsgo/routes"
	"github.com/uber-go/zap"
	"github.com/urfave/negroni"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	configPath = kingpin.Flag("config", "specify config to use").Required().Short('c').String()
)

func main() {
	kingpin.Parse()

	config, e := config.LoadConfig(*configPath)

	if e != nil {
		log.Log.Fatal("Could not load config.", zap.Error(e))
	}
	log.Log.Info("Logging level", zap.String("log-level", config.Logging.Level))

	log.SetLogger(zap.New(zap.NewTextEncoder(), zapLogLevelFrom(config.Logging.Level), zap.AddCaller()))

	rootRouter := mux.NewRouter()
	rootRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusBadRequest)
	})

	internalRouter := mux.NewRouter()

	rootRouter.Host(config.PrivateEndpointUrl().Host).Handler(internalRouter)

	appStashBlobstore := createAppStashBlobstore(config.AppStash)
	packageBlobstore, signPackageURLHandler := createBlobstoreAndSignURLHandler(config.Packages, config.PublicEndpointUrl().Host, config.Port, config.Secret, "packages")
	dropletBlobstore, signDropletURLHandler := createBlobstoreAndSignURLHandler(config.Droplets, config.PublicEndpointUrl().Host, config.Port, config.Secret, "droplets")
	buildpackBlobstore, signBuildpackURLHandler := createBlobstoreAndSignURLHandler(config.Buildpacks, config.PublicEndpointUrl().Host, config.Port, config.Secret, "buildpacks")
	buildpackCacheBlobstore, signBuildpackCacheURLHandler := createBuildpackCacheSignURLHandler(config.Droplets, config.PublicEndpointUrl().Host, config.Port, config.Secret, "droplets")

	routes.SetUpSignRoute(internalRouter, basic_auth_middleware.NewBasicAuthMiddleWare(basicAuthCredentialsFrom(config.SigningUsers)...),
		signPackageURLHandler, signDropletURLHandler, signBuildpackURLHandler, signBuildpackCacheURLHandler)

	routes.SetUpAppStashRoutes(internalRouter, appStashBlobstore)
	routes.SetUpPackageRoutes(internalRouter, packageBlobstore)
	routes.SetUpBuildpackRoutes(internalRouter, buildpackBlobstore)
	routes.SetUpDropletRoutes(internalRouter, dropletBlobstore)
	routes.SetUpBuildpackCacheRoutes(internalRouter, buildpackCacheBlobstore)

	publicRouter := mux.NewRouter()
	rootRouter.Host(config.PublicEndpointUrl().Host).Handler(negroni.New(
		&local.SignatureVerificationMiddleware{&pathsigner.PathSignerValidator{config.Secret, clock.New()}},
		negroni.Wrap(publicRouter),
	))
	if config.Packages.BlobstoreType == "local" {
		routes.SetUpPackageRoutes(publicRouter, packageBlobstore)
	}
	if config.Buildpacks.BlobstoreType == "local" {
		routes.SetUpBuildpackRoutes(publicRouter, buildpackBlobstore)
	}
	if config.Droplets.BlobstoreType == "local" {
		routes.SetUpDropletRoutes(publicRouter, dropletBlobstore)
		routes.SetUpBuildpackCacheRoutes(publicRouter, buildpackCacheBlobstore)
	}

	httpHandler := negroni.New(middlewares.NewZapLoggerMiddleware(log.Log))
	if config.MaxBodySizeBytes() != 0 {
		httpHandler.Use(middlewares.NewBodySizeLimitMiddleware(config.MaxBodySizeBytes()))
	}
	httpHandler.UseHandler(rootRouter)

	httpServer := &http.Server{
		Handler: httpHandler,
		Addr:    fmt.Sprintf("0.0.0.0:%v", config.Port),
		// TODO possibly remove timeouts completely?
		WriteTimeout: 60 * time.Minute,
		ReadTimeout:  60 * time.Minute,
	}

	e = httpServer.ListenAndServe()
	log.Log.Fatal("http server crashed", zap.Error(e))
}

func zapLogLevelFrom(configLogLevel string) zap.Level {
	switch strings.ToLower(configLogLevel) {
	case "", "debug":
		return zap.DebugLevel
	case "info":
		return zap.InfoLevel
	case "warn":
		return zap.WarnLevel
	case "error":
		return zap.ErrorLevel
	case "fatal":
		return zap.FatalLevel
	default:
		log.Log.Fatal("Invalid log level in config", zap.String("log-level", configLogLevel))
		return -1
	}
}

func basicAuthCredentialsFrom(configCredententials []config.Credential) (basicAuthCredentials []basic_auth_middleware.Credential) {
	basicAuthCredentials = make([]basic_auth_middleware.Credential, len(configCredententials))
	for i := range configCredententials {
		basicAuthCredentials[i] = basic_auth_middleware.Credential(configCredententials[i])
	}
	return
}

func createBlobstoreAndSignURLHandler(blobstoreConfig config.BlobstoreConfig, publicHost string, port int, secret string, resourceType string) (routes.Blobstore, *routes.SignResourceHandler) {
	switch strings.ToLower(blobstoreConfig.BlobstoreType) {
	case "local":
		log.Log.Info("Creating local blobstore", zap.String("path-prefix", blobstoreConfig.LocalConfig.PathPrefix))
		return decorator.ForBlobstoreWithPathPartitioning(
				local.NewBlobstore(blobstoreConfig.LocalConfig.PathPrefix)),
			createLocalSignResourceHandler(publicHost, port, secret, resourceType)
	case "s3", "aws":
		log.Log.Info("Creating S3 blobstore", zap.String("bucket", blobstoreConfig.S3Config.Bucket))
		return decorator.ForBlobstoreWithPathPartitioning(
				s3.NewBlobstore(*blobstoreConfig.S3Config)),
			routes.NewSignResourceHandler(
				decorator.ForResourceSignerWithPathPartitioning(
					s3.NewResourceSigner(*blobstoreConfig.S3Config)))
	case "webdav":
		log.Log.Info("Creating Webdav blobstore",
			zap.String("public-endpoint", blobstoreConfig.WebdavConfig.PublicEndpoint),
			zap.String("private-endpoint", blobstoreConfig.WebdavConfig.PrivateEndpoint))
		return decorator.ForBlobstoreWithPathPartitioning(
				decorator.ForBlobstoreWithPathPrefixing(
					webdav.NewBlobstore(*blobstoreConfig.WebdavConfig),
					resourceType+"/")),
			routes.NewSignResourceHandler(
				decorator.ForResourceSignerWithPathPartitioning(
					decorator.ForResourceSignerWithPathPrefixing(
						webdav.NewWebdavResourceSigner(*blobstoreConfig.WebdavConfig), resourceType+"/")))

	default:
		log.Log.Fatal("blobstoreConfig is invalid.", zap.String("blobstore-type", blobstoreConfig.BlobstoreType))
		return nil, nil // satisfy compiler
	}
}

func createBuildpackCacheSignURLHandler(blobstoreConfig config.BlobstoreConfig, publicHost string, port int, secret string, resourceType string) (routes.Blobstore, *routes.SignResourceHandler) {
	switch strings.ToLower(blobstoreConfig.BlobstoreType) {
	case "local":
		log.Log.Info("Creating local blobstore", zap.String("path-prefix", blobstoreConfig.LocalConfig.PathPrefix))
		return decorator.ForBlobstoreWithPathPartitioning(
				decorator.ForBlobstoreWithPathPrefixing(
					local.NewBlobstore(blobstoreConfig.LocalConfig.PathPrefix),
					"buildpack_cache/")),
			createLocalSignResourceHandler(publicHost, port, secret, resourceType)
	case "s3", "aws":
		log.Log.Info("Creating S3 blobstore", zap.String("bucket", blobstoreConfig.S3Config.Bucket))
		return decorator.ForBlobstoreWithPathPartitioning(
				decorator.ForBlobstoreWithPathPrefixing(
					s3.NewBlobstore(*blobstoreConfig.S3Config),
					"buildpack_cache/")),
			routes.NewSignResourceHandler(
				decorator.ForResourceSignerWithPathPartitioning(
					decorator.ForResourceSignerWithPathPrefixing(
						s3.NewResourceSigner(*blobstoreConfig.S3Config),
						"buildpack_cache")))
	case "webdav":
		log.Log.Info("Creating Webdav blobstore",
			zap.String("public-endpoint", blobstoreConfig.WebdavConfig.PublicEndpoint),
			zap.String("private-endpoint", blobstoreConfig.WebdavConfig.PrivateEndpoint))
		return decorator.ForBlobstoreWithPathPartitioning(
				decorator.ForBlobstoreWithPathPrefixing(
					webdav.NewBlobstore(*blobstoreConfig.WebdavConfig),
					resourceType+"/buildpack_cache/")),
			routes.NewSignResourceHandler(
				decorator.ForResourceSignerWithPathPartitioning(
					decorator.ForResourceSignerWithPathPrefixing(
						webdav.NewWebdavResourceSigner(*blobstoreConfig.WebdavConfig),
						"buildpack_cache")))
	default:
		log.Log.Fatal("blobstoreConfig is invalid.", zap.String("blobstore-type", blobstoreConfig.BlobstoreType))
		return nil, nil // satisfy compiler
	}
}

func createLocalSignResourceHandler(publicHost string, port int, secret string, resourceType string) *routes.SignResourceHandler {
	return routes.NewSignResourceHandler(&local.LocalResourceSigner{
		DelegateEndpoint:   fmt.Sprintf("http://%v:%v", publicHost, port),
		Signer:             &pathsigner.PathSignerValidator{secret, clock.New()},
		ResourcePathPrefix: "/" + resourceType + "/",
		Clock:              clock.New(),
	})
}

func createAppStashBlobstore(blobstoreConfig config.BlobstoreConfig) routes.NoRedirectBlobstore {
	switch strings.ToLower(blobstoreConfig.BlobstoreType) {
	case "local":
		log.Log.Info("Creating local blobstore", zap.String("path-prefix", blobstoreConfig.LocalConfig.PathPrefix))
		return decorator.ForBlobstoreWithPathPartitioning(
			local.NewBlobstore(blobstoreConfig.LocalConfig.PathPrefix))

	case "s3", "aws":
		log.Log.Info("Creating S3 blobstore", zap.String("bucket", blobstoreConfig.S3Config.Bucket))
		return decorator.ForBlobstoreWithPathPartitioning(
			s3.NewBlobstore(*blobstoreConfig.S3Config))
	case "webdav":
		log.Log.Info("Creating Webdav blobstore",
			zap.String("public-endpoint", blobstoreConfig.WebdavConfig.PublicEndpoint),
			zap.String("private-endpoint", blobstoreConfig.WebdavConfig.PrivateEndpoint))
		return decorator.ForBlobstoreWithPathPartitioning(
			decorator.ForBlobstoreWithPathPrefixing(
				webdav.NewBlobstore(*blobstoreConfig.WebdavConfig),
				"app_stash/"))
	default:
		log.Log.Fatal("blobstoreConfig is invalid.", zap.String("blobstore-type", blobstoreConfig.BlobstoreType))
		return nil // satisfy compiler
	}
}
<commit_msg>Remove obsolete TODO<commit_after>package main

import (
	"fmt"
	"net/http"
	"strings"
	"time"

	"github.com/benbjohnson/clock"
	"github.com/gorilla/mux"
	"github.com/petergtz/bitsgo/basic_auth_middleware"
	"github.com/petergtz/bitsgo/blobstores/decorator"
	"github.com/petergtz/bitsgo/blobstores/local"
	"github.com/petergtz/bitsgo/blobstores/s3"
	"github.com/petergtz/bitsgo/blobstores/webdav"
	"github.com/petergtz/bitsgo/config"
	log "github.com/petergtz/bitsgo/logger"
	"github.com/petergtz/bitsgo/middlewares"
	"github.com/petergtz/bitsgo/pathsigner"
	"github.com/petergtz/bitsgo/routes"
	"github.com/uber-go/zap"
	"github.com/urfave/negroni"
	"gopkg.in/alecthomas/kingpin.v2"
)

var (
	configPath = kingpin.Flag("config", "specify config to use").Required().Short('c').String()
)

func main() {
	kingpin.Parse()

	config, e := config.LoadConfig(*configPath)

	if e != nil {
		log.Log.Fatal("Could not load config.", zap.Error(e))
	}
	log.Log.Info("Logging level", zap.String("log-level", config.Logging.Level))

	log.SetLogger(zap.New(zap.NewTextEncoder(), zapLogLevelFrom(config.Logging.Level), zap.AddCaller()))

	rootRouter := mux.NewRouter()
	rootRouter.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusBadRequest)
	})

	internalRouter := mux.NewRouter()

	rootRouter.Host(config.PrivateEndpointUrl().Host).Handler(internalRouter)

	appStashBlobstore := createAppStashBlobstore(config.AppStash)
	packageBlobstore, signPackageURLHandler := createBlobstoreAndSignURLHandler(config.Packages, config.PublicEndpointUrl().Host, config.Port, config.Secret, "packages")
	dropletBlobstore, signDropletURLHandler := createBlobstoreAndSignURLHandler(config.Droplets, config.PublicEndpointUrl().Host, config.Port, config.Secret, "droplets")
	buildpackBlobstore, signBuildpackURLHandler := createBlobstoreAndSignURLHandler(config.Buildpacks, config.PublicEndpointUrl().Host, config.Port, config.Secret, "buildpacks")
	buildpackCacheBlobstore, signBuildpackCacheURLHandler := createBuildpackCacheSignURLHandler(config.Droplets, config.PublicEndpointUrl().Host, config.Port, config.Secret, "droplets")

	routes.SetUpSignRoute(internalRouter, basic_auth_middleware.NewBasicAuthMiddleWare(basicAuthCredentialsFrom(config.SigningUsers)...),
		signPackageURLHandler, signDropletURLHandler, signBuildpackURLHandler, signBuildpackCacheURLHandler)

	routes.SetUpAppStashRoutes(internalRouter, appStashBlobstore)
	routes.SetUpPackageRoutes(internalRouter, packageBlobstore)
	routes.SetUpBuildpackRoutes(internalRouter, buildpackBlobstore)
	routes.SetUpDropletRoutes(internalRouter, dropletBlobstore)
	routes.SetUpBuildpackCacheRoutes(internalRouter, buildpackCacheBlobstore)

	publicRouter := mux.NewRouter()
	rootRouter.Host(config.PublicEndpointUrl().Host).Handler(negroni.New(
		&local.SignatureVerificationMiddleware{&pathsigner.PathSignerValidator{config.Secret, clock.New()}},
		negroni.Wrap(publicRouter),
	))
	if config.Packages.BlobstoreType == "local" {
		routes.SetUpPackageRoutes(publicRouter, packageBlobstore)
	}
	if config.Buildpacks.BlobstoreType == "local" {
		routes.SetUpBuildpackRoutes(publicRouter, buildpackBlobstore)
	}
	if config.Droplets.BlobstoreType == "local" {
		routes.SetUpDropletRoutes(publicRouter, dropletBlobstore)
		routes.SetUpBuildpackCacheRoutes(publicRouter, buildpackCacheBlobstore)
	}

	httpHandler := negroni.New(middlewares.NewZapLoggerMiddleware(log.Log))
	if config.MaxBodySizeBytes() != 0 {
		httpHandler.Use(middlewares.NewBodySizeLimitMiddleware(config.MaxBodySizeBytes()))
	}
	httpHandler.UseHandler(rootRouter)

	httpServer := &http.Server{
		Handler:      httpHandler,
		Addr:         fmt.Sprintf("0.0.0.0:%v", config.Port),
		WriteTimeout: 60 * time.Minute,
		ReadTimeout:  60 * time.Minute,
	}

	e = httpServer.ListenAndServe()
	log.Log.Fatal("http server crashed", zap.Error(e))
}

func zapLogLevelFrom(configLogLevel string) zap.Level {
	switch strings.ToLower(configLogLevel) {
	case "", "debug":
		return zap.DebugLevel
	case "info":
		return zap.InfoLevel
	case "warn":
		return zap.WarnLevel
	case "error":
		return zap.ErrorLevel
	case "fatal":
		return zap.FatalLevel
	default:
		log.Log.Fatal("Invalid log level in config", zap.String("log-level", configLogLevel))
		return -1
	}
}

func basicAuthCredentialsFrom(configCredententials []config.Credential) (basicAuthCredentials []basic_auth_middleware.Credential) {
	basicAuthCredentials = make([]basic_auth_middleware.Credential, len(configCredententials))
	for i := range configCredententials {
		basicAuthCredentials[i] = basic_auth_middleware.Credential(configCredententials[i])
	}
	return
}

func createBlobstoreAndSignURLHandler(blobstoreConfig config.BlobstoreConfig, publicHost string, port int, secret string, resourceType string) (routes.Blobstore, *routes.SignResourceHandler) {
	switch strings.ToLower(blobstoreConfig.BlobstoreType) {
	case "local":
		log.Log.Info("Creating local blobstore", zap.String("path-prefix", blobstoreConfig.LocalConfig.PathPrefix))
		return decorator.ForBlobstoreWithPathPartitioning(
				local.NewBlobstore(blobstoreConfig.LocalConfig.PathPrefix)),
			createLocalSignResourceHandler(publicHost, port, secret, resourceType)
	case "s3", "aws":
		log.Log.Info("Creating S3 blobstore", zap.String("bucket", blobstoreConfig.S3Config.Bucket))
		return decorator.ForBlobstoreWithPathPartitioning(
				s3.NewBlobstore(*blobstoreConfig.S3Config)),
			routes.NewSignResourceHandler(
				decorator.ForResourceSignerWithPathPartitioning(
					s3.NewResourceSigner(*blobstoreConfig.S3Config)))
	case "webdav":
		log.Log.Info("Creating Webdav blobstore",
			zap.String("public-endpoint", blobstoreConfig.WebdavConfig.PublicEndpoint),
			zap.String("private-endpoint", blobstoreConfig.WebdavConfig.PrivateEndpoint))
		return decorator.ForBlobstoreWithPathPartitioning(
				decorator.ForBlobstoreWithPathPrefixing(
					webdav.NewBlobstore(*blobstoreConfig.WebdavConfig),
					resourceType+"/")),
			routes.NewSignResourceHandler(
				decorator.ForResourceSignerWithPathPartitioning(
					decorator.ForResourceSignerWithPathPrefixing(
						webdav.NewWebdavResourceSigner(*blobstoreConfig.WebdavConfig), resourceType+"/")))

	default:
		log.Log.Fatal("blobstoreConfig is invalid.", zap.String("blobstore-type", blobstoreConfig.BlobstoreType))
		return nil, nil // satisfy compiler
	}
}

func createBuildpackCacheSignURLHandler(blobstoreConfig config.BlobstoreConfig, publicHost string, port int, secret string, resourceType string) (routes.Blobstore, *routes.SignResourceHandler) {
	switch strings.ToLower(blobstoreConfig.BlobstoreType) {
	case "local":
		log.Log.Info("Creating local blobstore", zap.String("path-prefix", blobstoreConfig.LocalConfig.PathPrefix))
		return decorator.ForBlobstoreWithPathPartitioning(
				decorator.ForBlobstoreWithPathPrefixing(
					local.NewBlobstore(blobstoreConfig.LocalConfig.PathPrefix),
					"buildpack_cache/")),
			createLocalSignResourceHandler(publicHost, port, secret, resourceType)
	case "s3", "aws":
		log.Log.Info("Creating S3 blobstore", zap.String("bucket", blobstoreConfig.S3Config.Bucket))
		return decorator.ForBlobstoreWithPathPartitioning(
				decorator.ForBlobstoreWithPathPrefixing(
					s3.NewBlobstore(*blobstoreConfig.S3Config),
					"buildpack_cache/")),
			routes.NewSignResourceHandler(
				decorator.ForResourceSignerWithPathPartitioning(
					decorator.ForResourceSignerWithPathPrefixing(
						s3.NewResourceSigner(*blobstoreConfig.S3Config),
						"buildpack_cache")))
	case "webdav":
		log.Log.Info("Creating Webdav blobstore",
			zap.String("public-endpoint", blobstoreConfig.WebdavConfig.PublicEndpoint),
			zap.String("private-endpoint", blobstoreConfig.WebdavConfig.PrivateEndpoint))
		return decorator.ForBlobstoreWithPathPartitioning(
				decorator.ForBlobstoreWithPathPrefixing(
					webdav.NewBlobstore(*blobstoreConfig.WebdavConfig),
					resourceType+"/buildpack_cache/")),
			routes.NewSignResourceHandler(
				decorator.ForResourceSignerWithPathPartitioning(
					decorator.ForResourceSignerWithPathPrefixing(
						webdav.NewWebdavResourceSigner(*blobstoreConfig.WebdavConfig),
						"buildpack_cache")))
	default:
		log.Log.Fatal("blobstoreConfig is invalid.", zap.String("blobstore-type", blobstoreConfig.BlobstoreType))
		return nil, nil // satisfy compiler
	}
}

func createLocalSignResourceHandler(publicHost string, port int, secret string, resourceType string) *routes.SignResourceHandler {
	return routes.NewSignResourceHandler(&local.LocalResourceSigner{
		DelegateEndpoint:   fmt.Sprintf("http://%v:%v", publicHost, port),
		Signer:             &pathsigner.PathSignerValidator{secret, clock.New()},
		ResourcePathPrefix: "/" + resourceType + "/",
		Clock:              clock.New(),
	})
}

func createAppStashBlobstore(blobstoreConfig config.BlobstoreConfig) routes.NoRedirectBlobstore {
	switch strings.ToLower(blobstoreConfig.BlobstoreType) {
	case "local":
		log.Log.Info("Creating local blobstore", zap.String("path-prefix", blobstoreConfig.LocalConfig.PathPrefix))
		return decorator.ForBlobstoreWithPathPartitioning(
			local.NewBlobstore(blobstoreConfig.LocalConfig.PathPrefix))

	case "s3", "aws":
		log.Log.Info("Creating S3 blobstore", zap.String("bucket", blobstoreConfig.S3Config.Bucket))
		return decorator.ForBlobstoreWithPathPartitioning(
			s3.NewBlobstore(*blobstoreConfig.S3Config))
	case "webdav":
		log.Log.Info("Creating Webdav blobstore",
			zap.String("public-endpoint", blobstoreConfig.WebdavConfig.PublicEndpoint),
			zap.String("private-endpoint", blobstoreConfig.WebdavConfig.PrivateEndpoint))
		return decorator.ForBlobstoreWithPathPartitioning(
			decorator.ForBlobstoreWithPathPrefixing(
				webdav.NewBlobstore(*blobstoreConfig.WebdavConfig),
				"app_stash/"))
	default:
		log.Log.Fatal("blobstoreConfig is invalid.", zap.String("blobstore-type", blobstoreConfig.BlobstoreType))
		return nil // satisfy compiler
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"runtime/debug"

	"github.com/StackExchange/dnscontrol/v3/commands"
	"github.com/StackExchange/dnscontrol/v3/pkg/version"
	_ "github.com/StackExchange/dnscontrol/v3/providers/_all"
)

//go:generate go run build/generate/generate.go build/generate/featureMatrix.go

// Version management. Goals:
// 1. Someone who just does "go get" has at least some information.
// 2. If built with build/build.go, more specific build information gets put in.
// Update the number here manually each release, so at least we have a range for go-get people.
var (
	SHA       = ""
	Version   = "v3.7.0"
	BuildTime = ""
)

func main() {
	version.SHA = SHA
	version.Semver = Version
	version.BuildTime = BuildTime

	log.SetFlags(log.LstdFlags | log.Lshortfile)
	if info, ok := debug.ReadBuildInfo(); !ok && info == nil {
		fmt.Fprint(os.Stderr, "Warning: dnscontrol was built without Go modules. See https://github.com/StackExchange/dnscontrol#from-source for more information on how to build dnscontrol correctly.\n\n")
	}
	os.Exit(commands.Run("dnscontrol " + version.Banner()))
}
<commit_msg>Release v3.8.0 (#1111)<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"runtime/debug"

	"github.com/StackExchange/dnscontrol/v3/commands"
	"github.com/StackExchange/dnscontrol/v3/pkg/version"
	_ "github.com/StackExchange/dnscontrol/v3/providers/_all"
)

//go:generate go run build/generate/generate.go build/generate/featureMatrix.go

// Version management. Goals:
// 1. Someone who just does "go get" has at least some information.
// 2. If built with build/build.go, more specific build information gets put in.
// Update the number here manually each release, so at least we have a range for go-get people.
var (
	SHA       = ""
	Version   = "v3.8.0"
	BuildTime = ""
)

func main() {
	version.SHA = SHA
	version.Semver = Version
	version.BuildTime = BuildTime

	log.SetFlags(log.LstdFlags | log.Lshortfile)
	if info, ok := debug.ReadBuildInfo(); !ok && info == nil {
		fmt.Fprint(os.Stderr, "Warning: dnscontrol was built without Go modules. See https://github.com/StackExchange/dnscontrol#from-source for more information on how to build dnscontrol correctly.\n\n")
	}
	os.Exit(commands.Run("dnscontrol " + version.Banner()))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"os"
	"os/exec"
	"os/signal"
	"regexp"
	"strings"
	"time"

	"github.com/bitly/go-simplejson"
	"github.com/ninjasphere/gatt"
	"github.com/ninjasphere/go-ninja"
	"github.com/ninjasphere/go-ninja/logger"
)

const driverName = "driver-ble"

type waypointPayload struct {
	Sequence    uint8
	AddressType uint8
	Rssi        int8
	Valid       uint8
}

type adPacket struct {
	Device   string `json:"device"`
	Waypoint string `json:"waypoint"`
	Rssi     int8   `json:"rssi"`
	IsSphere bool   `json:"isSphere"`
}

// configure the agent logger
var log = logger.GetLogger("driver-go-ble")

//var mesh *udpMesh

func sendRssi(device string, name string, waypoint string, rssi int8, isSphere bool, conn *ninja.NinjaConnection) {
	device = strings.ToUpper(device)

	log.Debugf(">> Device:%s Waypoint:%s Rssi: %d", device, waypoint, rssi)

	packet, _ := simplejson.NewJson([]byte(`{
    "params": [
        {
            "device": "",
            "waypoint": "",
            "rssi": 0,
            "isSphere": true
        }
    ],
    "time": 0,
    "jsonrpc": "2.0"
}`))

	packet.Get("params").GetIndex(0).Set("device", device)
	if name != "" {
		packet.Get("params").GetIndex(0).Set("name", name)
	}
	packet.Get("params").GetIndex(0).Set("waypoint", waypoint)
	packet.Get("params").GetIndex(0).Set("rssi", rssi)
	packet.Get("params").GetIndex(0).Set("isSphere", isSphere)

	//spew.Dump(packet)
	conn.PublishMessage("$device/"+device+"/TEMPPATH/rssi", packet)

}

func main() {
	os.Exit(realMain())
}

func realMain() int {

	log.Infof("Starting " + driverName)

	conn, err := ninja.Connect("com.ninjablocks.ble")

	if err != nil {
		log.FatalErrorf(err, "Could not connect to MQTT Broker")
	}

	/*if mesh, err = newUdpMesh("239.255.12.34:12345", func(packet *adPacket) {

		spew.Dump("Got mesh packet", packet)

	}); err != nil {
		log.FatalErrorf(err, "Could not connect to UDP mesh")
	}*/

	statusJob, err := ninja.CreateStatusJob(conn, driverName)

	if err != nil {
		log.FatalErrorf(err, "Could not setup status job")
	}

	statusJob.Start()

	out, err := exec.Command("hciconfig").Output()
	if err != nil {
		log.Errorf(fmt.Sprintf("Error: %s", err))
	}
	re := regexp.MustCompile("([0-9A-F]{2}\\:{0,1}){6}")
	mac := strings.Replace(re.FindString(string(out)), ":", "", -1)
	log.Infof("The local mac is %s\n", mac)

	client := &gatt.Client{
		StateChange: func(newState string) {
			log.Infof("Client state change: %s", newState)
		},
	}

	/*
	  Waypoint notification characteristic {
	    "startHandle": 45,
	    "properties": 16, (useNotify = true, useIndicate = false)
	    "valueHandle": 46,
	    "uuid": "fff4",
	    "endHandle": 48,
	  }
	*/

	activeWaypoints := make(map[string]bool)

	go func() {
		for {
			time.Sleep(time.Second)
			waypoints := 0
			for id, active := range activeWaypoints {
				log.Debugf("Waypoint %s is active? %t", id, active)
				if active {
					waypoints++
				}
			}
			log.Debugf("%d waypoint(s) active", waypoints)

			packet, _ := simplejson.NewJson([]byte(fmt.Sprintf("%d", waypoints)))

			conn.PublishMessage("$location/waypoints", packet)
		}
	}()

	client.Rssi = func(address string, name string, rssi int8) {
		//log.Printf("Rssi update address:%s rssi:%d", address, rssi)
		sendRssi(strings.Replace(address, ":", "", -1), name, mac, rssi, true, conn)
		//spew.Dump(device);
	}

	client.Advertisement = func(device *gatt.DiscoveredDevice) {
		log.Debugf("Discovered address:%s rssi:%d", device.Address, device.Rssi)

		if device.Advertisement.LocalName != "NinjaSphereWaypoint" {
			return
		}

		if activeWaypoints[device.Address] {
			return
		}

		if device.Connected == nil {
			device.Connected = func() {
				log.Infof("Connected to waypoint: %s", device.Address)
				//spew.Dump(device.Advertisement)

				// XXX: Yes, magic numbers.... this enables the notification from our Waypoints
				client.Notify(device.Address, true, 45, 48, true, false)
			}

			device.Disconnected = func() {
				log.Infof("Disconnected from waypoint: %s", device.Address)

				activeWaypoints[device.Address] = false
			}

			device.Notification = func(notification *gatt.Notification) {
				//log.Printf("Got the notification!")

				//XXX: Add the ieee into the payload somehow??
				var payload waypointPayload
				err := binary.Read(bytes.NewReader(notification.Data), binary.LittleEndian, &payload)
				if err != nil {
					log.Errorf("Failed to read waypoint payload : %s", err)
				}

				//	ieee := net.HardwareAddr(reverse(notification.Data[4:]))

				//spew.Dump("ieee:", payload)

				packet := &adPacket{
					Device:   fmt.Sprintf("%x", reverse(notification.Data[4:])),
					Waypoint: strings.Replace(device.Address, ":", "", -1),
					Rssi:     payload.Rssi,
					IsSphere: false,
				}

				sendRssi(packet.Device, "", packet.Waypoint, packet.Rssi, packet.IsSphere, conn)
				//mesh.send(packet)
			}
		}

		err := client.Connect(device.Address, device.PublicAddress)
		if err != nil {
			log.Errorf("Connect error:%s", err)
			return
		}

		activeWaypoints[device.Address] = true

	}

	err = client.Start()

	if err != nil {
		log.FatalError(err, "Failed to start client")
	}

	err = client.StartScanning(true)
	if err != nil {
		log.FatalError(err, "Failed to start scanning")
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	// Block until a signal is received.
	s := <-c
	log.Infof("Got signal:", s)

	return 0
}

// reverse returns a reversed copy of u.
func reverse(u []byte) []byte {
	l := len(u)
	b := make([]byte, l)
	for i := 0; i < l/2+1; i++ {
		b[i], b[l-i-1] = u[l-i-1], u[i]
	}
	return b
}
<commit_msg>Replace PublishMessage with SendNotification.<commit_after>package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"os"
	"os/exec"
	"os/signal"
	"regexp"
	"strings"
	"time"

	"github.com/ninjasphere/gatt"
	"github.com/ninjasphere/go-ninja/api"
	"github.com/ninjasphere/go-ninja/logger"
)

const driverName = "driver-ble"

type waypointPayload struct {
	Sequence    uint8
	AddressType uint8
	Rssi        int8
	Valid       uint8
}

type adPacket struct {
	Device   string `json:"device"`
	Waypoint string `json:"waypoint"`
	Rssi     int8   `json:"rssi"`
	IsSphere bool   `json:"isSphere"`
}

type ninjaPacket struct {
     adPacket
     name	string `json:"name,omitempty"`
}

// configure the agent logger
var log = logger.GetLogger("driver-go-ble")

//var mesh *udpMesh

func sendRssi(device string, name string, waypoint string, rssi int8, isSphere bool, conn *ninja.Connection) {
	device = strings.ToUpper(device)

	log.Debugf(">> Device:%s Waypoint:%s Rssi: %d", device, waypoint, rssi)

	ninjaPacket := ninjaPacket{
		    adPacket: adPacket{
			Device: device,
			Waypoint: waypoint,
			Rssi: rssi,
			IsSphere: isSphere,
		    },
		    name: name,
	}

	//spew.Dump(packet)
	conn.SendNotification("$device/"+device+"/TEMPPATH/rssi", ninjaPacket)

}

func main() {
	os.Exit(realMain())
}

func realMain() int {

	log.Infof("Starting " + driverName)

	conn, err := ninja.Connect("com.ninjablocks.ble")

	if err != nil {
		log.FatalErrorf(err, "Could not connect to MQTT Broker")
	}

	/*if mesh, err = newUdpMesh("239.255.12.34:12345", func(packet *adPacket) {

		spew.Dump("Got mesh packet", packet)

	}); err != nil {
		log.FatalErrorf(err, "Could not connect to UDP mesh")
	}*/

	statusJob, err := ninja.CreateStatusJob(conn, driverName)

	if err != nil {
		log.FatalErrorf(err, "Could not setup status job")
	}

	statusJob.Start()

	out, err := exec.Command("hciconfig").Output()
	if err != nil {
		log.Errorf(fmt.Sprintf("Error: %s", err))
	}
	re := regexp.MustCompile("([0-9A-F]{2}\\:{0,1}){6}")
	mac := strings.Replace(re.FindString(string(out)), ":", "", -1)
	log.Infof("The local mac is %s\n", mac)

	client := &gatt.Client{
		StateChange: func(newState string) {
			log.Infof("Client state change: %s", newState)
		},
	}

	/*
	  Waypoint notification characteristic {
	    "startHandle": 45,
	    "properties": 16, (useNotify = true, useIndicate = false)
	    "valueHandle": 46,
	    "uuid": "fff4",
	    "endHandle": 48,
	  }
	*/

	activeWaypoints := make(map[string]bool)

	go func() {
		for {
			time.Sleep(time.Second)
			waypoints := 0
			for id, active := range activeWaypoints {
				log.Debugf("Waypoint %s is active? %t", id, active)
				if active {
					waypoints++
				}
			}
			log.Debugf("%d waypoint(s) active", waypoints)

			conn.SendNotification("$location/waypoints", waypoints)
		}
	}()

	client.Rssi = func(address string, name string, rssi int8) {
		//log.Printf("Rssi update address:%s rssi:%d", address, rssi)
		sendRssi(strings.Replace(address, ":", "", -1), name, mac, rssi, true, conn)
		//spew.Dump(device);
	}

	client.Advertisement = func(device *gatt.DiscoveredDevice) {
		log.Debugf("Discovered address:%s rssi:%d", device.Address, device.Rssi)

		if device.Advertisement.LocalName != "NinjaSphereWaypoint" {
			return
		}

		if activeWaypoints[device.Address] {
			return
		}

		if device.Connected == nil {
			device.Connected = func() {
				log.Infof("Connected to waypoint: %s", device.Address)
				//spew.Dump(device.Advertisement)

				// XXX: Yes, magic numbers.... this enables the notification from our Waypoints
				client.Notify(device.Address, true, 45, 48, true, false)
			}

			device.Disconnected = func() {
				log.Infof("Disconnected from waypoint: %s", device.Address)

				activeWaypoints[device.Address] = false
			}

			device.Notification = func(notification *gatt.Notification) {
				//log.Printf("Got the notification!")

				//XXX: Add the ieee into the payload somehow??
				var payload waypointPayload
				err := binary.Read(bytes.NewReader(notification.Data), binary.LittleEndian, &payload)
				if err != nil {
					log.Errorf("Failed to read waypoint payload : %s", err)
				}

				//	ieee := net.HardwareAddr(reverse(notification.Data[4:]))

				//spew.Dump("ieee:", payload)

				packet := &adPacket{
					Device:   fmt.Sprintf("%x", reverse(notification.Data[4:])),
					Waypoint: strings.Replace(device.Address, ":", "", -1),
					Rssi:     payload.Rssi,
					IsSphere: false,
				}

				sendRssi(packet.Device, "", packet.Waypoint, packet.Rssi, packet.IsSphere, conn)
				//mesh.send(packet)
			}
		}

		err := client.Connect(device.Address, device.PublicAddress)
		if err != nil {
			log.Errorf("Connect error:%s", err)
			return
		}

		activeWaypoints[device.Address] = true

	}

	err = client.Start()

	if err != nil {
		log.FatalError(err, "Failed to start client")
	}

	err = client.StartScanning(true)
	if err != nil {
		log.FatalError(err, "Failed to start scanning")
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	// Block until a signal is received.
	s := <-c
	log.Infof("Got signal:", s)

	return 0
}

// reverse returns a reversed copy of u.
func reverse(u []byte) []byte {
	l := len(u)
	b := make([]byte, l)
	for i := 0; i < l/2+1; i++ {
		b[i], b[l-i-1] = u[l-i-1], u[i]
	}
	return b
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"

	"./archive"
	"./image"
	"./utility/json"
)

const defaultPort = 5358

func main() {
	var port uint
	flag.UintVar(&port, "port", defaultPort, "listen port")
	flag.UintVar(&port, "p", defaultPort, "listen port")
	flag.Parse()

	// image data
	// image/image_file_path
	image.SetHttpRoute()

	// archive data
	// archive/archive_file_path[/image_file_path]
	archive.SetHttpRoute()

	// support type
	http.HandleFunc("/support", supportType)

	log.Printf("Listening on %d\n", port)
	err := http.ListenAndServe(fmt.Sprintf("localhost:%d", defaultPort), nil)
	if err != nil {
		log.Fatal("Listen And Serve:", err)
	}
}

func supportType(w http.ResponseWriter, r *http.Request) {
	data := map[string][]string{
		"image":   image.SupportType(),
		"archive": archive.SupportType(),
	}

	json.WriteResponse(w, data)
}
<commit_msg>update v2 routing<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"net/http"

	"./archive"
	"./image"
	"./utility/json"
)

const defaultPort = 5358

func main() {
	var port uint
	flag.UintVar(&port, "port", defaultPort, "listen port")
	flag.UintVar(&port, "p", defaultPort, "listen port")
	flag.Parse()

	// read directory :: json
	// localhost/base64(root/dir_path)

	// read archive :: json
	// localhost/base64(root/arch.ext)

	// read archive inner directory :: json
	// localhost/base64(root/arch.ext/dir_path)

	// read image :: binary
	// image/base64(root/image_file_path)

	// read image into archive :: binary
	// image/base64(root/arch.ext/image_file_path)
	//image.SetHttpRoute()

	// read support type :: json
	http.HandleFunc("/support", supportType)

	log.Printf("Listening on %d\n", port)
	err := http.ListenAndServe(fmt.Sprintf("localhost:%d", defaultPort), nil)
	if err != nil {
		log.Fatal("Listen And Serve:", err)
	}
}

func supportType(w http.ResponseWriter, r *http.Request) {
	data := map[string][]string{
		"image":   image.SupportType(),
		"archive": archive.SupportType(),
	}

	json.WriteResponse(w, data)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"flag"
	"fmt"
	"math"
	"math/rand"
	"os"
	"time"
)

const (
	Debug_AI                      = false
	Timeout                       = true
	N                             = 2
	FirstTurnTime                 = 100
	TimeLimit                     = 50
	extra_space_between_factories = 300
	W                             = 16000
	H                             = 6500
	Min_Production_Rate           = 4
	MOVE                          = moveType(0)
	BOMB                          = moveType(1)
	INCREASE                      = moveType(2)
)

var Move_Type_String = []string{"MOVE", "BOMB", "INC"}

type Vec struct {
	x int
	y int
}

func (a Vec) Sub(b Vec) Vec {
	return Vec{a.x - b.x, a.y - b.y}
}

type Factory struct {
	owner int
	units int
	prod  int
	turns int
	r     Vec
	l     []int
}

type Troop struct {
	owner  int
	source int
	target int
	units  int
	turns  int
}

type Bomb struct {
	owner  int
	source int
	target int
	turns  int
}

type State struct {
	F        []Factory
	T        []Troop
	B        map[int]Bomb
	N_Bombs  []int
	entityId int
}

type Play struct {
	moveType moveType
	from     int
	to       int
	amount   int
}

type moveType int

type strat []Vec

func main() {
	if !flag.Parsed() {
		flag.Parse()
	}

	if *aiFlag == "" {
		flag.Usage()
		os.Exit(1)
	}

	aiOne := NewAI()
	aiTwo := NewAI()

	for {
		PlayRound([]*AI{aiOne, aiTwo})
	}

}

func generator(min int, max int) int {
	if max == 0 {
		max = 1
	}
	rndSrc := rand.NewSource(time.Now().UnixNano())
	rnd := rand.New(rndSrc)
	if min > 0 {
		return rnd.Intn(max-min) + min
	} else {
		return rnd.Intn(max)
	}
}

func PlayRound(ai []*AI) int {
	swapDistrib := UniformIntDistribution{0, 1}
	playerSwap := swapDistrib.Gen() == 1
	if playerSwap {
		// TODO swap ai
	}
	state := State{}
	rndFactoryCount := generator(7, 15)
	if rndFactoryCount%2 == 0 { // must be odd
		rndFactoryCount++
	}
	state.F = make([]Factory, rndFactoryCount)

	factoryRadius := 700
	if rndFactoryCount > 10 {
		factoryRadius -= 100
	}
	minSpaceBetweenFactories := 2 * (factoryRadius + extra_space_between_factories)

	// center Factory
	state.F[0] = Factory{0, 0, 0, 0, Vec{W / 2, H / 2}, []int{}}

	// random distribution
	xDistrib := UniformIntDistribution{(0), (W/2 - 2*factoryRadius)}
	yDistrib := UniformIntDistribution{(0), (H - 2*factoryRadius)}
	productionDistrib := UniformIntDistribution{(0), (3)}
	initialUnitsDistrib := UniformIntDistribution{(15), (30)}

	for i := 1; i < len(state.F); i += 2 {
		var r Vec
		for !ValidSpawn(r, &state, i, minSpaceBetweenFactories) {
			r = Vec{xDistrib.Gen() + factoryRadius + extra_space_between_factories, yDistrib.Gen() + factoryRadius + extra_space_between_factories}
		}
		prod := productionDistrib.Gen()
		if i == 1 {
			units := initialUnitsDistrib.Gen()
			state.F[i] = Factory{1, units, prod, 0, r, make([]int, 0)}
			state.F[i+1] = Factory{-1, units, prod, 0, Vec{W, H}.Sub(r), make([]int, 0)}
		} else {
			initialNeutralsDistrib := UniformIntDistribution{(0), (5 * prod)}
			units := initialNeutralsDistrib.Gen()
			state.F[i] = Factory{0, units, prod, 0, r, make([]int, 0)}
			state.F[i+1] = Factory{0, units, prod, 0, Vec{W, H}.Sub(r), make([]int, 0)}
		}
	}

	total_prod := 0
	for i := 0; i < len(state.F); i++ {
		total_prod += state.F[i].prod
		state.F[i].l = make([]int, len(state.F))
	}
	for i := 0; i < len(state.F); i++ {
		for j := i + 1; j < len(state.F); j++ {
			d := int((Distance(state.F[i].r, state.F[j].r) - 2*factoryRadius) / 800.0)
			state.F[i].l[j] = d
			state.F[j].l[i] = d
		}
	}
	for i := 1; total_prod < Min_Production_Rate && i < len(state.F); i++ {
		f := state.F[i]
		if f.prod < 3 {
			f.prod++
			total_prod++
		}
	}
	state.N_Bombs = []int{2, 2}
	//println("PlayGame")
	winner := Play_Game(ai, &state)
	if playerSwap {
		if winner == -1 {
			return -1
		} else if winner == 0 {
			return 1
		}
		return 0
	} else {
		return winner
	}
}

func Play_Game(ai []*AI, state *State) int {
	for i := 0; i < N; i++ {
		ss := &bytes.Buffer{}
		fmt.Fprintf(ss, "%d %d\n", len(state.F), len(state.F)*len(state.F)-1/2)
		for j := 0; j < len(state.F); j++ {
			for k := j + 1; k < len(state.F); k++ {
				fmt.Fprintf(ss, "%d %d %d\n", j, k, state.F[j].l[k])
			}
		}
		ai[i].Feed_Inputs(ss)
	}
	state.entityId = 0
	for turn := 1; turn <= 400; turn++ {
		//println("Turn:", turn)
		M := []string{"WAIT", "WAIT"}
		for i := 0; i < N; i++ {
			if ai[i].Alive() {
				if Has_Won(ai, i) {
					//cerr << i << " has won in " << turn << " turns" << endl;
					return i
				}
				color := 1
				if i != 0 {
					color = -1
				}
				ss := &bytes.Buffer{}
				fmt.Fprintf(ss, "%d %d %d\n", len(state.F), len(state.T), len(state.B))
				for j := 0; j < len(state.F); j++ {
					fmt.Fprintf(ss, "%d FACTORY %d %d %d %d\n", color*state.F[j].owner, state.F[j].units, state.F[j].prod, state.F[j].turns, 0)
				}
				for j := 0; j < len(state.T); j++ {
					fmt.Fprintf(ss, "%d TROOP %d %d %d %d\n", color*state.T[j].owner, state.T[j].source, state.T[j].target, state.T[j].units, state.T[j].turns)
				}
				//for (const auto &it:S.B){
				//const bomb &b{it.second};
				//ss << it.first << " BOMB " << color*b.owner << " " << b.source << " " << (b.owner==color?b.target:-1) << " " << (b.owner==color?b.turns:-1) << " " << 0 << endl;
				//}
				for idx, b := range state.B {
					// TODO see above
					fmt.Fprintf(ss, "%d BOMB %d %d %d %d %d", idx, color*b.owner, b.source, -1, -1, 0)
				}
				ai[i].Feed_Inputs(ss)
				M[i] = GetMove(ai[i], turn)
			}
		}
		for i := 0; i < 2; i++ {
			Play_Move(state, ai[i], M[i])
		}
		Simulate(state)
		//for i := 0; i < N; i++ {
		//	if (!Player_Alive(state, i==0?1:-1)){
		//		ai[i].stop()
		//	}
		//}
		if turn == 200 {
			Units := []int{0, 0}
			for _, f := range state.F {
				if f.owner == 1 {
					Units[0] += f.units
				} else if f.owner == -1 {
					Units[1] += f.units
				}
			}
			for _, t := range state.T {
				if t.owner == 1 {
					Units[0] += t.units
				} else if t.owner == -1 {
					Units[1] += t.units
				}
			}
			if Units[0] == Units[1] {
				//cerr << "Draw" << endl;
				return -1
			} else if Units[0] > Units[1] {
				//cerr << 0 << " has won in " << turn << " turns" << endl;
				return 0
			} else {
				//cerr << 1 << " has won in " << turn << " turns" << endl;
				return 1
			}
		}

		if All_Dead(ai) {
			os.Exit(1)
			//return -1
		}
	}
	return -2
}

func Distance(a Vec, b Vec) int {
	sqrt := math.Sqrt(math.Pow(float64(a.x-b.x), 2.0) + math.Pow(float64(a.y-b.y), 2.0))
	return int(sqrt)
}

func ValidSpawn(r Vec, state *State, id int, minSpaceBetweenFactories int) bool {
	for j := 0; j < id; j++ {
		if Distance(r, state.F[j].r) < minSpaceBetweenFactories {
			return false
		}
	}
	return true
}

func Has_Won(bot []*AI, idx int) bool {
	for i := 0; i < N; i++ {
		if i != idx && bot[i].Alive() {
			return true
		}
	}
	return false
}

func GetMove(ai *AI, turn int) string {
	buf := &bytes.Buffer{}
	duration := TimeLimit * time.Second
	if turn == 1 {
		duration = FirstTurnTime * time.Millisecond
	}
	timer := time.NewTimer(duration)
	<-timer.C
	n, err := buf.ReadFrom(ai.outPipe)
	if err != nil {
		println(err)
		os.Exit(1)
	}

	//println("AI response:", buf.String())
	if n == 0 {
		println("Loss by Timeout of AI", ai.id, ai.name)
		os.Exit(1)
	}

	return buf.String()
}

func Simulate(s *State) {
	//println("Simulate++")
}

func Play_Move(state *State, ai *AI, m string) {
	//println("PlayMove")
}

func All_Dead(ai []*AI) bool {
	for _, bot := range ai {
		if bot.Alive() {
			return false
		}
	}
	return true
}
<commit_msg>Fixed calculation count of links<commit_after>package main

import (
	"bytes"
	"flag"
	"fmt"
	"math"
	"math/rand"
	"os"
	"time"
)

const (
	Debug_AI                      = false
	Timeout                       = true
	N                             = 2
	FirstTurnTime                 = 100
	TimeLimit                     = 50
	extra_space_between_factories = 300
	W                             = 16000
	H                             = 6500
	Min_Production_Rate           = 4
	MOVE                          = moveType(0)
	BOMB                          = moveType(1)
	INCREASE                      = moveType(2)
)

var Move_Type_String = []string{"MOVE", "BOMB", "INC"}

type Vec struct {
	x int
	y int
}

func (a Vec) Sub(b Vec) Vec {
	return Vec{a.x - b.x, a.y - b.y}
}

type Factory struct {
	owner int
	units int
	prod  int
	turns int
	r     Vec
	l     []int
}

type Troop struct {
	owner  int
	source int
	target int
	units  int
	turns  int
}

type Bomb struct {
	owner  int
	source int
	target int
	turns  int
}

type State struct {
	F        []Factory
	T        []Troop
	B        map[int]Bomb
	N_Bombs  []int
	entityId int
}

type Play struct {
	moveType moveType
	from     int
	to       int
	amount   int
}

type moveType int

type strat []Vec

func main() {
	if !flag.Parsed() {
		flag.Parse()
	}

	if *aiFlag == "" {
		flag.Usage()
		os.Exit(1)
	}

	aiOne := NewAI()
	aiTwo := NewAI()

	for {
		PlayRound([]*AI{aiOne, aiTwo})
	}

}

func generator(min int, max int) int {
	if max == 0 {
		max = 1
	}
	rndSrc := rand.NewSource(time.Now().UnixNano())
	rnd := rand.New(rndSrc)
	if min > 0 {
		return rnd.Intn(max-min) + min
	} else {
		return rnd.Intn(max)
	}
}

func PlayRound(ai []*AI) int {
	swapDistrib := UniformIntDistribution{0, 1}
	playerSwap := swapDistrib.Gen() == 1
	if playerSwap {
		// TODO swap ai
	}
	state := State{}
	rndFactoryCount := generator(7, 15)
	if rndFactoryCount%2 == 0 { // must be odd
		rndFactoryCount++
	}
	state.F = make([]Factory, rndFactoryCount)

	factoryRadius := 700
	if rndFactoryCount > 10 {
		factoryRadius -= 100
	}
	minSpaceBetweenFactories := 2 * (factoryRadius + extra_space_between_factories)

	// center Factory
	state.F[0] = Factory{0, 0, 0, 0, Vec{W / 2, H / 2}, []int{}}

	// random distribution
	xDistrib := UniformIntDistribution{(0), (W/2 - 2*factoryRadius)}
	yDistrib := UniformIntDistribution{(0), (H - 2*factoryRadius)}
	productionDistrib := UniformIntDistribution{(0), (3)}
	initialUnitsDistrib := UniformIntDistribution{(15), (30)}

	for i := 1; i < len(state.F); i += 2 {
		var r Vec
		for !ValidSpawn(r, &state, i, minSpaceBetweenFactories) {
			r = Vec{xDistrib.Gen() + factoryRadius + extra_space_between_factories, yDistrib.Gen() + factoryRadius + extra_space_between_factories}
		}
		prod := productionDistrib.Gen()
		if i == 1 {
			units := initialUnitsDistrib.Gen()
			state.F[i] = Factory{1, units, prod, 0, r, make([]int, 0)}
			state.F[i+1] = Factory{-1, units, prod, 0, Vec{W, H}.Sub(r), make([]int, 0)}
		} else {
			initialNeutralsDistrib := UniformIntDistribution{(0), (5 * prod)}
			units := initialNeutralsDistrib.Gen()
			state.F[i] = Factory{0, units, prod, 0, r, make([]int, 0)}
			state.F[i+1] = Factory{0, units, prod, 0, Vec{W, H}.Sub(r), make([]int, 0)}
		}
	}

	total_prod := 0
	for i := 0; i < len(state.F); i++ {
		total_prod += state.F[i].prod
		state.F[i].l = make([]int, len(state.F))
	}
	for i := 0; i < len(state.F); i++ {
		for j := i + 1; j < len(state.F); j++ {
			d := int((Distance(state.F[i].r, state.F[j].r) - 2*factoryRadius) / 800.0)
			state.F[i].l[j] = d
			state.F[j].l[i] = d
		}
	}
	for i := 1; total_prod < Min_Production_Rate && i < len(state.F); i++ {
		f := state.F[i]
		if f.prod < 3 {
			f.prod++
			total_prod++
		}
	}
	state.N_Bombs = []int{2, 2}
	//println("PlayGame")
	winner := Play_Game(ai, &state)
	if playerSwap {
		if winner == -1 {
			return -1
		} else if winner == 0 {
			return 1
		}
		return 0
	} else {
		return winner
	}
}

func Play_Game(ai []*AI, state *State) int {
	for i := 0; i < N; i++ {
		ss := &bytes.Buffer{}
		fmt.Fprintf(ss, "%d %d\n", len(state.F), len(state.F)*len(state.F-1)/2)
		for j := 0; j < len(state.F); j++ {
			for k := j + 1; k < len(state.F); k++ {
				fmt.Fprintf(ss, "%d %d %d\n", j, k, state.F[j].l[k])
			}
		}
		ai[i].Feed_Inputs(ss)
	}
	state.entityId = 0
	for turn := 1; turn <= 400; turn++ {
		//println("Turn:", turn)
		M := []string{"WAIT", "WAIT"}
		for i := 0; i < N; i++ {
			if ai[i].Alive() {
				if Has_Won(ai, i) {
					//cerr << i << " has won in " << turn << " turns" << endl;
					return i
				}
				color := 1
				if i != 0 {
					color = -1
				}
				ss := &bytes.Buffer{}
				fmt.Fprintf(ss, "%d %d %d\n", len(state.F), len(state.T), len(state.B))
				for j := 0; j < len(state.F); j++ {
					fmt.Fprintf(ss, "%d FACTORY %d %d %d %d\n", color*state.F[j].owner, state.F[j].units, state.F[j].prod, state.F[j].turns, 0)
				}
				for j := 0; j < len(state.T); j++ {
					fmt.Fprintf(ss, "%d TROOP %d %d %d %d\n", color*state.T[j].owner, state.T[j].source, state.T[j].target, state.T[j].units, state.T[j].turns)
				}
				//for (const auto &it:S.B){
				//const bomb &b{it.second};
				//ss << it.first << " BOMB " << color*b.owner << " " << b.source << " " << (b.owner==color?b.target:-1) << " " << (b.owner==color?b.turns:-1) << " " << 0 << endl;
				//}
				for idx, b := range state.B {
					// TODO see above
					fmt.Fprintf(ss, "%d BOMB %d %d %d %d %d", idx, color*b.owner, b.source, -1, -1, 0)
				}
				ai[i].Feed_Inputs(ss)
				M[i] = GetMove(ai[i], turn)
			}
		}
		for i := 0; i < 2; i++ {
			Play_Move(state, ai[i], M[i])
		}
		Simulate(state)
		//for i := 0; i < N; i++ {
		//	if (!Player_Alive(state, i==0?1:-1)){
		//		ai[i].stop()
		//	}
		//}
		if turn == 200 {
			Units := []int{0, 0}
			for _, f := range state.F {
				if f.owner == 1 {
					Units[0] += f.units
				} else if f.owner == -1 {
					Units[1] += f.units
				}
			}
			for _, t := range state.T {
				if t.owner == 1 {
					Units[0] += t.units
				} else if t.owner == -1 {
					Units[1] += t.units
				}
			}
			if Units[0] == Units[1] {
				//cerr << "Draw" << endl;
				return -1
			} else if Units[0] > Units[1] {
				//cerr << 0 << " has won in " << turn << " turns" << endl;
				return 0
			} else {
				//cerr << 1 << " has won in " << turn << " turns" << endl;
				return 1
			}
		}

		if All_Dead(ai) {
			os.Exit(1)
			//return -1
		}
	}
	return -2
}

func Distance(a Vec, b Vec) int {
	sqrt := math.Sqrt(math.Pow(float64(a.x-b.x), 2.0) + math.Pow(float64(a.y-b.y), 2.0))
	return int(sqrt)
}

func ValidSpawn(r Vec, state *State, id int, minSpaceBetweenFactories int) bool {
	for j := 0; j < id; j++ {
		if Distance(r, state.F[j].r) < minSpaceBetweenFactories {
			return false
		}
	}
	return true
}

func Has_Won(bot []*AI, idx int) bool {
	for i := 0; i < N; i++ {
		if i != idx && bot[i].Alive() {
			return true
		}
	}
	return false
}

func GetMove(ai *AI, turn int) string {
	buf := &bytes.Buffer{}
	duration := TimeLimit * time.Second
	if turn == 1 {
		duration = FirstTurnTime * time.Millisecond
	}
	timer := time.NewTimer(duration)
	<-timer.C
	n, err := buf.ReadFrom(ai.outPipe)
	if err != nil {
		println(err)
		os.Exit(1)
	}

	//println("AI response:", buf.String())
	if n == 0 {
		println("Loss by Timeout of AI", ai.id, ai.name)
		os.Exit(1)
	}

	return buf.String()
}

func Simulate(s *State) {
	//println("Simulate++")
}

func Play_Move(state *State, ai *AI, m string) {
	//println("PlayMove")
}

func All_Dead(ai []*AI) bool {
	for _, bot := range ai {
		if bot.Alive() {
			return false
		}
	}
	return true
}
<|endoftext|>


<commit_before>package zygo

import (
	"fmt"
	"testing"

	cv "github.com/glycerine/goconvey/convey"
)

func Test400SandboxFunctions(t *testing.T) {

	cv.Convey(`Given that the developer wishes to sandbox the Zygo interpreter when embedding it in their program, the NewZlispSandbox() function should return an interpreter that cannot call system/filesystem functions`, t, func() {

		sysFuncs := SystemFunctions()
		sandSafeFuncs := SandboxSafeFunctions()
		{
			env := NewZlispSandbox()

			// no system functions should pass
			for name := range sysFuncs {
				env.Clear()
				//P("checking name = '%v'", name)
				res, err := env.EvalString(fmt.Sprintf("(defined? %%%s)", name))
				cv.So(res, cv.ShouldResemble, &SexpBool{Val: false})
				cv.So(err, cv.ShouldResemble, nil)
			}

			// all sandSafeFuncs should be fine
			for name := range sandSafeFuncs {
				env.Clear()
				res, err := env.EvalString(fmt.Sprintf("(defined? %%%s)", name))
				switch y := res.(type) {
				case *SexpSentinel:
					P("'%s' wasn't defined but should be; defined? returned '%s'", name, y.SexpString(nil))
				case *SexpBool:
					cv.So(res, cv.ShouldResemble, &SexpBool{Val: true})
				}
				cv.So(err, cv.ShouldEqual, nil)
			}
		}

		{
			fmt.Printf("\n and all functions should be reachable from a non-sandboxed environment.\n")
			env := NewZlisp()
			for name := range sysFuncs {
				env.Clear()
				res, err := env.EvalString(fmt.Sprintf("(defined? %%%s)", name))
				cv.So(res, cv.ShouldResemble, &SexpBool{Val: true})
				cv.So(err, cv.ShouldEqual, nil)
			}

			// all sandSafeFuncs should be fine
			for name := range sandSafeFuncs {
				env.Clear()
				res, err := env.EvalString(fmt.Sprintf("(defined? %%%s)", name))
				cv.So(res, cv.ShouldResemble, &SexpBool{Val: true})
				cv.So(err, cv.ShouldEqual, nil)
			}

		}
	})
}

func BenchmarkCallUserFunction(b *testing.B) {
	env := NewZlisp()
	env.AddFunction("dosomething", func(*Zlisp, string, []Sexp) (r Sexp, err error) { return })
	script := fmt.Sprintf(`
		(for [(def i 0) (< i 1000000) (set i (+ i 1))]
			(dosomething)
		)
	`)
	b.ResetTimer()
	for i := 0; i < b.N; i++ {
		env.EvalString(script)
	}
}
<commit_msg>Add test verifying CallUserFunction recovers from panics<commit_after>package zygo

import (
	"fmt"
	"testing"

	cv "github.com/glycerine/goconvey/convey"
)

func Test400SandboxFunctions(t *testing.T) {

	cv.Convey(`Given that the developer wishes to sandbox the Zygo interpreter when embedding it in their program, the NewZlispSandbox() function should return an interpreter that cannot call system/filesystem functions`, t, func() {

		sysFuncs := SystemFunctions()
		sandSafeFuncs := SandboxSafeFunctions()
		{
			env := NewZlispSandbox()

			// no system functions should pass
			for name := range sysFuncs {
				env.Clear()
				//P("checking name = '%v'", name)
				res, err := env.EvalString(fmt.Sprintf("(defined? %%%s)", name))
				cv.So(res, cv.ShouldResemble, &SexpBool{Val: false})
				cv.So(err, cv.ShouldResemble, nil)
			}

			// all sandSafeFuncs should be fine
			for name := range sandSafeFuncs {
				env.Clear()
				res, err := env.EvalString(fmt.Sprintf("(defined? %%%s)", name))
				switch y := res.(type) {
				case *SexpSentinel:
					P("'%s' wasn't defined but should be; defined? returned '%s'", name, y.SexpString(nil))
				case *SexpBool:
					cv.So(res, cv.ShouldResemble, &SexpBool{Val: true})
				}
				cv.So(err, cv.ShouldEqual, nil)
			}
		}

		{
			fmt.Printf("\n and all functions should be reachable from a non-sandboxed environment.\n")
			env := NewZlisp()
			for name := range sysFuncs {
				env.Clear()
				res, err := env.EvalString(fmt.Sprintf("(defined? %%%s)", name))
				cv.So(res, cv.ShouldResemble, &SexpBool{Val: true})
				cv.So(err, cv.ShouldEqual, nil)
			}

			// all sandSafeFuncs should be fine
			for name := range sandSafeFuncs {
				env.Clear()
				res, err := env.EvalString(fmt.Sprintf("(defined? %%%s)", name))
				cv.So(res, cv.ShouldResemble, &SexpBool{Val: true})
				cv.So(err, cv.ShouldEqual, nil)
			}

		}
	})
}

func TestCallUserFunction(t *testing.T) {
	cv.Convey(`It should recover from user-land panics and give stack traces`, t, func() {
		env := NewZlisp()
		env.AddFunction("dosomething", func(*Zlisp, string, []Sexp) (r Sexp, err error) {
			panic("I don't know how to do anything")
		})
		_, err := env.EvalString("(dosomething)")
		cv.So(err, cv.ShouldNotBeNil)
		cv.So(err.Error(), cv.ShouldContainSubstring, "stack trace:")
		cv.So(err.Error(), cv.ShouldContainSubstring, "github.com/glycerine/zygomys/zygo.(*Zlisp).CallUserFunction")
	})
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/bitly/go-nsq"
	"github.com/boltdb/bolt"
)

var (
	showHelp = flag.Bool("help", false, "print help")
	topic    = flag.String("topic", "", "NSQ topic")
	channel  = flag.String("channel", "", "NSQ channel")
)

// bootstrap event struct
/*
type NSQMessage struct {
	Event      []string `json:event`      // event type
	Uuid       []string `json:uuid`       // event uuid
	InstanceId []string `json:instanceid` // instance id
	IpAddress  []string `json:ipaddress`  // ipaddess
	Os         []string `json:os`         // operaring system
}
*/

func main() {
	fmt.Println("Goloso.. starting")

	flag.Parse()

	if *showHelp {
		fmt.Println(`
Usage:
    goloso --help

    goloso --channel "orc.sys.events" --topic "ec2"
`)
		os.Exit(0)
	}

	if *channel == "" {
		log.Fatalln("Err: missing channel")
	}

	if *topic == "" {
		log.Fatalln("Err: missing topic. \"--topic is required\"")
	}

	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	var (
		consumer *nsq.Consumer
		err      error
	)

	// connect to database
	fmt.Print("Connecting to bolt...")

	// setup bolt db connection
	db, err := bolt.Open("my.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	fmt.Println("done")

	// create buquete
	db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucket([]byte("Goloso"))
		if err != nil {
			return fmt.Errorf("Create bucket: %s", err)
			fmt.Println("Goloso exists")
		}

		fmt.Println("Goloso bucket created")

		return nil
	})

	lookup := "localhost:4161"

	// setup nsq config
	conf := nsq.NewConfig()
	conf.MaxInFlight = 1000

	// setup nsq consumer
	consumer, err = nsq.NewConsumer(*topic, *channel, conf)
	if err != nil {
		log.Fatalln("Err: can't consume", err)
	}

	consumer.AddHandler(nsq.HandlerFunc(func(message *nsq.Message) error {
		log.Printf("Message: %s", message)

		// json_decode && store in KV

		// db.Update(func(tx *bolt.Tx) error {
		// 	b := tx.Bucket([]byte("Goloso"))
		// 	err := b.Put([]byte("answer"), []byte("42"))
		// 	return err
		// })

		return nil
	}))

	err = consumer.ConnectToNSQLookupd(lookup)
	if err != nil {
		log.Fatalln("Err: can't connect to lookupd", err)
	}

	for {
		select {
		case <-consumer.StopChan:
			return
		case <-sigChan:
			consumer.Stop()
		}
	}
}
<commit_msg>useless flag... version<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/bitly/go-nsq"
	"github.com/bitly/nsq/util"
	"github.com/boltdb/bolt"
)

var (
	showHelp    = flag.Bool("help", false, "print help")
	showVersion = flag.Bool("version", false, "print version")
	topic       = flag.String("topic", "", "NSQ topic")
	channel     = flag.String("channel", "", "NSQ channel")
)

// bootstrap event struct
/*
type NSQMessage struct {
	Event      []string `json:event`      // event type
	Uuid       []string `json:uuid`       // event uuid
	InstanceId []string `json:instanceid` // instance id
	IpAddress  []string `json:ipaddress`  // ipaddess
	Os         []string `json:os`         // operaring system
}
*/

func main() {

	flag.Parse()

	if *showHelp {
		fmt.Println(`
Usage:
    goloso --help
    goloso --version

    goloso --channel "orc.sys.events" --topic "ec2"
`)
		os.Exit(0)
	}

	if *showVersion {
		fmt.Printf("Goloso v%s\n", util.BINARY_VERSION)
		os.Exit(0)
	}

	fmt.Println("Goloso.. starting")

	if *channel == "" {
		log.Fatalln("Err: missing channel")
	}

	if *topic == "" {
		log.Fatalln("Err: missing topic. \"--topic is required\"")
	}

	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)

	var (
		consumer *nsq.Consumer
		err      error
	)

	// connect to database
	fmt.Print("Connecting to bolt...")

	// setup bolt db connection
	db, err := bolt.Open("my.db", 0600, nil)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	fmt.Println("done")

	// create buquete
	db.Update(func(tx *bolt.Tx) error {
		_, err := tx.CreateBucket([]byte("Goloso"))
		if err != nil {
			return fmt.Errorf("Create bucket: %s", err)
			fmt.Println("Goloso exists")
		}

		fmt.Println("Goloso bucket created")

		return nil
	})

	lookup := "localhost:4161"

	// setup nsq config
	conf := nsq.NewConfig()
	conf.MaxInFlight = 1000

	// setup nsq consumer
	consumer, err = nsq.NewConsumer(*topic, *channel, conf)
	if err != nil {
		log.Fatalln("Err: can't consume", err)
	}

	consumer.AddHandler(nsq.HandlerFunc(func(message *nsq.Message) error {
		log.Printf("Message: %s", message)

		// json_decode && store in KV

		// db.Update(func(tx *bolt.Tx) error {
		// 	b := tx.Bucket([]byte("Goloso"))
		// 	err := b.Put([]byte("answer"), []byte("42"))
		// 	return err
		// })

		return nil
	}))

	err = consumer.ConnectToNSQLookupd(lookup)
	if err != nil {
		log.Fatalln("Err: can't connect to lookupd", err)
	}

	for {
		select {
		case <-consumer.StopChan:
			return
		case <-sigChan:
			consumer.Stop()
		}
	}
}
<|endoftext|>