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

package main

import (
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/cmd/tsuru-base"
	"os"
)

const (
	version = "0.7.8"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version, header)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(&AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	m.Register(platformList{})
	return m
}

func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	manager.Run(os.Args[1:])
}
<commit_msg>cmd/tsuru: version 0.7.9<commit_after>// Copyright 2013 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"github.com/globocom/tsuru/cmd"
	"github.com/globocom/tsuru/cmd/tsuru-base"
	"os"
)

const (
	version = "0.7.9"
	header  = "Supported-Tsuru"
)

func buildManager(name string) *cmd.Manager {
	m := cmd.BuildBaseManager(name, version, header)
	m.Register(&tsuru.AppRun{})
	m.Register(&tsuru.AppInfo{})
	m.Register(&AppCreate{})
	m.Register(&AppRemove{})
	m.Register(&UnitAdd{})
	m.Register(&UnitRemove{})
	m.Register(tsuru.AppList{})
	m.Register(&tsuru.AppLog{})
	m.Register(&tsuru.AppGrant{})
	m.Register(&tsuru.AppRevoke{})
	m.Register(&tsuru.AppRestart{})
	m.Register(&tsuru.SetCName{})
	m.Register(&tsuru.UnsetCName{})
	m.Register(&tsuru.EnvGet{})
	m.Register(&tsuru.EnvSet{})
	m.Register(&tsuru.EnvUnset{})
	m.Register(&KeyAdd{})
	m.Register(&KeyRemove{})
	m.Register(tsuru.ServiceList{})
	m.Register(tsuru.ServiceAdd{})
	m.Register(tsuru.ServiceRemove{})
	m.Register(tsuru.ServiceDoc{})
	m.Register(tsuru.ServiceInfo{})
	m.Register(tsuru.ServiceInstanceStatus{})
	m.Register(&tsuru.ServiceBind{})
	m.Register(&tsuru.ServiceUnbind{})
	m.Register(platformList{})
	return m
}

func main() {
	name := cmd.ExtractProgramName(os.Args[0])
	manager := buildManager(name)
	manager.Run(os.Args[1:])
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"time"

	"github.com/fatih/color"
	"github.com/ladydascalie/dotmgmt/managers"
	"golang.org/x/sys/unix"
)

var
(
	dotFilesPath string
	shouldMake   string // the file that should be made
	shouldRemove string // the file that should be removed
	shouldReset  bool
	usr          *user.User // the current user
)

func init() {
	var err error
	usr, err = user.Current()
	if err != nil {
		panic(err)
	}
}

func main() {
	flag.StringVar(&dotFilesPath, "p", ".", "dotmgmt -p /path/to/dir")
	flag.StringVar(&shouldMake, "make", "", "dotmgmt -make /path/to/dir")
	flag.StringVar(&shouldRemove, "del", "", "dotmgmt -del /path/to/file")
	flag.BoolVar(&shouldReset, "reset", false, "dotmgmt -reset")
	flag.Parse()

	safetyCheck()

	var conf managers.Config
	conf.New() // Create a new config object
	// if the config files doesn't exist, create it
	if !conf.Exists() {
		conf.MakeFile()
	}

	// move and symlink the file
	if shouldMake != "" {
		moveAndSymlink(&conf)
		return
	}

	if shouldRemove != "" {
		undoSymlink(&conf)
		return
	}

	list := getFiles()

	if shouldReset {
		removeSymlink(list, &conf)
		return
	}

	makeSymlinks(list, &conf)
}

// make sure we aren't going to break things
func safetyCheck() {
	pwd := getPwd()
	danger := []string{"/", "/home",
			   "/usr", "/usr/bin", "/usr/local/bin",
			   "/etc", "/private/etc",
			   "/tmp", "/private/tmp",
			   "/var", "/private/var",
			   "/sbin", "/private"}

	for _, p := range danger {
		if pwd == p {
			color.Red("%s", "dotmgmt: Dangerous folder. Refusing to run.")
			os.Exit(1)
		} else if pwd == usr.HomeDir {
			color.Red("%s", "dotmgmt: Cannot run on the home directory")
			os.Exit(1)
		}
	}
}

//getFiles gets the list of files in the dotfiles folder
func getFiles() []os.FileInfo {
	list, err := ioutil.ReadDir(derive(dotFilesPath))
	if err != nil {
		color.Red("Could not get list of files")
		os.Exit(1)
	}

	return list
}

func moveAndSymlink(conf *managers.Config) {
	var list []os.FileInfo

	file := store(shouldMake)
	i, err := os.Stat(file)

	if err != nil {
		color.Red("No such file or directory")
		os.Exit(1)
	}
	list = append(list, i)

	makeSymlinks(list, conf)
}

func undoSymlink(conf *managers.Config) {
	var list []os.FileInfo

	fname := filepath.Join(dotFilesPath, filepath.Base(shouldRemove))

	i, err := os.Stat(fname)
	if err != nil {
		color.Red("No such file or directory")
		os.Exit(1)
	}
	list = append(list, i)

	removeSymlink(list, conf)
}

func derive(fname string) string {
	var err error
	fname, err = filepath.Abs(fname)
	if err != nil {
		color.Red("Could not derive path for file %s", fname)
		os.Exit(1)
	}

	return fname
}

func store(fname string) (newname string) {
	oldname := derive(fname)
	newname = filepath.Join(dotFilesPath, filepath.Base(fname))

	err := os.Rename(oldname, newname)
	if err != nil {
		color.Red("Could nor rename file")
		os.Exit(1)
	}

	return newname
}

// removeSymlink removes the symlinks from the user's home folder
func removeSymlink(list []os.FileInfo, conf *managers.Config) {
	// Notify user and defer closing statement
	color.Green("%s", "Removing Symlinks...")
	fmt.Println("____")
	defer fmt.Println("____")

	// Load the config file into memory
	var sc managers.SymlinkCollection
	config, err := ioutil.ReadFile(conf.Path)
	if err != nil {
		color.Red("Could not read config file")
		os.Exit(1)
	}

	json.Unmarshal(config, &sc)

	// Iterate over files...
	for _, v := range list {
		oldPath := filepath.Join(getPwd(), v.Name())
		newPath := filepath.Join(usr.HomeDir, v.Name())

		if oldPath != newPath {
			fmt.Println("Removing", color.RedString("%s", newPath))
			err := unix.Unlink(newPath)
			if err != nil {
				fmt.Println(newPath, err)
			}

			cp := sc.Symlinks
			for k, v := range sc.Symlinks {
				if v.Destination == newPath {
					cp = append(cp[:k], cp[k + 1:]...)
				}
			}

			sc.Symlinks = cp
		}
	}
	sc.Timestamp = time.Now().Format(time.RFC3339)
	sc.Save(conf)
}

func makeSymlinks(list []os.FileInfo, conf *managers.Config) {
	// Symlink the files
	color.Green("%s", "Creating symlinks...")
	fmt.Println("____")
	defer fmt.Println("____")

	// Load the config file into memory
	var sc managers.SymlinkCollection
	config, err := ioutil.ReadFile(conf.Path)
	if err != nil {
		color.Red("Could not read config file")
		os.Exit(1)
	}

	json.Unmarshal(config, &sc)
	for _, v := range list {
		oldPath := filepath.Join(getPwd(), v.Name())
		newPath := filepath.Join(usr.HomeDir, v.Name())

		s := managers.Symlink{
			Destination: newPath,
			Origin:      oldPath,
		}

		fmt.Println("Symlinking", color.RedString("%s", oldPath), color.BlueString("%s", "=>"), color.GreenString("%s", newPath))
		err := os.Symlink(oldPath, newPath)
		if err != nil {
			fmt.Println(err)
		}

		sc.Symlinks = append(sc.Symlinks, s)
	}
	sc.Timestamp = time.Now().Format(time.RFC3339)
	sc.Save(conf)
}

func getPwd() string {
	pwd, err := os.Getwd()
	if err != nil {
		color.Red("Could not get current working directory path")
		os.Exit(1)
	}
	return pwd
}
<commit_msg>Corrected missing exit statement in error check<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"path/filepath"
	"time"

	"github.com/fatih/color"
	"github.com/ladydascalie/dotmgmt/managers"
	"golang.org/x/sys/unix"
)

var
(
	dotFilesPath string
	shouldMake   string // the file that should be made
	shouldRemove string // the file that should be removed
	shouldReset  bool
	usr          *user.User // the current user
)

func init() {
	var err error
	usr, err = user.Current()
	if err != nil {
		panic(err)
	}
}

func main() {
	flag.StringVar(&dotFilesPath, "p", ".", "dotmgmt -p /path/to/dir")
	flag.StringVar(&shouldMake, "make", "", "dotmgmt -make /path/to/dir")
	flag.StringVar(&shouldRemove, "del", "", "dotmgmt -del /path/to/file")
	flag.BoolVar(&shouldReset, "reset", false, "dotmgmt -reset")
	flag.Parse()

	safetyCheck()

	var conf managers.Config
	conf.New() // Create a new config object
	// if the config files doesn't exist, create it
	if !conf.Exists() {
		conf.MakeFile()
	}

	// move and symlink the file
	if shouldMake != "" {
		moveAndSymlink(&conf)
		return
	}

	if shouldRemove != "" {
		undoSymlink(&conf)
		return
	}

	list := getFiles()

	if shouldReset {
		removeSymlink(list, &conf)
		return
	}

	makeSymlinks(list, &conf)
}

// make sure we aren't going to break things
func safetyCheck() {
	pwd := getPwd()
	danger := []string{"/", "/home",
			   "/usr", "/usr/bin", "/usr/local/bin",
			   "/etc", "/private/etc",
			   "/tmp", "/private/tmp",
			   "/var", "/private/var",
			   "/sbin", "/private"}

	for _, p := range danger {
		if pwd == p {
			color.Red("%s", "dotmgmt: Dangerous folder. Refusing to run.")
			os.Exit(1)
		} else if pwd == usr.HomeDir {
			color.Red("%s", "dotmgmt: Cannot run on the home directory")
			os.Exit(1)
		}
	}
}

//getFiles gets the list of files in the dotfiles folder
func getFiles() []os.FileInfo {
	list, err := ioutil.ReadDir(derive(dotFilesPath))
	if err != nil {
		color.Red("Could not get list of files")
		os.Exit(1)
	}

	return list
}

func moveAndSymlink(conf *managers.Config) {
	var list []os.FileInfo

	file := store(shouldMake)
	i, err := os.Stat(file)

	if err != nil {
		color.Red("No such file or directory")
		os.Exit(1)
	}
	list = append(list, i)

	makeSymlinks(list, conf)
}

func undoSymlink(conf *managers.Config) {
	var list []os.FileInfo

	fname := filepath.Join(dotFilesPath, filepath.Base(shouldRemove))

	i, err := os.Stat(fname)
	if err != nil {
		color.Red("No such file or directory")
		os.Exit(1)
	}
	list = append(list, i)

	removeSymlink(list, conf)
}

func derive(fname string) string {
	var err error
	fname, err = filepath.Abs(fname)
	if err != nil {
		color.Red("Could not derive path for file %s", fname)
		os.Exit(1)
	}

	return fname
}

func store(fname string) (newname string) {
	oldname := derive(fname)
	newname = filepath.Join(dotFilesPath, filepath.Base(fname))

	err := os.Rename(oldname, newname)
	if err != nil {
		color.Red("Could nor rename file")
		os.Exit(1)
	}

	return newname
}

// removeSymlink removes the symlinks from the user's home folder
func removeSymlink(list []os.FileInfo, conf *managers.Config) {
	// Notify user and defer closing statement
	color.Green("%s", "Removing Symlinks...")
	fmt.Println("____")
	defer fmt.Println("____")

	// Load the config file into memory
	var sc managers.SymlinkCollection
	config, err := ioutil.ReadFile(conf.Path)
	if err != nil {
		color.Red("Could not read config file")
		os.Exit(1)
	}

	json.Unmarshal(config, &sc)

	// Iterate over files...
	for _, v := range list {
		oldPath := filepath.Join(getPwd(), v.Name())
		newPath := filepath.Join(usr.HomeDir, v.Name())

		if oldPath != newPath {
			fmt.Println("Removing", color.RedString("%s", newPath))
			err := unix.Unlink(newPath)
			if err != nil {
				fmt.Println(newPath, err)
				os.Exit(1)
			}

			cp := sc.Symlinks
			for k, v := range sc.Symlinks {
				if v.Destination == newPath {
					cp = append(cp[:k], cp[k + 1:]...)
				}
			}

			sc.Symlinks = cp
		}
	}
	sc.Timestamp = time.Now().Format(time.RFC3339)
	sc.Save(conf)
}

