<commit_before>package main

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	"github.com/BurntSushi/toml"
	"github.com/ssut/pocketnpm/db"
	"github.com/ssut/pocketnpm/log"
	"github.com/ssut/pocketnpm/npm"
	"github.com/urfave/cli"
)

func main() {
	log.InitLogger()

	app := cli.NewApp()
	app.Name = "pocketnpm"
	app.Usage = "A simple but fast npm mirror client & server"
	app.Version = Version
	app.Flags = []cli.Flag{
		cli.BoolFlag{Name: "debug, d"},
		cli.IntFlag{Name: "cpus", Value: runtime.NumCPU()},
	}
	app.EnableBashCompletion = true

	app.Before = func(c *cli.Context) error {
		if c.GlobalBool("debug") {
			log.SetDebug()
			log.Debug("Activated debug mode")
		}

		cpus := c.GlobalInt("cpus")
		runtime.GOMAXPROCS(cpus)

		return nil
	}

	app.Commands = []cli.Command{
		{
			Name:    "init",
			Aliases: []string{"i"},
			Usage:   "Generate an example config file",
			Flags: []cli.Flag{
				cli.StringFlag{Name: "path, p", Value: "config.toml"},
			},
			Action: func(c *cli.Context) error {
				path, _ := filepath.Abs(c.String("path"))
				out, err := os.Create(path)
				if err != nil {
					log.Fatal(err)
				}
				defer out.Close()

				defaultToml, _ := defaultTomlBytes()
				_, err = out.Write(defaultToml)
				if err != nil {
					log.Fatal(err)
				}

				return nil
			},
		},
		{
			Name:    "mirror",
			Aliases: []string{"m"},
			Usage:   "Run mirroring process",
			Flags: []cli.Flag{
				cli.StringFlag{Name: "config, c", Value: "config.toml"},
			},
			Action: func(c *cli.Context) error {
				confPath, _ := filepath.Abs(c.String("config"))
				b, err := ioutil.ReadFile(confPath)
				if err != nil {
					log.Fatal(err)
				}

				var conf PocketConfig
				if _, err := toml.Decode(string(b), &conf); err != nil {
					log.Fatalf("Error in config file: %s", err)
				}

				pb := db.NewPocketBase(&conf.DB)
				client := npm.NewMirrorClient(pb, &conf.Mirror)
				client.Run()
				return nil
			},
		},
	}

	app.Run(os.Args)
}
<commit_msg>main: support pprof profiling<commit_after>package main

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"runtime"

	"net/http"
	_ "net/http/pprof"

	"github.com/BurntSushi/toml"
	"github.com/ssut/pocketnpm/db"
	"github.com/ssut/pocketnpm/log"
	"github.com/ssut/pocketnpm/npm"
	"github.com/urfave/cli"
)

func main() {
	log.InitLogger()

	app := cli.NewApp()
	app.Name = "pocketnpm"
	app.Usage = "A simple but fast npm mirror client & server"
	app.Version = Version
	app.Flags = []cli.Flag{
		cli.BoolFlag{Name: "debug, d"},
		cli.BoolFlag{Name: "profile, p", Usage: "activate pprof on port 18080 for profiling goroutines"},
		cli.IntFlag{Name: "cpus", Value: runtime.NumCPU()},
	}
	app.EnableBashCompletion = true

	app.Before = func(c *cli.Context) error {
		if c.GlobalBool("debug") {
			log.SetDebug()
			log.Debug("Activated debug mode")
		}

		if c.GlobalBool("profile") {
			log.Info("Starting pprof server on port 18080")
			go http.ListenAndServe("localhost:18080", nil)
		}

		cpus := c.GlobalInt("cpus")
		runtime.GOMAXPROCS(cpus)

		return nil
	}

	app.Commands = []cli.Command{
		{
			Name:    "init",
			Aliases: []string{"i"},
			Usage:   "Generate an example config file",
			Flags: []cli.Flag{
				cli.StringFlag{Name: "path, p", Value: "config.toml"},
			},
			Action: func(c *cli.Context) error {
				path, _ := filepath.Abs(c.String("path"))
				out, err := os.Create(path)
				if err != nil {
					log.Fatal(err)
				}
				defer out.Close()

				defaultToml, _ := defaultTomlBytes()
				_, err = out.Write(defaultToml)
				if err != nil {
					log.Fatal(err)
				}

				return nil
			},
		},
		{
			Name:    "mirror",
			Aliases: []string{"m"},
			Usage:   "Run mirroring process",
			Flags: []cli.Flag{
				cli.StringFlag{Name: "config, c", Value: "config.toml"},
			},
			Action: func(c *cli.Context) error {
				confPath, _ := filepath.Abs(c.String("config"))
				b, err := ioutil.ReadFile(confPath)
				if err != nil {
					log.Fatal(err)
				}

				var conf PocketConfig
				if _, err := toml.Decode(string(b), &conf); err != nil {
					log.Fatalf("Error in config file: %s", err)
				}

				pb := db.NewPocketBase(&conf.DB)
				client := npm.NewMirrorClient(pb, &conf.Mirror)
				client.Run()
				return nil
			},
		},
	}

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


<commit_before>package main

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

	"github.com/bitrise-io/go-utils/cmdex"
	"github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-utils/pathutil"
	"github.com/bitrise-tools/go-xamarin/builder"
	"github.com/bitrise-tools/go-xamarin/buildtool"
	"github.com/bitrise-tools/go-xamarin/constants"
	"github.com/bitrise-tools/go-xamarin/project"
	shellquote "github.com/kballard/go-shellquote"
)

// ConfigsModel ...
type ConfigsModel struct {
	XamarinSolution      string
	XamarinConfiguration string
	XamarinPlatform      string
	ProjectTypeWhitelist string

	AndroidCustomOptions string
	IOSCustomOptions     string
	TvOSCustomOptions    string
	MacOSCustomOptions   string
	ForceMDTool          string

	DeployDir string
}

func createConfigsModelFromEnvs() ConfigsModel {
	return ConfigsModel{
		XamarinSolution:      os.Getenv("xamarin_solution"),
		XamarinConfiguration: os.Getenv("xamarin_configuration"),
		XamarinPlatform:      os.Getenv("xamarin_platform"),
		ProjectTypeWhitelist: os.Getenv("project_type_whitelist"),

		AndroidCustomOptions: os.Getenv("android_build_command_custom_options"),
		IOSCustomOptions:     os.Getenv("ios_build_command_custom_options"),
		TvOSCustomOptions:    os.Getenv("tvos_build_command_custom_options"),
		MacOSCustomOptions:   os.Getenv("macos_build_command_custom_options"),
		ForceMDTool:          os.Getenv("force_mdtool"),

		DeployDir: os.Getenv("BITRISE_DEPLOY_DIR"),
	}
}

func (configs ConfigsModel) print() {
	log.Info("Configs:")

	log.Detail("- XamarinSolution: %s", configs.XamarinSolution)
	log.Detail("- XamarinConfiguration: %s", configs.XamarinConfiguration)
	log.Detail("- XamarinPlatform: %s", configs.XamarinPlatform)
	log.Detail("- ProjectTypeWhitelist: %s", configs.ProjectTypeWhitelist)

	log.Info("Experimental Configs:")

	log.Detail("- AndroidCustomOptions: %s", configs.AndroidCustomOptions)
	log.Detail("- IOSCustomOptions: %s", configs.IOSCustomOptions)
	log.Detail("- TvOSCustomOptions: %s", configs.TvOSCustomOptions)
	log.Detail("- MacOSCustomOptions: %s", configs.MacOSCustomOptions)
	log.Detail("- ForceMDTool: %s", configs.ForceMDTool)

	log.Info("Other Configs:")

	log.Detail("- DeployDir: %s", configs.DeployDir)
}

func (configs ConfigsModel) validate() error {
	// required
	if configs.XamarinSolution == "" {
		return errors.New("No XamarinSolution parameter specified!")
	}
	if exist, err := pathutil.IsPathExists(configs.XamarinSolution); err != nil {
		return fmt.Errorf("Failed to check if XamarinSolution exist at: %s, error: %s", configs.XamarinSolution, err)
	} else if !exist {
		return fmt.Errorf("XamarinSolution not exist at: %s", configs.XamarinSolution)
	}

	if configs.XamarinConfiguration == "" {
		return errors.New("No XamarinConfiguration parameter specified!")
	}

	if configs.XamarinPlatform == "" {
		return errors.New("No XamarinPlatform parameter specified!")
	}

	return nil
}

func exportEnvironmentWithEnvman(keyStr, valueStr string) error {
	cmd := cmdex.NewCommand("envman", "add", "--key", keyStr)
	cmd.SetStdin(strings.NewReader(valueStr))
	return cmd.Run()
}

func exportZipedArtifactDir(pth, deployDir, envKey string) error {
	parentDir := filepath.Dir(pth)
	dirName := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, dirName+".zip")
	cmd := cmdex.NewCommand("/usr/bin/zip", "-rTy", deployPth, dirName)
	cmd.SetDir(parentDir)
	out, err := cmd.RunAndReturnTrimmedCombinedOutput()
	if err != nil {
		return fmt.Errorf("Failed to zip dir: %s, output: %s, error: %s", pth, out, err)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	log.Done("artifact path (%s) is available in (%s) environment variable", deployPth, envKey)

	return nil
}

func exportArtifactDir(pth, deployDir, envKey string) error {
	base := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, base)

	if err := cmdex.CopyDir(pth, deployPth, false); err != nil {
		return fmt.Errorf("Failed to move artifact (%s) to (%s)", pth, deployPth)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	log.Done("artifact path (%s) is available in (%s) environment variable", deployPth, envKey)

	return nil
}

func exportArtifactFile(pth, deployDir, envKey string) error {
	base := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, base)

	if err := cmdex.CopyFile(pth, deployPth); err != nil {
		return fmt.Errorf("Failed to move artifact (%s) to (%s)", pth, deployPth)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	log.Done("artifact path (%s) is available in (%s) environment variable", deployPth, envKey)

	return nil
}

