<commit_before>// Copyright 2016 Danko Miocevic. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: Danko Miocevic

package main

import (
	"flag"
	"fmt"
	"github.com/dankomiocevic/mulifs/store"
	"github.com/dankomiocevic/mulifs/tools"
	"log"
	"os"
	"path/filepath"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
)

type fs_config struct {
	uid         uint
	gid         uint
	allow_users bool
	allow_root  bool
}

var config_params fs_config
var progName = filepath.Base(os.Args[0])

const progVer = "0.1"

// usage specifies how the command should be called
// showing a message on the standard output.
func usage() {
	fmt.Fprintf(os.Stderr, "Name:\n")
	fmt.Fprintf(os.Stderr, "  %s %s\n", progName, progVer)
	fmt.Fprintf(os.Stderr, "\nSynopsis:\n")
	fmt.Fprintf(os.Stderr, "  %s [global_options] MUSIC_SOURCE MOUNTPOINT \n", progName)
	fmt.Fprintf(os.Stderr, "\nDescription:\n")
	fmt.Fprintf(os.Stderr, "  Mounts a filesystem in MOUNTPOINT with the music files obtained\n")
	fmt.Fprintf(os.Stderr, "  from MUSIC_SOURCE ordered in folders by Artist and Album.\n")
	fmt.Fprintf(os.Stderr, "\n  For more information please visit:\n")
	fmt.Fprintf(os.Stderr, "    <http://github.com/dankomiocevic/mulifs>\n")
	fmt.Fprintf(os.Stderr, "\nParams:\n")
	fmt.Fprintf(os.Stderr, "  MUSIC_SOURCE: The path of the folder containing the music files.\n")
	fmt.Fprintf(os.Stderr, "  MOUNTPOINT: The path where MuLi should be mounted.\n")
	fmt.Fprintf(os.Stderr, "\nGlobal Options:\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\n")
}

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

	flag.Usage = usage
	var db_path string
	flag.StringVar(&db_path, "db_path", "muli.db", "Database path.")
	uid_conf := flag.Uint("uid", 0, "User owner of the files.")
	gid_conf := flag.Uint("gid", 0, "Group owner of the files.")
	allow_other := flag.Bool("allow_other", false, "Allow other users to access the filesystem.")
	allow_root := flag.Bool("allow_root", false, "Allow root to access the filesystem.")

	flag.Parse()

	config_params = fs_config{
		uid: *uid_conf, gid: *gid_conf, allow_users: *allow_other, allow_root: *allow_root,
	}

	if flag.NArg() < 2 {
		usage()
		os.Exit(2)
	}
	path := flag.Arg(0)
	mountpoint := flag.Arg(1)

	if path[0] == '-' {
		usage()
		os.Exit(3)
	}

	if mountpoint[0] == '-' {
		usage()
		os.Exit(4)
	}

	err := store.InitDB(db_path)
	if err != nil {
		log.Fatal(err)
		os.Exit(5)
	}

	path, err = filepath.Abs(path)
	if err != nil {
		log.Fatal(err)
		os.Exit(6)
	}

	err = tools.ScanFolder(path)
	if err != nil {
		log.Fatal(err)
		os.Exit(7)
	}

	err = tools.ScanPlaylistFolder(path)
	if err != nil {
		log.Fatal(err)
		os.Exit(8)
	}

	// Init the dispatcher system to process
	// delayed events.
	InitDispatcher()

	if err = mount(path, mountpoint); err != nil {
		log.Fatal(err)
		os.Exit(9)
	}
}

// mount calls the fuse library to specify
// the details of the mounted filesystem.
func mount(path, mountpoint string) error {
	// TODO: Check that there is no folder named

	mountOptions := []fuse.MountOption{
		fuse.FSName("MuLi"),
		fuse.Subtype("MuLiFS"),
		fuse.LocalVolume(),
		fuse.VolumeName("Music Library"),
	}

	if config_params.allow_users {
		mountOptions = append(mountOptions, fuse.AllowOther())
	} else {
		if config_params.allow_root {
			mountOptions = append(mountOptions, fuse.AllowRoot())
		}
	}
	// playlist or drop in the path.
	c, err := fuse.Mount(
		mountpoint, mountOptions...)

	if err != nil {
		return err
	}
	defer c.Close()

	filesys := &FS{
		mPoint: path,
	}

	if err := fs.Serve(c, filesys); err != nil {
		return err
	}

	// check if the mount process has an error to report
	<-c.Ready
	if err := c.MountError; err != nil {
		return err
	}

	return nil
}
<commit_msg>Add default mount options.<commit_after>// Copyright 2016 Danko Miocevic. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: Danko Miocevic

package main

import (
	"flag"
	"fmt"
	"github.com/dankomiocevic/mulifs/store"
	"github.com/dankomiocevic/mulifs/tools"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"bazil.org/fuse"
	"bazil.org/fuse/fs"
)

type fs_config struct {
	uid         uint
	gid         uint
	allow_users bool
	allow_root  bool
}

var config_params fs_config
var progName = filepath.Base(os.Args[0])

const progVer = "0.1"

// usage specifies how the command should be called
// showing a message on the standard output.
func usage() {
	fmt.Fprintf(os.Stderr, "Name:\n")
	fmt.Fprintf(os.Stderr, "  %s %s\n", progName, progVer)
	fmt.Fprintf(os.Stderr, "\nSynopsis:\n")
	fmt.Fprintf(os.Stderr, "  %s [global_options] MUSIC_SOURCE MOUNTPOINT \n", progName)
	fmt.Fprintf(os.Stderr, "\nDescription:\n")
	fmt.Fprintf(os.Stderr, "  Mounts a filesystem in MOUNTPOINT with the music files obtained\n")
	fmt.Fprintf(os.Stderr, "  from MUSIC_SOURCE ordered in folders by Artist and Album.\n")
	fmt.Fprintf(os.Stderr, "\n  For more information please visit:\n")
	fmt.Fprintf(os.Stderr, "    <http://github.com/dankomiocevic/mulifs>\n")
	fmt.Fprintf(os.Stderr, "\nParams:\n")
	fmt.Fprintf(os.Stderr, "  MUSIC_SOURCE: The path of the folder containing the music files.\n")
	fmt.Fprintf(os.Stderr, "  MOUNTPOINT: The path where MuLi should be mounted.\n")
	fmt.Fprintf(os.Stderr, "\nGlobal Options:\n")
	flag.PrintDefaults()
	fmt.Fprintf(os.Stderr, "\n")
}

func newTrue() *bool {
	b := true
	return &b
}

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

	flag.Usage = usage
	var err error
	var db_path string
	var mount_ops string
	flag.StringVar(&db_path, "db_path", "muli.db", "Database path.")
	flag.StringVar(&mount_ops, "o", "", "Default mount options.")
	uid_conf := flag.Uint("uid", 0, "User owner of the files.")
	gid_conf := flag.Uint("gid", 0, "Group owner of the files.")
	allow_other := flag.Bool("allow_other", false, "Allow other users to access the filesystem.")
	allow_root := flag.Bool("allow_root", false, "Allow root to access the filesystem.")

	flag.Parse()

	if len(mount_ops) > 0 {
		opts_tokens := strings.Split(mount_ops, ",")
		for _, token := range opts_tokens {
			if strings.Compare(token, "allow_root") == 0 {
				allow_root = newTrue()
			} else if strings.Compare(token, "allow_other") == 0 {
				allow_other = newTrue()
			} else if strings.HasPrefix(token, "uid=") {
				parsed_uid, err := strconv.ParseUint(token[len("uid="):], 10, 32)
				if err != nil {
					log.Fatal(err)
					os.Exit(1)
				} else {
					uint_uid := uint(parsed_uid)
					uid_conf = &uint_uid
				}
			} else if strings.HasPrefix(token, "gid=") {
				parsed_gid, err := strconv.ParseUint(token[len("gid="):], 10, 32)
				if err != nil {
					log.Fatal(err)
					os.Exit(1)
				} else {
					uint_gid := uint(parsed_gid)
					gid_conf = &uint_gid
				}
			} else if strings.HasPrefix(token, "db_path=") {
				db_path = token[len("db_path="):]
				if len(db_path) < 3 {
					log.Fatal("Error in db_path")
					os.Exit(1)
				}
			}
		}
	}

	config_params = fs_config{
		uid: *uid_conf, gid: *gid_conf, allow_users: *allow_other, allow_root: *allow_root,
	}

	if flag.NArg() < 2 {
		usage()
		os.Exit(2)
	}
	path := flag.Arg(0)
	mountpoint := flag.Arg(1)

	if path[0] == '-' {
		usage()
		os.Exit(3)
	}

	if mountpoint[0] == '-' {
		usage()
		os.Exit(4)
	}

	err = store.InitDB(db_path)
	if err != nil {
		log.Fatal(err)
		os.Exit(5)
	}

	path, err = filepath.Abs(path)
	if err != nil {
		log.Fatal(err)
		os.Exit(6)
	}

	err = tools.ScanFolder(path)
	if err != nil {
		log.Fatal(err)
		os.Exit(7)
	}

	err = tools.ScanPlaylistFolder(path)
	if err != nil {
		log.Fatal(err)
		os.Exit(8)
	}

	// Init the dispatcher system to process
	// delayed events.
	InitDispatcher()

	if err = mount(path, mountpoint); err != nil {
		log.Fatal(err)
		os.Exit(9)
	}
}

// mount calls the fuse library to specify
// the details of the mounted filesystem.
func mount(path, mountpoint string) error {
	// TODO: Check that there is no folder named

	mountOptions := []fuse.MountOption{
		fuse.FSName("MuLi"),
		fuse.Subtype("MuLiFS"),
		fuse.LocalVolume(),
		fuse.VolumeName("Music Library"),
	}

	if config_params.allow_users {
		mountOptions = append(mountOptions, fuse.AllowOther())
	} else {
		if config_params.allow_root {
			mountOptions = append(mountOptions, fuse.AllowRoot())
		}
	}
	// playlist or drop in the path.
	c, err := fuse.Mount(
		mountpoint, mountOptions...)

	if err != nil {
		return err
	}
	defer c.Close()

	filesys := &FS{
		mPoint: path,
	}

	if err := fs.Serve(c, filesys); err != nil {
		return err
	}

	// check if the mount process has an error to report
	<-c.Ready
	if err := c.MountError; err != nil {
		return err
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/XML-Comp/XML-Comp/comparer"
)

const ver = "v0.23"

func main() {
	var (
		original    = flag.String("original", "", "Full path directory of your RimWorld English folder (required)")
		translation = flag.String("translation", "", "Full path directory of your RimWorld Translation folder (required)")
		docType     = flag.String("doc", "xml", "Type of the Doc that you want to compare (not required)")
		version     = flag.Bool("version", false, "Prints current version")
	)
	flag.Parse()
	args := os.Args
	switch {
	case len(args) < 2 || args[1] == "-h":
		flag.Usage()
		os.Exit(1)
	case *version:
		fmt.Println(ver)
		os.Exit(0)
	case len(*original) == 0 || len(*translation) == 0:
		flag.Usage()
		os.Exit(1)
	}
	fmt.Println("Creating instance ...")
	fmt.Print("Output:- ")
	comparer.DocType = *docType
	err := comparer.Compare(*original, *translation)
	if err != nil {
		panic(err)
	}
	fmt.Println("Docs comparisons are DONE!")
	fmt.Printf("Documents scanned: %v | Lines scanned: %v | Translations needed: %v\n", comparer.Docs, comparer.Lines, comparer.InNeed)
}
<commit_msg>new version<commit_after>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/XML-Comp/XML-Comp/comparer"
)