func makeSymlinks(list []os.FileInfo, conf *managers.Config) {
	// Symlink the files
	color.Green("%s", "Creating symlinks...")
	fmt.Println("____")
	defer fmt.Println("____")

	// Load the config file into memory
	var sc managers.SymlinkCollection
	config, err := ioutil.ReadFile(conf.Path)
	if err != nil {
		color.Red("Could not read config file")
		os.Exit(1)
	}

	json.Unmarshal(config, &sc)
	for _, v := range list {
		oldPath := filepath.Join(getPwd(), v.Name())
		newPath := filepath.Join(usr.HomeDir, v.Name())

		s := managers.Symlink{
			Destination: newPath,
			Origin:      oldPath,
		}

		fmt.Println("Symlinking", color.RedString("%s", oldPath), color.BlueString("%s", "=>"), color.GreenString("%s", newPath))
		err := os.Symlink(oldPath, newPath)
		if err != nil {
			fmt.Println(err)
		}

		sc.Symlinks = append(sc.Symlinks, s)
	}
	sc.Timestamp = time.Now().Format(time.RFC3339)
	sc.Save(conf)
}

func getPwd() string {
	pwd, err := os.Getwd()
	if err != nil {
		color.Red("Could not get current working directory path")
		os.Exit(1)
	}
	return pwd
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"io/ioutil"
	"os"

	"github.com/mithrandie/csvq/lib/action"
	"github.com/mithrandie/csvq/lib/cmd"
	"github.com/mithrandie/csvq/lib/query"

	"github.com/urfave/cli"
)

var version = "v0.5.8"

func main() {
	cli.AppHelpTemplate = appHHelpTemplate
	cli.CommandHelpTemplate = commandHelpTemplate

	app := cli.NewApp()

	app.Name = "csvq"
	app.Usage = "SQL like query language for csv"
	app.ArgsUsage = "[\"query\"|\"statements\"]"
	app.Version = version

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "delimiter, d",
			Usage: "field delimiter. Default is \",\" for csv files, \"\\t\" for tsv files.",
		},
		cli.StringFlag{
			Name:  "encoding, e",
			Value: "UTF8",
			Usage: "file encoding. one of: UTF8|SJIS",
		},
		cli.StringFlag{
			Name:  "line-break, l",
			Value: "LF",
			Usage: "line break. one of: CRLF|LF|CR",
		},
		cli.StringFlag{
			Name:  "timezone, z",
			Value: "Local",
			Usage: "default timezone. \"Local\", \"UTC\" or a timezone name(e.g. \"America/Los_Angeles\")",
		},
		cli.StringFlag{
			Name:  "repository, r",
			Usage: "directory path where files are located",
		},
		cli.StringFlag{
			Name:  "source, s",
			Usage: "load query from `FILE`",
		},
		cli.StringFlag{
			Name:  "datetime-format, t",
			Usage: "set datetime format to parse strings",
		},
		cli.BoolFlag{
			Name:  "no-header, n",
			Usage: "import the first line as a record",
		},
		cli.BoolFlag{
			Name:  "without-null, a",
			Usage: "parse empty fields as empty strings",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:      "write",
			Usage:     "Write output to a file",
			ArgsUsage: "[\"query\"|\"statements\"]",

			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "write-encoding, E",
					Value: "UTF8",
					Usage: "file encoding. one of: UTF8|SJIS",
				},
				cli.StringFlag{
					Name:  "out, o",
					Usage: "write output to `FILE`",
				},
				cli.StringFlag{
					Name:  "format, f",
					Usage: "output format. one of: CSV|TSV|JSON|TEXT",
				},
				cli.StringFlag{
					Name:  "write-delimiter, D",
					Usage: "field delimiter for CSV",
				},
				cli.BoolFlag{
					Name:  "without-header, N",
					Usage: "when the file format is specified as CSV or TSV, write without the header line",
				},
			},
			Before: func(c *cli.Context) error {
				return setWriteFlags(c)
			},
			Action: func(c *cli.Context) error {
				queryString, err := readQuery(c)
				if err != nil {
					cli.ShowCommandHelp(c, "write")
					return cli.NewExitError(err.Error(), 1)
				}

				return exec(queryString)
			},
		},
		{
			Name:      "fields",
			Usage:     "Show fields in a file",
			ArgsUsage: "CSV_FILE_PATH",
			Action: func(c *cli.Context) error {
				if c.NArg() != 1 {
					cli.ShowCommandHelp(c, "fields")
					return cli.NewExitError("table is not specified", 1)
				}

				table := c.Args().First()

				err := action.ShowFields(table)
				if err != nil {
					return cli.NewExitError(err.Error(), 1)
				}

				return nil
			},
		},
		{
			Name:      "calc",
			Usage:     "Calculate a value from stdin",
			ArgsUsage: "\"expression\"",
			Action: func(c *cli.Context) error {
				if c.NArg() != 1 {
					cli.ShowCommandHelp(c, "calc")
					return cli.NewExitError("expression is empty", 1)
				}

				expr := c.Args().First()
				err := action.Calc(expr)
				if err != nil {
					return cli.NewExitError(err.Error(), 1)
				}

				return nil
			},
		},
	}

	app.Before = func(c *cli.Context) error {
		return setGlobalFlags(c)
	}

	app.Action = func(c *cli.Context) error {
		queryString, err := readQuery(c)
		if err != nil {
			cli.ShowAppHelp(c)
			return cli.NewExitError(err.Error(), 1)
		}

		return exec(queryString)
	}

	app.Run(os.Args)
}

func exec(queryString string) error {
	err := action.Write(queryString, cmd.GetFlags().Source)
	if err != nil {
		code := 1
		if apperr, ok := err.(query.AppError); ok {
			code = apperr.GetCode()
		}
		return cli.NewExitError(err.Error(), code)
	}

	return nil
}

func readQuery(c *cli.Context) (string, error) {
	var queryString string

	flags := cmd.GetFlags()
	if 0 < len(flags.Source) {
		fp, err := os.Open(flags.Source)
		if err != nil {
			return queryString, err
		}
		defer fp.Close()

		buf, err := ioutil.ReadAll(fp)
		if err != nil {
			return queryString, err
		}
		queryString = string(buf)

	} else {
		if c.NArg() != 1 {
			return queryString, errors.New("query is empty")
		}
		queryString = c.Args().First()
	}

	return queryString, nil
}

func setGlobalFlags(c *cli.Context) error {
	if err := cmd.SetDelimiter(c.GlobalString("delimiter")); err != nil {
		return err
	}
	if err := cmd.SetEncoding(c.GlobalString("encoding")); err != nil {
		return err
	}
	if err := cmd.SetLineBreak(c.String("line-break")); err != nil {
		return err
	}
	if err := cmd.SetLocation(c.String("timezone")); err != nil {
		return err
	}
	if err := cmd.SetRepository(c.GlobalString("repository")); err != nil {
		return err
	}
	if err := cmd.SetSource(c.GlobalString("source")); err != nil {
		return err
	}
	cmd.SetDatetimeFormat(c.GlobalString("datetime-format"))
	cmd.SetNoHeader(c.GlobalBool("no-header"))
	cmd.SetWithoutNull(c.GlobalBool("without-null"))
	return nil
}

func setWriteFlags(c *cli.Context) error {
	if err := cmd.SetWriteEncoding(c.String("write-encoding")); err != nil {
		return err
	}
	if err := cmd.SetOut(c.String("out")); err != nil {
		return err
	}
	if err := cmd.SetFormat(c.String("format")); err != nil {
		return err
	}
	if err := cmd.SetWriteDelimiter(c.String("write-delimiter")); err != nil {
		return err
	}
	cmd.SetWithoutHeader(c.Bool("without-header"))
	return nil
}
<commit_msg>Update version for Release v0.5.9<commit_after>package main

import (
	"errors"
	"io/ioutil"
	"os"

	"github.com/mithrandie/csvq/lib/action"
	"github.com/mithrandie/csvq/lib/cmd"
	"github.com/mithrandie/csvq/lib/query"

	"github.com/urfave/cli"
)

var version = "v0.5.9"

func main() {
	cli.AppHelpTemplate = appHHelpTemplate
	cli.CommandHelpTemplate = commandHelpTemplate

	app := cli.NewApp()

	app.Name = "csvq"
	app.Usage = "SQL like query language for csv"
	app.ArgsUsage = "[\"query\"|\"statements\"]"
	app.Version = version

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "delimiter, d",
			Usage: "field delimiter. Default is \",\" for csv files, \"\\t\" for tsv files.",
		},
		cli.StringFlag{
			Name:  "encoding, e",
			Value: "UTF8",
			Usage: "file encoding. one of: UTF8|SJIS",
		},
		cli.StringFlag{
			Name:  "line-break, l",
			Value: "LF",
			Usage: "line break. one of: CRLF|LF|CR",
		},
		cli.StringFlag{
			Name:  "timezone, z",
			Value: "Local",
			Usage: "default timezone. \"Local\", \"UTC\" or a timezone name(e.g. \"America/Los_Angeles\")",
		},
		cli.StringFlag{
			Name:  "repository, r",
			Usage: "directory path where files are located",
		},
		cli.StringFlag{
			Name:  "source, s",
			Usage: "load query from `FILE`",
		},
		cli.StringFlag{
			Name:  "datetime-format, t",
			Usage: "set datetime format to parse strings",
		},
		cli.BoolFlag{
			Name:  "no-header, n",
			Usage: "import the first line as a record",
		},
		cli.BoolFlag{
			Name:  "without-null, a",
			Usage: "parse empty fields as empty strings",
		},
	}

	app.Commands = []cli.Command{
		{
			Name:      "write",
			Usage:     "Write output to a file",
			ArgsUsage: "[\"query\"|\"statements\"]",

			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "write-encoding, E",
					Value: "UTF8",
					Usage: "file encoding. one of: UTF8|SJIS",
				},
				cli.StringFlag{
					Name:  "out, o",
					Usage: "write output to `FILE`",
				},
				cli.StringFlag{
					Name:  "format, f",
					Usage: "output format. one of: CSV|TSV|JSON|TEXT",
				},
				cli.StringFlag{
					Name:  "write-delimiter, D",
					Usage: "field delimiter for CSV",
				},
				cli.BoolFlag{
					Name:  "without-header, N",
					Usage: "when the file format is specified as CSV or TSV, write without the header line",
				},
			},
			Before: func(c *cli.Context) error {
				return setWriteFlags(c)
			},
			Action: func(c *cli.Context) error {
				queryString, err := readQuery(c)
				if err != nil {
					cli.ShowCommandHelp(c, "write")
					return cli.NewExitError(err.Error(), 1)
				}

				return exec(queryString)
			},
		},
		{
			Name:      "fields",
			Usage:     "Show fields in a file",
			ArgsUsage: "CSV_FILE_PATH",
			Action: func(c *cli.Context) error {
				if c.NArg() != 1 {
					cli.ShowCommandHelp(c, "fields")
					return cli.NewExitError("table is not specified", 1)
				}

				table := c.Args().First()

				err := action.ShowFields(table)
				if err != nil {
					return cli.NewExitError(err.Error(), 1)
				}

				return nil
			},
		},
		{
			Name:      "calc",
			Usage:     "Calculate a value from stdin",
			ArgsUsage: "\"expression\"",
			Action: func(c *cli.Context) error {
				if c.NArg() != 1 {
					cli.ShowCommandHelp(c, "calc")
					return cli.NewExitError("expression is empty", 1)
				}

				expr := c.Args().First()
				err := action.Calc(expr)
				if err != nil {
					return cli.NewExitError(err.Error(), 1)
				}

				return nil
			},
		},
	}

	app.Before = func(c *cli.Context) error {
		return setGlobalFlags(c)
	}

	app.Action = func(c *cli.Context) error {
		queryString, err := readQuery(c)
		if err != nil {
			cli.ShowAppHelp(c)
			return cli.NewExitError(err.Error(), 1)
		}

		return exec(queryString)
	}

	app.Run(os.Args)
}

func exec(queryString string) error {
	err := action.Write(queryString, cmd.GetFlags().Source)
	if err != nil {
		code := 1
		if apperr, ok := err.(query.AppError); ok {
			code = apperr.GetCode()
		}
		return cli.NewExitError(err.Error(), code)
	}

	return nil
}