func main() {
	configs := createConfigsModelFromEnvs()

	fmt.Println()
	configs.print()

	if err := configs.validate(); err != nil {
		fmt.Println()
		log.Error("Issue with input: %s", err)
		fmt.Println()

		os.Exit(1)
	}

	// parse project type filters
	projectTypeWhitelist := []constants.ProjectType{}
	if len(configs.ProjectTypeWhitelist) > 0 {
		split := strings.Split(configs.ProjectTypeWhitelist, ",")
		for _, item := range split {
			item := strings.TrimSpace(item)
			projectType, err := constants.ParseProjectType(item)
			if err != nil {
				log.Error("Failed to parse project type (%s), error: %s", item, err)
				os.Exit(1)
			}
			projectTypeWhitelist = append(projectTypeWhitelist, projectType)
		}
	}
	// ---

	// prepare custom options
	projectTypeCustomOptions := map[constants.ProjectType][]string{}
	projectTypeRawCustomOptions := map[constants.ProjectType]string{
		constants.ProjectTypeAndroid: configs.AndroidCustomOptions,
		constants.ProjectTypeIOS:     configs.IOSCustomOptions,
		constants.ProjectTypeTvOS:    configs.TvOSCustomOptions,
		constants.ProjectTypeMacOS:   configs.MacOSCustomOptions,
	}
	for projectType, rawOptions := range projectTypeRawCustomOptions {
		if rawOptions == "" {
			continue
		}

		split, err := shellquote.Split(rawOptions)
		if err != nil {
			log.Error("Failed to split options (%s), error: %s", err)
		}
		projectTypeCustomOptions[projectType] = split
	}
	// ---

	//
	// build
	fmt.Println()
	log.Info("Building all projects in solution: %s", configs.XamarinSolution)

	builder, err := builder.New(configs.XamarinSolution, projectTypeWhitelist, (configs.ForceMDTool == "yes"))
	if err != nil {
		log.Error("Failed to create xamarin builder, error: %s", err)
		os.Exit(1)
	}

	prepareCallback := func(project project.Model, command *buildtool.EditableCommand) {
		options, ok := projectTypeCustomOptions[project.ProjectType]
		if ok {
			(*command).AppendOptions(options)
		}
	}

	callback := func(project project.Model, command buildtool.PrintableCommand, alreadyPerformed bool) {
		fmt.Println()
		log.Info("Building project: %s", project.Name)
		log.Done("$ %s", command.PrintableCommand())
		if alreadyPerformed {
			log.Warn("build command already performed, skipping...")
		}
		fmt.Println()
	}

	warnings, err := builder.BuildAllProjects(configs.XamarinConfiguration, configs.XamarinPlatform, prepareCallback, callback)
	if len(warnings) > 0 {
		log.Warn("Build warnings:")
		for _, warning := range warnings {
			log.Warn(warning)
		}
	}
	if err != nil {
		log.Error("Build failed, error: %s", err)
		os.Exit(1)
	}

	output, warnings := builder.CollectOutput(configs.XamarinConfiguration, configs.XamarinPlatform)
	if len(warnings) > 0 {
		log.Warn("Output warnings:")
		for _, warning := range warnings {
			log.Warn(warning)
		}
	}
	// ---

	// export outputs
	fmt.Println()
	log.Info("Exporting generated outputs...")

	for projectType, outputMap := range output {
		fmt.Println()
		log.Info("%s outputs:", projectType)

		switch projectType {
		case constants.ProjectTypeIOS:
			xcarchivePth, ok := outputMap[constants.OutputTypeXCArchive]
			if ok {
				log.Detail("exporintg iOS xcarchive: %s", xcarchivePth)
				if err := exportArtifactDir(xcarchivePth, configs.DeployDir, "BITRISE_IOS_XCARCHIVE_PATH"); err != nil {
					log.Error("Failed to export xcarchive, error: %s", err)
					os.Exit(1)
				}
			}
			ipaPth, ok := outputMap[constants.OutputTypeIPA]
			if ok {
				log.Detail("exporintg iOS ipa: %s", ipaPth)
				if err := exportArtifactFile(ipaPth, configs.DeployDir, "BITRISE_IOS_IPA_PATH"); err != nil {
					log.Error("Failed to export ipa, error: %s", err)
					os.Exit(1)
				}
			}
			dsymPth, ok := outputMap[constants.OutputTypeDSYM]
			if ok {
				log.Detail("exporintg iOS dSYM: %s", dsymPth)
				if err := exportZipedArtifactDir(dsymPth, configs.DeployDir, "BITRISE_IOS_DSYM_PATH"); err != nil {
					log.Error("Failed to export dsym, error: %s", err)
					os.Exit(1)
				}
			}
		case constants.ProjectTypeAndroid:
			apkPth, ok := outputMap[constants.OutputTypeAPK]
			if ok {
				log.Detail("exporintg apk: %s", apkPth)
				if err := exportArtifactFile(apkPth, configs.DeployDir, "BITRISE_APK_PATH"); err != nil {
					log.Error("Failed to export apk, error: %s", err)
					os.Exit(1)
				}
			}
		case constants.ProjectTypeMacOS:
			xcarchivePth, ok := outputMap[constants.OutputTypeXCArchive]
			if ok {
				log.Detail("exporintg macOS xcarchive: %s", xcarchivePth)
				if err := exportArtifactDir(xcarchivePth, configs.DeployDir, "BITRISE_MACOS_XCARCHIVE_PATH"); err != nil {
					log.Error("Failed to export xcarchive, error: %s", err)
					os.Exit(1)
				}
			}
			appPth, ok := outputMap[constants.OutputTypeAPP]
			if ok {
				log.Detail("exporintg macOS app: %s", appPth)
				if err := exportArtifactDir(appPth, configs.DeployDir, "BITRISE_MACOS_APP_PATH"); err != nil {
					log.Error("Failed to export xcarchive, error: %s", err)
					os.Exit(1)
				}
			}
			pkgPth, ok := outputMap[constants.OutputTypePKG]
			if ok {
				log.Detail("exporintg macOS pkg: %s", pkgPth)
				if err := exportArtifactFile(pkgPth, configs.DeployDir, "BITRISE_MACOS_PKG_PATH"); err != nil {
					log.Error("Failed to export pkg, error: %s", err)
					os.Exit(1)
				}
			}
		case constants.ProjectTypeTvOS:
			xcarchivePth, ok := outputMap[constants.OutputTypeXCArchive]
			if ok {
				log.Detail("exporintg tvOS xcarchive: %s", xcarchivePth)
				if err := exportArtifactDir(xcarchivePth, configs.DeployDir, "BITRISE_TVOS_XCARCHIVE_PATH"); err != nil {
					log.Error("Failed to export xcarchive, error: %s", err)
					os.Exit(1)
				}
			}
			ipaPth, ok := outputMap[constants.OutputTypeIPA]
			if ok {
				log.Detail("exporintg tvOS ipa: %s", ipaPth)
				if err := exportArtifactFile(ipaPth, configs.DeployDir, "BITRISE_TVOS_IPA_PATH"); err != nil {
					log.Error("Failed to export ipa, error: %s", err)
					os.Exit(1)
				}
			}
			dsymPth, ok := outputMap[constants.OutputTypeDSYM]
			if ok {
				log.Detail("exporintg tvOS dSYM: %s", dsymPth)
				if err := exportZipedArtifactDir(dsymPth, configs.DeployDir, "BITRISE_TVOS_DSYM_PATH"); err != nil {
					log.Error("Failed to export dsym, error: %s", err)
					os.Exit(1)
				}
			}
		}
	}
	// ---
}
<commit_msg>godeps update fix<commit_after>package main

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

	"github.com/bitrise-io/go-utils/cmdex"
	"github.com/bitrise-io/go-utils/log"
	"github.com/bitrise-io/go-utils/pathutil"
	"github.com/bitrise-tools/go-xamarin/builder"
	"github.com/bitrise-tools/go-xamarin/buildtool"
	"github.com/bitrise-tools/go-xamarin/constants"
	"github.com/bitrise-tools/go-xamarin/project"
	shellquote "github.com/kballard/go-shellquote"
)

// ConfigsModel ...
type ConfigsModel struct {
	XamarinSolution      string
	XamarinConfiguration string
	XamarinPlatform      string
	ProjectTypeWhitelist string

	AndroidCustomOptions string
	IOSCustomOptions     string
	TvOSCustomOptions    string
	MacOSCustomOptions   string
	ForceMDTool          string

	DeployDir string
}

func createConfigsModelFromEnvs() ConfigsModel {
	return ConfigsModel{
		XamarinSolution:      os.Getenv("xamarin_solution"),
		XamarinConfiguration: os.Getenv("xamarin_configuration"),
		XamarinPlatform:      os.Getenv("xamarin_platform"),
		ProjectTypeWhitelist: os.Getenv("project_type_whitelist"),

		AndroidCustomOptions: os.Getenv("android_build_command_custom_options"),
		IOSCustomOptions:     os.Getenv("ios_build_command_custom_options"),
		TvOSCustomOptions:    os.Getenv("tvos_build_command_custom_options"),
		MacOSCustomOptions:   os.Getenv("macos_build_command_custom_options"),
		ForceMDTool:          os.Getenv("force_mdtool"),

		DeployDir: os.Getenv("BITRISE_DEPLOY_DIR"),
	}
}

func (configs ConfigsModel) print() {
	log.Info("Configs:")

	log.Detail("- XamarinSolution: %s", configs.XamarinSolution)
	log.Detail("- XamarinConfiguration: %s", configs.XamarinConfiguration)
	log.Detail("- XamarinPlatform: %s", configs.XamarinPlatform)
	log.Detail("- ProjectTypeWhitelist: %s", configs.ProjectTypeWhitelist)

	log.Info("Experimental Configs:")

	log.Detail("- AndroidCustomOptions: %s", configs.AndroidCustomOptions)
	log.Detail("- IOSCustomOptions: %s", configs.IOSCustomOptions)
	log.Detail("- TvOSCustomOptions: %s", configs.TvOSCustomOptions)
	log.Detail("- MacOSCustomOptions: %s", configs.MacOSCustomOptions)
	log.Detail("- ForceMDTool: %s", configs.ForceMDTool)

	log.Info("Other Configs:")

	log.Detail("- DeployDir: %s", configs.DeployDir)
}

func (configs ConfigsModel) validate() error {
	// required
	if configs.XamarinSolution == "" {
		return errors.New("No XamarinSolution parameter specified!")
	}
	if exist, err := pathutil.IsPathExists(configs.XamarinSolution); err != nil {
		return fmt.Errorf("Failed to check if XamarinSolution exist at: %s, error: %s", configs.XamarinSolution, err)
	} else if !exist {
		return fmt.Errorf("XamarinSolution not exist at: %s", configs.XamarinSolution)
	}

	if configs.XamarinConfiguration == "" {
		return errors.New("No XamarinConfiguration parameter specified!")
	}

	if configs.XamarinPlatform == "" {
		return errors.New("No XamarinPlatform parameter specified!")
	}

	return nil
}

func exportEnvironmentWithEnvman(keyStr, valueStr string) error {
	cmd := cmdex.NewCommand("envman", "add", "--key", keyStr)
	cmd.SetStdin(strings.NewReader(valueStr))
	return cmd.Run()
}