const ver = "v0.24"

func main() {
	var (
		original    = flag.String("original", "", "Full path directory of your RimWorld English folder (required)")
		translation = flag.String("translation", "", "Full path directory of your RimWorld Translation folder (required)")
		docType     = flag.String("doc", "xml", "Type of the Doc that you want to compare (not required)")
		version     = flag.Bool("version", false, "Prints current version")
	)
	flag.Parse()
	args := os.Args
	switch {
	case len(args) < 2 || args[1] == "-h":
		flag.Usage()
		os.Exit(1)
	case *version:
		fmt.Println(ver)
		os.Exit(0)
	case len(*original) == 0 || len(*translation) == 0:
		flag.Usage()
		os.Exit(1)
	}
	fmt.Println("Creating instance ...")
	fmt.Print("Output:- ")
	comparer.DocType = *docType
	err := comparer.Compare(*original, *translation)
	if err != nil {
		panic(err)
	}
	fmt.Println("Docs comparisons are DONE!")
	fmt.Printf("Documents scanned: %v | Lines scanned: %v | Translations needed: %v\n", comparer.Docs, comparer.Lines, comparer.InNeed)
}
<|endoftext|>


<commit_before>package main // import "github.com/CenturyLinkLabs/panamaxcli"

import (
	"errors"
	"fmt"
	"os"
	"os/user"
	"strings"

	"github.com/CenturyLinkLabs/panamax-remote-agent-go/client"
	"github.com/CenturyLinkLabs/panamaxcli/actions"
	"github.com/CenturyLinkLabs/panamaxcli/config"
	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
)

var (
	Config   config.Config
	Commands []cli.Command
)

func init() {
	client.DefaultHTTPTimeout = 10

	Commands = []cli.Command{
		{
			Name:    "remote",
			Aliases: []string{"re"},
			Usage:   "Manage remotes",
			Subcommands: []cli.Command{
				{
					Name:    "list",
					Aliases: []string{"l"},
					Usage:   "List remotes",
					Action:  remoteListAction,
				},
				{
					Name:    "describe",
					Aliases: []string{"d"},
					Usage:   "Describe a remote",
					Before:  actionRequiresArgument("remote name"),
					Action:  remoteDescribeAction,
				},
				{
					Name:        "add",
					Usage:       "Add a remote",
					Description: "Arguments are the name of the remote and the path to the token file.",
					Before:      actionRequiresArgument("remote name", "file path"),
					Action:      remoteAddAction,
				},
				{
					Name:        "active",
					Usage:       "Set the active remote",
					Description: "Passing a remote name as an argument makes it the active remote.",
					Before:      actionRequiresArgument("remote name"),
					Action:      setActiveRemoteAction,
				},
				{
					Name:        "remove",
					Usage:       "Remove a remote",
					Description: "Argument is a remote name.",
					Before:      actionRequiresArgument("remote name"),
					Action:      removeRemoteAction,
				},
				{
					Name:        "token",
					Usage:       "Show the remote's token",
					Description: "Argument is a remote name.",
					Before:      actionRequiresArgument("remote name"),
					Action:      getTokenAction,
				},
			},
		},
		{
			Name:    "deployment",
			Aliases: []string{"de"},
			Usage:   "Manage deployments",
			Before:  actionRequiresActiveRemote,
			Subcommands: []cli.Command{
				{
					Name:    "list",
					Aliases: []string{"l"},
					Usage:   "List deployments",
					Action:  deploymentsListAction,
				},
				{
					Name:        "describe",
					Aliases:     []string{"d"},
					Usage:       "Describe a deployment",
					Description: "Argument is a deployment ID.",
					Before:      actionRequiresArgument("deployment ID"),
					Action:      describeDeploymentAction,
				},
				{
					Name:        "redeploy",
					Usage:       "Redeploy a deployment",
					Description: "Argument is a deployment ID.",
					Before:      actionRequiresArgument("deployment ID"),
					Action:      redeployDeploymentAction,
				},
				{
					Name:        "delete",
					Usage:       "Delete a deployment",
					Description: "Argument is a deployment ID.",
					Before:      actionRequiresArgument("deployment ID"),
					Action:      deleteDeploymentAction,
				},
			},
		},
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "panamaxcli"
	app.Version = "0.0.1"
	app.Usage = "Panamax command-line utility."
	app.Authors = []cli.Author{{"CenturyLink Labs", "clt-labs-futuretech@centurylink.com"}}
	app.Commands = Commands
	app.Before = initializeApp
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "Enable verbose logging",
		},
	}

	app.Run(os.Args)
}

func initializeApp(c *cli.Context) error {
	if c.GlobalBool("debug") {
		// Remote Agent Client will write to logrus with helpful info!
		log.SetLevel(log.DebugLevel)
	}

	// Surprise! CLI wants an error from this method but, only uses it to abort
	// execution, not for display anywhere.
	if err := loadConfig(c); err != nil {
		log.Error(err)
	}

	return nil
}

func loadConfig(c *cli.Context) error {
	user, err := user.Current()
	if err != nil {
		return err
	}
	dir := user.HomeDir
	fileConfig := config.FileConfig{Path: dir + "/.agents"}
	if err := fileConfig.Load(); err != nil {
		log.Error(err)
		return err
	}
	Config = config.Config(&fileConfig)

	return nil
}

func actionRequiresArgument(args ...string) func(c *cli.Context) error {
	return func(c *cli.Context) error {
		if len(c.Args()) != len(args) {
			s := strings.Join(args, ", ")
			message := fmt.Sprintf("This command requires the following arguments: %s", s)
			log.Errorln(message)
			return errors.New(message)
		}

		return nil
	}
}

func actionRequiresActiveRemote(c *cli.Context) error {
	if Config.Active() == nil {
		message := "an active remote is required for this command"
		log.Errorln(message)
		return errors.New(message)
	}

	return nil
}