func readQuery(c *cli.Context) (string, error) {
	var queryString string

	flags := cmd.GetFlags()
	if 0 < len(flags.Source) {
		fp, err := os.Open(flags.Source)
		if err != nil {
			return queryString, err
		}
		defer fp.Close()

		buf, err := ioutil.ReadAll(fp)
		if err != nil {
			return queryString, err
		}
		queryString = string(buf)

	} else {
		if c.NArg() != 1 {
			return queryString, errors.New("query is empty")
		}
		queryString = c.Args().First()
	}

	return queryString, nil
}

func setGlobalFlags(c *cli.Context) error {
	if err := cmd.SetDelimiter(c.GlobalString("delimiter")); err != nil {
		return err
	}
	if err := cmd.SetEncoding(c.GlobalString("encoding")); err != nil {
		return err
	}
	if err := cmd.SetLineBreak(c.String("line-break")); err != nil {
		return err
	}
	if err := cmd.SetLocation(c.String("timezone")); err != nil {
		return err
	}
	if err := cmd.SetRepository(c.GlobalString("repository")); err != nil {
		return err
	}
	if err := cmd.SetSource(c.GlobalString("source")); err != nil {
		return err
	}
	cmd.SetDatetimeFormat(c.GlobalString("datetime-format"))
	cmd.SetNoHeader(c.GlobalBool("no-header"))
	cmd.SetWithoutNull(c.GlobalBool("without-null"))
	return nil
}

func setWriteFlags(c *cli.Context) error {
	if err := cmd.SetWriteEncoding(c.String("write-encoding")); err != nil {
		return err
	}
	if err := cmd.SetOut(c.String("out")); err != nil {
		return err
	}
	if err := cmd.SetFormat(c.String("format")); err != nil {
		return err
	}
	if err := cmd.SetWriteDelimiter(c.String("write-delimiter")); err != nil {
		return err
	}
	cmd.SetWithoutHeader(c.Bool("without-header"))
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"errors"
	"fmt"
	"golang.org/x/net/html/charset"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
)

type songInfo struct {
	artist, title string
}

func main() {
	home := os.Getenv("HOME")
	if home == "" {
		log.Fatal("HOME not found")
	}

	songinfo, err := getSongInfo()
	if err != nil {
		log.Fatal(err)
	}

	// TODO
	// artist and title can contain slashes
	dotDir := path.Join(home, ".show-lyrics")
	cacheDir := path.Join(dotDir, "cache")
	cacheArtistDir := path.Join(cacheDir, songinfo.artist)
	songFile := path.Join(cacheArtistDir, songinfo.title + ".txt")

	for _, dir := range []string{dotDir, cacheDir, cacheArtistDir} {
		err := mkdirUnlessExists(dir)
		if err != nil {
			log.Fatal(err)
		}
	}

	client := &http.Client{}

	lyrics, err := fetchLyrics(client, songinfo)
	if err != nil {
		log.Fatal(err)
	}

	err = ioutil.WriteFile(songFile, lyrics, 0644)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(lyrics))
}

func getSongInfo() (*songInfo, error) {
	cmusStatus, err := getCmusStatus()
	if err != nil {
		return nil, err
	}
	songinfo, err := parseCmusStatus(cmusStatus)
	if err != nil {
		return nil, err
	}
	return songinfo, nil
}

func mkdirUnlessExists(dir string) error {
	_, err := os.Stat(dir)
	if err != nil {
		err = os.Mkdir(dir, 0755)
		if err != nil {
			return err
		}
	}
	return nil
}

func getCmusStatus() ([]byte, error) {
	cmd := exec.Command("cmus-remote", "-Q")
	return cmd.Output()
}

var artistRe = regexp.MustCompile(`(?m)^tag\s+artist\s+(.+)\s*$`)
var titleRe = regexp.MustCompile(`(?m)^tag\s+title\s+(.+)\s*$`)

func regexpMatch(re *regexp.Regexp, buf []byte) []byte {
	match := re.FindAllSubmatch(buf, 1)
	if len(match) > 0 {
		return match[0][1]
	}
	return nil
}

func parseCmusStatus(cmusStatus []byte) (*songInfo, error) {
	artist := regexpMatch(artistRe, cmusStatus)
	title := regexpMatch(titleRe, cmusStatus)

	if artist == nil || title == nil {
		return nil, errors.New("Failed to parse cmus status")
	}

	si := songInfo{
		artist: string(artist),
		title:  string(title),
	}

	return &si, nil
}

func makeURL(si *songInfo) string {
	artist := []byte(si.artist)
	title := []byte(si.title)

	theRe := regexp.MustCompile(`(?i)^the `)
	weirdRe := regexp.MustCompile(`(?i)[^a-z0-9]`)

	artist = theRe.ReplaceAll(artist, []byte{})

	artist = bytes.ToLower(artist)
	title = bytes.ToLower(title)

	for _, str := range []*[]byte{&artist, &title} {
		*str = bytes.ToLower(*str)
		*str = weirdRe.ReplaceAll(*str, []byte{})
	}

	url := "https://www.azlyrics.com/lyrics/"
	url += string(artist) + "/" + string(title) + ".html"

	return url
}

func fetchLyrics(client *http.Client, si *songInfo) ([]byte, error) {
	reqUrl := makeURL(si)

	req, err := http.NewRequest("GET", reqUrl, nil)
	if err != nil {
		return []byte{}, err
	}

	resp, err := client.Do(req)
	if err != nil {
		return []byte{}, err
	}

	if resp.StatusCode != 200 {
		return []byte{}, errors.New(resp.Status)
	}

	utf8, err := charset.NewReader(resp.Body, resp.Header.Get("Content-Type"))
	if err != nil {
		return []byte{}, err
	}
	body, err := ioutil.ReadAll(utf8)
	if err != nil {
		return []byte{}, err
	}

	lyrics, err := parseLyrics(body)
	if err != nil {
		return []byte{}, err
	}

	return lyrics, nil
}

func htmlStrip(html []byte) []byte {
	commentsRe := regexp.MustCompile(`(?s)<!--.*?-->`)
	brRe := regexp.MustCompile(`<br/?>`)

	html = commentsRe.ReplaceAll(html, []byte{})
	html = brRe.ReplaceAll(html, []byte{})

	// TODO
	// trim leading|trainling whitespace for every line

	return html
}

func parseLyrics(lyricsHtml []byte) ([]byte, error) {
	re := regexp.MustCompile(
		`(?s)<div[^<>]*?class="lyricsh"[^<>]*?>.*?</div>\s*?` +
			`<div[^<>]*?>.*?</div>\s*` +
			`.*?` +
			`<div[^<>]*?>(.*?)</div>`)

	match := re.FindAllSubmatch(lyricsHtml, 1)
	if match == nil {
		return []byte{}, errors.New("Failed to parse html")
	}

	lyrics := htmlStrip(match[0][1])
	return lyrics, nil
}
<commit_msg>Trim space<commit_after>package main

import (
	"bytes"
	"errors"
	"fmt"
	"golang.org/x/net/html/charset"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
)

type songInfo struct {
	artist, title string
}

func main() {
	home := os.Getenv("HOME")
	if home == "" {
		log.Fatal("HOME not found")
	}

	songinfo, err := getSongInfo()
	if err != nil {
		log.Fatal(err)
	}

	// TODO
	// artist and title can contain slashes
	dotDir := path.Join(home, ".show-lyrics")
	cacheDir := path.Join(dotDir, "cache")
	cacheArtistDir := path.Join(cacheDir, songinfo.artist)
	songFile := path.Join(cacheArtistDir, songinfo.title + ".txt")

	for _, dir := range []string{dotDir, cacheDir, cacheArtistDir} {
		err := mkdirUnlessExists(dir)
		if err != nil {
			log.Fatal(err)
		}
	}

	client := &http.Client{}

	lyrics, err := fetchLyrics(client, songinfo)
	if err != nil {
		log.Fatal(err)
	}

	err = ioutil.WriteFile(songFile, lyrics, 0644)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(lyrics))
}

func getSongInfo() (*songInfo, error) {
	cmusStatus, err := getCmusStatus()
	if err != nil {
		return nil, err
	}
	songinfo, err := parseCmusStatus(cmusStatus)
	if err != nil {
		return nil, err
	}
	return songinfo, nil
}

func mkdirUnlessExists(dir string) error {
	_, err := os.Stat(dir)
	if err != nil {
		err = os.Mkdir(dir, 0755)
		if err != nil {
			return err
		}
	}
	return nil
}

func getCmusStatus() ([]byte, error) {
	cmd := exec.Command("cmus-remote", "-Q")
	return cmd.Output()
}

var artistRe = regexp.MustCompile(`(?m)^tag\s+artist\s+(.+)\s*$`)
var titleRe = regexp.MustCompile(`(?m)^tag\s+title\s+(.+)\s*$`)

func regexpMatch(re *regexp.Regexp, buf []byte) []byte {
	match := re.FindAllSubmatch(buf, 1)
	if len(match) > 0 {
		return match[0][1]
	}
	return nil
}

func parseCmusStatus(cmusStatus []byte) (*songInfo, error) {
	artist := regexpMatch(artistRe, cmusStatus)
	title := regexpMatch(titleRe, cmusStatus)

	if artist == nil || title == nil {
		return nil, errors.New("Failed to parse cmus status")
	}

	si := songInfo{
		artist: string(artist),
		title:  string(title),
	}

	return &si, nil
}

func makeURL(si *songInfo) string {
	artist := []byte(si.artist)
	title := []byte(si.title)

	theRe := regexp.MustCompile(`(?i)^the `)
	weirdRe := regexp.MustCompile(`(?i)[^a-z0-9]`)

	artist = theRe.ReplaceAll(artist, []byte{})

	artist = bytes.ToLower(artist)
	title = bytes.ToLower(title)

	for _, str := range []*[]byte{&artist, &title} {
		*str = bytes.ToLower(*str)
		*str = weirdRe.ReplaceAll(*str, []byte{})
	}

	url := "https://www.azlyrics.com/lyrics/"
	url += string(artist) + "/" + string(title) + ".html"

	return url
}

func fetchLyrics(client *http.Client, si *songInfo) ([]byte, error) {
	reqUrl := makeURL(si)

	req, err := http.NewRequest("GET", reqUrl, nil)
	if err != nil {
		return []byte{}, err
	}

	resp, err := client.Do(req)
	if err != nil {
		return []byte{}, err
	}

	if resp.StatusCode != 200 {
		return []byte{}, errors.New(resp.Status)
	}

	utf8, err := charset.NewReader(resp.Body, resp.Header.Get("Content-Type"))
	if err != nil {
		return []byte{}, err
	}
	body, err := ioutil.ReadAll(utf8)
	if err != nil {
		return []byte{}, err
	}

	lyrics, err := parseLyrics(body)
	if err != nil {
		return []byte{}, err
	}

	return lyrics, nil
}

func htmlStrip(html []byte) []byte {
	commentsRe := regexp.MustCompile(`(?s)<!--.*?-->`)
	brRe := regexp.MustCompile(`<br/?>`)

	html = commentsRe.ReplaceAll(html, []byte{})
	html = brRe.ReplaceAll(html, []byte{})
	html = bytes.TrimSpace(html)

	return html
}

func parseLyrics(lyricsHtml []byte) ([]byte, error) {
	re := regexp.MustCompile(
		`(?s)<div[^<>]*?class="lyricsh"[^<>]*?>.*?</div>\s*?` +
			`<div[^<>]*?>.*?</div>\s*` +
			`.*?` +
			`<div[^<>]*?>(.*?)</div>`)

	match := re.FindAllSubmatch(lyricsHtml, 1)
	if match == nil {
		return []byte{}, errors.New("Failed to parse html")
	}

	lyrics := htmlStrip(match[0][1])
	return lyrics, nil
}
<|endoftext|>


<commit_before>package main

import (
	"database/sql"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/jmoiron/sqlx"
	"github.com/joho/sqltocsv"
	_ "github.com/lib/pq"
	"html/template"
	"log"
	"os"
	"strconv"
	"time"
)

func CampbellTime(myTime time.Time) (int, int, int) {
	hourmin := myTime.Hour()*100 + myTime.Minute()
	doy := myTime.YearDay()
	if hourmin == 0 {
		hourmin = 2400
		doy = doy - 1
	}
	return myTime.Year(), doy, hourmin
}

type User struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

func checkErr(err error, msg string) {
	if err != nil {
		log.Fatalln(msg, err)
	}
}

type Datum struct {
	Time  time.Time `json:"time"`
	Value float64   `json:"value"`
}

type Variate struct {
	Id      int
	Title   string
	Y_label string
}

func variates(db *sqlx.DB, c *gin.Context) {
	var variates []Variate
	db.Select(&variates, "select id, title, y_label from weather.variates where updated is true")

	obj := gin.H{"variates": variates}
	c.HTML(200, "variates.html", obj)
}