func exportZipedArtifactDir(pth, deployDir, envKey string) (string, error) {
	parentDir := filepath.Dir(pth)
	dirName := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, dirName+".zip")
	cmd := cmdex.NewCommand("/usr/bin/zip", "-rTy", deployPth, dirName)
	cmd.SetDir(parentDir)
	out, err := cmd.RunAndReturnTrimmedCombinedOutput()
	if err != nil {
		return "", fmt.Errorf("Failed to zip dir: %s, output: %s, error: %s", pth, out, err)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func exportArtifactDir(pth, deployDir, envKey string) (string, error) {
	base := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, base)

	if err := cmdex.CopyDir(pth, deployPth, false); err != nil {
		return "", fmt.Errorf("Failed to move artifact (%s) to (%s)", pth, deployPth)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func exportArtifactFile(pth, deployDir, envKey string) (string, error) {
	base := filepath.Base(pth)
	deployPth := filepath.Join(deployDir, base)

	if err := cmdex.CopyFile(pth, deployPth); err != nil {
		return "", fmt.Errorf("Failed to move artifact (%s) to (%s)", pth, deployPth)
	}

	if err := exportEnvironmentWithEnvman(envKey, deployPth); err != nil {
		return "", fmt.Errorf("Failed to export artifact path (%s) into (%s)", deployPth, envKey)
	}

	return deployPth, nil
}

func main() {
	configs := createConfigsModelFromEnvs()

	fmt.Println()
	configs.print()

	if err := configs.validate(); err != nil {
		fmt.Println()
		log.Error("Issue with input: %s", err)
		fmt.Println()

		os.Exit(1)
	}

	// parse project type filters
	projectTypeWhitelist := []constants.ProjectType{}
	if len(configs.ProjectTypeWhitelist) > 0 {
		split := strings.Split(configs.ProjectTypeWhitelist, ",")
		for _, item := range split {
			item := strings.TrimSpace(item)
			projectType, err := constants.ParseProjectType(item)
			if err != nil {
				log.Error("Failed to parse project type (%s), error: %s", item, err)
				os.Exit(1)
			}
			projectTypeWhitelist = append(projectTypeWhitelist, projectType)
		}
	}
	// ---

	// prepare custom options
	projectTypeCustomOptions := map[constants.ProjectType][]string{}
	projectTypeRawCustomOptions := map[constants.ProjectType]string{
		constants.ProjectTypeAndroid: configs.AndroidCustomOptions,
		constants.ProjectTypeIOS:     configs.IOSCustomOptions,
		constants.ProjectTypeTvOS:    configs.TvOSCustomOptions,
		constants.ProjectTypeMacOS:   configs.MacOSCustomOptions,
	}
	for projectType, rawOptions := range projectTypeRawCustomOptions {
		if rawOptions == "" {
			continue
		}

		split, err := shellquote.Split(rawOptions)
		if err != nil {
			log.Error("Failed to split options (%s), error: %s", err)
		}
		projectTypeCustomOptions[projectType] = split
	}
	// ---

	//
	// build
	fmt.Println()
	log.Info("Building all projects in solution: %s", configs.XamarinSolution)

	builder, err := builder.New(configs.XamarinSolution, projectTypeWhitelist, (configs.ForceMDTool == "yes"))
	if err != nil {
		log.Error("Failed to create xamarin builder, error: %s", err)
		os.Exit(1)
	}

	prepareCallback := func(project project.Model, command *buildtool.EditableCommand) {
		options, ok := projectTypeCustomOptions[project.ProjectType]
		if ok {
			(*command).SetCustomOptions(options...)
		}
	}

	callback := func(project project.Model, command buildtool.PrintableCommand, alreadyPerformed bool) {
		fmt.Println()
		log.Info("Building project: %s", project.Name)
		log.Done("$ %s", command.PrintableCommand())
		if alreadyPerformed {
			log.Warn("build command already performed, skipping...")
		}
		fmt.Println()
	}

	warnings, err := builder.BuildAllProjects(configs.XamarinConfiguration, configs.XamarinPlatform, prepareCallback, callback)
	if len(warnings) > 0 {
		log.Warn("Build warnings:")
		for _, warning := range warnings {
			log.Warn(warning)
		}
	}
	if err != nil {
		log.Error("Build failed, error: %s", err)
		os.Exit(1)
	}

	output, err := builder.CollectOutput(configs.XamarinConfiguration, configs.XamarinPlatform)
	if err != nil {
		log.Error("Failed to collect output, error: %s", err)
		os.Exit(1)
	}
	// ---

	// export outputs
	fmt.Println()
	log.Info("Exporting generated outputs...")

	for projectType, outputMap := range output {
		fmt.Println()
		log.Info("%s outputs:", projectType)

		switch projectType {
		case constants.ProjectTypeIOS:
			xcarchivePth, ok := outputMap[constants.OutputTypeXCArchive]
			if ok {
				envKey := "BITRISE_IOS_XCARCHIVE_PATH"
				pth, err := exportArtifactDir(xcarchivePth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export xcarchive, error: %s", err)
					os.Exit(1)
				}
				log.Done("xcarchive path (%s) is available in (%s) environment variable", pth, envKey)
			}
			ipaPth, ok := outputMap[constants.OutputTypeIPA]
			if ok {
				envKey := "BITRISE_IOS_IPA_PATH"
				pth, err := exportArtifactFile(ipaPth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export ipa, error: %s", err)
					os.Exit(1)
				}
				log.Done("ipa path (%s) is available in (%s) environment variable", pth, envKey)
			}
			dsymPth, ok := outputMap[constants.OutputTypeDSYM]
			if ok {
				envKey := "BITRISE_IOS_DSYM_PATH"
				pth, err := exportZipedArtifactDir(dsymPth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export dsym, error: %s", err)
					os.Exit(1)
				}
				log.Done("dsym path (%s) is available in (%s) environment variable", pth, envKey)
			}
		case constants.ProjectTypeAndroid:
			apkPth, ok := outputMap[constants.OutputTypeAPK]
			if ok {
				envKey := "BITRISE_APK_PATH"
				pth, err := exportArtifactFile(apkPth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export apk, error: %s", err)
					os.Exit(1)
				}
				log.Done("apk path (%s) is available in (%s) environment variable", pth, envKey)
			}
		case constants.ProjectTypeMacOS:
			xcarchivePth, ok := outputMap[constants.OutputTypeXCArchive]
			if ok {
				envKey := "BITRISE_MACOS_XCARCHIVE_PATH"
				pth, err := exportArtifactDir(xcarchivePth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export xcarchive, error: %s", err)
					os.Exit(1)
				}
				log.Done("apk path (%s) is available in (%s) environment variable", pth, envKey)
			}
			appPth, ok := outputMap[constants.OutputTypeAPP]
			if ok {
				envKey := "BITRISE_MACOS_APP_PATH"
				pth, err := exportArtifactDir(appPth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export xcarchive, error: %s", err)
					os.Exit(1)
				}
				log.Done("app path (%s) is available in (%s) environment variable", pth, envKey)
			}
			pkgPth, ok := outputMap[constants.OutputTypePKG]
			if ok {
				envKey := "BITRISE_MACOS_PKG_PATH"
				pth, err := exportArtifactFile(pkgPth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export pkg, error: %s", err)
					os.Exit(1)
				}
				log.Done("pkg path (%s) is available in (%s) environment variable", pth, envKey)
			}
		case constants.ProjectTypeTvOS:
			xcarchivePth, ok := outputMap[constants.OutputTypeXCArchive]
			if ok {
				envKey := "BITRISE_TVOS_XCARCHIVE_PATH"
				pth, err := exportArtifactDir(xcarchivePth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export xcarchive, error: %s", err)
					os.Exit(1)
				}
				log.Done("xcarchive path (%s) is available in (%s) environment variable", pth, envKey)
			}
			ipaPth, ok := outputMap[constants.OutputTypeIPA]
			if ok {
				envKey := "BITRISE_TVOS_IPA_PATH"
				pth, err := exportArtifactFile(ipaPth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export ipa, error: %s", err)
					os.Exit(1)
				}
				log.Done("ipa path (%s) is available in (%s) environment variable", pth, envKey)
			}
			dsymPth, ok := outputMap[constants.OutputTypeDSYM]
			if ok {
				envKey := "BITRISE_TVOS_DSYM_PATH"
				pth, err := exportZipedArtifactDir(dsymPth, configs.DeployDir, envKey)
				if err != nil {
					log.Error("Failed to export dsym, error: %s", err)
					os.Exit(1)
				}
				log.Done("dsym path (%s) is available in (%s) environment variable", pth, envKey)
			}
		}
	}
	// ---
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	"github.com/VonC/ggb/cmd"
)

func main() {
	fmt.Printf("ggb: ")
	err := cmd.RunCommand(os.Args)
	if err != nil {
		fmt.Printf("%s", err.Error())
		os.Exit(1)
	}
}

func build(args []string) error {
	fmt.Printf("build to be done with args '%v'", args)
	return nil
}

func checkGlobalFlag() {
	if help {
		usage()
		os.Exit(0)
	}
}

func usage() {
	fmt.Print(`ggb [-h],
builds a go project with git submodule dependencies`)
}
<commit_msg>main.go: build() gets a projectwith root folder<commit_after>package main

import (
	"fmt"
	"os"

	"github.com/VonC/ggb/cmd"
	"github.com/VonC/ggb/prj"
)

func main() {
	fmt.Printf("ggb: ")
	err := cmd.RunCommand(os.Args)
	if err != nil {
		fmt.Printf("%s", err.Error())
		os.Exit(1)
	}
}

func build(args []string) error {
	fmt.Printf("build to be done with args '%v'", args)
	p, err := prj.GetProject()
	if err != nil {
		fmt.Printf("%s", err.Error())
		os.Exit(1)
	}
	fmt.Printf(" in root folder '%s'", p.RootFolder())
	return nil
}

func checkGlobalFlag() {
	if help {
		usage()
		os.Exit(0)
	}
}

func usage() {
	fmt.Print(`ggb [-h],
builds a go project with git submodule dependencies`)
}
<|endoftext|>


<commit_before>package main

import(
  "github.com/TykTechnologies/tykcommon"
  "github.com/TykTechnologies/goverify"

  "encoding/base64"
  "encoding/json"
  "fmt"
  "flag"
  "errors"
  "io/ioutil"
  "bytes"
  "archive/zip"
  "crypto/md5"
  "strings"
  "os"
  "io"
)

// tyk-cli <module> <submodule> <command> [--options] args...

var module, submodule, command string

var bundleOutput, privKey string

const(
  defaultBundleOutput = "bundle.zip"
)

func init() {
  if len(os.Args) == 1 {
    fmt.Println("No module specified!")
    os.Exit(1)
  }
  if len(os.Args) == 2 {
    fmt.Println("No command specified!")
    os.Exit(1)
  }

  module = os.Args[1]
  command = os.Args[2]

  os.Args = os.Args[2:]

  flag.StringVar(&bundleOutput, "output", "", "Bundle output")
  flag.StringVar(&privKey, "key", "", "Key for bundle signature")

  flag.Parse()
}

// main is the entrypoint.
func main() {
  fmt.Println("tyk-cli:", flag.CommandLine, os.Args)

  fmt.Println("module =", module)
  fmt.Println("command =", command)

  var err error

  switch module {
  case "bundle":
    fmt.Println("Using bundle module.")
    err = bundle(command)
  default:
    err = errors.New("Invalid module")
  }

  if err != nil {
    fmt.Println("Error:", err)
    os.Exit(1)
  }
}

// bundle will handle the bundle command calls.
func bundle(command string) (err error) {
  switch command {
  case "build":
    var manifestPath = "./manifest.json"
    if _, err := os.Stat(manifestPath); err == nil {
      var manifestData []byte
      manifestData, err = ioutil.ReadFile(manifestPath)

      var manifest tykcommon.BundleManifest
      err = json.Unmarshal(manifestData, &manifest)

      if err != nil {
        fmt.Println("Couldn't parse manifest file!")
        break
      }

      err = bundleValidateManifest(&manifest)

      if err != nil {
        fmt.Println("Bundle validation error:")
        fmt.Println(err)
        break
      }

      // The manifest is valid, we should do the checksum and sign step at this point.
      bundleBuild(&manifest)

    } else {
      err = errors.New("Manifest file doesn't exist.")
    }
  default:
    err = errors.New("Invalid command.")
  }
  return err
}

// bundleValidateManifest will validate the manifest file before building a bundle.
func bundleValidateManifest(manifest *tykcommon.BundleManifest) (err error) {
  // Validate manifest file list:
  for _, file := range manifest.FileList {
    if _, statErr := os.Stat(file); statErr != nil {
      err = errors.New("Referencing a nonexistent file: " + file)
      break
    }
  }

  // The custom middleware block must specify at least one hook:
  var definedHooks int
  definedHooks = len(manifest.CustomMiddleware.Pre) + len(manifest.CustomMiddleware.Post) + len(manifest.CustomMiddleware.PostKeyAuth)

  // We should count the auth check middleware (single), if it's present:
  if manifest.CustomMiddleware.AuthCheck.Name != "" {
    definedHooks++
  }

  if definedHooks == 0 {
    err = errors.New("No hooks defined!")
    return err
  }

  // The custom middleware block must specify a driver:
  if manifest.CustomMiddleware.Driver == "" {
    err = errors.New("No driver specified!")
    return err
  }

  return err
}

// bundleBuild will build and generate a bundle file.
func bundleBuild(manifest *tykcommon.BundleManifest) (err error) {
  var useSignature bool

  if bundleOutput == "" {
    fmt.Println("No output specified, using bundle.zip")
    bundleOutput = defaultBundleOutput
  }

  if privKey == "" {
    // Warning?
    fmt.Println("The bundle won't be signed.")
  } else {
    fmt.Println("The bundle will be signed.")
    useSignature = true
  }

  var signer goverify.Signer

  if useSignature {
    signer, err = goverify.LoadPrivateKeyFromFile(privKey)
    if err != nil {
      return err
    }
  }

  // Checksum and signature:

  var bundleChecksums []string
  var bundleSignatures []string

  for _, file := range manifest.FileList {
    var data []byte
    data, err = ioutil.ReadFile(file)
    if err != nil {
      fmt.Println("*** Error: ", err)
      return err
    }
    hash := fmt.Sprintf("%x", md5.Sum(data))
    bundleChecksums = append(bundleChecksums, hash)

    if useSignature {
      var signed []byte
      signed, err = signer.Sign(data)

      sig := base64.StdEncoding.EncodeToString(signed)
      bundleSignatures = append(bundleSignatures, sig)
      fmt.Printf("Signature: %v %s\n", sig, file)
    }
  }

  mergedChecksums := strings.Join(bundleChecksums, "")
  mergedSignatures := strings.Join(bundleSignatures, "")

  // Update the manifest file:

  manifest.Checksum = fmt.Sprintf("%x", md5.Sum([]byte(mergedChecksums)))
  manifest.Signature = mergedSignatures

  var newManifestData []byte
  newManifestData, err = json.Marshal(&manifest)

  // Write the bundle file:
  buf := new(bytes.Buffer)
  bundleWriter := zip.NewWriter(buf)

  for _, file := range manifest.FileList {
    var outputFile io.Writer
    outputFile, err = bundleWriter.Create(file)
    if err != nil {
      return err
    }
    var data []byte
    data, err = ioutil.ReadFile(file)

    _, err = outputFile.Write(data)

    if err != nil {
      return err
    }
  }

  // Write manifest file:
  var newManifest io.Writer
  newManifest, err = bundleWriter.Create("manifest.json")
  _, err = newManifest.Write(newManifestData)

  err = bundleWriter.Close()
  err = ioutil.WriteFile(bundleOutput, buf.Bytes(), 0755)

  return err
}
<commit_msg>gofmt<commit_after>package main

import (
	"github.com/TykTechnologies/goverify"
	"github.com/TykTechnologies/tykcommon"

	"archive/zip"
	"bytes"
	"crypto/md5"
	"encoding/base64"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
)

// tyk-cli <module> <submodule> <command> [--options] args...

var module, submodule, command string

var bundleOutput, privKey string

const (
	defaultBundleOutput = "bundle.zip"
)

func init() {
	if len(os.Args) == 1 {
		fmt.Println("No module specified!")
		os.Exit(1)
	}
	if len(os.Args) == 2 {
		fmt.Println("No command specified!")
		os.Exit(1)
	}

	module = os.Args[1]
	command = os.Args[2]

	os.Args = os.Args[2:]

	flag.StringVar(&bundleOutput, "output", "", "Bundle output")
	flag.StringVar(&privKey, "key", "", "Key for bundle signature")

	flag.Parse()
}

// main is the entrypoint.
func main() {
	fmt.Println("tyk-cli:", flag.CommandLine, os.Args)

	fmt.Println("module =", module)
	fmt.Println("command =", command)

	var err error

	switch module {
	case "bundle":
		fmt.Println("Using bundle module.")
		err = bundle(command)
	default:
		err = errors.New("Invalid module")
	}

	if err != nil {
		fmt.Println("Error:", err)
		os.Exit(1)
	}
}

// bundle will handle the bundle command calls.
func bundle(command string) (err error) {
	switch command {
	case "build":
		var manifestPath = "./manifest.json"
		if _, err := os.Stat(manifestPath); err == nil {
			var manifestData []byte
			manifestData, err = ioutil.ReadFile(manifestPath)

			var manifest tykcommon.BundleManifest
			err = json.Unmarshal(manifestData, &manifest)

			if err != nil {
				fmt.Println("Couldn't parse manifest file!")
				break
			}

			err = bundleValidateManifest(&manifest)

			if err != nil {
				fmt.Println("Bundle validation error:")
				fmt.Println(err)
				break
			}

			// The manifest is valid, we should do the checksum and sign step at this point.
			bundleBuild(&manifest)

		} else {
			err = errors.New("Manifest file doesn't exist.")
		}
	default:
		err = errors.New("Invalid command.")
	}
	return err
}

// bundleValidateManifest will validate the manifest file before building a bundle.
func bundleValidateManifest(manifest *tykcommon.BundleManifest) (err error) {
	// Validate manifest file list:
	for _, file := range manifest.FileList {
		if _, statErr := os.Stat(file); statErr != nil {
			err = errors.New("Referencing a nonexistent file: " + file)
			break
		}
	}

	// The custom middleware block must specify at least one hook:
	var definedHooks int
	definedHooks = len(manifest.CustomMiddleware.Pre) + len(manifest.CustomMiddleware.Post) + len(manifest.CustomMiddleware.PostKeyAuth)

	// We should count the auth check middleware (single), if it's present:
	if manifest.CustomMiddleware.AuthCheck.Name != "" {
		definedHooks++
	}

	if definedHooks == 0 {
		err = errors.New("No hooks defined!")
		return err
	}

	// The custom middleware block must specify a driver:
	if manifest.CustomMiddleware.Driver == "" {
		err = errors.New("No driver specified!")
		return err
	}

	return err
}

// bundleBuild will build and generate a bundle file.
func bundleBuild(manifest *tykcommon.BundleManifest) (err error) {
	var useSignature bool

	if bundleOutput == "" {
		fmt.Println("No output specified, using bundle.zip")
		bundleOutput = defaultBundleOutput
	}

	if privKey == "" {
		// Warning?
		fmt.Println("The bundle won't be signed.")
	} else {
		fmt.Println("The bundle will be signed.")
		useSignature = true
	}

	var signer goverify.Signer

	if useSignature {
		signer, err = goverify.LoadPrivateKeyFromFile(privKey)
		if err != nil {
			return err
		}
	}

	// Checksum and signature:

	var bundleChecksums []string
	var bundleSignatures []string

	for _, file := range manifest.FileList {
		var data []byte
		data, err = ioutil.ReadFile(file)
		if err != nil {
			fmt.Println("*** Error: ", err)
			return err
		}
		hash := fmt.Sprintf("%x", md5.Sum(data))
		bundleChecksums = append(bundleChecksums, hash)

		if useSignature {
			var signed []byte
			signed, err = signer.Sign(data)

			sig := base64.StdEncoding.EncodeToString(signed)
			bundleSignatures = append(bundleSignatures, sig)
			fmt.Printf("Signature: %v %s\n", sig, file)
		}
	}

	mergedChecksums := strings.Join(bundleChecksums, "")
	mergedSignatures := strings.Join(bundleSignatures, "")

	// Update the manifest file:

	manifest.Checksum = fmt.Sprintf("%x", md5.Sum([]byte(mergedChecksums)))
	manifest.Signature = mergedSignatures

	var newManifestData []byte
	newManifestData, err = json.Marshal(&manifest)

	// Write the bundle file:
	buf := new(bytes.Buffer)
	bundleWriter := zip.NewWriter(buf)

	for _, file := range manifest.FileList {
		var outputFile io.Writer
		outputFile, err = bundleWriter.Create(file)
		if err != nil {
			return err
		}
		var data []byte
		data, err = ioutil.ReadFile(file)

		_, err = outputFile.Write(data)

		if err != nil {
			return err
		}
	}

	// Write manifest file:
	var newManifest io.Writer
	newManifest, err = bundleWriter.Create("manifest.json")
	_, err = newManifest.Write(newManifestData)

	err = bundleWriter.Close()
	err = ioutil.WriteFile(bundleOutput, buf.Bytes(), 0755)

	return err
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"os"
)
import "github.com/rogeralsing/goactor/actor"

func main() {
	// decider := func(child actor.ActorRef, reason interface{}) actor.Directive {
	// 	fmt.Println("restarting failing child")
	// 	return actor.Restart
	// }

	props := actor.
		Props(NewParentActor).
		WithMailbox(actor.NewUnboundedMailbox()).
		WithSupervisor(actor.DefaultStrategy())

	parent := actor.Spawn(props)
	parent.Tell(Hello{Name: "Roger"})
	parent.Tell(Hello{Name: "Go"})

	reader := bufio.NewReader(os.Stdin)
	reader.ReadString('\n')
}

type Ping struct {
	Sender actor.ActorRef
	Name   string
}
type Pong struct{}
type Hello struct{ Name string }

type ChildActor struct{ messageCount int }

func NewChildActor() actor.Actor {
	return &ChildActor{}
}

func (state *ChildActor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case actor.Starting:
		fmt.Println("Im starting")
	case actor.Stopping:
		fmt.Println("stopping child")
	case actor.Stopped:
		fmt.Println("stopped child")
	case Ping:
		fmt.Printf("Hello %v\n", msg.Name)
		panic("hej")
		state.messageCount++
		fmt.Printf("message count %v \n", state.messageCount)
		msg.Sender.Tell(Pong{})
	}
}

type ParentActor struct {
	Child actor.ActorRef
}

func NewParentActor() actor.Actor {
	return &ParentActor{}
}

func (state *ParentActor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case actor.Starting:
		state.Child = context.SpawnChild(actor.Props(NewChildActor))
	case actor.Stopping:
		fmt.Println("stopping parent")
	case actor.Stopped:
		fmt.Println("stopped parent")

	case Hello:
		fmt.Printf("Parent got hello %v\n", msg.Name)
		state.Child.Tell(Ping{
			Name:   msg.Name,
			Sender: context.Self(),
		})
		context.Become(state.Other)
	}
}