func remoteAddAction(c *cli.Context) {
	name := c.Args().First()
	path := c.Args().Get(1)

	output, err := actions.AddRemote(Config, name, path)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func removeRemoteAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.RemoveRemote(Config, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func remoteListAction(c *cli.Context) {
	output := actions.ListRemotes(Config)
	fmt.Println(output.ToPrettyOutput())
}

func remoteDescribeAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.DescribeRemote(Config, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func setActiveRemoteAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.SetActiveRemote(Config, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func deploymentsListAction(c *cli.Context) {
	output, err := actions.ListDeployments(*Config.Active())

	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(output.ToPrettyOutput())
}

func describeDeploymentAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.DescribeDeployment(*Config.Active(), name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func redeployDeploymentAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.RedeployDeployment(*Config.Active(), name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func deleteDeploymentAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.DeleteDeployment(*Config.Active(), name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func getTokenAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.GetRemoteToken(Config, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}
<commit_msg>Fix home directory under cross compilation.<commit_after>package main // import "github.com/CenturyLinkLabs/panamaxcli"

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

	"github.com/CenturyLinkLabs/panamax-remote-agent-go/client"
	"github.com/CenturyLinkLabs/panamaxcli/actions"
	"github.com/CenturyLinkLabs/panamaxcli/config"
	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
)

var (
	Config   config.Config
	Commands []cli.Command
)

func init() {
	client.DefaultHTTPTimeout = 10

	Commands = []cli.Command{
		{
			Name:    "remote",
			Aliases: []string{"re"},
			Usage:   "Manage remotes",
			Subcommands: []cli.Command{
				{
					Name:    "list",
					Aliases: []string{"l"},
					Usage:   "List remotes",
					Action:  remoteListAction,
				},
				{
					Name:    "describe",
					Aliases: []string{"d"},
					Usage:   "Describe a remote",
					Before:  actionRequiresArgument("remote name"),
					Action:  remoteDescribeAction,
				},
				{
					Name:        "add",
					Usage:       "Add a remote",
					Description: "Arguments are the name of the remote and the path to the token file.",
					Before:      actionRequiresArgument("remote name", "file path"),
					Action:      remoteAddAction,
				},
				{
					Name:        "active",
					Usage:       "Set the active remote",
					Description: "Passing a remote name as an argument makes it the active remote.",
					Before:      actionRequiresArgument("remote name"),
					Action:      setActiveRemoteAction,
				},
				{
					Name:        "remove",
					Usage:       "Remove a remote",
					Description: "Argument is a remote name.",
					Before:      actionRequiresArgument("remote name"),
					Action:      removeRemoteAction,
				},
				{
					Name:        "token",
					Usage:       "Show the remote's token",
					Description: "Argument is a remote name.",
					Before:      actionRequiresArgument("remote name"),
					Action:      getTokenAction,
				},
			},
		},
		{
			Name:    "deployment",
			Aliases: []string{"de"},
			Usage:   "Manage deployments",
			Before:  actionRequiresActiveRemote,
			Subcommands: []cli.Command{
				{
					Name:    "list",
					Aliases: []string{"l"},
					Usage:   "List deployments",
					Action:  deploymentsListAction,
				},
				{
					Name:        "describe",
					Aliases:     []string{"d"},
					Usage:       "Describe a deployment",
					Description: "Argument is a deployment ID.",
					Before:      actionRequiresArgument("deployment ID"),
					Action:      describeDeploymentAction,
				},
				{
					Name:        "redeploy",
					Usage:       "Redeploy a deployment",
					Description: "Argument is a deployment ID.",
					Before:      actionRequiresArgument("deployment ID"),
					Action:      redeployDeploymentAction,
				},
				{
					Name:        "delete",
					Usage:       "Delete a deployment",
					Description: "Argument is a deployment ID.",
					Before:      actionRequiresArgument("deployment ID"),
					Action:      deleteDeploymentAction,
				},
			},
		},
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "panamaxcli"
	app.Version = "0.0.1"
	app.Usage = "Panamax command-line utility."
	app.Authors = []cli.Author{{"CenturyLink Labs", "clt-labs-futuretech@centurylink.com"}}
	app.Commands = Commands
	app.Before = initializeApp
	app.Flags = []cli.Flag{
		cli.BoolFlag{
			Name:  "debug",
			Usage: "Enable verbose logging",
		},
	}

	app.Run(os.Args)
}

func initializeApp(c *cli.Context) error {
	if c.GlobalBool("debug") {
		// Remote Agent Client will write to logrus with helpful info!
		log.SetLevel(log.DebugLevel)
	}

	// Surprise! CLI wants an error from this method but, only uses it to abort
	// execution, not for display anywhere.
	if err := loadConfig(c); err != nil {
		log.Error(err)
	}

	return nil
}

func loadConfig(c *cli.Context) error {
	// Stolen from: https://github.com/awslabs/aws-sdk-go/pull/136 Originally
	// cleaner with os/user.Current(), but that failed under cross-compilation on
	// non-linux platforms.
	dir := os.Getenv("HOME") // *nix
	if dir == "" {           // Windows
		dir = os.Getenv("USERPROFILE")
	}
	if dir == "" {
		return errors.New("Couldn't determine your home directory!")
	}

	fileConfig := config.FileConfig{Path: filepath.Join(dir, ".agents")}
	if err := fileConfig.Load(); err != nil {
		log.Error(err)
		return err
	}
	Config = config.Config(&fileConfig)

	return nil
}

func actionRequiresArgument(args ...string) func(c *cli.Context) error {
	return func(c *cli.Context) error {
		if len(c.Args()) != len(args) {
			s := strings.Join(args, ", ")
			message := fmt.Sprintf("This command requires the following arguments: %s", s)
			log.Errorln(message)
			return errors.New(message)
		}

		return nil
	}
}

func actionRequiresActiveRemote(c *cli.Context) error {
	if Config.Active() == nil {
		message := "an active remote is required for this command"
		log.Errorln(message)
		return errors.New(message)
	}

	return nil
}

func remoteAddAction(c *cli.Context) {
	name := c.Args().First()
	path := c.Args().Get(1)

	output, err := actions.AddRemote(Config, name, path)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func removeRemoteAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.RemoveRemote(Config, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func remoteListAction(c *cli.Context) {
	output := actions.ListRemotes(Config)
	fmt.Println(output.ToPrettyOutput())
}

func remoteDescribeAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.DescribeRemote(Config, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func setActiveRemoteAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.SetActiveRemote(Config, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func deploymentsListAction(c *cli.Context) {
	output, err := actions.ListDeployments(*Config.Active())

	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(output.ToPrettyOutput())
}

func describeDeploymentAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.DescribeDeployment(*Config.Active(), name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func redeployDeploymentAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.RedeployDeployment(*Config.Active(), name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func deleteDeploymentAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.DeleteDeployment(*Config.Active(), name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}

func getTokenAction(c *cli.Context) {
	name := c.Args().First()
	output, err := actions.GetRemoteToken(Config, name)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(output.ToPrettyOutput())
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/xml"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/f440/podcast-feed-server/config"
	"github.com/f440/podcast-feed-server/rss"
)

func escapeURL(str string) (string, error) {
	u, err := url.Parse(str)
	if err != nil {
		return "", err
	}
	return u.String(), nil
}

func main() {
	config := config.Config{}
	if err := config.Load("config.toml"); err != nil {
		panic(err)
	}

	fs := http.FileServer(http.Dir(config.Server.FileRoot))
	http.Handle("/", userAgentHandler(fs))

	http.Handle(config.Server.FeedPath, userAgentHandler(http.HandlerFunc(feedHandler)))

	http.ListenAndServe(config.Server.Listen, nil)
}

func userAgentHandler(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		config := config.Config{}
		if err := config.Load("config.toml"); err != nil {
			panic(err)
		}

		if config.Server.PermitUA != "" {
			ua := r.Header.Get("User-Agent")
			if strings.Index(ua, config.Server.PermitUA) == -1 {
				http.Error(w, "Forbidden", http.StatusForbidden)
				return
			}
		}

		next.ServeHTTP(w, r)
	})
}

func feedHandler(w http.ResponseWriter, r *http.Request) {
	config := config.Config{}
	if err := config.Load("config.toml"); err != nil {
		panic(err)
	}

	link, err := url.Parse(config.RSS.URL)
	if err != nil {
		panic(err)
	}
	feedURL, err := url.Parse(config.RSS.URL)
	if err != nil {
		panic(err)
	}
	feedURL.Path = config.Server.FeedPath

	feed := rss.RSS{
		XMLXmlnsAtom:   "http://www.w3.org/2005/Atom",
		XMLXmlnsItunes: "http://www.itunes.com/dtds/podcast-1.0.dtd",
		XMLVersion:     "2.0",
	}
	feed.Channel = &rss.Channel{
		Title:       config.RSS.Title,
		Description: config.RSS.Description,
		Link:        link.String(),
		AtomLink: &rss.AtomLink{
			Href: feedURL.String(),
			Rel:  "self",
			Type: "application/rss+xml",
		},
	}

	items := []*rss.Item{}
	err = filepath.Walk(config.Server.FileRoot, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			return nil
		}
		if !strings.HasSuffix(info.Name(), ".m4a") {
			return nil
		}

		title := strings.Replace(info.Name(), ".m4a", "", 1)
		pubDate := info.ModTime().Format(time.RFC1123)
		url, err := escapeURL(config.RSS.URL + strings.Replace(path, config.Server.FileRoot, "", 1))
		if err != nil {
			panic(err)
		}
		enclosure := rss.Enclosure{URL: url, Type: "audio/mpeg", Length: info.Size()}
		item := rss.Item{
			Title:     title,
			PubDate:   pubDate,
			Guid:      url,
			Enclosure: &enclosure,
		}

		items = append(items, &item)
		return nil
	})
	if err != nil {
		panic(err)
	}

	sort.Sort(sort.Reverse(rss.ByPubDate(items)))
	feed.Channel.Item = items

	buf, err := xml.MarshalIndent(feed, "", " ")
	if err != nil {
		panic(err)
	}

	w.Header().Set("Content-Type", "application/atom+xml")
	w.Header().Set("Last-Modified", items[0].PubDate)
	w.Write([]byte(xml.Header))
	w.Write(buf)
}
<commit_msg>Handle error<commit_after>package main

import (
	"encoding/xml"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"github.com/f440/podcast-feed-server/config"
	"github.com/f440/podcast-feed-server/rss"
)

func escapeURL(str string) (string, error) {
	u, err := url.Parse(str)
	if err != nil {
		return "", err
	}
	return u.String(), nil
}

func main() {
	config := config.Config{}
	if err := config.Load("config.toml"); err != nil {
		panic(err)
	}

	fs := http.FileServer(http.Dir(config.Server.FileRoot))
	http.Handle("/", userAgentHandler(fs))

	http.Handle(config.Server.FeedPath, userAgentHandler(http.HandlerFunc(feedHandler)))

	if err := http.ListenAndServe(config.Server.Listen, nil); err != nil {
		panic(err)
	}
}

func userAgentHandler(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		config := config.Config{}
		if err := config.Load("config.toml"); err != nil {
			panic(err)
		}

		if config.Server.PermitUA != "" {
			ua := r.Header.Get("User-Agent")
			if strings.Index(ua, config.Server.PermitUA) == -1 {
				http.Error(w, "Forbidden", http.StatusForbidden)
				return
			}
		}

		next.ServeHTTP(w, r)
	})
}

func feedHandler(w http.ResponseWriter, r *http.Request) {
	config := config.Config{}
	if err := config.Load("config.toml"); err != nil {
		panic(err)
	}

	link, err := url.Parse(config.RSS.URL)
	if err != nil {
		panic(err)
	}
	feedURL, err := url.Parse(config.RSS.URL)
	if err != nil {
		panic(err)
	}
	feedURL.Path = config.Server.FeedPath

	feed := rss.RSS{
		XMLXmlnsAtom:   "http://www.w3.org/2005/Atom",
		XMLXmlnsItunes: "http://www.itunes.com/dtds/podcast-1.0.dtd",
		XMLVersion:     "2.0",
	}
	feed.Channel = &rss.Channel{
		Title:       config.RSS.Title,
		Description: config.RSS.Description,
		Link:        link.String(),
		AtomLink: &rss.AtomLink{
			Href: feedURL.String(),
			Rel:  "self",
			Type: "application/rss+xml",
		},
	}

	items := []*rss.Item{}
	err = filepath.Walk(config.Server.FileRoot, func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			return nil
		}
		if !strings.HasSuffix(info.Name(), ".m4a") {
			return nil
		}

		title := strings.Replace(info.Name(), ".m4a", "", 1)
		pubDate := info.ModTime().Format(time.RFC1123)
		url, err := escapeURL(config.RSS.URL + strings.Replace(path, config.Server.FileRoot, "", 1))
		if err != nil {
			panic(err)
		}
		enclosure := rss.Enclosure{URL: url, Type: "audio/mpeg", Length: info.Size()}
		item := rss.Item{
			Title:     title,
			PubDate:   pubDate,
			Guid:      url,
			Enclosure: &enclosure,
		}

		items = append(items, &item)
		return nil
	})
	if err != nil {
		panic(err)
	}

	sort.Sort(sort.Reverse(rss.ByPubDate(items)))
	feed.Channel.Item = items

	buf, err := xml.MarshalIndent(feed, "", " ")
	if err != nil {
		panic(err)
	}

	w.Header().Set("Content-Type", "application/atom+xml")
	w.Header().Set("Last-Modified", items[0].PubDate)
	w.Write([]byte(xml.Header))
	w.Write(buf)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"
)

// TODO: better messaging

var (
	help   = flag.Bool("h", false, "show this message")
	target = flag.String("t", mustGetwd(), "target dir to upgrade/install")
	src    = flag.String("s", "release", "source of update: release,develop,canary")
)

func mustGetwd() string {
	d, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	return d
}

func saveFileInfo(fname string, t fileInfoTable) error {
	f, err := os.Create(fname)
	if err != nil {
		return nil
	}
	defer f.Close()
	for _, v := range t {
		fmt.Fprintf(f, fileInfoFormat, v.name, v.size, v.hash)
	}
	return f.Sync()
}

// cleanFiles removes unused/untracked files.
func cleanFiles(dir string, prev, curr fileInfoTable) {
	for _, p := range prev {
		if _, ok := curr[p.name]; ok {
			continue
		}
		fpath := filepath.Join(dir, p.name)
		if r, _ := p.compareWithFile(fpath); r != fileIsMatch {
			continue
		}
		os.Remove(fpath)
	}
}

func extract(dir, zipName, recipeName string) error {
	prev, err := loadFileInfo(recipeName)
	if err != nil {
		log.Printf("WARN: failed to load recipe: %s", err)
		log.Println("INFO: try to extract all files")
		prev = make(fileInfoTable)
	}
	last := -1
	curr, err := extractZip(zipName, dir, 1, prev, func(curr, max uint64) {
		v := int(curr * 100 / max)
		if v != last {
			fmt.Printf("\rextract %d%%", v)
			last = v
		}
	})
	fmt.Println()
	if err != nil {
		return err
	}
	if err := saveFileInfo(recipeName, curr); err != nil {
		log.Printf("WARN: failed to save recipe: %s", err)
	}
	cleanFiles(dir, prev, curr)
	return nil
}

func update(c *config) error {
	t, err := c.anchor()
	if err != nil {
		return err
	}
	s, err := determineSource(c.source, c.cpu)
	if err != nil {
		return err
	}
	last := -1
	p, err := s.download(c.tmpDir, t, func(curr, max int64) {
		// TODO: pretty progress.
		v := int(curr * 100 / max)
		if v != last {
			fmt.Printf("\rdownload %d%%", v)
			last = v
		}
	})
	fmt.Println()
	if err != nil {
		if err == errSourceNotModified {
			err = nil
		}
		return err
	}
	// capture anchor's new value.
	t = time.Now()
	if err := extract(c.targetDir, p, c.recipePath()); err != nil {
		return err
	}
	if err := c.updateAnchor(t); err != nil {
		os.Remove(c.anchorPath())
		return err
	}
	if err := os.Remove(p); err != nil {
		log.Printf("WARN: failed to remove: %s", err)
	}
	return nil
}

func showHelp() {
	fmt.Fprintf(os.Stderr, `%[1]s is tool to upgrade/install Vim (+kaoriya) in/to target dir.

Usage: %[1]s [options]

Options are:
`, filepath.Base(os.Args[0]))
	flag.PrintDefaults()
}

func main() {
	flag.Parse()
	if *help {
		showHelp()
		os.Exit(1)
	}
	c, err := newConfig(*target, *src)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.prepare(); err != nil {
		log.Fatal(err)
	}
	if err := update(c); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>restore mode<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"time"
)

// TODO: better messaging

// Options
var (
	help   = flag.Bool("h", false, "show this message")
	target = flag.String("t", mustGetwd(), "target dir to upgrade/install")
	src    = flag.String("s", "release", "source of update: release,develop,canary")

	restoreMode = flag.Bool("restore", false, "force download & extract all files")
)

func mustGetwd() string {
	d, err := os.Getwd()
	if err != nil {
		panic(err)
	}
	return d
}

func saveFileInfo(fname string, t fileInfoTable) error {
	f, err := os.Create(fname)
	if err != nil {
		return nil
	}
	defer f.Close()
	for _, v := range t {
		fmt.Fprintf(f, fileInfoFormat, v.name, v.size, v.hash)
	}
	return f.Sync()
}

// cleanFiles removes unused/untracked files.
func cleanFiles(dir string, prev, curr fileInfoTable) {
	for _, p := range prev {
		if _, ok := curr[p.name]; ok {
			continue
		}
		fpath := filepath.Join(dir, p.name)
		if r, _ := p.compareWithFile(fpath); r != fileIsMatch {
			continue
		}
		os.Remove(fpath)
	}
}

func extract(dir, zipName, recipeName string) error {
	prev, err := loadFileInfo(recipeName)
	if err != nil {
		log.Printf("WARN: failed to load recipe: %s", err)
		log.Println("INFO: try to extract all files")
		prev = make(fileInfoTable)
	}
	last := -1
	curr, err := extractZip(zipName, dir, 1, prev, func(curr, max uint64) {
		v := int(curr * 100 / max)
		if v != last {
			fmt.Printf("\rextract %d%%", v)
			last = v
		}
	})
	fmt.Println()
	if err != nil {
		return err
	}
	if err := saveFileInfo(recipeName, curr); err != nil {
		log.Printf("WARN: failed to save recipe: %s", err)
	}
	cleanFiles(dir, prev, curr)
	return nil
}

func update(c *config) error {
	t, err := c.anchor()
	if err != nil {
		return err
	}
	s, err := determineSource(c.source, c.cpu)
	if err != nil {
		return err
	}
	last := -1
	p, err := s.download(c.tmpDir, t, func(curr, max int64) {
		// TODO: pretty progress.
		v := int(curr * 100 / max)
		if v != last {
			fmt.Printf("\rdownload %d%%", v)
			last = v
		}
	})
	fmt.Println()
	if err != nil {
		if err == errSourceNotModified {
			err = nil
		}
		return err
	}
	// capture anchor's new value.
	t = time.Now()
	if err := extract(c.targetDir, p, c.recipePath()); err != nil {
		return err
	}
	if err := c.updateAnchor(t); err != nil {
		os.Remove(c.anchorPath())
		return err
	}
	if err := os.Remove(p); err != nil {
		log.Printf("WARN: failed to remove: %s", err)
	}
	return nil
}

func restore(c *config) error {
	if err := os.Remove(c.anchorPath()); os.IsExist(err) {
		return err
	}
	if err := os.Remove(c.recipePath()); os.IsExist(err) {
		return err
	}
	return update(c)
}

func showHelp() {
	fmt.Fprintf(os.Stderr, `%[1]s is tool to upgrade/install Vim (+kaoriya) in/to target dir.

Usage: %[1]s [options]

Options are:
`, filepath.Base(os.Args[0]))
	flag.PrintDefaults()
}

func main() {
	flag.Parse()
	if *help {
		showHelp()
		os.Exit(1)
	}
	c, err := newConfig(*target, *src)
	if err != nil {
		log.Fatal(err)
	}
	if err := c.prepare(); err != nil {
		log.Fatal(err)
	}
	proc := update
	if *restoreMode {
		proc = restore
	}
	if err := proc(c); err != nil {
		log.Fatal(err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/goauth2/oauth"
	"flag"
	"fmt"
	"github.com/google/go-github/github"
	"github.com/oleiade/reflections"
	"log"
	"os"
	"strings"
)

var commandLineName = "github-release"

var commandLineUsage = `github-release is a utility to create GitHub releases and upload packages.

Usage:
  $ github-release "v1.0" pkg/*.tar.gz --commit "branch-or-sha" \ # defaults to master
                                       --tag "1-0-0-stable" \ # defaults to the name of the release
                                       --github-repository "your/repo" \
                                       --github-access-token [..]

Environment variables can also be used:

  $ export GITHUB_RELEASE_ACCESS_TOKEN="..."
  $ export GITHUB_RELEASE_REPOSITORY="..."
  $ export GITHUB_RELEASE_TAG="..."
  $ export GITHUB_RELEASE_COMMIT="..."
  $ github-release "v1.0" pkg/*.tar.gz

Help:
  $ github-release --help

See https://github.com/buildboxhq/github-release and the GitHub
create release documentation https://developer.github.com/v3/repos/releases/#create-a-release
for more information.`

type commandLineOptions struct {
	GithubAccessToken string `flag:"github-access-token" env:"GITHUB_RELEASE_ACCESS_TOKEN" required:"true"`
	GithubRepository  string `flag:"github-repository" env:"GITHUB_RELEASE_REPOSITORY" required:"true"`
	Tag               string `flag:"tag" env:"GITHUB_RELEASE_TAG"`
	Commit            string `flag:"commit" env:"GITHUB_RELEASE_COMMIT"`
}

func main() {
	if len(os.Args) == 1 {
		exitAndError("invalid usage")
	}

	// Collect the release assets from the command line
	releaseAssets := collectReleaseAssets(os.Args)

	// Parse our command line options
	options := commandLineOptions{}
	parseArgs(&options, os.Args)

	// Grab our release name. If it starts with a '--', then they haven't
	// entered one.
	releaseName := os.Args[1]
	if strings.HasPrefix(releaseName, "--") {
		exitAndError("invalid usage")
	}

	// fmt.Printf("name: %s\n", releaseName)
	// fmt.Printf("assets: %s\n", releaseAssets)
	// fmt.Printf("options: %s\n", options.GithubAccessToken)

	// Finally do the release
	release(releaseName, releaseAssets, &options)
}

// Finds the assets from the argument list by looping over every argument,
// and checking if it's a file.
func collectReleaseAssets(args []string) (files []string) {
	for i := 0; i < len(args); i++ {
		arg := args[i]

		// Check if the file exists
		if _, err := os.Stat(arg); err == nil {
			files = append(files, arg)
		}

		// If the arg is an option, we've gone to far
		if strings.HasPrefix(arg, "--") {
			break
		}
	}

	return
}

// Reflects on the values in the commandLineOptions structure, and fills it
// with values either from the command line, or from the ENV.
func parseArgs(opts *commandLineOptions, args []string) {
	// Create a flag set for args
	flags := flag.NewFlagSet(commandLineName, flag.ExitOnError)

	// Get the fields for the strucutre
	fields, _ := reflections.Fields(opts)

	// Loop through each field of the structure, and define a flag for it
	for i := 0; i < len(fields); i++ {
		fieldName := fields[i]
		flagName, _ := reflections.GetFieldTag(opts, fieldName, "flag")

		flags.String(flagName, "", "")
	}

	// Define our custom usage text
	flags.Usage = func() {
		fmt.Printf("%s\n", commandLineUsage)
		os.Exit(0)
	}

	// Search the args until we find a "--", which signifies the user has started
	// defining options.
	var argumentFlags []string
	started := false
	for i := 0; i < len(args); i++ {
		if strings.HasPrefix(args[i], "--") {
			started = true
		}

		if started {
			argumentFlags = append(argumentFlags, args[i])
		}
	}

	// Now parse the flags
	flags.Parse(argumentFlags)

	// Now the flag set has been populated with values, retrieve them and
	// set them (or use the ENV variable if empty)
	for i := 0; i < len(fields); i++ {
		fieldName := fields[i]

		// Grab the flags we need
		flagName, _ := reflections.GetFieldTag(opts, fieldName, "flag")
		envName, _ := reflections.GetFieldTag(opts, fieldName, "env")
		required, _ := reflections.GetFieldTag(opts, fieldName, "required")

		// Grab the value from the flag
		value := flags.Lookup(flagName).Value.String()

		// If the value of the flag is empty, try the ENV
		if value == "" {
			value = os.Getenv(envName)
		}

		// Do validation
		if required == "true" && value == "" {
			exitAndError(fmt.Sprintf("missing %s", flagName))
		}

		reflections.SetField(opts, fieldName, value)
	}
}

func exitAndError(message interface{}) {
	fmt.Printf("%s: %s\nSee '%s --help'\n", commandLineName, message, commandLineName)
	os.Exit(1)
}

func release(releaseName string, releaseAssets []string, options *commandLineOptions) {
	log.Printf("Creating release %s for repository: %s", releaseName, options.GithubRepository)

	// Split the repository into two parts (owner and repository)
	repositoryParts := strings.Split(options.GithubRepository, "/")
	if len(repositoryParts) != 2 {
		exitAndError("github-repository is in the wrong format")
	}

	// If no tag was provided, use the name of the release
	tag := options.Tag
	if tag == "" {
		tag = releaseName
	}

	// Create an oAuth transport
	t := &oauth.Transport{
		Token: &oauth.Token{AccessToken: options.GithubAccessToken},
	}

	// Create a GitHub client with the transport
	client := github.NewClient(t.Client())

	// List all repositories for the authenticated user
	repos, _, err := client.Repositories.ListReleases(repositoryParts[0], repositoryParts[1], nil)
	if err != nil {
		log.Fatalf("Failed to get repos: %s", err)
	}

	log.Printf("%s", repos)
	log.Printf("name: %s", releaseName)
	log.Printf("assets: %s", releaseAssets)
	log.Printf("commit: %s", options.Commit)
	log.Printf("tag: %s", tag)
}
<commit_msg>Creating releases now works (no assets yet)<commit_after>package main

import (
	"code.google.com/p/goauth2/oauth"
	"flag"
	"fmt"
	"github.com/google/go-github/github"
	"github.com/oleiade/reflections"
	"log"
	"os"
	"strings"
)

var commandLineName = "github-release"

var commandLineUsage = `github-release is a utility to create GitHub releases and upload packages.

Usage:
  $ github-release "v1.0" pkg/*.tar.gz --commit "branch-or-sha" \ # defaults to master
                                       --tag "1-0-0-stable" \ # defaults to the name of the release
                                       --prerelease "true" \ # defaults to false
                                       --github-repository "your/repo" \
                                       --github-access-token [..]

Environment variables can also be used:

  $ export GITHUB_RELEASE_ACCESS_TOKEN="..."
  $ export GITHUB_RELEASE_REPOSITORY="..."
  $ export GITHUB_RELEASE_TAG="..."
  $ export GITHUB_RELEASE_COMMIT="..."
  $ export GITHUB_RELEASE_PRERELEASE="..."
  $ github-release "v1.0" pkg/*.tar.gz

Help:
  $ github-release --help

See https://github.com/buildboxhq/github-release and the GitHub
create release documentation https://developer.github.com/v3/repos/releases/#create-a-release
for more information.`

type commandLineOptions struct {
	GithubAccessToken string `flag:"github-access-token" env:"GITHUB_RELEASE_ACCESS_TOKEN" required:"true"`
	GithubRepository  string `flag:"github-repository" env:"GITHUB_RELEASE_REPOSITORY" required:"true"`
	Tag               string `flag:"tag" env:"GITHUB_RELEASE_TAG"`
	Commit            string `flag:"commit" env:"GITHUB_RELEASE_COMMIT"`
	Prerelease        string `flag:"prerelease" env:"GITHUB_RELEASE_PRERELEASE"`
}

func main() {
	if len(os.Args) == 1 {
		exitAndError("invalid usage")
	}

	// Collect the release assets from the command line
	releaseAssets := collectReleaseAssets(os.Args)

	// Parse our command line options
	options := commandLineOptions{}
	parseArgs(&options, os.Args)

	// Grab our release name. If it starts with a '--', then they haven't
	// entered one.
	releaseName := os.Args[1]
	if strings.HasPrefix(releaseName, "--") {
		exitAndError("invalid usage")
	}

	// fmt.Printf("name: %s\n", releaseName)
	// fmt.Printf("assets: %s\n", releaseAssets)
	// fmt.Printf("options: %s\n", options.GithubAccessToken)

	// Finally do the release
	release(releaseName, releaseAssets, &options)
}

// Finds the assets from the argument list by looping over every argument,
// and checking if it's a file.
func collectReleaseAssets(args []string) (files []string) {
	for i := 0; i < len(args); i++ {
		arg := args[i]

		// Check if the file exists
		if _, err := os.Stat(arg); err == nil {
			files = append(files, arg)
		}

		// If the arg is an option, we've gone to far
		if strings.HasPrefix(arg, "--") {
			break
		}
	}

	return
}

// Reflects on the values in the commandLineOptions structure, and fills it
// with values either from the command line, or from the ENV.
func parseArgs(opts *commandLineOptions, args []string) {
	// Create a flag set for args
	flags := flag.NewFlagSet(commandLineName, flag.ExitOnError)

	// Get the fields for the strucutre
	fields, _ := reflections.Fields(opts)

	// Loop through each field of the structure, and define a flag for it
	for i := 0; i < len(fields); i++ {
		fieldName := fields[i]
		flagName, _ := reflections.GetFieldTag(opts, fieldName, "flag")

		flags.String(flagName, "", "")
	}

	// Define our custom usage text
	flags.Usage = func() {
		fmt.Printf("%s\n", commandLineUsage)
		os.Exit(0)
	}

	// Search the args until we find a "--", which signifies the user has started
	// defining options.
	var argumentFlags []string
	started := false
	for i := 0; i < len(args); i++ {
		if strings.HasPrefix(args[i], "--") {
			started = true
		}

		if started {
			argumentFlags = append(argumentFlags, args[i])
		}
	}

	// Now parse the flags
	flags.Parse(argumentFlags)

	// Now the flag set has been populated with values, retrieve them and
	// set them (or use the ENV variable if empty)
	for i := 0; i < len(fields); i++ {
		fieldName := fields[i]

		// Grab the flags we need
		flagName, _ := reflections.GetFieldTag(opts, fieldName, "flag")
		envName, _ := reflections.GetFieldTag(opts, fieldName, "env")
		required, _ := reflections.GetFieldTag(opts, fieldName, "required")

		// Grab the value from the flag
		value := flags.Lookup(flagName).Value.String()

		// If the value of the flag is empty, try the ENV
		if value == "" {
			value = os.Getenv(envName)
		}

		// Do validation
		if required == "true" && value == "" {
			exitAndError(fmt.Sprintf("missing %s", flagName))
		}

		reflections.SetField(opts, fieldName, value)
	}
}

func exitAndError(message interface{}) {
	fmt.Printf("%s: %s\nSee '%s --help'\n", commandLineName, message, commandLineName)
	os.Exit(1)
}

func release(releaseName string, releaseAssets []string, options *commandLineOptions) {
	log.Printf("Creating release %s for repository: %s", releaseName, options.GithubRepository)

	// Split the repository into two parts (owner and repository)
	repositoryParts := strings.Split(options.GithubRepository, "/")
	if len(repositoryParts) != 2 {
		exitAndError("github-repository is in the wrong format")
	}

	// If no tag was provided, use the name of the release
	tagName := options.Tag
	if tagName == "" {
		tagName = releaseName
	}

	// Toggle prerelease
	prerelease := false
	if options.Prerelease == "true" {
		prerelease = true
	}

	// log.Printf("%s", repos)
	// log.Printf("name: %s", releaseName)
	// log.Printf("assets: %s", releaseAssets)
	// log.Printf("commit: %s", options.Commit)
	// log.Printf("tag: %s", tag)

	// Create an oAuth transport
	t := &oauth.Transport{
		Token: &oauth.Token{AccessToken: options.GithubAccessToken},
	}

	// Create a GitHub client with the transport
	client := github.NewClient(t.Client())

	// Create an object that represents the release
	release := &github.RepositoryRelease{
		Name:            &releaseName,
		TagName:         &tagName,
		TargetCommitish: &options.Commit,
		Prerelease:      &prerelease,
	}

	// Create the GitHub release
	createdRelease, _, err := client.Repositories.CreateRelease(repositoryParts[0], repositoryParts[1], release)
	if err != nil {
		log.Fatalf("Failed to create release: %T %v", err, err)
	}

	log.Printf("Successfully created release: %s", github.Stringify(createdRelease.HTMLURL))
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"

	"github.com/FarmRadioHangar/fessboxconfig/gsm"
	"github.com/gernest/hot"
	"github.com/gorilla/mux"
)

type Config struct {
	Port           int64  `json:"port"`
	Host           string `json:"host"`
	StaticDir      string `json:"static_dir"`
	TemplatesDir   string `json:"templates_dir"`
	AsteriskConfig string `json:"asterisk_config_dir"`
}

func defaultConfig() *Config {
	return &Config{
		Port:           8080,
		Host:           "",
		StaticDir:      "static",
		TemplatesDir:   "templates",
		AsteriskConfig: "/etc/asterisk",
	}
}

func main() {
	c := flag.String("c", "conf/config.json", "path to the configuration file")
	dev := flag.Bool("dev", false, "set true if running in dev mode")
	flag.Parse()
	b, err := ioutil.ReadFile(*c)
	if err != nil {
		log.Fatal(err)
	}
	cfg := &Config{}
	err = json.Unmarshal(b, cfg)
	if err != nil {
		log.Fatal(err)
	}
	if *dev {
		cfg.AsteriskConfig = "sample"
		tmp, err := ioutil.TempDir("", "fconf")
		if err != nil {
			log.Fatal(err)
		}
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
		go func(dir string) {
		END:
			for {
				select {
				case <-c:
					log.Println("removing ", dir)
					_ = os.RemoveAll(dir)
					break END
				}
			}
		}(tmp)
		cfg.AsteriskConfig = tmp
		err = copyFiles(tmp, "sample")
		if err != nil {
			log.Fatal(err)
		}
	}
	s := newServer(cfg)
	log.Printf(" starting server on  localhost:%d\n", cfg.Port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", cfg.Port), s))
}

//copyFiles copies files from src to dst, directories are ignored
func copyFiles(dst, src string) error {
	files, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}
	for _, file := range files {
		if file.IsDir() {
			continue
		}
		fname := filepath.Join(src, file.Name())
		f, err := ioutil.ReadFile(fname)
		if err != nil {
			return err
		}
		err = ioutil.WriteFile(filepath.Join(dst, file.Name()), f, 0600)
		if err != nil {
			return err
		}
	}
	return nil
}

//newServer returns a http.Handler with all the routes for configuring supported
//devices registered.
func newServer(c *Config) http.Handler {
	s := mux.NewRouter()
	w := newWeb(c)
	s.HandleFunc("/device/dongle", w.Dongle).Methods("GET")
	s.HandleFunc("/device/dongle", w.UpdateDongle).Methods("POST")
	s.PathPrefix("/static/").
		Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(c.StaticDir))))
	s.HandleFunc("/", w.Home)
	return s
}

type web struct {
	cfg *Config
	tpl *hot.Template
}

func newWeb(cfg *Config) *web {
	w := &web{cfg: cfg}
	config := &hot.Config{
		Watch:          true,
		BaseName:       "fconf",
		Dir:            cfg.TemplatesDir,
		FilesExtension: []string{".tpl", ".html", ".tmpl"},
	}

	tpl, err := hot.New(config)
	if err != nil {
		panic(err)
	}
	w.tpl = tpl
	return w
}

func (ww *web) Home(w http.ResponseWriter, r *http.Request) {
	err := ww.tpl.Execute(w, "index.html", nil)
	if err != nil {
		log.Println(err)
	}
}

type errMSG struct {
	Message string `json:"error"`
}

// Dongle implements http.HandleFunc for serving the dongle configuration values
// as a json object
func (ww *web) Dongle(w http.ResponseWriter, r *http.Request) {
	fName := filepath.Join(ww.cfg.AsteriskConfig, "dongle.conf")
	enc := json.NewEncoder(w)
	w.Header().Set("Content-Type", "application/json")

	f, err := os.Open(fName)
	if err != nil {
		log.Println(err)
		enc.Encode(&errMSG{"trouble opening dongle configuration"})
		return
	}
	defer f.Close()
	p, err := gsm.NewParser(f)
	if err != nil {
		log.Println(err)
		enc.Encode(&errMSG{"trouble scanning dongle configuration"})
		return
	}
	ast, err := p.Parse()
	if err != nil {
		log.Println(err)
		enc.Encode(&errMSG{"trouble parsing dongle configuration"})
		return
	}
	err = ast.ToJSON(w)
	if err != nil {
		log.Println(err)
	}
}

func (ww *web) UpdateDongle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	ast := &gsm.Ast{}
	src := &bytes.Buffer{}
	enc := json.NewEncoder(w)
	_, err := io.Copy(src, r.Body)
	if err != nil {
		enc.Encode(&errMSG{Message: "trouble reading request body"})
		return
	}
	err = ast.LoadJSON(src.Bytes())
	if err != nil {
		enc.Encode(&errMSG{Message: "trouble loading request body"})
		return
	}
	fName := filepath.Join(ww.cfg.AsteriskConfig, "dongle.conf")
	info, err := os.Stat(fName)
	if err != nil {
		log.Println(err)
		enc.Encode(&errMSG{"trouble opening dongle configuration"})
		return
	}
	dst := &bytes.Buffer{}
	gsm.PrintAst(dst, ast)
	ioutil.WriteFile(fName, dst.Bytes(), info.Mode())
	io.Copy(w, src)
}
<commit_msg>Add documentation<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"path/filepath"
	"syscall"

	"github.com/FarmRadioHangar/fessboxconfig/gsm"
	"github.com/gernest/hot"
	"github.com/gorilla/mux"
)

//Config holds configuration values for this application.
type Config struct {
	Port           int64  `json:"port"`
	Host           string `json:"host"`
	StaticDir      string `json:"static_dir"`
	TemplatesDir   string `json:"templates_dir"`
	AsteriskConfig string `json:"asterisk_config_dir"`
}

func defaultConfig() *Config {
	return &Config{
		Port:           8080,
		Host:           "",
		StaticDir:      "static",
		TemplatesDir:   "templates",
		AsteriskConfig: "/etc/asterisk",
	}
}

func main() {
	c := flag.String("c", "conf/config.json", "path to the configuration file")
	dev := flag.Bool("dev", false, "set true if running in dev mode")
	flag.Parse()
	b, err := ioutil.ReadFile(*c)
	if err != nil {
		log.Fatal(err)
	}
	cfg := &Config{}
	err = json.Unmarshal(b, cfg)
	if err != nil {
		log.Fatal(err)
	}
	if *dev {
		cfg.AsteriskConfig = "sample"
		tmp, err := ioutil.TempDir("", "fconf")
		if err != nil {
			log.Fatal(err)
		}
		c := make(chan os.Signal, 1)
		signal.Notify(c, syscall.SIGTERM, syscall.SIGINT)
		go func(dir string) {
		END:
			for {
				select {
				case <-c:
					log.Println("removing ", dir)
					_ = os.RemoveAll(dir)
					break END
				}
			}
		}(tmp)
		cfg.AsteriskConfig = tmp
		err = copyFiles(tmp, "sample")
		if err != nil {
			log.Fatal(err)
		}
	}
	s := newServer(cfg)
	log.Printf(" starting server on  localhost:%d\n", cfg.Port)
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", cfg.Port), s))
}

//copyFiles copies files from src to dst, directories are ignored
func copyFiles(dst, src string) error {
	files, err := ioutil.ReadDir(src)
	if err != nil {
		return err
	}
	for _, file := range files {
		if file.IsDir() {
			continue
		}
		fname := filepath.Join(src, file.Name())
		f, err := ioutil.ReadFile(fname)
		if err != nil {
			return err
		}
		err = ioutil.WriteFile(filepath.Join(dst, file.Name()), f, 0600)
		if err != nil {
			return err
		}
	}
	return nil
}

//newServer returns a http.Handler with all the routes for configuring supported
//devices registered.
func newServer(c *Config) http.Handler {
	s := mux.NewRouter()
	w := newWeb(c)
	s.HandleFunc("/device/dongle", w.Dongle).Methods("GET")
	s.HandleFunc("/device/dongle", w.UpdateDongle).Methods("POST")
	s.PathPrefix("/static/").
		Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(c.StaticDir))))
	s.HandleFunc("/", w.Home)
	return s
}