func variatesById(db *sqlx.DB, c *gin.Context) {
	idString := c.Params.ByName("id")
	var query string
	id, err := strconv.Atoi(idString)
	if err == nil {
		var data = []Datum{}
		err = db.Get(&query, "select query from weather.variates where id = $1", id)
		if err == nil {
			db.Select(&data, query)
		}
		c.JSON(200, data)
	}
}

type Table struct {
	Id    int
	Name  string
	Query string
}

func tables(db *sqlx.DB, c *gin.Context) {
	var tables []Table
	db.Select(&tables, "select id, name from weather.tables")

	obj := gin.H{"tables": tables}
	c.HTML(200, "tables.html", obj)
}

func tablesById(db *sqlx.DB, c *gin.Context) {
	id := c.Params.ByName("id")
	var query Table
	err := db.Get(&query, "select id, name, query from weather.tables where id = $1", id)
	if err == nil {
		rows, _ := db.Query(query.Query)
		defer rows.Close()

		w := c.Writer
		w.Header().Set("Content-type", "text/csv")
		w.Header().Set("Content-Disposition", "attachment; filename=\""+query.Name+".csv\"")

		sqltocsv.Write(w, rows)
	}
}

func floatToString(value sql.NullFloat64) string {
	result := "nil"
	if value.Valid {
		result = strconv.FormatFloat(value.Float64, 'f', 5, 64)
	}
	return result
}

func intToString(value sql.NullInt64) string {
	result := "nil"
	if value.Valid {
		result = strconv.FormatInt(value.Int64, 10)
	}
	return result
}

func limit(c *gin.Context, limit int) int {
	query := c.Request.URL.Query()
	if query["limit"] != nil {
		value, err := strconv.Atoi(query["limit"][0])
		if err != nil {
			log.Fatal(err)
		}
		limit = value
	}
	return limit
}

func Router(db *sqlx.DB) *gin.Engine {
	router := gin.Default()
	templates := template.Must(template.ParseFiles("templates/tables.html", "templates/variates.html"))
	router.SetHTMLTemplate(templates)

	// router.Static("/assets", "/Users/bohms/code/go/src/weather-tap/assets")
	router.Static("/assets", "./assets")

	router.GET("/tables", func(c *gin.Context) {
		tables(db, c)
	})
	router.GET("/tables/:id", func(c *gin.Context) {
		tablesById(db, c)
	})
	router.GET("/variates", func(c *gin.Context) {
		variates(db, c)
	})
	router.GET("/variates/:id", func(c *gin.Context) {
		variatesById(db, c)
	})
	router.GET("/day_observations.mawn", func(c *gin.Context) {
		day_observations(db, c)
	})
	router.GET("/hour_observations.mawn", func(c *gin.Context) {
		hour_observations(db, c)
	})
	router.GET("/five_minute_observations.mawn", func(c *gin.Context) {
		five_minute_observations(db, c)
	})
	router.GET("/five_minute_observations.js", func(c *gin.Context) {
		five_minute_observations_js(db, c)
	})
	router.GET("/five_minute_observations.xml", func(c *gin.Context) {
		five_minute_observations_xml(db, c)
	})

	return router
}

func main() {
	configFile, err := os.Open(".env")
	checkErr(err, "can't read .env file")

	u := User{}
	jsonParser := json.NewDecoder(configFile)
	if err = jsonParser.Decode(&u); err != nil {
		checkErr(err, "parsing config file")
	}

	connection := "user=" + u.Name + " password=" + u.Password + " dbname=metadata host=granby.kbs.msu.edu port=5432"
	// connection := "user=" + u.Name + " password=" + u.Password + " dbname=metadata host=127.0.0.1 port=5430"
	db, err := sqlx.Open("postgres", connection)
	checkErr(err, "sql.Open failed")
	defer db.Close()

	Router(db).Run(":9000")
}
<commit_msg>Revert "Revert "Revert "removed unnessary search path statements""" need to leave the search path in until i update all of the queries<commit_after>package main

import (
	"database/sql"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/jmoiron/sqlx"
	"github.com/joho/sqltocsv"
	_ "github.com/lib/pq"
	"html/template"
	"log"
	"os"
	"strconv"
	"time"
)

func CampbellTime(myTime time.Time) (int, int, int) {
	hourmin := myTime.Hour()*100 + myTime.Minute()
	doy := myTime.YearDay()
	if hourmin == 0 {
		hourmin = 2400
		doy = doy - 1
	}
	return myTime.Year(), doy, hourmin
}

type User struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

func checkErr(err error, msg string) {
	if err != nil {
		log.Fatalln(msg, err)
	}
}

type Datum struct {
	Time  time.Time `json:"time"`
	Value float64   `json:"value"`
}

type Variate struct {
	Id      int
	Title   string
	Y_label string
}

func variates(db *sqlx.DB, c *gin.Context) {
	var variates []Variate
	db.Select(&variates, "select id, title, y_label from weather.variates where updated is true")

	obj := gin.H{"variates": variates}
	c.HTML(200, "variates.html", obj)
}

func variatesById(db *sqlx.DB, c *gin.Context) {
	idString := c.Params.ByName("id")
	var query string
	db.Exec("set search_path=weather")
	id, err := strconv.Atoi(idString)
	if err == nil {
		var data = []Datum{}
		err = db.Get(&query, "select query from weather.variates where id = $1", id)
		if err == nil {
			db.Select(&data, query)
		}
		c.JSON(200, data)
	}
}

type Table struct {
	Id    int
	Name  string
	Query string
}

func tables(db *sqlx.DB, c *gin.Context) {
	db.Exec("set search_path=weather")
	var tables []Table
	db.Select(&tables, "select id, name from weather.tables")

	obj := gin.H{"tables": tables}
	c.HTML(200, "tables.html", obj)
}

func tablesById(db *sqlx.DB, c *gin.Context) {
	id := c.Params.ByName("id")
	var query Table
	db.Exec("set search_path=weather")
	err := db.Get(&query, "select id, name, query from weather.tables where id = $1", id)
	if err == nil {
		rows, _ := db.Query(query.Query)
		defer rows.Close()

		w := c.Writer
		w.Header().Set("Content-type", "text/csv")
		w.Header().Set("Content-Disposition", "attachment; filename=\""+query.Name+".csv\"")

		sqltocsv.Write(w, rows)
	}
}

func floatToString(value sql.NullFloat64) string {
	result := "nil"
	if value.Valid {
		result = strconv.FormatFloat(value.Float64, 'f', 5, 64)
	}
	return result
}

func intToString(value sql.NullInt64) string {
	result := "nil"
	if value.Valid {
		result = strconv.FormatInt(value.Int64, 10)
	}
	return result
}

func limit(c *gin.Context, limit int) int {
	query := c.Request.URL.Query()
	if query["limit"] != nil {
		value, err := strconv.Atoi(query["limit"][0])
		if err != nil {
			log.Fatal(err)
		}
		limit = value
	}
	return limit
}

func Router(db *sqlx.DB) *gin.Engine {
	router := gin.Default()
	templates := template.Must(template.ParseFiles("templates/tables.html", "templates/variates.html"))
	router.SetHTMLTemplate(templates)

	// router.Static("/assets", "/Users/bohms/code/go/src/weather-tap/assets")
	router.Static("/assets", "./assets")

	router.GET("/tables", func(c *gin.Context) {
		tables(db, c)
	})
	router.GET("/tables/:id", func(c *gin.Context) {
		tablesById(db, c)
	})
	router.GET("/variates", func(c *gin.Context) {
		variates(db, c)
	})
	router.GET("/variates/:id", func(c *gin.Context) {
		variatesById(db, c)
	})
	router.GET("/day_observations.mawn", func(c *gin.Context) {
		day_observations(db, c)
	})
	router.GET("/hour_observations.mawn", func(c *gin.Context) {
		hour_observations(db, c)
	})
	router.GET("/five_minute_observations.mawn", func(c *gin.Context) {
		five_minute_observations(db, c)
	})
	router.GET("/five_minute_observations.js", func(c *gin.Context) {
		five_minute_observations_js(db, c)
	})
	router.GET("/five_minute_observations.xml", func(c *gin.Context) {
		five_minute_observations_xml(db, c)
	})

	return router
}

func main() {
	configFile, err := os.Open(".env")
	checkErr(err, "can't read .env file")

	u := User{}
	jsonParser := json.NewDecoder(configFile)
	if err = jsonParser.Decode(&u); err != nil {
		checkErr(err, "parsing config file")
	}

	connection := "user=" + u.Name + " password=" + u.Password + " dbname=metadata host=granby.kbs.msu.edu port=5432"
	// connection := "user=" + u.Name + " password=" + u.Password + " dbname=metadata host=127.0.0.1 port=5430"
	db, err := sqlx.Open("postgres", connection)
	checkErr(err, "sql.Open failed")
	defer db.Close()

	Router(db).Run(":9000")
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
)

type slackResp struct {
	Text string
}

var (
	port     = ":8000"
	commands = map[string]slackResp{
		"ping":     slackResp{"PING FIVE! WHOO-PSH! SNAP!"},
		"betrayal": slackResp{"<https://www.youtube.com/watch?v=uw5P2up5bL4>"},
		"miracle":  slackResp{"<https://www.youtube.com/watch?v=uehf8e43Vtk>"},
		"meow":     slackResp{"<https://www.youtube.com/watch?v=xRhATB9NelU>"},
	}
	notFound = slackResp{"That command was bad and you should feel bad."}
	hookURL  = os.Getenv("SLACK_WEBHOOK_URL")
)

func handleHook(res http.ResponseWriter, req *http.Request) {
	client := &http.Client{}
	the_string := `{"text": "<https://www.youtube.com/watch?v=uehf8e43Vtk>"}`
	print(hookURL)
	req, err := http.NewRequest("POST", hookURL, bytes.NewBuffer([]byte(the_string)))
	req.Header.Add("Content-Type", "application/json")
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	print(resp.Status, resp.StatusCode)
}

func handleQuery(res http.ResponseWriter, req *http.Request) {
	res.Header().Set("Content-Type", "application/json")
	qMap := req.URL.Query()
	qVal := qMap["q"][0]
	if commands[qVal] != (slackResp{}) {
		data, err := json.Marshal(commands[qVal])
		if err != nil {
			log.Fatal(err)
		}
		io.WriteString(res, string(data))
	} else {
		data, err := json.Marshal(notFound)
		if err != nil {
			log.Fatal(err)
		}
		io.WriteString(res, string(data))
	}
}

func main() {
	fmt.Println("Server running listening on port", port)
	http.HandleFunc("/hook", handleHook)
	http.HandleFunc("/command", handleQuery)
	http.ListenAndServe(port, nil)
}
<commit_msg>Done. Going to write some tests.<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
)

var (
	port     = ":8000"
	commands = map[string]string{
		"ping":     `{"text": "PING FIVE! WHOO-PSH! SNAP!"}`,
		"betrayal": `{"text": "<https://www.youtube.com/watch?v=uw5P2up5bL4>"}`,
		"miracle":  `{"text": "<https://www.youtube.com/watch?v=uehf8e43Vtk>"}`,
		"meow":     `{"text": "<https://www.youtube.com/watch?v=xRhATB9NelU>"}`,
	}
	notFound = `{"text": "That command was bad and you should feel bad."}`
	hookURL  = os.Getenv("SLACK_WEBHOOK_URL")
)

func handleHook(res http.ResponseWriter, req *http.Request, val string) {
	client := &http.Client{}
	req, err := http.NewRequest("POST", hookURL, bytes.NewBuffer([]byte(val)))
	req.Header.Add("Content-Type", "application/json")
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("Status:", resp.Status)
}

func handleQuery(res http.ResponseWriter, req *http.Request) {
	res.Header().Set("Content-Type", "application/json")
	qMap := req.URL.Query()
	qVal := qMap["q"][0]
	if commands[qVal] != "" {
		handleHook(res, req, commands[qVal])
		io.WriteString(res, `{"status": "Valid Command"}`)
	} else {
		handleHook(res, req, notFound)
		io.WriteString(res, `{"status": "Invalid Command"}`)
	}
}

func main() {
	fmt.Println("Server running listening on port", port)
	http.HandleFunc("/command", handleQuery)
	http.ListenAndServe(port, nil)
}
<|endoftext|>


<commit_before>// Copyright (C) 2014 JT Olds, see provided LICENSE file

package main

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

	"github.com/SpaceMonkeyGo/flagfile"
	"github.com/jtolds/oom-watcher/watch"
)