func (state *ParentActor) Other(context actor.Context) {
	switch context.Message().(type) {
	case actor.Stopping:
		fmt.Println("stopping parent in become")
	case actor.Stopped:
		fmt.Println("stopped parent in become")

	case Pong:
		fmt.Println("Got pong")
		context.Self().Stop()
	}
}
<commit_msg>hello world<commit_after>package main

import (
	"bufio"
	"fmt"
	"os"
)
import "github.com/rogeralsing/goactor/actor"

func main() {
	props := actor.
		Props(NewParentActor).
		WithMailbox(actor.NewUnboundedMailbox()).
		WithSupervisor(actor.DefaultStrategy())

	parent := actor.Spawn(props)
	parent.Tell(Hello{Name: "Roger"})
	parent.Tell(Hello{Name: "Go"})

	reader := bufio.NewReader(os.Stdin)
	reader.ReadString('\n')
}

type Ping struct{ Sender actor.ActorRef }
type Pong struct{}
type Hello struct{ Name string }

type ChildActor struct{ messageCount int }

func NewChildActor() actor.Actor {
	return &ChildActor{}
}

func (state *ChildActor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case Ping:
		state.messageCount++
		fmt.Printf("message count %v \n", state.messageCount)
		msg.Sender.Tell(Pong{})
	}
}

type ParentActor struct {
	Child actor.ActorRef
}

func NewParentActor() actor.Actor {
	return &ParentActor{}
}

func (state *ParentActor) Receive(context actor.Context) {
	switch msg := context.Message().(type) {
	case actor.Starting:
		state.Child = context.SpawnChild(actor.Props(NewChildActor))
	case Hello:
		fmt.Printf("Parent got hello %v\n", msg.Name)
		state.Child.Tell(Ping{Sender: context.Self()})
	}
}
<|endoftext|>


<commit_before>package main

import (
	"io"
	"log"
	"os"

	"github.com/codegangsta/cli"
	"github.com/ricbra/rabbitmq-cli-consumer/command"
	"github.com/ricbra/rabbitmq-cli-consumer/config"
	"github.com/ricbra/rabbitmq-cli-consumer/consumer"
)

func main() {
	app := cli.NewApp()
	app.Name = "rabbitmq-cli-consumer"
	app.Usage = "Consume RabbitMQ easily to any cli program"
	app.Author = "Richard van den Brand"
	app.Email = "richard@vandenbrand.org"
	app.Version = "1.4.1"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "executable, e",
			Usage: "Location of executable",
		},
		cli.StringFlag{
			Name:  "configuration, c",
			Usage: "Location of configuration file",
		},
		cli.BoolFlag{
			Name:  "verbose, V",
			Usage: "Enable verbose mode (logs to stdout and stderr)",
		},
		cli.BoolFlag{
			Name:  "include, i",
			Usage: "Include metadata. Passes message as JSON data including headers, properties and message body.",
		},
		cli.BoolFlag{
			Name:  "strict-exit-code",
			Usage: "Strict exit code processing will rise a fatal error if exit code is different from allowed onces.",
		},
	}
	app.Action = func(c *cli.Context) {
		if c.String("configuration") == "" && c.String("executable") == "" {
			cli.ShowAppHelp(c)
			os.Exit(1)
		}

		verbose := c.Bool("verbose")

		logger := log.New(os.Stderr, "", log.Ldate|log.Ltime)
		cfg, err := config.LoadAndParse(c.String("configuration"))

		if err != nil {
			logger.Fatalf("Failed parsing configuration: %s\n", err)
		}

		errLogger, err := createLogger(cfg.Logs.Error, verbose, os.Stderr)
		if err != nil {
			logger.Fatalf("Failed creating error log: %s", err)
		}

		infLogger, err := createLogger(cfg.Logs.Info, verbose, os.Stdout)
		if err != nil {
			logger.Fatalf("Failed creating info log: %s", err)
		}

		factory := command.Factory(c.String("executable"))

		client, err := consumer.New(cfg, factory, errLogger, infLogger)
		if err != nil {
			errLogger.Fatalf("Failed creating consumer: %s", err)
		}
		client.IncludeMetadata = c.Bool("include")
		client.StrictExitCode = c.Bool("strict-exit-code")

		client.Consume()
	}

	app.Run(os.Args)
}