// web is the application struct, it defines all the handlers for this
// application as its methods.
//
// It is safe to use this in multiple goroutines
//
// This contains a a loaded hot template, so when run in development mode the
// templates will automatially be reloaded withouth the need to re run the
// application process. The auto reloading of templates is disabled in
// production.
type web struct {
	cfg *Config
	tpl *hot.Template
}

func newWeb(cfg *Config) *web {
	w := &web{cfg: cfg}
	config := &hot.Config{
		Watch:          true,
		BaseName:       "fconf",
		Dir:            cfg.TemplatesDir,
		FilesExtension: []string{".tpl", ".html", ".tmpl"},
	}

	tpl, err := hot.New(config)
	if err != nil {
		panic(err)
	}
	w.tpl = tpl
	return w
}

func (ww *web) Home(w http.ResponseWriter, r *http.Request) {
	err := ww.tpl.Execute(w, "index.html", nil)
	if err != nil {
		log.Println(err)
	}
}

type errMSG struct {
	Message string `json:"error"`
}

// Dongle implements http.HandleFunc for serving the dongle configuration values
// as a json object
func (ww *web) Dongle(w http.ResponseWriter, r *http.Request) {
	fName := filepath.Join(ww.cfg.AsteriskConfig, "dongle.conf")
	enc := json.NewEncoder(w)
	w.Header().Set("Content-Type", "application/json")

	f, err := os.Open(fName)
	if err != nil {
		log.Println(err)
		enc.Encode(&errMSG{"trouble opening dongle configuration"})
		return
	}
	defer f.Close()
	p, err := gsm.NewParser(f)
	if err != nil {
		log.Println(err)
		enc.Encode(&errMSG{"trouble scanning dongle configuration"})
		return
	}
	ast, err := p.Parse()
	if err != nil {
		log.Println(err)
		enc.Encode(&errMSG{"trouble parsing dongle configuration"})
		return
	}
	err = ast.ToJSON(w)
	if err != nil {
		log.Println(err)
	}
}