var (
	cgroupPath = flag.String("cgroup", "", "Path to the cgroup to monitor, "+
		"e.g.: /sys/fs/cgroup/memory/mycgroup")
)

func main() {
	flagfile.Load()
	if *cgroupPath == "" || len(flag.Args()) == 0 {
		fmt.Printf("usage: %s --cgroup <path> -- <subprocess> [args...]\n",
			os.Args[0])
		os.Exit(1)
	}

	panic(watch.NewWatcher(*cgroupPath).Watch(func(count int64) {
		log.Printf("%d ooms detected, running %v %d times",
			count, flag.Args(), count)

		for i := int64(0); i < count; i++ {
			cmd := exec.Command(flag.Arg(0), flag.Args()[1:]...)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				log.Printf("failed running %v: %s", flag.Args(), err)
			}
		}
	}))
}
<commit_msg>fix the casing on the import path for flagfile<commit_after>// Copyright (C) 2014 JT Olds, see provided LICENSE file

package main

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

	"github.com/spacemonkeygo/flagfile"
	"github.com/jtolds/oom-watcher/watch"
)

var (
	cgroupPath = flag.String("cgroup", "", "Path to the cgroup to monitor, "+
		"e.g.: /sys/fs/cgroup/memory/mycgroup")
)

func main() {
	flagfile.Load()
	if *cgroupPath == "" || len(flag.Args()) == 0 {
		fmt.Printf("usage: %s --cgroup <path> -- <subprocess> [args...]\n",
			os.Args[0])
		os.Exit(1)
	}

	panic(watch.NewWatcher(*cgroupPath).Watch(func(count int64) {
		log.Printf("%d ooms detected, running %v %d times",
			count, flag.Args(), count)

		for i := int64(0); i < count; i++ {
			cmd := exec.Command(flag.Arg(0), flag.Args()[1:]...)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			err := cmd.Run()
			if err != nil {
				log.Printf("failed running %v: %s", flag.Args(), err)
			}
		}
	}))
}
<|endoftext|>


<commit_before>package strconv

import "unsafe"

const digits = "0123456789abcdefghijklmnopqrstuvwxyz"

func panicBuffer() {
	panic("strconv: buffer too short")
}

func panicBase() {
	panic("strconv: unsupported base")
}

func checkBase(base int) (int, bool) {
	move := false
	if base < 0 {
		base = -base
		move = true
	}
	if base < 2 || base > len(digits) {
		panicBase()
	}
	return base, move
}

func finish(buf []byte, n int, move bool) int {
	if n == len(buf) {
		if n == 0 {
			panicBuffer()
		}
		n--
		buf[n] = '0'
	}
	if n == 0 {
		return 0
	}
	i := 0
	end := n
	if move {
		i = copy(buf, buf[n:])
		end = len(buf)
		n = i
	}
	for i < end {
		buf[i] = ' '
		i++
	}
	return n
}

// FormatUint32 stores text representation of u in buf using 2 <= |base| <= 36.
// Unused portion of the buffer is filed with spaces. If base > 0 then formatted
// value is right-justified and FormatUint32 returns offset to its first char.
// If base < 0 then formatted value is left-justified and FormatUint32 returns
// its length.
func FormatUint32(buf []byte, u uint32, base int) int {
	base, move := checkBase(base)
	b := uint32(base)
	n := len(buf)
	for u != 0 {
		if n == 0 {
			panicBuffer()
		}
		n--
		newU := u / b
		buf[n] = digits[u-newU*b]
		u = newU
	}
	return finish(buf, n, move)
}

// FormatInt32 works like FormatUint32.
func FormatInt32(buf []byte, i int32, base int) int {
	if i >= 0 {
		return FormatUint32(buf, uint32(i), base)
	}
	if len(buf) < 2 {
		panicBuffer()
	}
	n := FormatUint32(buf[1:], uint32(-i), base)
	if base > 0 {
		buf[0] = ' '
		buf[n] = '-'
	} else {
		buf[0] = '-'
		n++
	}
	return n
}

// FormatUint64 works like FormatUint32
func FormatUint64(buf []byte, u uint64, base int) int {
	base, move := checkBase(base)
	b := uint64(base)
	n := len(buf)
	for u != 0 {
		if n == 0 {
			panicBuffer()
		}
		n--
		newU := u / b
		buf[n] = digits[u-newU*b]
		u = newU
	}
	return finish(buf, n, move)
}

// FormatInt64 works like FormatUint32.
func FormatInt64(buf []byte, i int64, base int) int {
	if i >= 0 {
		return FormatUint64(buf, uint64(i), base)
	}
	if len(buf) < 2 {
		panicBuffer()
	}
	n := FormatUint64(buf[1:], uint64(-i), base)
	if base > 0 {
		buf[0] = ' '
		buf[n] = '-'
	} else {
		buf[0] = '-'
		n++
	}
	return n
}

func FormatUint(buf []byte, u uint, base int) int {
	if unsafe.Sizeof(u) <= 4 {
		return FormatUint32(buf, uint32(u), base)
	}
	return FormatUint64(buf, uint64(u), base)
}

func FormatInt(buf []byte, i, base int) int {
	if unsafe.Sizeof(i) <= 4 {
		return FormatInt32(buf, int32(i), base)
	}
	return FormatInt64(buf, int64(i), base)
}
<commit_msg>strconv: Several simplifications.<commit_after>package strconv

import "unsafe"

const digits = "0123456789abcdefghijklmnopqrstuvwxyz"

func panicBuffer() {
	panic("strconv: buffer too short")
}

func fixBase(base int) int {
	if base < 0 {
		base = -base
	}
	if base < 2 || base > len(digits) {
		panic("strconv: unsupported base")
	}
	return base
}

func finish(buf []byte, n int, move bool) int {
	if n == len(buf) {
		if n == 0 {
			panicBuffer()
		}
		n--
		buf[n] = '0'
	}
	if n == 0 {
		return 0
	}
	i := 0
	end := n
	if move {
		i = copy(buf, buf[n:])
		end = len(buf)
		n = i
	}
	for i < end {
		buf[i] = ' '
		i++
	}
	return n
}

// FormatUint32 works like FormatInt.
func FormatUint32(buf []byte, u uint32, base int) int {
	b := uint32(fixBase(base))
	n := len(buf)
	for u != 0 {
		if n == 0 {
			panicBuffer()
		}
		n--
		newU := u / b
		buf[n] = digits[u-newU*b]
		u = newU
	}
	return finish(buf, n, base < 0)
}

// FormatInt32 works like FormatInt.
func FormatInt32(buf []byte, i int32, base int) int {
	if i >= 0 {
		return FormatUint32(buf, uint32(i), base)
	}
	if len(buf) < 2 {
		panicBuffer()
	}
	n := FormatUint32(buf[1:], uint32(-i), base)
	if base > 0 {
		buf[0] = ' '
		buf[n] = '-'
	} else {
		buf[0] = '-'
		n++
	}
	return n
}

// FormatUint64 works like FormatInt.
func FormatUint64(buf []byte, u uint64, base int) int {
	b := uint64(fixBase(base))
	n := len(buf)
	for u != 0 {
		if n == 0 {
			panicBuffer()
		}
		n--
		newU := u / b
		buf[n] = digits[u-newU*b]
		u = newU
	}
	return finish(buf, n, base < 0)
}

// FormatInt64 works like FormatInt.
func FormatInt64(buf []byte, i int64, base int) int {
	if i >= 0 {
		return FormatUint64(buf, uint64(i), base)
	}
	if len(buf) < 2 {
		panicBuffer()
	}
	n := FormatUint64(buf[1:], uint64(-i), base)
	if base > 0 {
		buf[0] = ' '
		buf[n] = '-'
	} else {
		buf[0] = '-'
		n++
	}
	return n
}

// FormatUint works like FormatInt.
func FormatUint(buf []byte, u uint, base int) int {
	if unsafe.Sizeof(u) <= 4 {
		return FormatUint32(buf, uint32(u), base)
	}
	return FormatUint64(buf, uint64(u), base)
}

// FormatInt stores text representation of u in buf using 2 <= |base| <= 36.
// Unused portion of the buffer is filed with spaces.
// If base > 0 then formatted value is right-justified and FormatInt returns
// offset to its first char. If base < 0 then formatted value is left-justified
// and FormatInt returns its length.
func FormatInt(buf []byte, i, base int) int {
	if unsafe.Sizeof(i) <= 4 {
		return FormatInt32(buf, int32(i), base)
	}
	return FormatInt64(buf, int64(i), base)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"strings"
)

type line struct {
	ip, hostname string
}

const filename = "/etc/hosts"

func containsPart(haystack, needle string) bool {
	return strings.Contains(haystack, "\t"+needle) || strings.Contains(haystack, needle+"\t")
}

func reverse(a []int) []int {
	for i := len(a)/2 - 1; i >= 0; i-- {
		opp := len(a) - 1 - i
		a[i], a[opp] = a[opp], a[i]
	}

	return a
}

func amIRoot() bool {
	cmd := exec.Command("whoami")
	user, err := cmd.Output()
	if err != nil {
		// couldn't determine root due to error, run anyway - the user won't be able
		// to mod anything without root rights anyway
		return true
	}

	return strings.TrimSpace(string(user)) == "root"
}

type hostlist struct {
	lines []string
}

func (hl *hostlist) Read(fn string) error {
	b, err := ioutil.ReadFile(fn)
	if err != nil {
		return err
	}

	hl.Parse(b)
	return nil
}

func (hl *hostlist) Parse(b []byte) {
	hl.lines = strings.Split(string(b), "\n")
}

func (hl *hostlist) Write(fn string) error {
	return ioutil.WriteFile(fn, hl.Bytes(), 0644)
}

func (hl *hostlist) Bytes() []byte {
	return []byte(strings.Join(hl.lines, "\n"))

func (hl *hostlist) Contains(a, b string) (bool, error) {
	var ip, hostname string

	if net.ParseIP(a) == nil && net.ParseIP(b) == nil {
		return false, fmt.Errorf("neither %s or %s is a valid IP address", a, b)
	}

	if net.ParseIP(a) == nil {
		hostname = a
		ip = b
	}

	for _, line := range hl.lines {
		if line == fmt.Sprintf("%s\t%s", ip, hostname) {
			return true, nil
		}
	}

	return false, nil
}

func (hl *hostlist) Add(a, b string) error {
	var ip, hostname string

	if net.ParseIP(a) == nil && net.ParseIP(b) == nil {
		return fmt.Errorf("neither %s or %s is a valid IP address", a, b)
	}

	if net.ParseIP(a) == nil {
		hostname = a
		ip = b
	}

	hl.lines = append(hl.lines, fmt.Sprintf("%s\t%s", ip, hostname))
	return nil
}

func (hl *hostlist) Remove(thing string) error {
	deletes := []int{}
	for i, line := range hl.lines {
		if containsPart(line, thing) {
			deletes = append(deletes, i)
		}
	}

	for _, i := range reverse(deletes) {
		hl.lines = append(hl.lines[:i], hl.lines[i+1:]...)
	}

	return nil
}

func (hl *hostlist) Comment(thing string) error {
	for i, line := range hl.lines {
		if containsPart(line, thing) {
			hl.lines[i] = "#" + line
		}
	}

	return nil
}

func (hl *hostlist) Uncomment(thing string) error {
	for i, line := range hl.lines {
		if containsPart(line, thing) {
			hl.lines[i] = strings.TrimLeft(line, "#")
		}
	}

	return nil
}

func main() {
	log.SetFlags(0)

	if !amIRoot() {
		log.Fatal("Please run this program as Root!")
	}

	if len(os.Args) <= 1 {
		log.Fatal("Nothing to do, please specify command")
	}

	hosts := hostlist{}
	hosts.Read(filename)

	command := string(os.Args[1])

	// fmt.Println(command)
	switch command {
	default:
		log.Fatalf("Unknown command: %s", command)

	case "list", "ls":
		fmt.Println(string(hosts.Bytes()))

	case "del", "rm", "-":
		if len(os.Args) != 3 {
			log.Fatal("Please give an IP or hostname to delete")
		}
		hosts.Remove(os.Args[2])

	case "ucom":
		if len(os.Args) != 3 {
			log.Fatal("Please give an IP or hostname to uncomment")
		}
		hosts.Uncomment(os.Args[2])

	case "com":
		if len(os.Args) != 3 {
			log.Fatal("Please give an IP or hostname to comment out")
		}
		hosts.Comment(os.Args[2])

	case "add", "+":
		if len(os.Args) != 4 {
			log.Fatal("Please give arguments in the form ip, hostname")
		}
		err := hosts.Add(os.Args[2], os.Args[3])
		if err != nil {
			log.Fatal(err)
		}

	case "has", "?", "contains":
		if len(os.Args) != 4 {
			log.Fatal("Please give arguments in the form ip, hostname")
		}

		yes, err := hosts.Contains(os.Args[2], os.Args[3])
		if err != nil {
			log.Fatal(err)
		}

		if yes {
			os.Exit(0) // exit code 0 means it was contained within
		}

		os.Exit(1) // exit code 1 means not contained within

	}

	hosts.Write(filename)
}
<commit_msg>add change tracking<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net"
	"os"
	"os/exec"
	"strings"
)