func createLogger(filename string, verbose bool, out io.Writer) (*log.Logger, error) {
	file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660)

	if err != nil {
		return nil, err
	}

	var writers = []io.Writer{
		file,
	}

	if verbose {
		writers = append(writers, out)
	}

	return log.New(io.MultiWriter(writers...), "", log.Ldate|log.Ltime), nil
}
<commit_msg>Prepared 1.4.2<commit_after>package main

import (
	"io"
	"log"
	"os"

	"github.com/codegangsta/cli"
	"github.com/ricbra/rabbitmq-cli-consumer/command"
	"github.com/ricbra/rabbitmq-cli-consumer/config"
	"github.com/ricbra/rabbitmq-cli-consumer/consumer"
)

func main() {
	app := cli.NewApp()
	app.Name = "rabbitmq-cli-consumer"
	app.Usage = "Consume RabbitMQ easily to any cli program"
	app.Author = "Richard van den Brand"
	app.Email = "richard@vandenbrand.org"
	app.Version = "1.4.2"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:  "executable, e",
			Usage: "Location of executable",
		},
		cli.StringFlag{
			Name:  "configuration, c",
			Usage: "Location of configuration file",
		},
		cli.BoolFlag{
			Name:  "verbose, V",
			Usage: "Enable verbose mode (logs to stdout and stderr)",
		},
		cli.BoolFlag{
			Name:  "include, i",
			Usage: "Include metadata. Passes message as JSON data including headers, properties and message body.",
		},
		cli.BoolFlag{
			Name:  "strict-exit-code",
			Usage: "Strict exit code processing will rise a fatal error if exit code is different from allowed onces.",
		},
	}
	app.Action = func(c *cli.Context) {
		if c.String("configuration") == "" && c.String("executable") == "" {
			cli.ShowAppHelp(c)
			os.Exit(1)
		}

		verbose := c.Bool("verbose")

		logger := log.New(os.Stderr, "", log.Ldate|log.Ltime)
		cfg, err := config.LoadAndParse(c.String("configuration"))

		if err != nil {
			logger.Fatalf("Failed parsing configuration: %s\n", err)
		}

		errLogger, err := createLogger(cfg.Logs.Error, verbose, os.Stderr)
		if err != nil {
			logger.Fatalf("Failed creating error log: %s", err)
		}

		infLogger, err := createLogger(cfg.Logs.Info, verbose, os.Stdout)
		if err != nil {
			logger.Fatalf("Failed creating info log: %s", err)
		}

		factory := command.Factory(c.String("executable"))

		client, err := consumer.New(cfg, factory, errLogger, infLogger)
		if err != nil {
			errLogger.Fatalf("Failed creating consumer: %s", err)
		}
		client.IncludeMetadata = c.Bool("include")
		client.StrictExitCode = c.Bool("strict-exit-code")

		client.Consume()
	}

	app.Run(os.Args)
}

func createLogger(filename string, verbose bool, out io.Writer) (*log.Logger, error) {
	file, err := os.OpenFile(filename, os.O_RDWR|os.O_APPEND|os.O_CREATE, 0660)

	if err != nil {
		return nil, err
	}

	var writers = []io.Writer{
		file,
	}

	if verbose {
		writers = append(writers, out)
	}

	return log.New(io.MultiWriter(writers...), "", log.Ldate|log.Ltime), nil
}
<|endoftext|>


<commit_before>package main

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

	"github.com/Tinker-Ware/gh-service/infrastructure"
	"github.com/Tinker-Ware/gh-service/interfaces"
	"github.com/Tinker-Ware/gh-service/usecases"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
)

const defaultPath = "/etc/gh-service.conf"

// Define configuration flags
var confFilePath = flag.String("conf", defaultPath, "Custom path for configuration file")

func main() {

	flag.Parse()

	config, err := infrastructure.GetConfiguration(*confFilePath)
	if err != nil {
		fmt.Println(err.Error())
		panic("Cannot parse configuration")
	}

	ghrepo, err := interfaces.NewGithubRepository(config.ClientID, config.ClientSecret, config.Scopes)
	if err != nil {
		panic(err.Error())
	}

	ghinteractor := usecases.GHInteractor{
		GithubRepository: ghrepo,
	}

	handler := interfaces.WebServiceHandler{
		GHInteractor: ghinteractor,
		APIHost:      config.APIHost,
	}

	// Add CORS Support
	headers := handlers.AllowedHeaders([]string{"Accept", "Content-Type", "Authorization"})
	origins := handlers.AllowedOrigins([]string{"http://localhost", "http://provision.tinkerware.io", "https://provision.tinkerware.io"})

	r := mux.NewRouter()

	subrouter := r.PathPrefix("/api/v1/repository/github").Subrouter()
	subrouter.Handle("/oauth", interfaces.Adapt(http.HandlerFunc(handler.Callback), interfaces.Notify())).Methods("POST")
	subrouter.Handle("/{username}/repos", interfaces.Adapt(http.HandlerFunc(handler.ShowRepos), interfaces.Notify(), interfaces.GetToken(ghrepo, config.APIHost, config.Salt))) //.Methods("GET")
	subrouter.Handle("/{username}/{repo}", interfaces.Adapt(http.HandlerFunc(handler.ShowRepo), interfaces.Notify(), interfaces.GetToken(ghrepo, config.APIHost, config.Salt))) //.Methods("GET")
	subrouter.Handle("/{username}/{repo}/deploy_key", interfaces.Adapt(http.HandlerFunc(handler.CreateRepoDeployKey), interfaces.Notify(), interfaces.GetToken(ghrepo, config.APIHost, config.Salt))).Methods("POST")
	// subrouter.Handle("/user/{username}/repos", interfaces.Adapt(http.HandlerFunc(handler.CreateRepo), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/keys", interfaces.Adapt(http.HandlerFunc(handler.CreateRepo), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/keys", interfaces.Adapt(http.HandlerFunc(handler.CreateKey), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/keys/{id}", interfaces.Adapt(http.HandlerFunc(handler.ShowKey), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/{repo}/addfile", interfaces.Adapt(http.HandlerFunc(handler.AddFileToRepository), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/{repo}/addfiles", interfaces.Adapt(http.HandlerFunc(handler.AddMultipleFilesToRepository), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.HandleFunc("/user_info", handler.GetCurrentUser).Methods("GET")

	n := negroni.Classic()
	n.UseHandler(handlers.CORS(headers, origins)(r))

	port := bytes.Buffer{}

	port.WriteString(":")
	port.WriteString(config.Port)

	n.Run(port.String())
}
<commit_msg>Include mydevop as an authorized domain<commit_after>package main

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

	"github.com/Tinker-Ware/gh-service/infrastructure"
	"github.com/Tinker-Ware/gh-service/interfaces"
	"github.com/Tinker-Ware/gh-service/usecases"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/handlers"
	"github.com/gorilla/mux"
)

const defaultPath = "/etc/gh-service.conf"

// Define configuration flags
var confFilePath = flag.String("conf", defaultPath, "Custom path for configuration file")

func main() {

	flag.Parse()

	config, err := infrastructure.GetConfiguration(*confFilePath)
	if err != nil {
		fmt.Println(err.Error())
		panic("Cannot parse configuration")
	}

	ghrepo, err := interfaces.NewGithubRepository(config.ClientID, config.ClientSecret, config.Scopes)
	if err != nil {
		panic(err.Error())
	}

	ghinteractor := usecases.GHInteractor{
		GithubRepository: ghrepo,
	}

	handler := interfaces.WebServiceHandler{
		GHInteractor: ghinteractor,
		APIHost:      config.APIHost,
	}

	// Add CORS Support
	headers := handlers.AllowedHeaders([]string{"Accept", "Content-Type", "Authorization"})
	origins := handlers.AllowedOrigins([]string{"http://localhost", "http://provision.tinkerware.io", "https://provision.tinkerware.io", "http://mydevop.tinkerware.io", "https://mydevop.tinkerware.io"})

	r := mux.NewRouter()

	subrouter := r.PathPrefix("/api/v1/repository/github").Subrouter()
	subrouter.Handle("/oauth", interfaces.Adapt(http.HandlerFunc(handler.Callback), interfaces.Notify())).Methods("POST")
	subrouter.Handle("/{username}/repos", interfaces.Adapt(http.HandlerFunc(handler.ShowRepos), interfaces.Notify(), interfaces.GetToken(ghrepo, config.APIHost, config.Salt))) //.Methods("GET")
	subrouter.Handle("/{username}/{repo}", interfaces.Adapt(http.HandlerFunc(handler.ShowRepo), interfaces.Notify(), interfaces.GetToken(ghrepo, config.APIHost, config.Salt))) //.Methods("GET")
	subrouter.Handle("/{username}/{repo}/deploy_key", interfaces.Adapt(http.HandlerFunc(handler.CreateRepoDeployKey), interfaces.Notify(), interfaces.GetToken(ghrepo, config.APIHost, config.Salt))).Methods("POST")
	// subrouter.Handle("/user/{username}/repos", interfaces.Adapt(http.HandlerFunc(handler.CreateRepo), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/keys", interfaces.Adapt(http.HandlerFunc(handler.CreateRepo), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/keys", interfaces.Adapt(http.HandlerFunc(handler.CreateKey), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/keys/{id}", interfaces.Adapt(http.HandlerFunc(handler.ShowKey), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("GET")
	// subrouter.Handle("/user/{username}/{repo}/addfile", interfaces.Adapt(http.HandlerFunc(handler.AddFileToRepository), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.Handle("/user/{username}/{repo}/addfiles", interfaces.Adapt(http.HandlerFunc(handler.AddMultipleFilesToRepository), interfaces.Notify(), interfaces.SetToken(ghrepo))).Methods("POST")
	// subrouter.HandleFunc("/user_info", handler.GetCurrentUser).Methods("GET")

	n := negroni.Classic()
	n.UseHandler(handlers.CORS(headers, origins)(r))

	port := bytes.Buffer{}

	port.WriteString(":")
	port.WriteString(config.Port)

	n.Run(port.String())
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/dmportella/docker-beat/logging"
	"github.com/fsouza/go-dockerclient"
	"io/ioutil"
	"os"
	"os/signal"
)

// Set on build
var (
	Build    string
	Branch   string
	Revision string
	OSArch   string
)

// Variables used for command line parameters
var (
	DockerEndpoint string
	Version        bool
	Verbose        bool
)

func init() {
	const (
		defaultDockerEndpoint = "unix:///var/run/docker.sock"
		dockerEndpointUsage   = "The Url or unix socket address for the Docker Remote API."
	)

	flag.StringVar(&DockerEndpoint, "docker-endpoint", defaultDockerEndpoint, dockerEndpointUsage)

	const (
		defaultVerbose = false
		verboseUsage   = "Redirect trace information to the standard out."
	)

	flag.BoolVar(&Verbose, "verbose", defaultVerbose, verboseUsage)
	flag.Parse()

	flag.Usage = func() {
		fmt.Printf("Usage of %s:\n", os.Args[0])
		flag.PrintDefaults()
	}
}