func (ww *web) UpdateDongle(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	ast := &gsm.Ast{}
	src := &bytes.Buffer{}
	enc := json.NewEncoder(w)
	_, err := io.Copy(src, r.Body)
	if err != nil {
		enc.Encode(&errMSG{Message: "trouble reading request body"})
		return
	}
	err = ast.LoadJSON(src.Bytes())
	if err != nil {
		enc.Encode(&errMSG{Message: "trouble loading request body"})
		return
	}
	fName := filepath.Join(ww.cfg.AsteriskConfig, "dongle.conf")
	info, err := os.Stat(fName)
	if err != nil {
		log.Println(err)
		enc.Encode(&errMSG{"trouble opening dongle configuration"})
		return
	}
	dst := &bytes.Buffer{}
	gsm.PrintAst(dst, ast)
	ioutil.WriteFile(fName, dst.Bytes(), info.Mode())
	io.Copy(w, src)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"runtime/pprof"
	"time"
)

const (
	name    string = "godedupe"
	version string = "1.0.0"
)

var (
	cpuprofile         string
	currentDir         string
	excludeEmptyDir    bool
	excludeEmptyFiles  bool
	excludeHiddenFiles bool
	showCurrentValues  bool
	enableRecursion    bool
	ignoreSymLinks     bool
	showSummary        bool
	quiet              bool
	showNotification   bool
)