type line struct {
	ip, hostname string
}

const filename = "/etc/hosts"

func containsPart(haystack, needle string) bool {
	return strings.Contains(haystack, "\t"+needle) || strings.Contains(haystack, needle+"\t")
}

func reverse(a []int) []int {
	for i := len(a)/2 - 1; i >= 0; i-- {
		opp := len(a) - 1 - i
		a[i], a[opp] = a[opp], a[i]
	}

	return a
}

func amIRoot() bool {
	cmd := exec.Command("whoami")
	user, err := cmd.Output()
	if err != nil {
		// couldn't determine root due to error, run anyway - the user won't be able
		// to mod anything without root rights anyway
		return true
	}

	return strings.TrimSpace(string(user)) == "root"
}

type hostlist struct {
	lines   []string
	changed bool
}

func (hl *hostlist) Read(fn string) error {
	b, err := ioutil.ReadFile(fn)
	if err != nil {
		return err
	}

	hl.Parse(b)
	return nil
}

func (hl *hostlist) Parse(b []byte) {
	hl.lines = strings.Split(string(b), "\n")
}

func (hl *hostlist) Write(fn string) error {
	return ioutil.WriteFile(fn, hl.Bytes(), 0644)
}

func (hl *hostlist) Bytes() []byte {
	return []byte(strings.Join(hl.lines, "\n"))

func (hl *hostlist) Contains(a, b string) (bool, error) {
	var ip, hostname string

	if net.ParseIP(a) == nil && net.ParseIP(b) == nil {
		return false, fmt.Errorf("neither %s or %s is a valid IP address", a, b)
	}

	if net.ParseIP(a) == nil {
		hostname = a
		ip = b
	}

	for _, line := range hl.lines {
		if line == fmt.Sprintf("%s\t%s", ip, hostname) {
			return true, nil
		}
	}

	return false, nil
}

func (hl *hostlist) Add(a, b string) error {
	var ip, hostname string

	if net.ParseIP(a) == nil && net.ParseIP(b) == nil {
		return fmt.Errorf("neither %s or %s is a valid IP address", a, b)
	}

	if net.ParseIP(a) == nil {
		hostname = a
		ip = b
	}

	hl.lines = append(hl.lines, fmt.Sprintf("%s\t%s", ip, hostname))
	hl.changed = true
	return nil
}

func (hl *hostlist) Remove(thing string) error {
	deletes := []int{}
	for i, line := range hl.lines {
		if containsPart(line, thing) {
			deletes = append(deletes, i)
		}
	}

	for _, i := range reverse(deletes) {
		hl.lines = append(hl.lines[:i], hl.lines[i+1:]...)
	}

	hl.changed = true
	return nil
}

func (hl *hostlist) Comment(thing string) error {
	for i, line := range hl.lines {
		if containsPart(line, thing) {
			hl.lines[i] = "#" + line
		}
	}

	hl.changed = true
	return nil
}

func (hl *hostlist) Uncomment(thing string) error {
	for i, line := range hl.lines {
		if containsPart(line, thing) {
			hl.lines[i] = strings.TrimLeft(line, "#")
		}
	}

	hl.changed = true
	return nil
}

func main() {
	log.SetFlags(0)

	if !amIRoot() {
		log.Fatal("Please run this program as Root!")
	}

	if len(os.Args) <= 1 {
		log.Fatal("Nothing to do, please specify command")
	}

	hosts := hostlist{}
	hosts.Read(filename)

	command := string(os.Args[1])

	// fmt.Println(command)
	switch command {
	default:
		log.Fatalf("Unknown command: %s", command)

	case "list", "ls":
		fmt.Println(string(hosts.Bytes()))

	case "del", "rm", "-":
		if len(os.Args) != 3 {
			log.Fatal("Please give an IP or hostname to delete")
		}
		hosts.Remove(os.Args[2])

	case "ucom":
		if len(os.Args) != 3 {
			log.Fatal("Please give an IP or hostname to uncomment")
		}
		hosts.Uncomment(os.Args[2])

	case "com":
		if len(os.Args) != 3 {
			log.Fatal("Please give an IP or hostname to comment out")
		}
		hosts.Comment(os.Args[2])

	case "add", "+":
		if len(os.Args) != 4 {
			log.Fatal("Please give arguments in the form ip, hostname")
		}
		err := hosts.Add(os.Args[2], os.Args[3])
		if err != nil {
			log.Fatal(err)
		}

	case "has", "?", "contains":
		if len(os.Args) != 4 {
			log.Fatal("Please give arguments in the form ip, hostname")
		}

		yes, err := hosts.Contains(os.Args[2], os.Args[3])
		if err != nil {
			log.Fatal(err)
		}

		if yes {
			os.Exit(0) // exit code 0 means it was contained within
		}

		os.Exit(1) // exit code 1 means not contained within

	}

	if hosts.changed {
		log.Printf("writing changes to %s", filename)
		hosts.Write(filename)
	}
}
<|endoftext|>


<commit_before>/*
Hound is a Git plugin that helps prevent sensitive data from being committed
into a repository by sniffing potential commits against regular expressions
*/
package main

import (
	"flag"
	"fmt"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/github.com/fatih/color"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff"
	"os"
)

var (
	noColor = flag.Bool("no-color", false, "Disable color output")
	config  = flag.String("config", ".githound.yml", "Hound config file")
	bin     = flag.String("bin", "git", "Executable binary to use for git command")
)

func main() {
	flag.Parse()

	if *noColor {
		color.NoColor = true
	}

	hound := &Hound{Config: *config}
	git := &Command{Bin: *bin}

	if ok := hound.New(); ok {
		out, _ := git.Exec("diff", "-U0", "--staged")
		fileDiffs, err := diff.ParseMultiFileDiff([]byte(out))
		if err != nil {
			fmt.Print(err)
			os.Exit(1)
		}

		hunkCount := 0
		warnc := make(chan string)
		failc := make(chan error)
		donec := make(chan bool)

		for _, fileDiff := range fileDiffs {
			fileName := fileDiff.NewName
			hunks := fileDiff.GetHunks()

			for _, hunk := range hunks {
				go hound.Sniff(fileName, hunk, warnc, failc, donec)
				hunkCount++
			}
		}

		for c := 0; c < hunkCount; {
			select {
			case msg := <-warnc:
				fmt.Print(msg)
			case err := <-failc:
				fmt.Print(err)
				os.Exit(1)
			case <-donec:
				c++
			}
		}
	}

	out, code := git.Exec(flag.Args()...)
	fmt.Print(out)
	os.Exit(code)
}
<commit_msg>update package comment to follow convention<commit_after>/*
Command git-hound is a Git plugin that helps prevent sensitive data from being committed
into a repository by sniffing potential commits against regular expressions
*/
package main

import (
	"flag"
	"fmt"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/github.com/fatih/color"
	"github.com/ezekg/git-hound/Godeps/_workspace/src/sourcegraph.com/sourcegraph/go-diff/diff"
	"os"
)

var (
	noColor = flag.Bool("no-color", false, "Disable color output")
	config  = flag.String("config", ".githound.yml", "Hound config file")
	bin     = flag.String("bin", "git", "Executable binary to use for git command")
)

func main() {
	flag.Parse()

	if *noColor {
		color.NoColor = true
	}

	hound := &Hound{Config: *config}
	git := &Command{Bin: *bin}

	if ok := hound.New(); ok {
		out, _ := git.Exec("diff", "-U0", "--staged")
		fileDiffs, err := diff.ParseMultiFileDiff([]byte(out))
		if err != nil {
			fmt.Print(err)
			os.Exit(1)
		}

		hunkCount := 0
		warnc := make(chan string)
		failc := make(chan error)
		donec := make(chan bool)

		for _, fileDiff := range fileDiffs {
			fileName := fileDiff.NewName
			hunks := fileDiff.GetHunks()

			for _, hunk := range hunks {
				go hound.Sniff(fileName, hunk, warnc, failc, donec)
				hunkCount++
			}
		}

		for c := 0; c < hunkCount; {
			select {
			case msg := <-warnc:
				fmt.Print(msg)
			case err := <-failc:
				fmt.Print(err)
				os.Exit(1)
			case <-donec:
				c++
			}
		}
	}

	out, code := git.Exec(flag.Args()...)
	fmt.Print(out)
	os.Exit(code)
}
<|endoftext|>


<commit_before>// THTML is a static website generator based on text/template package.
//
// Includes a development webserver to help creating HTML websites and components
// compiling the templates on the fight, allowing a edit-save-refresh development process.
//
// Usage:
//		thtml [OPTIONS] [COMMAND]
//
// [COMMAND] can be the following:
//
//		-build
//			Build the assets from the [-public] directory to the [-output] directory by parsing the [-templates] directory.
//  	-run
//			Run development webserver listening to [-listen] to build pages on-the-fly.
//
// [OPTIONS] are:
//
//  	-exts string
// 	    	Provides a comma separated filename extensions list to support when parsing templates. (default ".thtml,.html,.css,.js")
//
//  	-listen string
// 	 		Run the dev server listening on the provided host:port. (default ":5500")
//
//  	-minify
// 	  		Minify the build output. (default true)
//
//  	-output string
// 	  		Sets the path for the build output. (default "build")
//
//  	-public string
// 	  		Sets the path for the web root. (default "public")
//
//		- templates string
// 	  		Sets the path for the template files. (default "templates")
//
//
//
// Getting started:
//
// By running `thtml -run` on a directory, the tool will use the default options that assume the following directory structure:
//
//		./public
//		./templates
//		./build
//
// The `public` directory and all its sub-directories will contain the source files for the template website structure,
// including assets that have to be included during the static website compilation.
// It works as the "web root" directory of the development webserver and contains the desired final structure.
//
// The `templates` directory and all its sub-directories is where all the reusable templates have to be placed
// so they can be used from the pages in the `public` directory and from other templates.
//
// The `build` directory will be used to write the output of the static website compilation and then deploy it.
//
// Check the `_example` directory on the repository to see a simple layout: https://github.com/leonelquinteros/thtml/tree/master/_example
//
// After creating the website using the development webserver, it can be built running `thtml -build`
// and the content of the `build` directory can be deployed to any static web server on production.
//
//
//
// Template syntax:
//
// THTML uses pure Go's text/template package to render the templates together.
// Check the package documentation for details about the syntax: https://golang.org/pkg/text/template/
//
package main

import (
	"flag"
	"fmt"
	"os"
)

// Configuration options
var (
	// -public /path/to/public/dir
	_publicPath string

	// -templates /path/to/templates/dir
	_templatesPath string

	// -build
	_build bool

	// -output
	_outputPath string

	// -run
	_run bool

	// -listen ":5500"
	_httpListen string

	// -minify
	_minify bool

	// -exts .html,.css,.js
	_exts string
)

func init() {
	// Parse config flags
	flag.BoolVar(&_run, "run", false, "Run a dev web server serving the public directory.")
	flag.BoolVar(&_build, "build", false, "Build the assets from the -public directory to the -output directory by parsing the -templates directory.")
	flag.BoolVar(&_minify, "minify", true, "Minify the build output.")
	flag.StringVar(&_publicPath, "public", "public", "Sets the path for the web root.")
	flag.StringVar(&_templatesPath, "templates", "templates", "Sets the path for the template files.")
	flag.StringVar(&_httpListen, "listen", ":5500", "Run the dev server listening on the provided host:port.")
	flag.StringVar(&_outputPath, "output", "build", "Sets the path for the build output.")
	flag.StringVar(&_exts, "exts", ".thtml,.html,.css,.js", "Provides a comma separated filename extensions list to support when parsing templates.")
}

func main() {
	flag.Parse()

	if !_run && !_build {
		fmt.Println("")
		fmt.Println("Run:")
		fmt.Println("     ", os.Args[0], "-h")
		fmt.Println("")
		fmt.Println("To view help")
		fmt.Println("")
		return
	}

	// Build first
	if _build {
		build()
	}

	// Run
	if _run {
		runServer()
	}
}
<commit_msg>Format comments<commit_after>// THTML is a static website generator based on text/template package.
//
// Includes a development webserver to help creating HTML websites and components
// compiling the templates on the fight, allowing a edit-save-refresh development process.
//
// Usage:
//		thtml [OPTIONS] [COMMAND]
//
// [COMMAND] can be the following:
//
//	    -build
//	        Build the assets from the [-public] directory to the [-output] directory by parsing the [-templates] directory.
//
//      -run
//	        Run development webserver listening to [-listen] to build pages on-the-fly.
//
// [OPTIONS] are:
//
//      -exts string
// 	        Provides a comma separated filename extensions list to support when parsing templates. (default ".thtml,.html,.css,.js")
//
//      -listen string
// 	        Run the dev server listening on the provided host:port. (default ":5500")
//
//      -minify
// 	        Minify the build output. (default true)
//
//      -output string
// 	        Sets the path for the build output. (default "build")
//
//      -public string
// 	        Sets the path for the web root. (default "public")
//
//      - templates string
// 	        Sets the path for the template files. (default "templates")
//
//
//
// Getting started:
//
// By running `thtml -run` on a directory, the tool will use the default options that assume the following directory structure:
//
//		./public
//		./templates
//		./build
//
// The `public` directory and all its sub-directories will contain the source files for the template website structure,
// including assets that have to be included during the static website compilation.
// It works as the "web root" directory of the development webserver and contains the desired final structure.
//
// The `templates` directory and all its sub-directories is where all the reusable templates have to be placed
// so they can be used from the pages in the `public` directory and from other templates.
//
// The `build` directory will be used to write the output of the static website compilation and then deploy it.
//
// Check the `_example` directory on the repository to see a simple layout: https://github.com/leonelquinteros/thtml/tree/master/_example
//
// After creating the website using the development webserver, it can be built running `thtml -build`
// and the content of the `build` directory can be deployed to any static web server on production.
//
//
//
// Template syntax:
//
// THTML uses pure Go's text/template package to render the templates together.
// Check the package documentation for details about the syntax: https://golang.org/pkg/text/template/
//
package main

import (
	"flag"
	"fmt"
	"os"
)

// Configuration options
var (
	// -public /path/to/public/dir
	_publicPath string

	// -templates /path/to/templates/dir
	_templatesPath string

	// -build
	_build bool

	// -output
	_outputPath string

	// -run
	_run bool

	// -listen ":5500"
	_httpListen string

	// -minify
	_minify bool

	// -exts .html,.css,.js
	_exts string
)

func init() {
	// Parse config flags
	flag.BoolVar(&_run, "run", false, "Run a dev web server serving the public directory.")
	flag.BoolVar(&_build, "build", false, "Build the assets from the -public directory to the -output directory by parsing the -templates directory.")
	flag.BoolVar(&_minify, "minify", true, "Minify the build output.")
	flag.StringVar(&_publicPath, "public", "public", "Sets the path for the web root.")
	flag.StringVar(&_templatesPath, "templates", "templates", "Sets the path for the template files.")
	flag.StringVar(&_httpListen, "listen", ":5500", "Run the dev server listening on the provided host:port.")
	flag.StringVar(&_outputPath, "output", "build", "Sets the path for the build output.")
	flag.StringVar(&_exts, "exts", ".thtml,.html,.css,.js", "Provides a comma separated filename extensions list to support when parsing templates.")
}

func main() {
	flag.Parse()

	if !_run && !_build {
		fmt.Println("")
		fmt.Println("Run:")
		fmt.Println("     ", os.Args[0], "-h")
		fmt.Println("")
		fmt.Println("To view help")
		fmt.Println("")
		return
	}

	// Build first
	if _build {
		build()
	}

	// Run
	if _run {
		runServer()
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/gob"
	"fmt"
	"html/template"
	"log"
	"net/http"

	"github.com/gorilla/sessions"
	"github.com/qbit/dnews/src"
)

var store = sessions.NewCookieStore([]byte("something-very-secret"))

func getArticles(w http.ResponseWriter, r *http.Request) {

}

func handler(w http.ResponseWriter, r *http.Request) {
	a := dnews.Articles{}
	fmt.Fprintf(w, "Hi there, I love %s! %v", r.URL.Path[1:], a)
}

var funcMap = template.FuncMap{
	"formatDate": dnews.FormatDate,
	"printHTML": func(b []byte) template.HTML {
		return template.HTML(string(b))
	},
}

var templ, err = template.New("dnews").Funcs(funcMap).ParseGlob("templates/*.html")

func init() {
	gob.Register(&dnews.User{})
}

func main() {
	fs := http.FileServer(http.Dir("public"))
	http.Handle("/public/", http.StripPrefix("/public/", fs))
	http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		session, err := store.Get(r, "session-name")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		user := r.FormValue("user")
		passwd := r.FormValue("passwd")

		if user == "" && passwd == "" {
			err = templ.ExecuteTemplate(w, "login.html", nil)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		} else {
			// do auth
			u, err := dnews.Auth(user, passwd)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			if u.Authed {
				session.Values["user"] = u
				session.Save(r, w)
				http.Redirect(w, r, "/", http.StatusFound)
			} else {
				log.Printf("Invalid user: %s", user)
				err = templ.ExecuteTemplate(w, "login.html", struct {
					Error string
				}{
					"Invalid User!",
				})
				if err != nil {
					http.Error(w, err.Error(), http.StatusInternalServerError)
					return
				}
			}
		}
	})
	http.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) {
		session, err := store.Get(r, "session-name")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		session.Options = &sessions.Options{
			MaxAge: -1,
		}
		session.Save(r, w)
		http.Redirect(w, r, "/", http.StatusFound)

	})
	http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "NO!", http.StatusNotFound)
		return
	})
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		session, err := store.Get(r, "session-name")

		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		a, err := dnews.GetNArticles(10)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		val := session.Values["user"]
		if _, ok := val.(*dnews.User); !ok {
			val = &dnews.User{}
			session.Values["user"] = &val
			session.Save(r, w)
		}

		data := struct {
			Articles *dnews.Articles
			// we did a type check above, but it would be nice to
			// be able to use the actual type when sending to the
			// templating stuffs :(
			User interface{}
		}{
			&a,
			&val,
		}

		err = templ.ExecuteTemplate(w, "index.html", data)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	})

	http.ListenAndServe(":8080", nil)
}
<commit_msg>use mux, add a few handlers<commit_after>package main