func main() {
	fmt.Printf("docker-beat - Version: %s Branch: %s Revision: %s. OSArch: %s.\n\rDaniel Portella (c) 2016\n\r", Build, Branch, Revision, OSArch)

	if Verbose {
		logging.Init(os.Stdout, os.Stdout, os.Stdout, os.Stderr)
	} else {
		logging.Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)
	}

	if len(os.Args) == 1 {
		flag.Usage()
		os.Exit(1)
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for sig := range c {
			if sig.String() == "interrupt" {
				logging.Info.Printf("Application ended on %s\n\r", sig)

				os.Exit(0)
			}
		}
	}()

	dockerEvents := make(chan *docker.APIEvents)

	client, err := docker.NewClient(DockerEndpoint)

	if err != nil {
		logging.Error.Printf(err.Error())
	}

	go listContainers(client)

	go dockerEventListener(dockerEvents, client)

	// Simple way to keep program running until CTRL-C is pressed.
	<-make(chan struct{})
}

func listContainers(client *docker.Client) {
	containers, _ := client.ListContainers(docker.ListContainersOptions{All: true})

	for _, containerEntry := range containers {
		if container, _ := client.InspectContainer(containerEntry.ID); container != nil {
			logging.Info.Printf("Container '%s' with ID '%s'.", container.Name, container.ID)
		}
	}
}

func dockerEventListener(dockerEvents chan *docker.APIEvents, client *docker.Client) {

	err := client.AddEventListener(dockerEvents)

	if err != nil {
		logging.Error.Printf(err.Error())
		panic(err)
	}

	for event := range dockerEvents {
		if event.Status == "start" {
			if container, _ := client.InspectContainer(event.ID); container != nil {
				logging.Info.Printf("Container '%s' with ID '%s' STARTED.", container.Name, container.ID)
			}
		}
	}
}
<commit_msg>just added status to the existing containers<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/dmportella/docker-beat/logging"
	"github.com/fsouza/go-dockerclient"
	"io/ioutil"
	"os"
	"os/signal"
)

// Set on build
var (
	Build    string
	Branch   string
	Revision string
	OSArch   string
)

// Variables used for command line parameters
var (
	DockerEndpoint string
	Version        bool
	Verbose        bool
)

func init() {
	const (
		defaultDockerEndpoint = "unix:///var/run/docker.sock"
		dockerEndpointUsage   = "The Url or unix socket address for the Docker Remote API."
	)

	flag.StringVar(&DockerEndpoint, "docker-endpoint", defaultDockerEndpoint, dockerEndpointUsage)

	const (
		defaultVerbose = false
		verboseUsage   = "Redirect trace information to the standard out."
	)

	flag.BoolVar(&Verbose, "verbose", defaultVerbose, verboseUsage)
	flag.Parse()

	flag.Usage = func() {
		fmt.Printf("Usage of %s:\n", os.Args[0])
		flag.PrintDefaults()
	}
}

func main() {
	fmt.Printf("docker-beat - Version: %s Branch: %s Revision: %s. OSArch: %s.\n\rDaniel Portella (c) 2016\n\r", Build, Branch, Revision, OSArch)

	if Verbose {
		logging.Init(os.Stdout, os.Stdout, os.Stdout, os.Stderr)
	} else {
		logging.Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)
	}

	if len(os.Args) == 1 {
		flag.Usage()
		os.Exit(1)
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)
	go func() {
		for sig := range c {
			if sig.String() == "interrupt" {
				logging.Info.Printf("Application ended on %s\n\r", sig)

				os.Exit(0)
			}
		}
	}()

	dockerEvents := make(chan *docker.APIEvents)

	client, err := docker.NewClient(DockerEndpoint)

	if err != nil {
		logging.Error.Printf(err.Error())
	}

	go listContainers(client)

	go dockerEventListener(dockerEvents, client)

	// Simple way to keep program running until CTRL-C is pressed.
	<-make(chan struct{})
}

func listContainers(client *docker.Client) {
	containers, _ := client.ListContainers(docker.ListContainersOptions{All: true})

	for _, containerEntry := range containers {
		if container, _ := client.InspectContainer(containerEntry.ID); container != nil {
			logging.Info.Printf("Container '%s' with ID '%s' %s.", container.Name, container.ID, container.State.Status)
		}
	}
}

func dockerEventListener(dockerEvents chan *docker.APIEvents, client *docker.Client) {

	err := client.AddEventListener(dockerEvents)

	if err != nil {
		logging.Error.Printf(err.Error())
		panic(err)
	}

	for event := range dockerEvents {
		if event.Status == "start" {
			if container, _ := client.InspectContainer(event.ID); container != nil {
				logging.Info.Printf("Container '%s' with ID '%s' STARTED.", container.Name, container.ID)
			}
		}
	}
}
<|endoftext|>


<commit_before>// Wago (Watch, Go)
// A general purpose watch / build development tool.

// TODO: catch SIGINT and send dog.TR to ensure a clean term
// see https://askubuntu.com/questions/171449/shell-does-not-show-typed-in-commands-reset-works-but-what-happened

package main

import (
	"flag"
	"fmt"
	"github.com/JonahBraun/dog"
	"github.com/howeyc/fsnotify"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"sync"
)

var (
	log     = dog.NewDog(dog.DEBUG)
	verbose = flag.Bool("v", false, "Verbose")
	quiet   = flag.Bool("q", false, "Quiet, only warnings and errors")

	buildCmd      = flag.String("cmd", "", "Bash command to run on change, Wabo will wait for this command to finish")
	daemonCmd     = flag.String("daemon", "", "Bash command that starts a daemon, Wago will halt if the daemon exits before the trigger or timer")
	daemonTimer   = flag.Int("timer", 0, "Miliseconds to wait after starting daemon before continuing")
	daemonTrigger = flag.String("trigger", "", "A string the daemon will output that indicates it has started successfuly, Wago will continue on this trigger")
	exitWait      = flag.Int("exitwait", 0, "If 0, kills processes immediately, if >0, sends SIGINT and waits X ms for process to exit before killing")
	fiddle        = flag.Bool("fiddle", false, "CLI fiddle mode, starts a web server and opens url to targetDir/index.html")
	leader        = flag.String("leader", "", "Leader character for wago output (to differentiate from command output), defaults to emoji")
	postCmd       = flag.String("pcmd", "", "Bash command to run after the daemon has successfully started, use this to kick off your test suite")
	recursive     = flag.Bool("recursive", true, "Watch directory tree recursively")
	targetDir     = flag.String("dir", "", "Directory to watch, defaults to current")
	url           = flag.String("url", "", "URL to open")
	watchRegex    = flag.String("watch", `/\w[\w\.]*": (CREATE|MODIFY)`, "Regex to match watch event, use -v to see all events")
	webServer     = flag.String("web", "", "Start a web server at this address, e.g. :8420")
	shell         = flag.String("shell", "", "Shell used to run commands, defaults to $SHELL, fallback to /bin/sh")
)

type Watcher struct {
	Event chan fmt.Stringer
	Error chan error
}

func main() {
	// the following function calls merely serve to logically organize what
	// is otherwise a VERY lengthy setup

	// TODO: have configSetup return a config object so that the reliance on
	// config globals is removed
	configSetup()

	startWebServer()

	runChain(newWatcher(), make(chan struct{}))
}

func runChain(watcher *Watcher, quit chan struct{}) {
	chain := make([]Runnable, 0, 5)

	// build chain of runnables
	if len(*buildCmd) > 0 {
		chain = append(chain, NewRunWait(*buildCmd))
	}
	if len(*daemonCmd) > 0 {
		if len(*daemonTrigger) > 0 {
			chain = append(chain, NewDaemonTrigger(*daemonCmd, *daemonTrigger))
		} else {
			chain = append(chain, NewDaemonTimer(*daemonCmd, *daemonTimer))
		}
	}
	if len(*postCmd) > 0 {
		chain = append(chain, NewRunWait(*postCmd))
	}
	if *url != "" {
		chain = append(chain, NewBrowser(*url))
	}

	eventRegex, err := regexp.Compile(*watchRegex)
	if err != nil {
		log.Fatal("Watch regex compile error:", err)(1)
	}

	var wg sync.WaitGroup

	// main loop
	for {
		// all channels of struct{} are disposable, single use
		// kill is passed to all Runnable so they know when they should exit
		kill := make(chan struct{})

		var drain func()
		drain = func() {
			select {
			case ev := <-watcher.Event:
				log.Debug("Extra event ignored:", ev.String())
				drain()
			default:
			}
		}
		drain()

		// event loop
		go func() {
			for {
				select {
				case ev := <-watcher.Event:
					if eventRegex.MatchString(ev.String()) {
						log.Info("Matched event:", ev.String())
						close(kill)
						return
					} else {
						log.Debug("Ignored event:", ev.String())
					}
				case err = <-watcher.Error:
					log.Fatal("Watcher error:", err)(5)
				case <-quit:
					// currently only used by test suite
					close(kill)
					return
				}
			}
		}()

	RunLoop:
		for _, runnable := range chain {
			done, dead := runnable(kill)
			wg.Add(1)

			go func() {
				wg.Done()
				<-dead
			}()

			select {
			case d := <-done:
				if !d {
					// Runnable's success metric failed, break out of the chain
					break RunLoop
				}
			case <-kill:
				break RunLoop
			}
		}

		// ensure an event has occured, we may be here because all runnables completed
		<-kill

		// ensure all runnables (procs) are dead before restarting the chain
		wg.Wait()

		// check if we should quit, currently only used by test suites for teardown
		select {
		case <-quit:
			log.Warn("Quitting run chain")
			return
		default:
		}
	}
}

func newWatcher() *Watcher {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		panic(err)
	}

	watchDir := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			return nil
		}

		log.Debug("Watching dir:", path)

		if err != nil {
			log.Err("Skipping dir:", path, err)
			return filepath.SkipDir
		}

		err = watcher.Watch(path)
		if err != nil {
			panic(err)
		}

		return nil
	}

	if *recursive == true {
		err = filepath.Walk(*targetDir, watchDir)
		if err != nil {
			panic(err)
		}
	} else {
		err = watcher.Watch(*targetDir)
		if err != nil {
			panic(err)
		}
	}

	// To facilitate testing (which sends artifical events from a timer),
	// we have an abstracted struct Watcher that holds the applicable channels.
	// fsnotify.FileEvent is a fmt.Stringer, but channels cannot be converted.
	// Unfortunately, an extra channel is necessary to perform the conversion.
	event := make(chan fmt.Stringer)
	go func() {
		for {
			event <- <-watcher.Event
		}
	}()

	return &Watcher{event, watcher.Error}
}

func startWebServer() {
	if *webServer != "" {
		go func() {
			log.Info("Starting web server on port", *webServer)
			err := http.ListenAndServe(*webServer, http.FileServer(http.Dir(*targetDir)))
			if err != nil {
				log.Fatal("Error starting web server:", err)(2)
			}
		}()
	}
}

func configSetup() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	flag.Usage = func() {
		fmt.Println("WaGo (Watch, Go) build tool. Usage:")
		flag.PrintDefaults()
	}

	// TODO: this should check for actions
	if len(os.Args) < 2 {
		flag.Usage()
		log.Fatal("You must specify an action")(1)
	}

	flag.Parse()

	if *verbose {
		log = dog.NewDog(dog.DEBUG)
	} else if *quiet {
		log = dog.NewDog(dog.WARN)
	} else {
		log = dog.NewDog(dog.INFO)
	}

	if len(*shell) == 0 {
		*shell = os.Getenv("SHELL")
		if len(*shell) == 0 {
			*shell = "/bin/sh"
		}
	}
	log.Debug("Using shell", *shell)

	if (len(*daemonTrigger) > 0) && (*daemonTimer > 0) {
		log.Fatal("Both daemon trigger and timer specified, use only one")(1)
	}

	if (len(*daemonTrigger) > 0 || *daemonTimer > 0) && len(*daemonCmd) == 0 {
		log.Fatal("Specify a daemon command to use the trigger or timer")(1)
	}

	if len(*buildCmd) == 0 && len(*daemonCmd) == 0 && !*fiddle && len(*postCmd) == 0 && len(*url) == 0 && len(*webServer) == 0 {
		flag.Usage()
		log.Fatal("You must specify an action")(1)
	}

	if *fiddle {
		if *webServer == "" {
			*webServer = ":9933"
		}
		if *url == "" {
			*url = "http://localhost" + *webServer + "/"
		}
	}

	if *targetDir == "" {
		cwd, err := os.Getwd()
		if err != nil {
			panic(err)
		}
		targetDir = &cwd
	}
	log.Debug("Target dir:", *targetDir)
}
<commit_msg>update doc<commit_after>// Wago (Watch, Go)
// A general purpose watch / build development tool.