// Options for start the program
type Options struct {
	currentDir         string
	excludeEmptyFiles  bool
	excludeHiddenFiles bool
	enableRecursion    bool
	ignoreSymLinks     bool
	showSummary        bool
	quiet              bool
	showNotification   bool
}

// Init the options to run the program
func initOptions() {
	flag.StringVar(&cpuprofile, "cpuprofile", "", "Enable profiling")
	flag.StringVar(&currentDir, "t", GetUserHome(),
		"Current directory where the program search for duplicated files")
	flag.BoolVar(&excludeEmptyFiles, "z", true, "Exclude the zero length files")
	flag.BoolVar(&excludeHiddenFiles, "h", true, "Exclude the hidden files")
	flag.BoolVar(&showCurrentValues, "debug", false,
		"Show the current values of the program options")
	flag.BoolVar(&enableRecursion, "r", true, "Follow subdirectories (recursion)")
	flag.BoolVar(&ignoreSymLinks, "sym", true, "Ignore symlinks")
	flag.BoolVar(&showSummary, "m", false, "Show a summary")
	flag.BoolVar(&quiet, "q", false, "Don't show status info")
	flag.BoolVar(&showNotification, "show-notification", false,
		"Show a desktop notification when the program finish")
	flag.Parse()
}

// Header show the program name and current version
func header() {
	if !quiet {
		fmt.Println("------------------------")
		fmt.Printf("%s - version %s\n", name, version)
		fmt.Println("------------------------")
	}
}

// ShowDebugInfo print all the current option values
func showDebugInfo() {
	if showCurrentValues && !quiet {
		fmt.Println()
		fmt.Println("------------------------")
		fmt.Println("Current option values")
		fmt.Println("------------------------")
		fmt.Println("Target directory          :", currentDir)
		fmt.Println("Exclude zero length files :", excludeEmptyFiles)
		fmt.Println("Exclude hidden files      :", excludeHiddenFiles)
		fmt.Println("Ignore symlinks           :", ignoreSymLinks)
		fmt.Println("Recursive search          :", enableRecursion)
		fmt.Println("Show a summary            :", showSummary)
		fmt.Println("Quiet                     :", quiet)
		if cpuprofile != "" {
			fmt.Println("Profile output            :", cpuprofile)
		}
		fmt.Println("------------------------")
	}
}

func trackTime(now time.Time) {
	expired := time.Since(now)
	if !quiet {
		fmt.Printf("[+] Program terminated in %v\n", expired)
	}
}

func executeCPUProfile() {
	f, err := os.Create(cpuprofile)
	if err != nil {
		panic(err)
	}
	pprof.StartCPUProfile(f)
}

func main() {
	initOptions()

	header()
	showDebugInfo()

	options := Options{
		currentDir,
		excludeEmptyFiles,
		excludeHiddenFiles,
		enableRecursion,
		ignoreSymLinks,
		showSummary,
		quiet,
		showNotification,
	}

	if cpuprofile != "" {
		executeCPUProfile()
		defer pprof.StopCPUProfile()
	}

	defer trackTime(time.Now())

	runtime.GOMAXPROCS(runtime.NumCPU())
	Start(options)
}
<commit_msg>version bump<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"runtime"
	"runtime/pprof"
	"time"
)

const (
	name    string = "godedupe"
	version string = "1.1.0"
)

var (
	cpuprofile         string
	currentDir         string
	excludeEmptyDir    bool
	excludeEmptyFiles  bool
	excludeHiddenFiles bool
	showCurrentValues  bool
	enableRecursion    bool
	ignoreSymLinks     bool
	showSummary        bool
	quiet              bool
	showNotification   bool
)

// Options for start the program
type Options struct {
	currentDir         string
	excludeEmptyFiles  bool
	excludeHiddenFiles bool
	enableRecursion    bool
	ignoreSymLinks     bool
	showSummary        bool
	quiet              bool
	showNotification   bool
}