import (
	"encoding/gob"
	"fmt"
	"html/template"
	"log"
	"net/http"
	"strconv"

	"github.com/gorilla/mux"
	"github.com/gorilla/sessions"
	"github.com/qbit/dnews/src"
)

var store = sessions.NewCookieStore([]byte("something-very-secret"))

func getArticles(w http.ResponseWriter, r *http.Request) {

}

func handler(w http.ResponseWriter, r *http.Request) {
	a := dnews.Articles{}
	fmt.Fprintf(w, "Hi there, I love %s! %v", r.URL.Path[1:], a)
}

var funcMap = template.FuncMap{
	"formatDate": dnews.FormatDate,
	"printHTML": func(b []byte) template.HTML {
		return template.HTML(string(b))
	},
}

var templ, err = template.New("dnews").Funcs(funcMap).ParseGlob("templates/*.html")

func init() {
	gob.Register(&dnews.User{})
}

func main() {
	r := mux.NewRouter()
	fs := http.FileServer(http.Dir("public"))
	http.Handle("/public/", http.StripPrefix("/public/", fs))
	r.HandleFunc("/article/raw/{id:[0-9]+}", func(w http.ResponseWriter, r *http.Request) {
		vars := mux.Vars(r)
		id, err := strconv.Atoi(vars["id"])
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		article, err := dnews.GetRawArticle(id)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		fmt.Fprintf(w, "%s", article.Body)
	})
	r.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		session, err := store.Get(r, "session-name")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		user := r.FormValue("user")
		passwd := r.FormValue("passwd")

		if user == "" && passwd == "" {
			err = templ.ExecuteTemplate(w, "login.html", nil)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
		} else {
			// do auth
			u, err := dnews.Auth(user, passwd)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			if u.Authed {
				session.Values["user"] = u
				session.Save(r, w)
				http.Redirect(w, r, "/", http.StatusFound)
			} else {
				log.Printf("Invalid user: %s", user)
				err = templ.ExecuteTemplate(w, "login.html", struct {
					Error string
				}{
					"Invalid User!",
				})
				if err != nil {
					http.Error(w, err.Error(), http.StatusInternalServerError)
					return
				}
			}
		}
	})
	r.HandleFunc("/logout", func(w http.ResponseWriter, r *http.Request) {
		session, err := store.Get(r, "session-name")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		session.Options = &sessions.Options{
			MaxAge: -1,
		}
		session.Save(r, w)
		http.Redirect(w, r, "/", http.StatusFound)

	})
	r.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
		http.Error(w, "NO!", http.StatusNotFound)
		return
	})
	r.HandleFunc("/advocacy", func(w http.ResponseWriter, r *http.Request) {
		session, err := store.Get(r, "session-name")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		val := session.Values["user"]
		if _, ok := val.(*dnews.User); !ok {
			val = &dnews.User{}
			session.Values["user"] = &val
			session.Save(r, w)
		}

		data := struct {
			User interface{}
		}{
			&val,
		}

		err = templ.ExecuteTemplate(w, "advocacy.html", data)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	})
	r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		session, err := store.Get(r, "session-name")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		val := session.Values["user"]
		if _, ok := val.(*dnews.User); !ok {
			val = &dnews.User{}
			session.Values["user"] = &val
			session.Save(r, w)
		}

		a, err := dnews.GetNArticles(10)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		data := struct {
			Articles *dnews.Articles
			// we did a type check above, but it would be nice to
			// be able to use the actual type when sending to the
			// templating stuffs :(
			User interface{}
		}{
			&a,
			&val,
		}

		err = templ.ExecuteTemplate(w, "index.html", data)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	})

	http.Handle("/", r)
	http.ListenAndServe(":8080", nil)
}
<|endoftext|>


<commit_before>package main

import (
	//"bytes"
	//"compress/gzip"
	//"io"
	log "github.com/Sirupsen/logrus"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/defaults"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
	"github.com/codegangsta/cli"
	"github.com/mitchellh/go-homedir"

	"github.com/asimihsan/arqinator/arq"
	//"github.com/asimihsan/arqinator/arq/types"
	"github.com/asimihsan/arqinator/connector"
	"errors"
	"fmt"
	"runtime"
)

func cliSetup(c *cli.Context) error {
	if c.GlobalString("backup-type") != "s3" {
		return errors.New("Currently only support backup-type of 's3'")
	}
	if c.GlobalBool("verbose") {
		log.SetLevel(log.DebugLevel)
	}
	return nil
}

func awsSetup(c *cli.Context) (*connector.S3Connection, error) {
	region := c.GlobalString("s3-region")
	cacheDirectory := c.GlobalString("cache-directory")

	defaults.DefaultConfig.Region = aws.String(region)
	svc := s3.New(nil)
	opts := &s3manager.DownloadOptions{
		S3: svc,
		Concurrency: runtime.GOMAXPROCS(0)}
	s3Connection := connector.NewS3Connection(svc, cacheDirectory, opts)
	return s3Connection, nil
}

func listBackupSets(c *cli.Context, s3Connection *connector.S3Connection) error {
	s3BucketName := c.GlobalString("s3-bucket-name")
	password := []byte(os.Getenv("ARQ_ENCRYPTION_PASSWORD"))

	arqBackupSets, err := arq.GetArqBackupSets(s3BucketName, s3Connection, password)
	if err != nil {
		log.Debugf("Error during awsSetup GetArqBackupSets: %s", err)
		return err
	}
	for _, arqBackupSet := range arqBackupSets {
		fmt.Printf("ArqBackupSet\n")
		fmt.Printf("    UUID %s\n", arqBackupSet.Uuid)
		fmt.Printf("    ComputerName %s\n", arqBackupSet.ComputerInfo.ComputerName)
		fmt.Printf("    UserName %s\n", arqBackupSet.ComputerInfo.UserName)
		fmt.Printf("    Folders\n")
		for _, bucket := range arqBackupSet.Buckets {
			fmt.Printf("        LocalPath %s\n", bucket.LocalPath)
			fmt.Printf("        UUID %s\n", bucket.UUID)
		}
	}

	return nil
	//abs, _ := arq.NewArqBackupSet(s3BucketName, s3Connection, arqBackupSetUuid, password)
	//log.Debugln("ArqBackupSet: ", abs)
	//abs.CacheTreePackSets()
}