// TODO: catch SIGINT and send dog.TR to ensure a clean term
// see https://askubuntu.com/questions/171449/shell-does-not-show-typed-in-commands-reset-works-but-what-happened

package main

import (
	"flag"
	"fmt"
	"github.com/JonahBraun/dog"
	"github.com/howeyc/fsnotify"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"sync"
)

var (
	log     = dog.NewDog(dog.DEBUG)
	verbose = flag.Bool("v", false, "Verbose")
	quiet   = flag.Bool("q", false, "Quiet, only warnings and errors")

	buildCmd      = flag.String("cmd", "", "Run command, wait for it to complete.")
	daemonCmd     = flag.String("daemon", "", "Run command and leave running in the background.")
	daemonTimer   = flag.Int("timer", 0, "Wait miliseconds after starting daemon, then continue.")
	daemonTrigger = flag.String("trigger", "", "Wait for daemon to output this string, then continue.")
	exitWait      = flag.Int("exitwait", 0, "If 0, kills processes immediately, if >0, sends SIGINT and waits X ms for process to exit before killing.")
	fiddle        = flag.Bool("fiddle", false, "CLI fiddle mode! Start a web server, open browser to URL of targetDir/index.html")
	postCmd       = flag.String("pcmd", "", "Run command after daemon starts. Use this to kick off your test suite.")
	recursive     = flag.Bool("recursive", true, "Watch directory tree recursively.")
	targetDir     = flag.String("dir", "", "Directory to watch, defaults to current.")
	url           = flag.String("url", "", "Open browser to this URL after all commands are successful.")
	watchRegex    = flag.String("watch", `/\w[\w\.]*": (CREATE|MODIFY)`, "Regex to match watch event, use -v to see all events.")
	webServer     = flag.String("web", "", "Start a web server at this address, e.g. :8420")
	shell         = flag.String("shell", "", "Shell used to run commands, defaults to $SHELL, fallback to /bin/sh")
)

type Watcher struct {
	Event chan fmt.Stringer
	Error chan error
}

func main() {
	// the following function calls merely serve to logically organize what
	// is otherwise a VERY lengthy setup

	// TODO: have configSetup return a config object so that the reliance on
	// config globals is removed
	configSetup()

	startWebServer()

	runChain(newWatcher(), make(chan struct{}))
}

func runChain(watcher *Watcher, quit chan struct{}) {
	chain := make([]Runnable, 0, 5)

	// build chain of runnables
	if len(*buildCmd) > 0 {
		chain = append(chain, NewRunWait(*buildCmd))
	}
	if len(*daemonCmd) > 0 {
		if len(*daemonTrigger) > 0 {
			chain = append(chain, NewDaemonTrigger(*daemonCmd, *daemonTrigger))
		} else {
			chain = append(chain, NewDaemonTimer(*daemonCmd, *daemonTimer))
		}
	}
	if len(*postCmd) > 0 {
		chain = append(chain, NewRunWait(*postCmd))
	}
	if *url != "" {
		chain = append(chain, NewBrowser(*url))
	}

	eventRegex, err := regexp.Compile(*watchRegex)
	if err != nil {
		log.Fatal("Watch regex compile error:", err)(1)
	}

	var wg sync.WaitGroup

	// main loop
	for {
		// all channels of struct{} are disposable, single use
		// kill is passed to all Runnable so they know when they should exit
		kill := make(chan struct{})

		var drain func()
		drain = func() {
			select {
			case ev := <-watcher.Event:
				log.Debug("Extra event ignored:", ev.String())
				drain()
			default:
			}
		}
		drain()

		// event loop
		go func() {
			for {
				select {
				case ev := <-watcher.Event:
					if eventRegex.MatchString(ev.String()) {
						log.Info("Matched event:", ev.String())
						close(kill)
						return
					} else {
						log.Debug("Ignored event:", ev.String())
					}
				case err = <-watcher.Error:
					log.Fatal("Watcher error:", err)(5)
				case <-quit:
					// currently only used by test suite
					close(kill)
					return
				}
			}
		}()

	RunLoop:
		for _, runnable := range chain {
			done, dead := runnable(kill)
			wg.Add(1)

			go func() {
				wg.Done()
				<-dead
			}()

			select {
			case d := <-done:
				if !d {
					// Runnable's success metric failed, break out of the chain
					break RunLoop
				}
			case <-kill:
				break RunLoop
			}
		}

		// ensure an event has occured, we may be here because all runnables completed
		<-kill

		// ensure all runnables (procs) are dead before restarting the chain
		wg.Wait()

		// check if we should quit, currently only used by test suites for teardown
		select {
		case <-quit:
			log.Warn("Quitting run chain")
			return
		default:
		}
	}
}

func newWatcher() *Watcher {
	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		panic(err)
	}

	watchDir := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() {
			return nil
		}

		log.Debug("Watching dir:", path)

		if err != nil {
			log.Err("Skipping dir:", path, err)
			return filepath.SkipDir
		}

		err = watcher.Watch(path)
		if err != nil {
			panic(err)
		}

		return nil
	}

	if *recursive == true {
		err = filepath.Walk(*targetDir, watchDir)
		if err != nil {
			panic(err)
		}
	} else {
		err = watcher.Watch(*targetDir)
		if err != nil {
			panic(err)
		}
	}

	// To facilitate testing (which sends artifical events from a timer),
	// we have an abstracted struct Watcher that holds the applicable channels.
	// fsnotify.FileEvent is a fmt.Stringer, but channels cannot be converted.
	// Unfortunately, an extra channel is necessary to perform the conversion.
	event := make(chan fmt.Stringer)
	go func() {
		for {
			event <- <-watcher.Event
		}
	}()

	return &Watcher{event, watcher.Error}
}

func startWebServer() {
	if *webServer != "" {
		go func() {
			log.Info("Starting web server on port", *webServer)
			err := http.ListenAndServe(*webServer, http.FileServer(http.Dir(*targetDir)))
			if err != nil {
				log.Fatal("Error starting web server:", err)(2)
			}
		}()
	}
}

func configSetup() {
	runtime.GOMAXPROCS(runtime.NumCPU())

	flag.Usage = func() {
		fmt.Println("WaGo (Watch, Go) build tool. Usage:")
		flag.PrintDefaults()
	}

	// TODO: this should check for actions
	if len(os.Args) < 2 {
		flag.Usage()
		log.Fatal("You must specify an action")(1)
	}

	flag.Parse()

	if *verbose {
		log = dog.NewDog(dog.DEBUG)
	} else if *quiet {
		log = dog.NewDog(dog.WARN)
	} else {
		log = dog.NewDog(dog.INFO)
	}

	if len(*shell) == 0 {
		*shell = os.Getenv("SHELL")
		if len(*shell) == 0 {
			*shell = "/bin/sh"
		}
	}
	log.Debug("Using shell", *shell)

	if (len(*daemonTrigger) > 0) && (*daemonTimer > 0) {
		log.Fatal("Both daemon trigger and timer specified, use only one")(1)
	}

	if (len(*daemonTrigger) > 0 || *daemonTimer > 0) && len(*daemonCmd) == 0 {
		log.Fatal("Specify a daemon command to use the trigger or timer")(1)
	}

	if len(*buildCmd) == 0 && len(*daemonCmd) == 0 && !*fiddle && len(*postCmd) == 0 && len(*url) == 0 && len(*webServer) == 0 {
		flag.Usage()
		log.Fatal("You must specify an action")(1)
	}

	if *fiddle {
		if *webServer == "" {
			*webServer = ":9933"
		}
		if *url == "" {
			*url = "http://localhost" + *webServer + "/"
		}
	}

	if *targetDir == "" {
		cwd, err := os.Getwd()
		if err != nil {
			panic(err)
		}
		targetDir = &cwd
	}
	log.Debug("Target dir:", *targetDir)
}
<|endoftext|>


<commit_before>// Copyright © 2017 Solf1re2 <jy1v07@gmail.com>
//
// 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.

package main

import (
	"database/sql"
	"fmt"

	_ "github.com/go-sql-driver/mysql"
	"github.com/gorilla/mux"
	"github.com/solf1re2/config"
	"github.com/solf1re2/gosol/cmd"
	"html/template"
	"log"
	"net/http"
	"os"
)

const (
	DBHost  = "127.0.0.1"
	DBPort  = ":3306"
	DBUser  = "root"
	DBPass  = "password"
	DBDbase = "cms"
)

var database *sql.DB

type Page struct {
	Title      string
	RawContent string
	Content    template.HTML
	Date       string
	GUID       string
}

func main() {
	// Load the config file - PORT,
	cfg := config.LoadConfig("./config.json")

	dbConn := fmt.Sprintf("%s:%s@tcp(%s%s)/%s", DBUser, DBPass, DBHost, DBPort, DBDbase)

	db, err := sql.Open("mysql", dbConn)
	if err != nil {
		log.Println("Couldn't connect!")
		log.Println(err.Error)
	}
	database = db

	rtr := mux.NewRouter()
	//rtr.HandleFunc("/pages/{id:[0-9]+}", pageHandler)
	//rtr.HandleFunc("/homepage", pageHandler)
	//rtr.HandleFunc("/contact", pageHandler)
	//rtr.HandleFunc("/page/{id:[0-9]+}", ServePage)

	rtr.HandleFunc("/api/pages", APIPage).
		Methods("GET").
		Schemes("https")
	rtr.HandleFunc("/api/pages/{guid:[0-9a-zA\\-]+}", APIPage).
		Methods("GET").
		Schemes("https")

	rtr.HandleFunc("/page/{guid:[0-9a-zA\\-]+}", ServePage)
	rtr.HandleFunc("/", RedirIndex)
	rtr.HandleFunc("/home", ServeIndex)

	fmt.Printf("Server port :%v\n", cfg.Server.Port)

	http.Handle("/", rtr)

	http.ListenAndServe(":"+cfg.Server.Port, nil)
	cmd.Execute()
}

func RedirIndex(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "/home", 301)
}

func ServeIndex(w http.ResponseWriter, r *http.Request) {
	var Pages = []Page{}
	pages, err := database.Query("SELECT page_title, page_content,page_date,page_guid FROM pages ORDER BY ? DESC", "page_date")
	if err != nil {
		fmt.Fprintln(w, err.Error())
	}
	defer pages.Close()
	for pages.Next() {
		thisPage := Page{}
		pages.Scan(&thisPage.Title, &thisPage.RawContent, &thisPage.Date, &thisPage.GUID)
		thisPage.Content = template.HTML(thisPage.RawContent)
		Pages = append(Pages, thisPage)
	}
	t, _ := template.ParseFiles("templates/index.html")
	t.Execute(w, Pages)
}

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

func pageHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	pageID := vars["id"]
	fileName := "files/" + pageID + ".html"
	_, err := os.Stat(fileName)
	if err != nil {
		fileName = "files/404.html"
	}

	http.ServeFile(w, r, fileName)
}

func APIPage(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	pageGUID := vars["guid"]
	thisPage := Page{}
	fmt.Println(pageGUID)
}

func ServePage(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	pageGUID := vars["guid"]
	thisPage := Page{}
	fmt.Println(pageGUID)
	err := database.QueryRow("SELECT page_title, page_content,page_date FROM pages WHERE page_guid=?", pageGUID).Scan(&thisPage.Title, &thisPage.RawContent, &thisPage.Date)
	thisPage.Content = template.HTML(thisPage.RawContent)
	if err != nil {
		http.Error(w, http.StatusText(404), http.StatusNotFound)
		log.Println("Couldn't get the page: " + pageGUID)
		log.Println(err.Error)
		return
	}
	//html := `<html><head><title>` + thisPage.Title + `</title></head><body><h1>` + thisPage.Title + `</h1><div>` + thisPage.Content + `</div></body></html>`
	//fmt.Fprintln(w, html)
	t, _ := template.ParseFiles("templates/blog.html")
	t.Execute(w, thisPage)
}