// Init the options to run the program
func initOptions() {
	flag.StringVar(&cpuprofile, "cpuprofile", "", "Enable profiling")
	flag.StringVar(&currentDir, "t", GetUserHome(),
		"Current directory where the program search for duplicated files")
	flag.BoolVar(&excludeEmptyFiles, "z", true, "Exclude the zero length files")
	flag.BoolVar(&excludeHiddenFiles, "h", true, "Exclude the hidden files")
	flag.BoolVar(&showCurrentValues, "debug", false,
		"Show the current values of the program options")
	flag.BoolVar(&enableRecursion, "r", true, "Follow subdirectories (recursion)")
	flag.BoolVar(&ignoreSymLinks, "sym", true, "Ignore symlinks")
	flag.BoolVar(&showSummary, "m", false, "Show a summary")
	flag.BoolVar(&quiet, "q", false, "Don't show status info")
	flag.BoolVar(&showNotification, "show-notification", false,
		"Show a desktop notification when the program finish")
	flag.Parse()
}

// Header show the program name and current version
func header() {
	if !quiet {
		fmt.Println("------------------------")
		fmt.Printf("%s - version %s\n", name, version)
		fmt.Println("------------------------")
	}
}

// ShowDebugInfo print all the current option values
func showDebugInfo() {
	if showCurrentValues && !quiet {
		fmt.Println()
		fmt.Println("------------------------")
		fmt.Println("Current option values")
		fmt.Println("------------------------")
		fmt.Println("Target directory          :", currentDir)
		fmt.Println("Exclude zero length files :", excludeEmptyFiles)
		fmt.Println("Exclude hidden files      :", excludeHiddenFiles)
		fmt.Println("Ignore symlinks           :", ignoreSymLinks)
		fmt.Println("Recursive search          :", enableRecursion)
		fmt.Println("Show a summary            :", showSummary)
		fmt.Println("Quiet                     :", quiet)
		if cpuprofile != "" {
			fmt.Println("Profile output            :", cpuprofile)
		}
		fmt.Println("------------------------")
	}
}

func trackTime(now time.Time) {
	expired := time.Since(now)
	if !quiet {
		fmt.Printf("[+] Program terminated in %v\n", expired)
	}
}

func executeCPUProfile() {
	f, err := os.Create(cpuprofile)
	if err != nil {
		panic(err)
	}
	pprof.StartCPUProfile(f)
}

func main() {
	initOptions()

	header()
	showDebugInfo()

	options := Options{
		currentDir,
		excludeEmptyFiles,
		excludeHiddenFiles,
		enableRecursion,
		ignoreSymLinks,
		showSummary,
		quiet,
		showNotification,
	}

	if cpuprofile != "" {
		executeCPUProfile()
		defer pprof.StopCPUProfile()
	}

	defer trackTime(time.Now())

	runtime.GOMAXPROCS(runtime.NumCPU())
	Start(options)
}
<|endoftext|>


<commit_before>package main

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

	"github.com/otherpirate/dbaas-metric-collector/collector"
	"github.com/otherpirate/dbaas-metric-collector/model"
)

func main() {
	http.HandleFunc("/", hello)
	http.HandleFunc("/loading", loading)
	http.HandleFunc("/showing", showing)

	fmt.Println("listening...")
	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}

func hello(res http.ResponseWriter, req *http.Request) {
	fmt.Fprintln(res, "hello, world!")
}

func loading(res http.ResponseWriter, req *http.Request) {
	collector.GetDatabases()
	fmt.Fprintln(res, "Loaded!")
}

func showing(res http.ResponseWriter, req *http.Request) {
	res.Header().Set("Content-Type", "application/json")

	connection := model.GetConnection()
	defer connection.Session.Close()

	counters := model.DatabaseCounterLoad(connection)
	content, err := json.Marshal(counters)
	if err != nil {
		panic(err)
	}

	res.Write(content)
}
<commit_msg>Removig hello world and showing index page<commit_after>package main

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

	"github.com/otherpirate/dbaas-metric-collector/collector"
	"github.com/otherpirate/dbaas-metric-collector/model"
)

func main() {
	http.Handle("/", http.FileServer(http.Dir("page")))
	http.HandleFunc("/loading", loading)
	http.HandleFunc("/showing", showing)

	fmt.Println("listening...")
	err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
	if err != nil {
		panic(err)
	}
}

func loading(res http.ResponseWriter, req *http.Request) {
	collector.GetDatabases()
	fmt.Fprintln(res, "Loaded!")
}

func showing(res http.ResponseWriter, req *http.Request) {
	res.Header().Set("Content-Type", "application/json")

	connection := model.GetConnection()
	defer connection.Session.Close()

	counters := model.DatabaseCounterLoad(connection)
	content, err := json.Marshal(counters)
	if err != nil {
		panic(err)
	}

	res.Write(content)
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"os"

	"github.com/michaelgaida/consul-mirror/configuration"
	"github.com/michaelgaida/consul-mirror/consul"
	"github.com/michaelgaida/consul-mirror/storage"
)

func main() {
	var (
		validate = flag.String("validate", "", "configuration file to be validated")
	)

	flag.Parse()

	if *validate != "" {
		// check the new config
		testConfiguration := configuration.GetConfig(*validate)
		os.Exit(testConfiguration.ValidateConfiguration())
	}

	config := configuration.GetConfig("config.json")
	if config.Debug {
		fmt.Printf(config.PrintDebug())
	}

	// s := storage.Mssql{}
	conn := storage.OpenConnection(config)
	defer conn.Close()

	consul := consul.GetConsul(config)
	kvs := consul.GetKVs("")
	if kvs == nil {
	}
	conn.WriteKVs(kvs)
	services := consul.GetServices()
	if services == nil {

	}
	nodes := consul.GetNodes()
	if nodes == nil {

	}
}
<commit_msg>changed cli parsing<commit_after>package main

import (
	"fmt"
	"log"
	"os"

	"github.com/michaelgaida/consul-mirror/configuration"
	"github.com/michaelgaida/consul-mirror/consul"
	"github.com/michaelgaida/consul-mirror/storage"
	"github.com/urfave/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "consul-mirror"
	app.Version = "0.1.0"

	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "validate",
			Value: "",
			Usage: "configuration file to be validated",
		},
		cli.BoolFlag{
			Name:  "verbose",
			Usage: "Switch on the verbose mode",
		},
	}

	app.Commands = []cli.Command{
		cli.Command{
			Name:  "import",
			Usage: "import from consul",
		},
		cli.Command{
			Name:  "export",
			Usage: "export from consul",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "dc",
					Usage: "keep the dcs",
				},
			},
		},
	}

	app.Action = func(c *cli.Context) error {
		if c.String("validate") != "" {
			testConfiguration := configuration.GetConfig(c.String("validate"))
			os.Exit(testConfiguration.ValidateConfiguration())
		}
		if (!(c.Bool("import"))) && (!(c.Bool("export"))) {
			fmt.Println("Nothing to do")
			os.Exit(0)
		}
		config := configuration.GetConfig("config.json")
		if c.Bool("verbose") {
			config.Debug = true
		}
		if config.Debug {
			log.Printf(config.PrintDebug())
		}

		// s := storage.Mssql{}
		conn := storage.OpenConnection(config)
		// defer conn.Close()

		consul := consul.GetConsul(config)

		dcs := consul.GetDCs()

		if c.Bool("export") {
			kvs := consul.GetKVs("", dcs)
			if kvs == nil {
			}
			conn.WriteKVs(kvs)
		}

		if c.Bool("import") {
			kvs, _ := conn.GetKVs()
			err := consul.WriteKVs(kvs, c.Bool("dc"))
			if err != nil {
				log.Fatal(err)
			}
		}

		return nil
	}

	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

// about using johnniedoe/contrib/gzip:
// johnniedoe's fork fixes a critical issue for which .String resulted in
// an ERR_DECODING_FAILED. This is an actual pull request on the contrib
// repo, but apparently, gin is dead.

import (
	"encoding/gob"
	"fmt"

	"git.zxq.co/ripple/rippleapi/app"
	"git.zxq.co/ripple/schiavolib"
	"git.zxq.co/x/rs"
	"github.com/fatih/structs"
	"github.com/getsentry/raven-go"
	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"github.com/johnniedoe/contrib/gzip"
	"github.com/thehowl/conf"
	"github.com/thehowl/qsql"
	"gopkg.in/mailgun/mailgun-go.v1"
)

// version is the version of hanayo
const version = "v1.0.4"

var (
	config struct {
		ListenTo string `description:"ip:port from which to take requests."`
		Unix     bool   `description:"Whether ListenTo is an unix socket."`

		DSN string `description:"MySQL server DSN"`

		CookieSecret string

		RedisEnable         bool
		RedisMaxConnections int
		RedisNetwork        string
		RedisAddress        string
		RedisPassword       string

		AvatarURL     string
		BaseURL       string
		DiscordServer string

		API       string
		BanchoAPI string
		APISecret string

		IP_API string

		Offline          bool   `description:"If this is true, files will be served from the local server instead of the CDN."`
		MainRippleFolder string `description:"Folder where all the non-go projects are contained, such as old-frontend, lets, ci-system."`
		AvatarsFolder    string `description:"location folder of avatars"`

		MailgunDomain        string
		MailgunPrivateAPIKey string
		MailgunPublicAPIKey  string
		MailgunFrom          string

		RecaptchaSite    string
		RecaptchaPrivate string

		DiscordOAuthID     string
		DiscordOAuthSecret string
		DonorBotURL        string
		DonorBotSecret     string

		SentryDSN string

		AnalyticsID string
	}
	configMap map[string]interface{}
	db        *sqlx.DB
	qb        *qsql.DB
	mg        mailgun.Mailgun
)

func main() {
	fmt.Println("hanayo " + version)

	err := conf.Load(&config, "hanayo.conf")
	switch err {
	case nil:
		// carry on
	case conf.ErrNoFile:
		conf.Export(config, "hanayo.conf")
		fmt.Println("The configuration file was not found. We created one for you.")
		return
	default:
		panic(err)
	}

	var configDefaults = map[*string]string{
		&config.ListenTo:         ":45221",
		&config.CookieSecret:     rs.String(46),
		&config.AvatarURL:        "https://a.ripple.moe",
		&config.BaseURL:          "https://ripple.moe",
		&config.BanchoAPI:        "https://c.ripple.moe",
		&config.API:              "http://localhost:40001/api/v1/",
		&config.APISecret:        "Potato",
		&config.IP_API:           "https://ip.zxq.co",
		&config.DiscordServer:    "#",
		&config.MainRippleFolder: "/home/ripple/ripple",
		&config.MailgunFrom:      `"Ripple" <noreply@ripple.moe>`,
	}
	for key, value := range configDefaults {
		if *key == "" {
			*key = value
		}
	}

	configMap = structs.Map(config)

	// initialise db
	db, err = sqlx.Open("mysql", config.DSN)
	if err != nil {
		panic(err)
	}
	qb = qsql.New(db.DB)
	if err != nil {
		panic(err)
	}

	// initialise mailgun
	mg = mailgun.NewMailgun(
		config.MailgunDomain,
		config.MailgunPrivateAPIKey,
		config.MailgunPublicAPIKey,
	)

	if gin.Mode() == gin.DebugMode {
		fmt.Println("Development environment detected. Starting fsnotify on template folder...")
		err := reloader()
		if err != nil {
			fmt.Println(err)
		}
	}

	schiavo.Prefix = "hanayo"
	schiavo.Bunker.Send(fmt.Sprintf("STARTUATO, mode: %s", gin.Mode()))

	// even if it's not release, we say that it's release
	// so that gin doesn't spam
	gin.SetMode(gin.ReleaseMode)

	gobRegisters := []interface{}{
		[]message{},
		errorMessage{},
		infoMessage{},
		neutralMessage{},
		warningMessage{},
		successMessage{},
	}
	for _, el := range gobRegisters {
		gob.Register(el)
	}

	fmt.Println("Importing templates...")
	loadTemplates("")

	fmt.Println("Setting up rate limiter...")
	setUpLimiter()

	fmt.Println("Exporting configuration...")

	conf.Export(config, "hanayo.conf")

	httpLoop()
}