func main() {
	defaultCacheDirectory, err := homedir.Expand("~/.arqinator_cache")
	if err != nil {
		log.Fatal("Failed to get user's home dir: ", err)
	}

	app := cli.NewApp()
	app.Name = "arqinator"
	app.Usage = "restore folders and files from Arq backups"
	app.Version = "0.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "backup-type",
			Usage: "Method used for backup, e.g. 's3'.",
		},
		cli.StringFlag{
			Name:  "s3-region",
			Usage: "AWS S3 region, e.g. 'us-west-2'.",
		},
		cli.StringFlag{
			Name:  "s3-bucket-name",
			Usage: "AWS S3 bucket name, e.g. 'arq-akiaabdefg-us-west-2'.",
		},
		cli.StringFlag{
			Name:  "cache-directory",
			Value: defaultCacheDirectory,
			Usage: fmt.Sprintf("Where to cache Arq files for browsing. Default: %s", defaultCacheDirectory),
		},
		cli.BoolFlag{
			Name:  "delete-cache-directory",
			Usage: "Delete cache directory before starting. Useful if seeing errors that could be due to truncated downloads.",
		},
		cli.BoolFlag{
			Name: "verbose",
			Usage: "Enable verbose logging",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "list-backup-sets",
			Usage: "List backup sets in this account.",
			Action: func(c *cli.Context) {
				if err := cliSetup(c); err != nil {
					log.Debugf("%s", err)
					return
				}
				s3Connection, err := awsSetup(c)
				if err != nil {
					log.Debugf("%s", err)
					return
				}
				if err := listBackupSets(c, s3Connection); err != nil {
					log.Debugf("%s", err)
					return
				}
			},
		},
		{
			Name: "list-directory-contents",
			Usage: "List contents of directory in backup.",
			Action: func(c *cli.Context) {
				if err := cliSetup(c); err != nil {
					log.Debugf("%s", err)
					return
				}
				s3Connection, err := awsSetup(c)
				if err != nil {
					log.Debugf("%s", err)
					return
				}
				if err := listBackupSets(c, s3Connection); err != nil {
					log.Debugf("%s", err)
					return
				}
			}
		},
	}
	app.Run(os.Args)

	/*
		defaults.DefaultConfig.Region = aws.String("us-west-2")
		svc := s3.New(nil)
		opts := &s3manager.DownloadOptions{S3: svc, Concurrency: 4}
		s3BucketName := "arq-akiajmthnhpkz2ixzrxq-us-west-2"
		arqBackupSetUuid := "98DB38F8-B9C6-4296-9385-3C1BF858ED5D"
		cacheDirectory, err := homedir.Expand("~/.arqinator_cache")
		if err != nil {
			log.Fatal("Failed to get user's home dir: ", err)
		}
		password := []byte(os.Getenv("ARQ_ENCRYPTION_PASSWORD"))

		s3Connection := connector.NewS3Connection(svc, cacheDirectory, opts)
		abs, _ := arq.NewArqBackupSet(s3BucketName, s3Connection, arqBackupSetUuid, password)
		log.Debugln("ArqBackupSet: ", abs)
		abs.CacheTreePackSets()

		ab := abs.Buckets[0]
		apsi, _ := arq.NewPackSetIndex(cacheDirectory, abs, ab)
		pf, _ := apsi.GetPackFile(abs, ab, ab.HeadSHA1)
		commit, err := arq_types.ReadCommit(bytes.NewBuffer(pf))
		if err != nil {
			log.Debugf("failed to parse commit: %s", err)
		}
		log.Debugf("commit: %s", commit)

		log.Debugf("get tree_packfile...")
		tree_packfile, _ := apsi.GetPackFile(abs, ab, *commit.TreeBlobKey.SHA1)
		if err != nil {
			log.Debugf("failed to get tree blob: %s", err)
		}
		log.Debugf("finished getting tree_packfile.")
		log.Debugf("decompress tree_packfile...")
		if commit.TreeBlobKey.IsCompressed.IsTrue() {
			var b bytes.Buffer
			r, _ := gzip.NewReader(bytes.NewBuffer(tree_packfile))
			io.Copy(&b, r)
			r.Close()
			tree_packfile = b.Bytes()
		}
		log.Debugf("finished decompressing tree_packfile.")

		log.Debugf("get tree...")
		tree, err := arq_types.ReadTree(bytes.NewBuffer(tree_packfile))
		if err != nil {
			log.Debugf("failed to get tree: %s", err)
		}
		log.Debugf("finished getting tree.")
		log.Debugf("tree: %s", tree)
	*/
}
<commit_msg>working on listing directory contents of backup<commit_after>package main

import (
	"bytes"
	"compress/gzip"
	"io"
	log "github.com/Sirupsen/logrus"
	"os"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/defaults"
	"github.com/aws/aws-sdk-go/service/s3"
	"github.com/aws/aws-sdk-go/service/s3/s3manager"
	"github.com/codegangsta/cli"
	"github.com/mitchellh/go-homedir"

	"github.com/asimihsan/arqinator/arq"
	"github.com/asimihsan/arqinator/connector"
	"errors"
	"fmt"
	"runtime"
	"github.com/asimihsan/arqinator/arq/types"
)

func cliSetup(c *cli.Context) error {
	if c.GlobalString("backup-type") != "s3" {
		return errors.New("Currently only support backup-type of 's3'")
	}
	if c.GlobalBool("verbose") {
		log.SetLevel(log.DebugLevel)
	}
	return nil
}

func awsSetup(c *cli.Context) (*connector.S3Connection, error) {
	region := c.GlobalString("s3-region")
	cacheDirectory := c.GlobalString("cache-directory")

	defaults.DefaultConfig.Region = aws.String(region)
	svc := s3.New(nil)
	opts := &s3manager.DownloadOptions{
		S3: svc,
		Concurrency: runtime.GOMAXPROCS(0)}
	s3Connection := connector.NewS3Connection(svc, cacheDirectory, opts)
	return s3Connection, nil
}

func getArqBackupSets(c *cli.Context, s3Connection *connector.S3Connection) ([]*arq.ArqBackupSet, error) {
	s3BucketName := c.GlobalString("s3-bucket-name")
	password := []byte(os.Getenv("ARQ_ENCRYPTION_PASSWORD"))

	arqBackupSets, err := arq.GetArqBackupSets(s3BucketName, s3Connection, password)
	if err != nil {
		log.Debugf("Error during getArqBackupSets: %s", err)
		return nil, err
	}
	return arqBackupSets, nil
}

func listBackupSets(c *cli.Context, s3Connection *connector.S3Connection) error {
	arqBackupSets, err := getArqBackupSets(c, s3Connection)
	if err != nil {
		log.Debugf("Error during listBackupSets: %s", err)
		return nil
	}
	for _, arqBackupSet := range arqBackupSets {
		fmt.Printf("ArqBackupSet\n")
		fmt.Printf("    UUID %s\n", arqBackupSet.Uuid)
		fmt.Printf("    ComputerName %s\n", arqBackupSet.ComputerInfo.ComputerName)
		fmt.Printf("    UserName %s\n", arqBackupSet.ComputerInfo.UserName)
		fmt.Printf("    Folders\n")
		for _, bucket := range arqBackupSet.Buckets {
			fmt.Printf("        LocalPath %s\n", bucket.LocalPath)
			fmt.Printf("        UUID %s\n", bucket.UUID)
		}
	}

	return nil
	//abs, _ := arq.NewArqBackupSet(s3BucketName, s3Connection, arqBackupSetUuid, password)
	//log.Debugln("ArqBackupSet: ", abs)
	//abs.CacheTreePackSets()
}

func listDirectoryContents(c *cli.Context, s3Connection *connector.S3Connection) error {
	cacheDirectory := c.GlobalString("cache-directory")
	backupSetUuid := c.String("backup-set-uuid")
	folderUuid := c.String("folder-uuid")

	arqBackupSets, err := getArqBackupSets(c, s3Connection)
	if err != nil {
		log.Debugf("Error during listBackupSets: %s", err)
		return nil
	}
	var bucket *arq.ArqBucket
	for _, arqBackupSet := range arqBackupSets {
		if arqBackupSet.Uuid == backupSetUuid {
			for _, folder := range arqBackupSet.Buckets {
				if folder.UUID == folderUuid {
					bucket = folder
				}
			}
		}
	}
	if bucket == nil {
		err := errors.New(fmt.Sprintf("Couldn't find backup set UUID %s, folder UUID %s.", backupSetUuid, folderUuid))
		log.Errorf("%s", err)
		return err
	}
	backupSet := bucket.ArqBackupSet
	backupSet.CacheTreePackSets()

	apsi, _ := arq.NewPackSetIndex(cacheDirectory, backupSet, bucket)
	pf, _ := apsi.GetPackFile(backupSet, bucket, bucket.HeadSHA1)
	commit, err := arq_types.ReadCommit(bytes.NewBuffer(pf))
	if err != nil {
		log.Debugf("failed to parse commit: %s", err)
	}
	log.Debugf("commit: %s", commit)

	log.Debugf("get tree_packfile...")
	tree_packfile, _ := apsi.GetPackFile(backupSet, bucket, *commit.TreeBlobKey.SHA1)
	if err != nil {
		log.Debugf("failed to get tree blob: %s", err)
	}
	log.Debugf("finished getting tree_packfile.")
	log.Debugf("decompress tree_packfile...")
	if commit.TreeBlobKey.IsCompressed.IsTrue() {
		var b bytes.Buffer
		r, _ := gzip.NewReader(bytes.NewBuffer(tree_packfile))
		io.Copy(&b, r)
		r.Close()
		tree_packfile = b.Bytes()
	}
	log.Debugf("finished decompressing tree_packfile.")

	log.Debugf("get tree...")
	tree, err := arq_types.ReadTree(bytes.NewBuffer(tree_packfile))
	if err != nil {
		log.Debugf("failed to get tree: %s", err)
	}
	log.Debugf("finished getting tree.")
	log.Debugf("tree: %s", tree)
	for _, node := range tree.Nodes {
		fmt.Printf("%s\n", node.Name)
	}

	return nil
}

func main() {
	defaultCacheDirectory, err := homedir.Expand("~/.arqinator_cache")
	if err != nil {
		log.Fatal("Failed to get user's home dir: ", err)
	}

	app := cli.NewApp()
	app.Name = "arqinator"
	app.Usage = "restore folders and files from Arq backups"
	app.Version = "0.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "backup-type",
			Usage: "Method used for backup, e.g. 's3'.",
		},
		cli.StringFlag{
			Name:  "s3-region",
			Usage: "AWS S3 region, e.g. 'us-west-2'.",
		},
		cli.StringFlag{
			Name:  "s3-bucket-name",
			Usage: "AWS S3 bucket name, e.g. 'arq-akiaabdefg-us-west-2'.",
		},
		cli.StringFlag{
			Name:  "cache-directory",
			Value: defaultCacheDirectory,
			Usage: fmt.Sprintf("Where to cache Arq files for browsing. Default: %s", defaultCacheDirectory),
		},
		cli.BoolFlag{
			Name:  "delete-cache-directory",
			Usage: "Delete cache directory before starting. Useful if seeing errors that could be due to truncated downloads.",
		},
		cli.BoolFlag{
			Name: "verbose",
			Usage: "Enable verbose logging",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "list-backup-sets",
			Usage: "List backup sets in this account.",
			Action: func(c *cli.Context) {
				if err := cliSetup(c); err != nil {
					log.Debugf("%s", err)
					return
				}
				s3Connection, err := awsSetup(c)
				if err != nil {
					log.Debugf("%s", err)
					return
				}
				if err := listBackupSets(c, s3Connection); err != nil {
					log.Debugf("%s", err)
					return
				}
			},
		},
		{
			Name: "list-directory-contents",
			Usage: "List contents of directory in backup.",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:  "backup-set-uuid",
					Usage: "UUID of backup set. Use 'list-backup-sets' to determine this.",
				},
				cli.StringFlag{
					Name:  "folder-uuid",
					Usage: "UUID of folder. Use 'list-backup-sets' to determine this.",
				},
				cli.StringFlag{
					Name:  "path",
					Usage: "Path of directory or file in backup",
				},
			},
			Action: func(c *cli.Context) {
				if err := cliSetup(c); err != nil {
					log.Debugf("%s", err)
					return
				}
				s3Connection, err := awsSetup(c)
				if err != nil {
					log.Debugf("%s", err)
					return
				}
				if err := listDirectoryContents(c, s3Connection); err != nil {
					log.Debugf("%s", err)
					return
				}
			},
		},
	}
	app.Run(os.Args)
}
<|endoftext|>