func (p Page) TruncatedText() string {
	chars := 0
	for i, _ := range p.RawContent {
		chars++
		if chars > 150 {
			return p.RawContent[:i] + `...`
		}
	}
	return p.RawContent
}
<commit_msg>fixed some compile errors<commit_after>// Copyright © 2017 Solf1re2 <jy1v07@gmail.com>
//
// 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.

package main

import (
	"database/sql"
	"fmt"

	"html/template"
	"log"
	"net/http"
	"os"

	_ "github.com/go-sql-driver/mysql"
	"github.com/gorilla/mux"
	"github.com/solf1re2/config"
	"github.com/solf1re2/gosol/cmd"
)

const (
	DBHost  = "127.0.0.1"
	DBPort  = ":3306"
	DBUser  = "root"
	DBPass  = "password"
	DBDbase = "cms"
)

var database *sql.DB

type Page struct {
	Title      string
	RawContent string
	Content    template.HTML
	Date       string
	GUID       string
}

func main() {
	// Load the config file - PORT,
	cfg := config.LoadConfig("./config.json")

	dbConn := fmt.Sprintf("%s:%s@tcp(%s%s)/%s", DBUser, DBPass, DBHost, DBPort, DBDbase)

	db, err := sql.Open("mysql", dbConn)
	if err != nil {
		log.Println("Couldn't connect!")
		log.Println(err.Error)
	}
	database = db

	rtr := mux.NewRouter()
	//rtr.HandleFunc("/pages/{id:[0-9]+}", pageHandler)
	//rtr.HandleFunc("/homepage", pageHandler)
	//rtr.HandleFunc("/contact", pageHandler)
	//rtr.HandleFunc("/page/{id:[0-9]+}", ServePage)

	rtr.HandleFunc("/api/pages", APIPage).
		Methods("GET").
		Schemes("https")
	rtr.HandleFunc("/api/pages/{guid:[0-9a-zA\\-]+}", APIPage).
		Methods("GET").
		Schemes("https")

	rtr.HandleFunc("/page/{guid:[0-9a-zA\\-]+}", ServePage)
	rtr.HandleFunc("/", RedirIndex)
	rtr.HandleFunc("/home", ServeIndex)

	fmt.Printf("Server port :%v\n", cfg.Server.Port)

	http.Handle("/", rtr)

	http.ListenAndServe(":"+cfg.Server.Port, nil)
	cmd.Execute()
}

func RedirIndex(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "/home", 301)
}

func ServeIndex(w http.ResponseWriter, r *http.Request) {
	var Pages = []Page{}
	pages, err := database.Query("SELECT page_title, page_content,page_date,page_guid FROM pages ORDER BY ? DESC", "page_date")
	if err != nil {
		fmt.Fprintln(w, err.Error())
	}
	defer pages.Close()
	for pages.Next() {
		thisPage := Page{}
		pages.Scan(&thisPage.Title, &thisPage.RawContent, &thisPage.Date, &thisPage.GUID)
		thisPage.Content = template.HTML(thisPage.RawContent)
		Pages = append(Pages, thisPage)
	}
	t, _ := template.ParseFiles("templates/index.html")
	t.Execute(w, Pages)
}

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

func pageHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	pageID := vars["id"]
	fileName := "files/" + pageID + ".html"
	_, err := os.Stat(fileName)
	if err != nil {
		fileName = "files/404.html"
	}

	http.ServeFile(w, r, fileName)
}

func APIPage(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	pageGUID := vars["guid"]
	thisPage := Page{}
	thisPage.GUID = pageGUID
	fmt.Println(pageGUID)
}

func ServePage(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	pageGUID := vars["guid"]
	thisPage := Page{}
	fmt.Println(pageGUID)
	err := database.QueryRow("SELECT page_title, page_content,page_date FROM pages WHERE page_guid=?", pageGUID).Scan(&thisPage.Title, &thisPage.RawContent, &thisPage.Date)
	thisPage.Content = template.HTML(thisPage.RawContent)
	if err != nil {
		http.Error(w, http.StatusText(404), http.StatusNotFound)
		log.Println("Couldn't get the page: " + pageGUID)
		log.Println(err.Error)
		return
	}
	//html := `<html><head><title>` + thisPage.Title + `</title></head><body><h1>` + thisPage.Title + `</h1><div>` + thisPage.Content + `</div></body></html>`
	//fmt.Fprintln(w, html)
	t, _ := template.ParseFiles("templates/blog.html")
	t.Execute(w, thisPage)
}

func (p Page) TruncatedText() string {
	chars := 0
	for i, _ := range p.RawContent {
		chars++
		if chars > 150 {
			return p.RawContent[:i] + `...`
		}
	}
	return p.RawContent
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"log"
	"os"
	"strings"
	"time"
)

const staticVersion = "v0.4.1+"

var version string

func setupFlag(name string) {
	viper.SetConfigName(name)
	viper.AddConfigPath("/etc/xdg/vv")
	viper.AddConfigPath("$HOME/.config/vv")
	pflag.String("mpd.host", "", "[DEPRECATED] mpd server hostname to connect")
	pflag.String("mpd.port", "", "[DEPRECATED] mpd server TCP port to connect")
	pflag.String("mpd.network", "tcp", "mpd server network to connect")
	pflag.String("mpd.addr", "localhost:6600", "mpd server address to connect")
	pflag.String("mpd.music_directory", "", "set music_directory in mpd.conf value to search album cover image")
	pflag.String("server.port", "", "[DEPRECATED] this app serving TCP port")
	pflag.String("server.addr", ":8080", "this app serving address")
	pflag.Bool("server.keepalive", true, "use HTTP keep-alive")
	pflag.BoolP("debug", "d", false, "use local assets if exists")
	pflag.Parse()
	viper.BindPFlags(pflag.CommandLine)
}

func getMusicDirectory(confpath string) (string, error) {
	f, err := os.Open(confpath)
	if err != nil {
		return "", err
	}
	defer f.Close()
	sc := bufio.NewScanner(f)
	for i := 1; sc.Scan(); i++ {
		if err := sc.Err(); err != nil {
			return "", err
		}
		l := sc.Text()
		if strings.HasPrefix(l, "music_directory") {
			q := strings.TrimSpace(strings.TrimPrefix(l, "music_directory"))
			if strings.HasPrefix(q, "\"") && strings.HasSuffix(q, "\"") {
				return strings.Trim(q, "\""), nil
			}
		}
	}
	return "", nil
}

//go:generate go-bindata assets
func main() {
	setupFlag("config")
	err := viper.ReadInConfig()
	if err != nil {
		if _, notfound := err.(viper.ConfigFileNotFoundError); !notfound {
			log.Println("[error]", "faied to load config file:", err)
			os.Exit(1)
		}
	}
	musicDirectory := viper.GetString("mpd.music_directory")
	if len(musicDirectory) == 0 && viper.GetString("mpd.host") == "localhost" {
		dir, err := getMusicDirectory("/etc/mpd.conf")
		if err == nil {
			musicDirectory = dir
		}
	}
	network := viper.GetString("mpd.network")
	addr := viper.GetString("mpd.addr")
	if viper.GetString("mpd.host") != "" && viper.GetString("mpd.port") != "" {
		log.Println("[warn]", "mpd.host and mpd.port are deprecated option. use mpd.addr")
		network = "tcp"
		addr = viper.GetString("mpd.host") + ":" + viper.GetString("mpd.port")
	}
	music, err := Dial(network, addr, "", musicDirectory)
	defer music.Close()
	if err != nil {
		log.Println("[error]", "faied to connect/initialize mpd:", err)
		os.Exit(1)
	}
	serverAddr := viper.GetString("server.addr")
	if viper.GetString("server.port") != "" {
		log.Println("[warn]", "server.port is deprecated option. use server.addr")
		serverAddr = ":" + viper.GetString("server.port")
	}
	s := Server{
		Music:          music,
		MusicDirectory: musicDirectory,
		Addr:           serverAddr,
		StartTime:      time.Now().UTC(),
		KeepAlive:      viper.GetBool("server.keepalive"),
		debug:          viper.GetBool("debug"),
	}
	s.Serve()
}
<commit_msg>fix bug: failed to get music_directory<commit_after>package main

import (
	"bufio"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"log"
	"os"
	"strings"
	"time"
)

const staticVersion = "v0.4.1+"

var version string

func setupFlag(name string) {
	viper.SetConfigName(name)
	viper.AddConfigPath("/etc/xdg/vv")
	viper.AddConfigPath("$HOME/.config/vv")
	pflag.String("mpd.host", "", "[DEPRECATED] mpd server hostname to connect")
	pflag.String("mpd.port", "", "[DEPRECATED] mpd server TCP port to connect")
	pflag.String("mpd.network", "tcp", "mpd server network to connect")
	pflag.String("mpd.addr", "localhost:6600", "mpd server address to connect")
	pflag.String("mpd.music_directory", "", "set music_directory in mpd.conf value to search album cover image")
	pflag.String("server.port", "", "[DEPRECATED] this app serving TCP port")
	pflag.String("server.addr", ":8080", "this app serving address")
	pflag.Bool("server.keepalive", true, "use HTTP keep-alive")
	pflag.BoolP("debug", "d", false, "use local assets if exists")
	pflag.Parse()
	viper.BindPFlags(pflag.CommandLine)
}

func getMusicDirectory(confpath string) (string, error) {
	f, err := os.Open(confpath)
	if err != nil {
		return "", err
	}
	defer f.Close()
	sc := bufio.NewScanner(f)
	for i := 1; sc.Scan(); i++ {
		if err := sc.Err(); err != nil {
			return "", err
		}
		l := sc.Text()
		if strings.HasPrefix(l, "music_directory") {
			q := strings.TrimSpace(strings.TrimPrefix(l, "music_directory"))
			if strings.HasPrefix(q, "\"") && strings.HasSuffix(q, "\"") {
				return strings.Trim(q, "\""), nil
			}
		}
	}
	return "", nil
}

//go:generate go-bindata assets
func main() {
	setupFlag("config")
	err := viper.ReadInConfig()
	if err != nil {
		if _, notfound := err.(viper.ConfigFileNotFoundError); !notfound {
			log.Println("[error]", "faied to load config file:", err)
			os.Exit(1)
		}
	}
	musicDirectory := viper.GetString("mpd.music_directory")
	if len(musicDirectory) == 0 {
		dir, err := getMusicDirectory("/etc/mpd.conf")
		if err == nil {
			musicDirectory = dir
		}
	}
	network := viper.GetString("mpd.network")
	addr := viper.GetString("mpd.addr")
	if viper.GetString("mpd.host") != "" && viper.GetString("mpd.port") != "" {
		log.Println("[warn]", "mpd.host and mpd.port are deprecated option. use mpd.addr")
		network = "tcp"
		addr = viper.GetString("mpd.host") + ":" + viper.GetString("mpd.port")
	}
	music, err := Dial(network, addr, "", musicDirectory)
	defer music.Close()
	if err != nil {
		log.Println("[error]", "faied to connect/initialize mpd:", err)
		os.Exit(1)
	}
	serverAddr := viper.GetString("server.addr")
	if viper.GetString("server.port") != "" {
		log.Println("[warn]", "server.port is deprecated option. use server.addr")
		serverAddr = ":" + viper.GetString("server.port")
	}
	s := Server{
		Music:          music,
		MusicDirectory: musicDirectory,
		Addr:           serverAddr,
		StartTime:      time.Now().UTC(),
		KeepAlive:      viper.GetBool("server.keepalive"),
		debug:          viper.GetBool("debug"),
	}
	s.Serve()
}
<|endoftext|>