func httpLoop() {
	for {
		e := generateEngine()
		fmt.Println("Starting webserver...")
		if !startuato(e) {
			break
		}
	}
}

func generateEngine() *gin.Engine {
	fmt.Println("Starting session system...")
	var store sessions.Store
	if config.RedisMaxConnections != 0 {
		var err error
		store, err = sessions.NewRedisStore(
			config.RedisMaxConnections,
			config.RedisNetwork,
			config.RedisAddress,
			config.RedisPassword,
			[]byte(config.CookieSecret),
		)
		if err != nil {
			fmt.Println(err)
			store = sessions.NewCookieStore([]byte(config.CookieSecret))
		}
	} else {
		store = sessions.NewCookieStore([]byte(config.CookieSecret))
	}

	r := gin.Default()

	// sentry
	if config.SentryDSN != "" {
		ravenClient, err := raven.New(config.SentryDSN)
		if err != nil {
			fmt.Println(err)
		} else {
			r.Use(app.Recovery(ravenClient, false))
		}
	}

	r.Use(
		gzip.Gzip(gzip.DefaultCompression),
		checkRedirect,
		sessions.Sessions("session", store),
		sessionInitializer(),
		rateLimiter(false),
		twoFALock,
	)

	r.Static("/static", "static")
	r.StaticFile("/favicon.ico", "static/favicon.ico")

	r.POST("/login", loginSubmit)
	r.GET("/logout", logout)

	r.GET("/register", register)
	r.POST("/register", registerSubmit)
	r.GET("/register/verify", verifyAccount)
	r.GET("/register/welcome", welcome)

	r.GET("/u/:user", userProfile)

	r.POST("/pwreset", passwordReset)
	r.GET("/pwreset/continue", passwordResetContinue)
	r.POST("/pwreset/continue", passwordResetContinueSubmit)

	r.GET("/2fa_gateway", tfaGateway)
	r.GET("/2fa_gateway/clear", clear2fa)
	r.GET("/2fa_gateway/verify", verify2fa)

	r.GET("/irc/generate", ircGenToken)

	r.GET("/settings/password", changePassword)
	r.POST("/settings/password", changePasswordSubmit)
	r.POST("/settings/userpage/parse", parseBBCode)
	r.POST("/settings/avatar", avatarSubmit)
	r.POST("/settings/2fa/disable", disable2fa)
	r.GET("/settings/discord/finish", discordFinish)
	r.POST("/settings/profbackground/:type", profBackground)

	r.GET("/donate/rates", getRates)

	loadSimplePages(r)

	r.NoRoute(notFound)

	return r
}

const alwaysRespondText = `Ooops! Looks like something went really wrong while trying to process your request.
Perhaps report this to a Ripple developer?
Retrying doing again what you were trying to do might work, too.`
<commit_msg>⬆ v1.1.0 ⬆<commit_after>package main

// about using johnniedoe/contrib/gzip:
// johnniedoe's fork fixes a critical issue for which .String resulted in
// an ERR_DECODING_FAILED. This is an actual pull request on the contrib
// repo, but apparently, gin is dead.

import (
	"encoding/gob"
	"fmt"

	"git.zxq.co/ripple/rippleapi/app"
	"git.zxq.co/ripple/schiavolib"
	"git.zxq.co/x/rs"
	"github.com/fatih/structs"
	"github.com/getsentry/raven-go"
	"github.com/gin-gonic/contrib/sessions"
	"github.com/gin-gonic/gin"
	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
	"github.com/johnniedoe/contrib/gzip"
	"github.com/thehowl/conf"
	"github.com/thehowl/qsql"
	"gopkg.in/mailgun/mailgun-go.v1"
)

// version is the version of hanayo
const version = "v1.1.0"

var (
	config struct {
		ListenTo string `description:"ip:port from which to take requests."`
		Unix     bool   `description:"Whether ListenTo is an unix socket."`

		DSN string `description:"MySQL server DSN"`

		CookieSecret string

		RedisEnable         bool
		RedisMaxConnections int
		RedisNetwork        string
		RedisAddress        string
		RedisPassword       string

		AvatarURL     string
		BaseURL       string
		DiscordServer string

		API       string
		BanchoAPI string
		APISecret string

		IP_API string

		Offline          bool   `description:"If this is true, files will be served from the local server instead of the CDN."`
		MainRippleFolder string `description:"Folder where all the non-go projects are contained, such as old-frontend, lets, ci-system."`
		AvatarsFolder    string `description:"location folder of avatars"`

		MailgunDomain        string
		MailgunPrivateAPIKey string
		MailgunPublicAPIKey  string
		MailgunFrom          string

		RecaptchaSite    string
		RecaptchaPrivate string

		DiscordOAuthID     string
		DiscordOAuthSecret string
		DonorBotURL        string
		DonorBotSecret     string

		SentryDSN string

		AnalyticsID string
	}
	configMap map[string]interface{}
	db        *sqlx.DB
	qb        *qsql.DB
	mg        mailgun.Mailgun
)

func main() {
	fmt.Println("hanayo " + version)

	err := conf.Load(&config, "hanayo.conf")
	switch err {
	case nil:
		// carry on
	case conf.ErrNoFile:
		conf.Export(config, "hanayo.conf")
		fmt.Println("The configuration file was not found. We created one for you.")
		return
	default:
		panic(err)
	}

	var configDefaults = map[*string]string{
		&config.ListenTo:         ":45221",
		&config.CookieSecret:     rs.String(46),
		&config.AvatarURL:        "https://a.ripple.moe",
		&config.BaseURL:          "https://ripple.moe",
		&config.BanchoAPI:        "https://c.ripple.moe",
		&config.API:              "http://localhost:40001/api/v1/",
		&config.APISecret:        "Potato",
		&config.IP_API:           "https://ip.zxq.co",
		&config.DiscordServer:    "#",
		&config.MainRippleFolder: "/home/ripple/ripple",
		&config.MailgunFrom:      `"Ripple" <noreply@ripple.moe>`,
	}
	for key, value := range configDefaults {
		if *key == "" {
			*key = value
		}
	}

	configMap = structs.Map(config)

	// initialise db
	db, err = sqlx.Open("mysql", config.DSN)
	if err != nil {
		panic(err)
	}
	qb = qsql.New(db.DB)
	if err != nil {
		panic(err)
	}

	// initialise mailgun
	mg = mailgun.NewMailgun(
		config.MailgunDomain,
		config.MailgunPrivateAPIKey,
		config.MailgunPublicAPIKey,
	)

	if gin.Mode() == gin.DebugMode {
		fmt.Println("Development environment detected. Starting fsnotify on template folder...")
		err := reloader()
		if err != nil {
			fmt.Println(err)
		}
	}

	schiavo.Prefix = "hanayo"
	schiavo.Bunker.Send(fmt.Sprintf("STARTUATO, mode: %s", gin.Mode()))

	// even if it's not release, we say that it's release
	// so that gin doesn't spam
	gin.SetMode(gin.ReleaseMode)

	gobRegisters := []interface{}{
		[]message{},
		errorMessage{},
		infoMessage{},
		neutralMessage{},
		warningMessage{},
		successMessage{},
	}
	for _, el := range gobRegisters {
		gob.Register(el)
	}

	fmt.Println("Importing templates...")
	loadTemplates("")

	fmt.Println("Setting up rate limiter...")
	setUpLimiter()

	fmt.Println("Exporting configuration...")

	conf.Export(config, "hanayo.conf")

	httpLoop()
}

func httpLoop() {
	for {
		e := generateEngine()
		fmt.Println("Starting webserver...")
		if !startuato(e) {
			break
		}
	}
}

func generateEngine() *gin.Engine {
	fmt.Println("Starting session system...")
	var store sessions.Store
	if config.RedisMaxConnections != 0 {
		var err error
		store, err = sessions.NewRedisStore(
			config.RedisMaxConnections,
			config.RedisNetwork,
			config.RedisAddress,
			config.RedisPassword,
			[]byte(config.CookieSecret),
		)
		if err != nil {
			fmt.Println(err)
			store = sessions.NewCookieStore([]byte(config.CookieSecret))
		}
	} else {
		store = sessions.NewCookieStore([]byte(config.CookieSecret))
	}

	r := gin.Default()

	// sentry
	if config.SentryDSN != "" {
		ravenClient, err := raven.New(config.SentryDSN)
		if err != nil {
			fmt.Println(err)
		} else {
			r.Use(app.Recovery(ravenClient, false))
		}
	}

	r.Use(
		gzip.Gzip(gzip.DefaultCompression),
		checkRedirect,
		sessions.Sessions("session", store),
		sessionInitializer(),
		rateLimiter(false),
		twoFALock,
	)

	r.Static("/static", "static")
	r.StaticFile("/favicon.ico", "static/favicon.ico")

	r.POST("/login", loginSubmit)
	r.GET("/logout", logout)

	r.GET("/register", register)
	r.POST("/register", registerSubmit)
	r.GET("/register/verify", verifyAccount)
	r.GET("/register/welcome", welcome)

	r.GET("/u/:user", userProfile)

	r.POST("/pwreset", passwordReset)
	r.GET("/pwreset/continue", passwordResetContinue)
	r.POST("/pwreset/continue", passwordResetContinueSubmit)

	r.GET("/2fa_gateway", tfaGateway)
	r.GET("/2fa_gateway/clear", clear2fa)
	r.GET("/2fa_gateway/verify", verify2fa)

	r.GET("/irc/generate", ircGenToken)

	r.GET("/settings/password", changePassword)
	r.POST("/settings/password", changePasswordSubmit)
	r.POST("/settings/userpage/parse", parseBBCode)
	r.POST("/settings/avatar", avatarSubmit)
	r.POST("/settings/2fa/disable", disable2fa)
	r.GET("/settings/discord/finish", discordFinish)
	r.POST("/settings/profbackground/:type", profBackground)

	r.GET("/donate/rates", getRates)

	loadSimplePages(r)

	r.NoRoute(notFound)

	return r
}

const alwaysRespondText = `Ooops! Looks like something went really wrong while trying to process your request.
Perhaps report this to a Ripple developer?
Retrying doing again what you were trying to do might work, too.`
<|endoftext|>