<commit_before>package cmd

import (
	"fmt"
	"os"

	"github.com/mpppk/hlb/etc"
	"github.com/mpppk/hlb/git"
	"github.com/mpppk/hlb/hlblib"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "hlb",
	Short: "multi git hosting service manager",
	Long:  ``,
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		bypassCmds := []string{"create"}
		configFilePath, err := etc.GetConfigDirPath()
		if err != nil {
			etc.PanicIfErrorExist(err)
		}

		for _, bypassCmd := range bypassCmds {
			if bypassCmd == cmd.Name() {
				return
			}
		}

		var config etc.Config
		err = viper.Unmarshal(&config)
		etc.PanicIfErrorExist(err)
		remote, err := git.GetDefaultRemote(".")
		etc.PanicIfErrorExist(err)
		serviceConfig, ok := config.FindServiceConfig(remote.ServiceHost)
		if !ok {
			fmt.Println(remote.ServiceHost, "is unknown host. Please add the service configuration to config file("+configFilePath+")")
			os.Exit(1)
		}
		if serviceConfig.Token == "" {
			if !hlblib.CanCreateToken(serviceConfig.Type) {
				fmt.Println("The token of", serviceConfig.Host, "can not create via hlb.")
				fmt.Println("Please add token to config file(" + configFilePath + ") manually.")
				os.Exit(1)
			}
			serviceUrl := serviceConfig.Protocol + "://" + serviceConfig.Host
			addServiceCmd.Run(cmd, []string{serviceConfig.Type, serviceUrl})
		}
	},
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)

	configFilePath, err := etc.GetConfigFilePath()
	etc.PanicIfErrorExist(err)

	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is "+configFilePath+")")
	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if cfgFile != "" { // enable ability to specify config file via flag
		viper.SetConfigFile(cfgFile)
	}

	viper.SetConfigName(".hlb") // name of config file (without extension)
	configFilePath, err := etc.GetConfigDirPath()
	etc.PanicIfErrorExist(err)

	viper.AddConfigPath(configFilePath) // adding home directory as first search path
	viper.AutomaticEnv()                // read in environment variables that match

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err != nil {
		initCmd.Run(nil, nil)
		err := viper.ReadInConfig()
		etc.PanicIfErrorExist(err)
	}
}
<commit_msg>Fix version command<commit_after>package cmd

import (
	"fmt"
	"os"

	"github.com/mpppk/hlb/etc"
	"github.com/mpppk/hlb/git"
	"github.com/mpppk/hlb/hlblib"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "hlb",
	Short: "multi git hosting service manager",
	Long:  ``,
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		bypassCmds := []string{"create", "version", "init", "add-service"}
		configFilePath, err := etc.GetConfigDirPath()
		if err != nil {
			etc.PanicIfErrorExist(err)
		}

		for _, bypassCmd := range bypassCmds {
			if bypassCmd == cmd.Name() {
				return
			}
		}

		var config etc.Config
		err = viper.Unmarshal(&config)
		etc.PanicIfErrorExist(err)
		remote, err := git.GetDefaultRemote(".")
		etc.PanicIfErrorExist(err)
		serviceConfig, ok := config.FindServiceConfig(remote.ServiceHost)
		if !ok {
			fmt.Println(remote.ServiceHost, "is unknown host. Please add the service configuration to config file("+configFilePath+")")
			os.Exit(1)
		}
		if serviceConfig.Token == "" {
			if !hlblib.CanCreateToken(serviceConfig.Type) {
				fmt.Println("The token of", serviceConfig.Host, "can not create via hlb.")
				fmt.Println("Please add token to config file(" + configFilePath + ") manually.")
				os.Exit(1)
			}
			serviceUrl := serviceConfig.Protocol + "://" + serviceConfig.Host
			addServiceCmd.Run(cmd, []string{serviceConfig.Type, serviceUrl})
		}
	},
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)

	configFilePath, err := etc.GetConfigFilePath()
	etc.PanicIfErrorExist(err)

	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is "+configFilePath+")")
	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if cfgFile != "" { // enable ability to specify config file via flag
		viper.SetConfigFile(cfgFile)
	}

	viper.SetConfigName(".hlb") // name of config file (without extension)
	configFilePath, err := etc.GetConfigDirPath()
	etc.PanicIfErrorExist(err)

	viper.AddConfigPath(configFilePath) // adding home directory as first search path
	viper.AutomaticEnv()                // read in environment variables that match

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err != nil {
		initCmd.Run(nil, nil)
		err := viper.ReadInConfig()
		etc.PanicIfErrorExist(err)
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"fmt"
	"os"

	"github.com/mpppk/hlb/etc"
	"github.com/mpppk/hlb/git"
	"github.com/mpppk/hlb/hlblib"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "hlb",
	Short: "multi git hosting service manager",
	Long:  ``,
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		bypassCmds := []string{"create"}
		configFilePath, err := etc.GetConfigDirPath()
		if err != nil {
			etc.PanicIfErrorExist(err)
		}

		for _, bypassCmd := range bypassCmds {
			if bypassCmd == cmd.Name() {
				return
			}
		}

		var config etc.Config
		err = viper.Unmarshal(&config)
		etc.PanicIfErrorExist(err)
		remote, err := git.GetDefaultRemote(".")
		etc.PanicIfErrorExist(err)
		serviceConfig, ok := config.FindServiceConfig(remote.ServiceHost)
		if !ok {
			fmt.Println(remote.ServiceHost, "is unknown host. Please add the service configuration to config file("+configFilePath+")")
			os.Exit(1)
		}
		if serviceConfig.Token == "" {
			if !hlblib.CanCreateToken(serviceConfig.Type) {
				fmt.Println("The token of", serviceConfig.Host, "can not create via hlb.")
				fmt.Println("Please add token to config file(" + configFilePath + ") manually.")
				os.Exit(1)
			}
			serviceUrl := serviceConfig.Protocol + "://" + serviceConfig.Host
			addServiceCmd.Run(cmd, []string{serviceConfig.Type, serviceUrl})
		}
	},
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)

	configFilePath, err := etc.GetConfigFilePath()
	etc.PanicIfErrorExist(err)

	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is "+configFilePath+")")
	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if cfgFile != "" { // enable ability to specify config file via flag
		viper.SetConfigFile(cfgFile)
	}

	viper.SetConfigName(".hlb") // name of config file (without extension)
	configFilePath, err := etc.GetConfigDirPath()
	etc.PanicIfErrorExist(err)

	viper.AddConfigPath(configFilePath) // adding home directory as first search path
	viper.AutomaticEnv()                // read in environment variables that match

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err == nil {
		fmt.Println("Using config file:", viper.ConfigFileUsed())
	} else {
		initCmd.Run(nil, nil)
		err := viper.ReadInConfig()
		etc.PanicIfErrorExist(err)
	}
}
<commit_msg>Remove config file path output<commit_after>package cmd

import (
	"fmt"
	"os"

	"github.com/mpppk/hlb/etc"
	"github.com/mpppk/hlb/git"
	"github.com/mpppk/hlb/hlblib"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var cfgFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "hlb",
	Short: "multi git hosting service manager",
	Long:  ``,
	PersistentPreRun: func(cmd *cobra.Command, args []string) {
		bypassCmds := []string{"create"}
		configFilePath, err := etc.GetConfigDirPath()
		if err != nil {
			etc.PanicIfErrorExist(err)
		}

		for _, bypassCmd := range bypassCmds {
			if bypassCmd == cmd.Name() {
				return
			}
		}

		var config etc.Config
		err = viper.Unmarshal(&config)
		etc.PanicIfErrorExist(err)
		remote, err := git.GetDefaultRemote(".")
		etc.PanicIfErrorExist(err)
		serviceConfig, ok := config.FindServiceConfig(remote.ServiceHost)
		if !ok {
			fmt.Println(remote.ServiceHost, "is unknown host. Please add the service configuration to config file("+configFilePath+")")
			os.Exit(1)
		}
		if serviceConfig.Token == "" {
			if !hlblib.CanCreateToken(serviceConfig.Type) {
				fmt.Println("The token of", serviceConfig.Host, "can not create via hlb.")
				fmt.Println("Please add token to config file(" + configFilePath + ") manually.")
				os.Exit(1)
			}
			serviceUrl := serviceConfig.Protocol + "://" + serviceConfig.Host
			addServiceCmd.Run(cmd, []string{serviceConfig.Type, serviceUrl})
		}
	},
}

// Execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)

	configFilePath, err := etc.GetConfigFilePath()
	etc.PanicIfErrorExist(err)

	RootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is "+configFilePath+")")
	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	RootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if cfgFile != "" { // enable ability to specify config file via flag
		viper.SetConfigFile(cfgFile)
	}

	viper.SetConfigName(".hlb") // name of config file (without extension)
	configFilePath, err := etc.GetConfigDirPath()
	etc.PanicIfErrorExist(err)

	viper.AddConfigPath(configFilePath) // adding home directory as first search path
	viper.AutomaticEnv()                // read in environment variables that match

	// If a config file is found, read it in.
	if err := viper.ReadInConfig(); err != nil {
		initCmd.Run(nil, nil)
		err := viper.ReadInConfig()
		etc.PanicIfErrorExist(err)
	}
}
<|endoftext|>


<commit_before>// Copyright © 2017 Teppei Fukuda
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package cmd

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

	"github.com/knqyf263/pet/config"
	"github.com/spf13/cobra"
)

const (
	version = "0.0.2"
)

var configFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "pet",
	Short: "Simple command-line snippet manager.",
	Long:  `pet - Simple command-line snippet manager.`,
}

// Execute adds all child commands to the root command sets flags appropriately.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)
	RootCmd.AddCommand(versionCmd)

	RootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file (default is $HOME/.config/pet/config.toml)")
	RootCmd.PersistentFlags().BoolVarP(&config.Flag.Debug, "debug", "", false, "debug mode")
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Print the version number",
	Long:  `Print the version number`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Printf("pet version %s\n", version)
	},
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if configFile == "" {
		dir, err := config.GetDefaultConfigDir()
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v", err)
			os.Exit(1)
		}
		configFile = filepath.Join(dir, "config.toml")
	}

	if err := config.Conf.Load(configFile); err != nil {
		fmt.Fprintf(os.Stderr, "%v", err)
		os.Exit(1)
	}
}
<commit_msg>v0.1.0<commit_after>// Copyright © 2017 Teppei Fukuda
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package cmd

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

	"github.com/knqyf263/pet/config"
	"github.com/spf13/cobra"
)

const (
	version = "0.1.0"
)

var configFile string

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
	Use:   "pet",
	Short: "Simple command-line snippet manager.",
	Long:  `pet - Simple command-line snippet manager.`,
}

// Execute adds all child commands to the root command sets flags appropriately.
func Execute() {
	if err := RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)
	RootCmd.AddCommand(versionCmd)

	RootCmd.PersistentFlags().StringVar(&configFile, "config", "", "config file (default is $HOME/.config/pet/config.toml)")
	RootCmd.PersistentFlags().BoolVarP(&config.Flag.Debug, "debug", "", false, "debug mode")
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Print the version number",
	Long:  `Print the version number`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Printf("pet version %s\n", version)
	},
}

// initConfig reads in config file and ENV variables if set.
func initConfig() {
	if configFile == "" {
		dir, err := config.GetDefaultConfigDir()
		if err != nil {
			fmt.Fprintf(os.Stderr, "%v", err)
			os.Exit(1)
		}
		configFile = filepath.Join(dir, "config.toml")
	}

	if err := config.Conf.Load(configFile); err != nil {
		fmt.Fprintf(os.Stderr, "%v", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>// +build linux darwin freebsd

package cmd

import (
	"fmt"
	"github.com/DataDog/datadog-go/statsd"
	"github.com/hpcloud/tail"
	"github.com/spf13/cobra"
	"os"
	"regexp"
)

var tailCmd = &cobra.Command{
	Use:   "tail",
	Short: "Tail logs, match lines and send metrics to Datadog.",
	Long:  `Tail logs, match lines and send metrics to Datadog.`,
	PreRun: func(cmd *cobra.Command, args []string) {
		checkTailFlags()
	},
	Run: startTail,
}

func startTail(cmd *cobra.Command, args []string) {
	// Try to compile the regex - throw an error if it doesn't work.
	regex, err := regexp.Compile(Match)
	if err != nil {
		fmt.Println("There's something wrong with your regex. Try again.")
		fmt.Printf("Error: %s\n", err)
		os.Exit(1)
	}
	dog := DogConnect()
	t := OpenLogfile(LogFile)
	TailLog(t, dog, regex)
}

func checkTailFlags() {
	if LogFile == "" {
		fmt.Println("Please enter a filename to tail '--log'")
		os.Exit(1)
	}
	if Match == "" {
		fmt.Println("Please enter a regex to match '--match'")
		os.Exit(1)
	}
	if MetricName == "" {
		fmt.Println("Please enter a metric name to send '--metric'")
		os.Exit(1)
	}
	fmt.Println("Press CTRL-C to shutdown.")
}

var (
	// LogFile is the file to tail.
	LogFile string

	// Match is the regex to match in the file.
	Match string

	// MetricName is the name of the metric to send to Datadog.
	MetricName string
)

func init() {
	tailCmd.Flags().StringVarP(&LogFile, "log", "", "", "File to tail.")
	tailCmd.Flags().StringVarP(&Match, "match", "", "", "Match this regex.")
	tailCmd.Flags().StringVarP(&MetricName, "metric", "", "", "Send this metric name.")
	RootCmd.AddCommand(tailCmd)
}

// TailLog tails a file and sends stats to Datadog.
func TailLog(t *tail.Tail, dog *statsd.Client, r *regexp.Regexp) {
	for line := range t.Lines {
		// Blank lines really mess this up - this protects against it.
		if line.Text == "" {
			continue
		}
		match := r.FindAllStringSubmatch(line.Text, -1)
		if match != nil {
			Log(fmt.Sprintf("Match: %s", match), "debug")
			Log(fmt.Sprintf("Sending Stat: %s", MetricName), "debug")
			dog.Count(MetricName, 1, dog.Tags, 1)
		}
	}
}
<commit_msg>Add the ability to add a tag to the metric sent in `tail`.<commit_after>// +build linux darwin freebsd

package cmd

import (
	"fmt"
	"github.com/DataDog/datadog-go/statsd"
	"github.com/hpcloud/tail"
	"github.com/spf13/cobra"
	"os"
	"regexp"
	"strings"
)

var tailCmd = &cobra.Command{
	Use:   "tail",
	Short: "Tail logs, match lines and send metrics to Datadog.",
	Long:  `Tail logs, match lines and send metrics to Datadog.`,
	PreRun: func(cmd *cobra.Command, args []string) {
		checkTailFlags()
	},
	Run: startTail,
}

func startTail(cmd *cobra.Command, args []string) {
	// Try to compile the regex - throw an error if it doesn't work.
	regex, err := regexp.Compile(Match)
	if err != nil {
		fmt.Println("There's something wrong with your regex. Try again.")
		fmt.Printf("Error: %s\n", err)
		os.Exit(1)
	}
	dog := DogConnect()
	t := OpenLogfile(LogFile)
	TailLog(t, dog, regex)
}

func checkTailFlags() {
	if LogFile == "" {
		fmt.Println("Please enter a filename to tail '--log'")
		os.Exit(1)
	}
	if Match == "" {
		fmt.Println("Please enter a regex to match '--match'")
		os.Exit(1)
	}
	if MetricName == "" {
		fmt.Println("Please enter a metric name to send '--metric'")
		os.Exit(1)
	}
	// If you're sending a MetricTag - it needs to have a ':'
	if MetricTag != "" && !strings.Contains(MetricTag, ":") {
		fmt.Println("Tags need to contain a ':'")
		os.Exit(1)
	}
	fmt.Println("Press CTRL-C to shutdown.")
}

var (
	// LogFile is the file to tail.
	LogFile string

	// Match is the regex to match in the file.
	Match string

	// MetricName is the name of the metric to send to Datadog.
	MetricName string

	// MetricTag is the name of the tag to add to the metric we're sending to Datadog.
	MetricTag string
)

func init() {
	tailCmd.Flags().StringVarP(&LogFile, "log", "", "", "File to tail.")
	tailCmd.Flags().StringVarP(&Match, "match", "", "", "Match this regex.")
	tailCmd.Flags().StringVarP(&MetricName, "metric", "", "", "Send this metric name.")
	tailCmd.Flags().StringVarP(&MetricTag, "tag", "", "", "Add this tag to the metric.")
	RootCmd.AddCommand(tailCmd)
}

// TailLog tails a file and sends stats to Datadog.
func TailLog(t *tail.Tail, dog *statsd.Client, r *regexp.Regexp) {
	for line := range t.Lines {
		// Blank lines really mess this up - this protects against it.
		if line.Text == "" {
			continue
		}
		match := r.FindAllStringSubmatch(line.Text, -1)
		if match != nil {
			Log(fmt.Sprintf("Match: %s", match), "debug")
			Log(fmt.Sprintf("Sending Stat: %s", MetricName), "debug")
			tags := dog.Tags
			if MetricTag != "" {
				tags = append(tags, MetricTag)
			}
			dog.Count(MetricName, 1, tags, 1)
		}
	}
}
<|endoftext|>


<commit_before>package api

import (
	"encoding/json"
	"fmt"
	"github.com/sacloud/libsacloud/sacloud"
	"time"
)

// SearchMobileGatewayResponse モバイルゲートウェイ検索レスポンス
type SearchMobileGatewayResponse struct {
	// Total 総件数
	Total int `json:",omitempty"`
	// From ページング開始位置
	From int `json:",omitempty"`
	// Count 件数
	Count int `json:",omitempty"`
	// MobileGateways モバイルゲートウェイ リスト
	MobileGateways []sacloud.MobileGateway `json:"Appliances,omitempty"`
}

// MobileGatewaySIMRequest SIM一覧取得リクエスト
type MobileGatewaySIMRequest struct {
	From    int                    `json:",omitempty"`
	Count   int                    `json:",omitempty"`
	Sort    []string               `json:",omitempty"`
	Filter  map[string]interface{} `json:",omitempty"`
	Exclude []string               `json:",omitempty"`
	Include []string               `json:",omitempty"`
}

type mobileGatewayResponse struct {
	*sacloud.ResultFlagValue
	*sacloud.MobileGateway `json:"Appliance,omitempty"`
	Success                interface{} `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
}

type mobileGatewaySIMResponse struct {
	*sacloud.ResultFlagValue
	SIM     []sacloud.SIMInfo `json:"sim,omitempty"`
	Success interface{}       `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
}

// MobileGatewayAPI モバイルゲートウェイAPI
type MobileGatewayAPI struct {
	*baseAPI
}

// NewMobileGatewayAPI モバイルゲートウェイAPI作成
func NewMobileGatewayAPI(client *Client) *MobileGatewayAPI {
	return &MobileGatewayAPI{
		&baseAPI{
			client: client,
			FuncGetResourceURL: func() string {
				return "appliance"
			},
			FuncBaseSearchCondition: func() *sacloud.Request {
				res := &sacloud.Request{}
				res.AddFilter("Class", "mobilegateway")
				return res
			},
		},
	}
}

// Find 検索
func (api *MobileGatewayAPI) Find() (*SearchMobileGatewayResponse, error) {
	data, err := api.client.newRequest("GET", api.getResourceURL(), api.getSearchState())
	if err != nil {
		return nil, err
	}
	var res SearchMobileGatewayResponse
	if err := json.Unmarshal(data, &res); err != nil {
		return nil, err
	}
	return &res, nil
}

func (api *MobileGatewayAPI) request(f func(*mobileGatewayResponse) error) (*sacloud.MobileGateway, error) {
	res := &mobileGatewayResponse{}
	err := f(res)
	if err != nil {
		return nil, err
	}
	return res.MobileGateway, nil
}

func (api *MobileGatewayAPI) createRequest(value *sacloud.MobileGateway) *mobileGatewayResponse {
	return &mobileGatewayResponse{MobileGateway: value}
}

// Create 新規作成
func (api *MobileGatewayAPI) Create(value *sacloud.MobileGateway) (*sacloud.MobileGateway, error) {
	return api.request(func(res *mobileGatewayResponse) error {
		return api.create(api.createRequest(value), res)
	})
}

// Read 読み取り
func (api *MobileGatewayAPI) Read(id int64) (*sacloud.MobileGateway, error) {
	return api.request(func(res *mobileGatewayResponse) error {
		return api.read(id, nil, res)
	})
}

// Update 更新
func (api *MobileGatewayAPI) Update(id int64, value *sacloud.MobileGateway) (*sacloud.MobileGateway, error) {
	return api.request(func(res *mobileGatewayResponse) error {
		return api.update(id, api.createRequest(value), res)
	})
}

// Delete 削除
func (api *MobileGatewayAPI) Delete(id int64) (*sacloud.MobileGateway, error) {
	return api.request(func(res *mobileGatewayResponse) error {
		return api.delete(id, nil, res)
	})
}

// Config 設定変更の反映
func (api *MobileGatewayAPI) Config(id int64) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/config", api.getResourceURL(), id)
	)
	return api.modify(method, uri, nil)
}

// IsUp 起動しているか判定
func (api *MobileGatewayAPI) IsUp(id int64) (bool, error) {
	lb, err := api.Read(id)
	if err != nil {
		return false, err
	}
	return lb.Instance.IsUp(), nil
}

// IsDown ダウンしているか判定
func (api *MobileGatewayAPI) IsDown(id int64) (bool, error) {
	lb, err := api.Read(id)
	if err != nil {
		return false, err
	}
	return lb.Instance.IsDown(), nil
}

// Boot 起動
func (api *MobileGatewayAPI) Boot(id int64) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
	)
	return api.modify(method, uri, nil)
}

// Shutdown シャットダウン(graceful)
func (api *MobileGatewayAPI) Shutdown(id int64) (bool, error) {
	var (
		method = "DELETE"
		uri    = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
	)

	return api.modify(method, uri, nil)
}

// Stop シャットダウン(force)
func (api *MobileGatewayAPI) Stop(id int64) (bool, error) {
	var (
		method = "DELETE"
		uri    = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
	)

	return api.modify(method, uri, map[string]bool{"Force": true})
}

// RebootForce 再起動
func (api *MobileGatewayAPI) RebootForce(id int64) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/reset", api.getResourceURL(), id)
	)

	return api.modify(method, uri, nil)
}

// ResetForce リセット
func (api *MobileGatewayAPI) ResetForce(id int64, recycleProcess bool) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/reset", api.getResourceURL(), id)
	)

	return api.modify(method, uri, map[string]bool{"RecycleProcess": recycleProcess})
}

// SleepUntilUp 起動するまで待機
func (api *MobileGatewayAPI) SleepUntilUp(id int64, timeout time.Duration) error {
	handler := waitingForUpFunc(func() (hasUpDown, error) {
		return api.Read(id)
	}, 0)
	return blockingPoll(handler, timeout)
}

// SleepUntilDown ダウンするまで待機
func (api *MobileGatewayAPI) SleepUntilDown(id int64, timeout time.Duration) error {
	handler := waitingForDownFunc(func() (hasUpDown, error) {
		return api.Read(id)
	}, 0)
	return blockingPoll(handler, timeout)
}

// SleepWhileCopying コピー終了まで待機
func (api *MobileGatewayAPI) SleepWhileCopying(id int64, timeout time.Duration, maxRetry int) error {
	handler := waitingForAvailableFunc(func() (hasAvailable, error) {
		return api.Read(id)
	}, maxRetry)
	return blockingPoll(handler, timeout)
}

// AsyncSleepWhileCopying コピー終了まで待機(非同期)
func (api *MobileGatewayAPI) AsyncSleepWhileCopying(id int64, timeout time.Duration, maxRetry int) (chan (interface{}), chan (interface{}), chan (error)) {
	handler := waitingForAvailableFunc(func() (hasAvailable, error) {
		return api.Read(id)
	}, maxRetry)
	return poll(handler, timeout)
}

// ConnectToSwitch 指定のインデックス位置のNICをスイッチへ接続
func (api *MobileGatewayAPI) ConnectToSwitch(id int64, switchID int64) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/interface/%d/to/switch/%d", api.getResourceURL(), id, 1, switchID)
	)
	return api.modify(method, uri, nil)
}

// DisconnectFromSwitch 指定のインデックス位置のNICをスイッチから切断
func (api *MobileGatewayAPI) DisconnectFromSwitch(id int64) (bool, error) {
	var (
		method = "DELETE"
		uri    = fmt.Sprintf("%s/%d/interface/%d/to/switch", api.getResourceURL(), id, 1)
	)
	return api.modify(method, uri, nil)
}

// SetDNS DNSサーバ設定
func (api *MobileGatewayAPI) SetDNS(id int64, dns *sacloud.MobileGatewayResolver) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/dnsresolver", api.getResourceURL(), id)
	)

	return api.modify(method, uri, dns)
}

// ListSIM SIM一覧取得
func (api *MobileGatewayAPI) ListSIM(id int64, req *MobileGatewaySIMRequest) ([]sacloud.SIMInfo, error) {
	var (
		method = "GET"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/sims", api.getResourceURL(), id)
	)

	data, err := api.client.newRequest(method, uri, req)
	if err != nil {
		return nil, err
	}
	var res mobileGatewaySIMResponse
	if err := json.Unmarshal(data, &res); err != nil {
		return nil, err
	}
	return res.SIM, nil
}

// AddSIM SIM登録
func (api *MobileGatewayAPI) AddSIM(id int64, simID int64) (bool, error) {
	var (
		method = "POST"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/sims", api.getResourceURL(), id)
	)

	return api.modify(method, uri, map[string]interface{}{
		"sim": map[string]interface{}{
			"resource_id": fmt.Sprintf("%d", simID),
		},
	})
}

// DeleteSIM SIM登録
func (api *MobileGatewayAPI) DeleteSIM(id int64, simID int64) (bool, error) {
	var (
		method = "DELETE"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/sims/%d", api.getResourceURL(), id, simID)
	)
	return api.modify(method, uri, nil)
}
<commit_msg>Add MGW Logs API<commit_after>package api

import (
	"encoding/json"
	"fmt"
	"github.com/sacloud/libsacloud/sacloud"
	"time"
)

// SearchMobileGatewayResponse モバイルゲートウェイ検索レスポンス
type SearchMobileGatewayResponse struct {
	// Total 総件数
	Total int `json:",omitempty"`
	// From ページング開始位置
	From int `json:",omitempty"`
	// Count 件数
	Count int `json:",omitempty"`
	// MobileGateways モバイルゲートウェイ リスト
	MobileGateways []sacloud.MobileGateway `json:"Appliances,omitempty"`
}

// MobileGatewaySIMRequest SIM一覧取得リクエスト
type MobileGatewaySIMRequest struct {
	From    int                    `json:",omitempty"`
	Count   int                    `json:",omitempty"`
	Sort    []string               `json:",omitempty"`
	Filter  map[string]interface{} `json:",omitempty"`
	Exclude []string               `json:",omitempty"`
	Include []string               `json:",omitempty"`
}

type mobileGatewayResponse struct {
	*sacloud.ResultFlagValue
	*sacloud.MobileGateway `json:"Appliance,omitempty"`
	Success                interface{} `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
}

type mobileGatewaySIMResponse struct {
	*sacloud.ResultFlagValue
	SIM     []sacloud.SIMInfo `json:"sim,omitempty"`
	Success interface{}       `json:",omitempty"` //HACK: さくらのAPI側仕様: 戻り値:Successがbool値へ変換できないためinterface{}
}

// MobileGatewayAPI モバイルゲートウェイAPI
type MobileGatewayAPI struct {
	*baseAPI
}

// NewMobileGatewayAPI モバイルゲートウェイAPI作成
func NewMobileGatewayAPI(client *Client) *MobileGatewayAPI {
	return &MobileGatewayAPI{
		&baseAPI{
			client: client,
			FuncGetResourceURL: func() string {
				return "appliance"
			},
			FuncBaseSearchCondition: func() *sacloud.Request {
				res := &sacloud.Request{}
				res.AddFilter("Class", "mobilegateway")
				return res
			},
		},
	}
}

// Find 検索
func (api *MobileGatewayAPI) Find() (*SearchMobileGatewayResponse, error) {
	data, err := api.client.newRequest("GET", api.getResourceURL(), api.getSearchState())
	if err != nil {
		return nil, err
	}
	var res SearchMobileGatewayResponse
	if err := json.Unmarshal(data, &res); err != nil {
		return nil, err
	}
	return &res, nil
}

func (api *MobileGatewayAPI) request(f func(*mobileGatewayResponse) error) (*sacloud.MobileGateway, error) {
	res := &mobileGatewayResponse{}
	err := f(res)
	if err != nil {
		return nil, err
	}
	return res.MobileGateway, nil
}

func (api *MobileGatewayAPI) createRequest(value *sacloud.MobileGateway) *mobileGatewayResponse {
	return &mobileGatewayResponse{MobileGateway: value}
}

// Create 新規作成
func (api *MobileGatewayAPI) Create(value *sacloud.MobileGateway) (*sacloud.MobileGateway, error) {
	return api.request(func(res *mobileGatewayResponse) error {
		return api.create(api.createRequest(value), res)
	})
}

// Read 読み取り
func (api *MobileGatewayAPI) Read(id int64) (*sacloud.MobileGateway, error) {
	return api.request(func(res *mobileGatewayResponse) error {
		return api.read(id, nil, res)
	})
}

// Update 更新
func (api *MobileGatewayAPI) Update(id int64, value *sacloud.MobileGateway) (*sacloud.MobileGateway, error) {
	return api.request(func(res *mobileGatewayResponse) error {
		return api.update(id, api.createRequest(value), res)
	})
}

// Delete 削除
func (api *MobileGatewayAPI) Delete(id int64) (*sacloud.MobileGateway, error) {
	return api.request(func(res *mobileGatewayResponse) error {
		return api.delete(id, nil, res)
	})
}

// Config 設定変更の反映
func (api *MobileGatewayAPI) Config(id int64) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/config", api.getResourceURL(), id)
	)
	return api.modify(method, uri, nil)
}

// IsUp 起動しているか判定
func (api *MobileGatewayAPI) IsUp(id int64) (bool, error) {
	lb, err := api.Read(id)
	if err != nil {
		return false, err
	}
	return lb.Instance.IsUp(), nil
}

// IsDown ダウンしているか判定
func (api *MobileGatewayAPI) IsDown(id int64) (bool, error) {
	lb, err := api.Read(id)
	if err != nil {
		return false, err
	}
	return lb.Instance.IsDown(), nil
}

// Boot 起動
func (api *MobileGatewayAPI) Boot(id int64) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
	)
	return api.modify(method, uri, nil)
}

// Shutdown シャットダウン(graceful)
func (api *MobileGatewayAPI) Shutdown(id int64) (bool, error) {
	var (
		method = "DELETE"
		uri    = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
	)

	return api.modify(method, uri, nil)
}

// Stop シャットダウン(force)
func (api *MobileGatewayAPI) Stop(id int64) (bool, error) {
	var (
		method = "DELETE"
		uri    = fmt.Sprintf("%s/%d/power", api.getResourceURL(), id)
	)

	return api.modify(method, uri, map[string]bool{"Force": true})
}

// RebootForce 再起動
func (api *MobileGatewayAPI) RebootForce(id int64) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/reset", api.getResourceURL(), id)
	)

	return api.modify(method, uri, nil)
}

// ResetForce リセット
func (api *MobileGatewayAPI) ResetForce(id int64, recycleProcess bool) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/reset", api.getResourceURL(), id)
	)

	return api.modify(method, uri, map[string]bool{"RecycleProcess": recycleProcess})
}

// SleepUntilUp 起動するまで待機
func (api *MobileGatewayAPI) SleepUntilUp(id int64, timeout time.Duration) error {
	handler := waitingForUpFunc(func() (hasUpDown, error) {
		return api.Read(id)
	}, 0)
	return blockingPoll(handler, timeout)
}

// SleepUntilDown ダウンするまで待機
func (api *MobileGatewayAPI) SleepUntilDown(id int64, timeout time.Duration) error {
	handler := waitingForDownFunc(func() (hasUpDown, error) {
		return api.Read(id)
	}, 0)
	return blockingPoll(handler, timeout)
}

// SleepWhileCopying コピー終了まで待機
func (api *MobileGatewayAPI) SleepWhileCopying(id int64, timeout time.Duration, maxRetry int) error {
	handler := waitingForAvailableFunc(func() (hasAvailable, error) {
		return api.Read(id)
	}, maxRetry)
	return blockingPoll(handler, timeout)
}

// AsyncSleepWhileCopying コピー終了まで待機(非同期)
func (api *MobileGatewayAPI) AsyncSleepWhileCopying(id int64, timeout time.Duration, maxRetry int) (chan (interface{}), chan (interface{}), chan (error)) {
	handler := waitingForAvailableFunc(func() (hasAvailable, error) {
		return api.Read(id)
	}, maxRetry)
	return poll(handler, timeout)
}

// ConnectToSwitch 指定のインデックス位置のNICをスイッチへ接続
func (api *MobileGatewayAPI) ConnectToSwitch(id int64, switchID int64) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/interface/%d/to/switch/%d", api.getResourceURL(), id, 1, switchID)
	)
	return api.modify(method, uri, nil)
}

// DisconnectFromSwitch 指定のインデックス位置のNICをスイッチから切断
func (api *MobileGatewayAPI) DisconnectFromSwitch(id int64) (bool, error) {
	var (
		method = "DELETE"
		uri    = fmt.Sprintf("%s/%d/interface/%d/to/switch", api.getResourceURL(), id, 1)
	)
	return api.modify(method, uri, nil)
}

// SetDNS DNSサーバ設定
func (api *MobileGatewayAPI) SetDNS(id int64, dns *sacloud.MobileGatewayResolver) (bool, error) {
	var (
		method = "PUT"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/dnsresolver", api.getResourceURL(), id)
	)

	return api.modify(method, uri, dns)
}

// ListSIM SIM一覧取得
func (api *MobileGatewayAPI) ListSIM(id int64, req *MobileGatewaySIMRequest) ([]sacloud.SIMInfo, error) {
	var (
		method = "GET"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/sims", api.getResourceURL(), id)
	)

	data, err := api.client.newRequest(method, uri, req)
	if err != nil {
		return nil, err
	}
	var res mobileGatewaySIMResponse
	if err := json.Unmarshal(data, &res); err != nil {
		return nil, err
	}
	return res.SIM, nil
}

// AddSIM SIM登録
func (api *MobileGatewayAPI) AddSIM(id int64, simID int64) (bool, error) {
	var (
		method = "POST"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/sims", api.getResourceURL(), id)
	)

	return api.modify(method, uri, map[string]interface{}{
		"sim": map[string]interface{}{
			"resource_id": fmt.Sprintf("%d", simID),
		},
	})
}

// DeleteSIM SIM登録
func (api *MobileGatewayAPI) DeleteSIM(id int64, simID int64) (bool, error) {
	var (
		method = "DELETE"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/sims/%d", api.getResourceURL(), id, simID)
	)
	return api.modify(method, uri, nil)
}

// Logs セッションログ取得(複数SIM)
func (api *MobileGatewayAPI) Logs(id int64, body interface{}) ([]sacloud.SIMLog, error) {
	var (
		method = "GET"
		uri    = fmt.Sprintf("%s/%d/mobilegateway/sessionlog", api.getResourceURL(), id)
	)

	res := &simLogResponse{}
	err := api.baseAPI.request(method, uri, body, res)
	if err != nil {
		return nil, err
	}
	return res.Logs, nil
}
<|endoftext|>


<commit_before>package RTJobRunner

import (
	"bufio"
	"encoding/json"
	"io/ioutil"
	"os"
	"strings"
	"sync"
	"fmt"
	"sync/atomic"

	"github.com/akundu/utilities/logger"
    "github.com/satori/go.uuid"
)

type JobHandler struct {
	jobs                chan Request
	results             chan Response
	ws_job_tracker      sync.WaitGroup
	num_added           int32

	done_channel        chan bool

	worker_list         []Worker
	id                  string

	Results             []interface{}
}

func NewJobHandler(num_to_setup int,
	createWorkerFunc CreateWorkerFunction,
	print_results bool,
	) *JobHandler {

	jh := &JobHandler{
		jobs:                make(chan Request, num_to_setup),
		results:             make(chan Response, num_to_setup),
		num_added:           0,
		worker_list:         make([]Worker, num_to_setup),
		done_channel:        make(chan bool, 1),
		id:                  fmt.Sprintf("%s", uuid.NewV4()),
	}

	for w := 0; w < num_to_setup; w++ {
		worker := createWorkerFunc()
		jh.worker_list[w] = worker
		worker.PreRun()
		go worker.Run(w, jh.jobs, jh.results)
	}

	jh.ws_job_tracker.Add(1) //goroutine to wait for results
	go jh.waitForResults(print_results)

	return jh
}

func (this *JobHandler) AddJob(job Request) {
	this.jobs <- job
	atomic.AddInt32(&this.num_added, 1)
}

type JobHandlerLineOutputFilter func(string) Request //line - outputline - if outputline is empty - dont add anything
func (this *JobHandler) GetJobsFromStdin(jhlo JobHandlerLineOutputFilter) {
	//read from stdin
	bio := bufio.NewReader(os.Stdin)
	for {
		line, err := bio.ReadString('\n')
		if err != nil {
			break
		}
		line = strings.Trim(line, "\n \r\n")
		logger.Trace.Println("adding ", line)
		if jhlo == nil {
			this.AddJob(line)
		} else {
			filtered_job := jhlo(line)
			if filtered_job != nil {
				this.AddJob(filtered_job)
			}
		}
	}

	//call the handler one last time - in case the filter wants to add anything else
	if jhlo != nil {
		filtered_job := jhlo("")
		if filtered_job != nil {
			this.AddJob(filtered_job)
		}
	}
}

//func (this *JobHandler) processJobsFromJSON(jhjp ParserObject) error {
func (this *JobHandler) processJobsFromJSON(jhjp *JHJSONParserString) error {
	var job_tracker sync.WaitGroup
	for i := range jhjp.GetDependentJobs() {
		job_tracker.Add(1)
		job := jhjp.GetDependentJobs()[i]
		go func() {
			this.processJobsFromJSON(job)
			job_tracker.Done()
		}()
	}
	job_tracker.Wait()

	if(jhjp.NumIterations == 0) {
		jhjp.NumIterations = 1
	}
	for i := 0 ; i < jhjp.NumIterations ; i++ {
		this.AddJob(jhjp)
	}
	return nil
}

//func (this *JobHandler) ProcessJobsFromJSON(filename string, parserObjectCreator CreateParserObjectFunc) error {
func (this *JobHandler) ProcessJobsFromJSON(filename string) error {
	file_data, err := ioutil.ReadFile(filename)
	if err != nil {
		logger.Error.Print(err)
		return err
	}

	/*
	if parserObjectCreator == nil {
		return utilities.NewBasicError("parserObjectCreator has to be provided")
	}
	*/

	//obj_to_use := parserObjectCreator()
	obj_to_use := CreateJHJSONParserString()
	if err := json.Unmarshal(file_data, obj_to_use); err != nil {
		return err
	}
	if err = this.processJobsFromJSON(obj_to_use); err != nil {
		return err
	}

	return nil
}

func (this *JobHandler) WaitForJobsToComplete() {
	this.ws_job_tracker.Wait()
}

func (this *JobHandler) waitForResults(print_results bool) {
	var num_processed int32 = 0
	done_adding := false
	for done_adding == false || num_processed < atomic.LoadInt32(&this.num_added) {
		select {
		case result := <-this.results:
			num_processed++
			if result != nil && print_results == true {
				logger.Info.Println(result)
			}
			this.Results = append(this.Results, result)
		case done_adding = <-this.done_channel:
			continue
		}
	}
	logger.Info.Println("done processing results")

	//clean up the workers if needed
	for i := range this.worker_list {
		this.worker_list[i].PostRun()
	}

	this.ws_job_tracker.Done()
}

func (this *JobHandler) DoneAddingJobs() {
	close(this.jobs)
	if atomic.LoadInt32(&this.num_added) == 0 {
		close(this.results)
	}
	this.done_channel <- true
}
<commit_msg>change the log level<commit_after>package RTJobRunner

import (
	"bufio"
	"encoding/json"
	"io/ioutil"
	"os"
	"strings"
	"sync"
	"fmt"
	"sync/atomic"

	"github.com/akundu/utilities/logger"
    "github.com/satori/go.uuid"
)

type JobHandler struct {
	jobs                chan Request
	results             chan Response
	ws_job_tracker      sync.WaitGroup
	num_added           int32

	done_channel        chan bool

	worker_list         []Worker
	id                  string

	Results             []interface{}
}

func NewJobHandler(num_to_setup int,
	createWorkerFunc CreateWorkerFunction,
	print_results bool,
	) *JobHandler {

	jh := &JobHandler{
		jobs:                make(chan Request, num_to_setup),
		results:             make(chan Response, num_to_setup),
		num_added:           0,
		worker_list:         make([]Worker, num_to_setup),
		done_channel:        make(chan bool, 1),
		id:                  fmt.Sprintf("%s", uuid.NewV4()),
	}

	for w := 0; w < num_to_setup; w++ {
		worker := createWorkerFunc()
		jh.worker_list[w] = worker
		worker.PreRun()
		go worker.Run(w, jh.jobs, jh.results)
	}

	jh.ws_job_tracker.Add(1) //goroutine to wait for results
	go jh.waitForResults(print_results)

	return jh
}

func (this *JobHandler) AddJob(job Request) {
	this.jobs <- job
	atomic.AddInt32(&this.num_added, 1)
}

type JobHandlerLineOutputFilter func(string) Request //line - outputline - if outputline is empty - dont add anything
func (this *JobHandler) GetJobsFromStdin(jhlo JobHandlerLineOutputFilter) {
	//read from stdin
	bio := bufio.NewReader(os.Stdin)
	for {
		line, err := bio.ReadString('\n')
		if err != nil {
			break
		}
		line = strings.Trim(line, "\n \r\n")
		logger.Trace.Println("adding ", line)
		if jhlo == nil {
			this.AddJob(line)
		} else {
			filtered_job := jhlo(line)
			if filtered_job != nil {
				this.AddJob(filtered_job)
			}
		}
	}

	//call the handler one last time - in case the filter wants to add anything else
	if jhlo != nil {
		filtered_job := jhlo("")
		if filtered_job != nil {
			this.AddJob(filtered_job)
		}
	}
}

//func (this *JobHandler) processJobsFromJSON(jhjp ParserObject) error {
func (this *JobHandler) processJobsFromJSON(jhjp *JHJSONParserString) error {
	var job_tracker sync.WaitGroup
	for i := range jhjp.GetDependentJobs() {
		job_tracker.Add(1)
		job := jhjp.GetDependentJobs()[i]
		go func() {
			this.processJobsFromJSON(job)
			job_tracker.Done()
		}()
	}
	job_tracker.Wait()

	if(jhjp.NumIterations == 0) {
		jhjp.NumIterations = 1
	}
	for i := 0 ; i < jhjp.NumIterations ; i++ {
		this.AddJob(jhjp)
	}
	return nil
}

//func (this *JobHandler) ProcessJobsFromJSON(filename string, parserObjectCreator CreateParserObjectFunc) error {
func (this *JobHandler) ProcessJobsFromJSON(filename string) error {
	file_data, err := ioutil.ReadFile(filename)
	if err != nil {
		logger.Error.Print(err)
		return err
	}

	/*
	if parserObjectCreator == nil {
		return utilities.NewBasicError("parserObjectCreator has to be provided")
	}
	*/

	//obj_to_use := parserObjectCreator()
	obj_to_use := CreateJHJSONParserString()
	if err := json.Unmarshal(file_data, obj_to_use); err != nil {
		return err
	}
	if err = this.processJobsFromJSON(obj_to_use); err != nil {
		return err
	}

	return nil
}

func (this *JobHandler) WaitForJobsToComplete() {
	this.ws_job_tracker.Wait()
}

func (this *JobHandler) waitForResults(print_results bool) {
	var num_processed int32 = 0
	done_adding := false
	for done_adding == false || num_processed < atomic.LoadInt32(&this.num_added) {
		select {
		case result := <-this.results:
			num_processed++
			if result != nil && print_results == true {
				logger.Info.Println(result)
			}
			this.Results = append(this.Results, result)
		case done_adding = <-this.done_channel:
			continue
		}
	}
	logger.Trace.Println("done processing results")

	//clean up the workers if needed
	for i := range this.worker_list {
		this.worker_list[i].PostRun()
	}

	this.ws_job_tracker.Done()
}

func (this *JobHandler) DoneAddingJobs() {
	close(this.jobs)
	if atomic.LoadInt32(&this.num_added) == 0 {
		close(this.results)
	}
	this.done_channel <- true
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. 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.

package handler

import (
	"encoding/json"
	"log"
	"net/http"
	"text/template"
	"time"
)

// AppHandler is a application handler.
type AppHandler func(http.ResponseWriter, *http.Request) (int, error)

// AppConfig is a global configuration of application.
type AppConfig struct {
	// ServerTime is current server time (milliseconds elapsed since 1 January 1970 00:00:00 UTC).
	ServerTime int64 `json:"serverTime"`
}

const (
	// ConfigTemplateName is a name of config template
	ConfigTemplateName string = "appConfig"
	// ConfigTemplate is a template of a config
	ConfigTemplate string = "var appConfig_DO_NOT_USE_DIRECTLY = {{.}}"
)

// ServeHTTP serves HTTP endpoint with application configuration.
func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if _, err := fn(w, r); err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError),
			http.StatusInternalServerError)
	}
}

func getAppConfigJSON() string {
	log.Printf("Getting application global configuration")

	config := &AppConfig{
		// TODO(maciaszczykm): Get time from API server instead directly from backend.
		ServerTime: time.Now().UTC().UnixNano() / 1e6,
	}

	json, _ := json.Marshal(config)
	log.Printf("Application configuration %s", json)
	return string(json)
}

func ConfigHandler(w http.ResponseWriter, r *http.Request) (int, error) {
	template, err := template.New(ConfigTemplateName).Parse(ConfigTemplate)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return http.StatusInternalServerError, err
	}
	return http.StatusOK, template.Execute(w, getAppConfigJSON())
}
<commit_msg>Set content type on app config handler (#1499)<commit_after>// Copyright 2015 Google Inc. 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.

package handler

import (
	"encoding/json"
	"log"
	"net/http"
	"text/template"
	"time"
)

// AppHandler is a application handler.
type AppHandler func(http.ResponseWriter, *http.Request) (int, error)

// AppConfig is a global configuration of application.
type AppConfig struct {
	// ServerTime is current server time (milliseconds elapsed since 1 January 1970 00:00:00 UTC).
	ServerTime int64 `json:"serverTime"`
}

const (
	// ConfigTemplateName is a name of config template
	ConfigTemplateName string = "appConfig"
	// ConfigTemplate is a template of a config
	ConfigTemplate string = "var appConfig_DO_NOT_USE_DIRECTLY = {{.}}"
)

// ServeHTTP serves HTTP endpoint with application configuration.
func (fn AppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if _, err := fn(w, r); err != nil {
		http.Error(w, http.StatusText(http.StatusInternalServerError),
			http.StatusInternalServerError)
	}
}

func getAppConfigJSON() string {
	log.Printf("Getting application global configuration")

	config := &AppConfig{
		// TODO(maciaszczykm): Get time from API server instead directly from backend.
		ServerTime: time.Now().UTC().UnixNano() / 1e6,
	}

	json, _ := json.Marshal(config)
	log.Printf("Application configuration %s", json)
	return string(json)
}

func ConfigHandler(w http.ResponseWriter, r *http.Request) (int, error) {
	template, err := template.New(ConfigTemplateName).Parse(ConfigTemplate)
	w.Header().Set("Content-Type", "application/javascript")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return http.StatusInternalServerError, err
	}
	return http.StatusOK, template.Execute(w, getAppConfigJSON())
}
<|endoftext|>


<commit_before>// +build ignore

package main

import (
	"."
	"github.com/bmizerany/pat"
	"github.com/timeredbull/tsuru/api/app"
	"github.com/timeredbull/tsuru/api/service"
	"github.com/timeredbull/tsuru/api/auth"
	"github.com/timeredbull/tsuru/db"
	"github.com/timeredbull/tsuru/log"
	"log/syslog"
	stdlog "log"
	"net/http"
)

func main() {
	var err error
	log.Target, err = syslog.NewLogger(syslog.LOG_INFO, stdlog.LstdFlags)
	if err != nil {
		panic(err)
	}

	db.Session, err = db.Open("127.0.0.1:27017", "tsuru")
	if err != nil {
		log.Panic(err.Error())
	}
	defer db.Session.Close()
	m := pat.New()

	m.Post("/services", webserver.Handler(service.CreateHandler))
	m.Get("/services", webserver.Handler(service.ServicesHandler))
	m.Get("/services/types", webserver.Handler(service.ServiceTypesHandler))
	m.Get("/services/:name", webserver.Handler(service.DeleteHandler))
	m.Post("/services/bind", webserver.Handler(service.BindHandler))
	m.Post("/services/unbind", webserver.Handler(service.UnbindHandler))

	m.Get("/apps/:name/delete", webserver.Handler(app.AppDelete))
	m.Get("/apps/:name", webserver.Handler(app.AppInfo))
	m.Post("/apps/:name/application", webserver.Handler(app.Upload))
	m.Get("/apps", webserver.Handler(app.AppList))
	m.Post("/apps", webserver.Handler(app.CreateAppHandler))

	m.Post("/users", webserver.Handler(auth.CreateUser))
	m.Post("/users/:email/tokens", webserver.Handler(auth.Login))
	m.Get("/users/check-authorization", webserver.Handler(auth.CheckAuthorization))

	log.Fatal(http.ListenAndServe(":4000", m))
}
<commit_msg>api/webserver: register CreateTeam for the /teams url<commit_after>// +build ignore

package main

import (
	"."
	"github.com/bmizerany/pat"
	"github.com/timeredbull/tsuru/api/app"
	"github.com/timeredbull/tsuru/api/service"
	"github.com/timeredbull/tsuru/api/auth"
	"github.com/timeredbull/tsuru/db"
	"github.com/timeredbull/tsuru/log"
	"log/syslog"
	stdlog "log"
	"net/http"
)

func main() {
	var err error
	log.Target, err = syslog.NewLogger(syslog.LOG_INFO, stdlog.LstdFlags)
	if err != nil {
		panic(err)
	}

	db.Session, err = db.Open("127.0.0.1:27017", "tsuru")
	if err != nil {
		log.Panic(err.Error())
	}
	defer db.Session.Close()
	m := pat.New()

	m.Post("/services", webserver.Handler(service.CreateHandler))
	m.Get("/services", webserver.Handler(service.ServicesHandler))
	m.Get("/services/types", webserver.Handler(service.ServiceTypesHandler))
	m.Get("/services/:name", webserver.Handler(service.DeleteHandler))
	m.Post("/services/bind", webserver.Handler(service.BindHandler))
	m.Post("/services/unbind", webserver.Handler(service.UnbindHandler))

	m.Get("/apps/:name/delete", webserver.Handler(app.AppDelete))
	m.Get("/apps/:name", webserver.Handler(app.AppInfo))
	m.Post("/apps/:name/application", webserver.Handler(app.Upload))
	m.Get("/apps", webserver.Handler(app.AppList))
	m.Post("/apps", webserver.Handler(app.CreateAppHandler))

	m.Post("/users", webserver.Handler(auth.CreateUser))
	m.Post("/users/:email/tokens", webserver.Handler(auth.Login))
	m.Get("/users/check-authorization", webserver.Handler(auth.CheckAuthorization))

	m.Post("/teams", webserver.AuthorizationRequiredHandler(auth.CreateTeam))

	log.Fatal(http.ListenAndServe(":4000", m))
}
<|endoftext|>


<commit_before>package admin

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

	"github.com/ponzu-cms/ponzu/system/db"
	"github.com/ponzu-cms/ponzu/system/item"
)

func deleteUploadFromDisk(target string) error {
	// get data on file
	data, err := db.Upload(target)
	if err != nil {
		return err
	}

	// unmarshal data
	upload := item.FileUpload{}
	if err = json.Unmarshal(data, &upload); err != nil {
		return err
	}

	// use path to delete the physical file from disk
	delPath := strings.Replace(upload.Path, "/api/", "./", 1)
	err = os.Remove(delPath)
	if err != nil {
		return err
	}

	return nil
}

func restrict(dir http.Dir) justFilesFilesystem {
	return justFilesFilesystem{dir}
}

// the code below removes the open directory listing when accessing a URL which
// normally would point to a directory. code from golang-nuts mailing list:
// https://groups.google.com/d/msg/golang-nuts/bStLPdIVM6w/hidTJgDZpHcJ
// credit: Brad Fitzpatrick (c) 2012

type justFilesFilesystem struct {
	fs http.FileSystem
}

func (fs justFilesFilesystem) Open(name string) (http.File, error) {
	f, err := fs.fs.Open(name)
	if err != nil {
		return nil, err
	}
	return neuteredReaddirFile{f}, nil
}

type neuteredReaddirFile struct {
	http.File
}

func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
	return nil, nil
}
<commit_msg>use filepath.Join for best OS compatiblity<commit_after>package admin

import (
	"encoding/json"
	"net/http"
	"os"
	"path/filepath"
	"strings"

	"github.com/ponzu-cms/ponzu/system/db"
	"github.com/ponzu-cms/ponzu/system/item"
)

func deleteUploadFromDisk(target string) error {
	// get data on file
	data, err := db.Upload(target)
	if err != nil {
		return err
	}

	// unmarshal data
	upload := item.FileUpload{}
	if err = json.Unmarshal(data, &upload); err != nil {
		return err
	}

	// split and rebuild path in OS friendly way
	// use path to delete the physical file from disk
	pathSplit := strings.Split(upload.Path, "/")
	pathJoin := filepath.Join(pathSplit[2:]...)
	err = os.Remove(pathJoin)
	if err != nil {
		return err
	}

	return nil
}

func restrict(dir http.Dir) justFilesFilesystem {
	return justFilesFilesystem{dir}
}

// the code below removes the open directory listing when accessing a URL which
// normally would point to a directory. code from golang-nuts mailing list:
// https://groups.google.com/d/msg/golang-nuts/bStLPdIVM6w/hidTJgDZpHcJ
// credit: Brad Fitzpatrick (c) 2012

type justFilesFilesystem struct {
	fs http.FileSystem
}

func (fs justFilesFilesystem) Open(name string) (http.File, error) {
	f, err := fs.fs.Open(name)
	if err != nil {
		return nil, err
	}
	return neuteredReaddirFile{f}, nil
}

type neuteredReaddirFile struct {
	http.File
}

func (f neuteredReaddirFile) Readdir(count int) ([]os.FileInfo, error) {
	return nil, nil
}
<|endoftext|>


<commit_before>package raft

import (
	"net"
)

type AppendEntriesRequest struct {
	// Provide the current term and leader
	Term   uint64
	Leader net.Addr

	// Provide the previous entries for integrity checking
	PrevLogEntry uint64
	PrevLogTerm  uint64

	// New entries to commit
	Entries []*Log

	// Commit index on the leader
	LeaderCommitIndex uint64
}

type AppendEntriesResponse struct {
	// Newer term if leader is out of date
	Term uint64

	// Last Log is a hint to help accelerate rebuilding slow nodes
	LastLog uint64

	// We may not succeed if we have a conflicting entry
	Success bool
}

type RequestVoteRequest struct {
	// Provide the term and our id
	Term      uint64
	Candidate net.Addr

	// Used to ensure safety
	LastLogIndex uint64
	LastLogTerm  uint64
}

type RequestVoteResponse struct {
	// Newer term if leader is out of date
	Term uint64

	// Return the peers, so that a node can shutdown on removal
	Peers []net.Addr

	// Is the vote granted
	Granted bool
}

type InstallSnapshotRequest struct {
	Term   uint64
	Leader net.Addr

	// These are the last index/term included in the snapshot
	LastLogIndex uint64
	LastLogTerm  uint64

	// Peer Set in the snapshot
	Peers []net.Addr

	// Size of the snapshot
	Size uint64
}

type InstallSnapshotResponse struct {
	Term    uint64
	Success bool
}
<commit_msg>Fixing Size type<commit_after>package raft

import (
	"net"
)

type AppendEntriesRequest struct {
	// Provide the current term and leader
	Term   uint64
	Leader net.Addr

	// Provide the previous entries for integrity checking
	PrevLogEntry uint64
	PrevLogTerm  uint64

	// New entries to commit
	Entries []*Log

	// Commit index on the leader
	LeaderCommitIndex uint64
}

type AppendEntriesResponse struct {
	// Newer term if leader is out of date
	Term uint64

	// Last Log is a hint to help accelerate rebuilding slow nodes
	LastLog uint64

	// We may not succeed if we have a conflicting entry
	Success bool
}

type RequestVoteRequest struct {
	// Provide the term and our id
	Term      uint64
	Candidate net.Addr

	// Used to ensure safety
	LastLogIndex uint64
	LastLogTerm  uint64
}

type RequestVoteResponse struct {
	// Newer term if leader is out of date
	Term uint64

	// Return the peers, so that a node can shutdown on removal
	Peers []net.Addr

	// Is the vote granted
	Granted bool
}

type InstallSnapshotRequest struct {
	Term   uint64
	Leader net.Addr

	// These are the last index/term included in the snapshot
	LastLogIndex uint64
	LastLogTerm  uint64

	// Peer Set in the snapshot
	Peers []net.Addr

	// Size of the snapshot
	Size int64
}

type InstallSnapshotResponse struct {
	Term    uint64
	Success bool
}
<|endoftext|>


<commit_before>package main

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

	"github.com/codegangsta/cli"
	"github.com/mackerelio/gomkr/utils"
	mkr "github.com/mackerelio/mackerel-client-go"
)

var Commands = []cli.Command{
	commandStatus,
	commandHosts,
	commandCreate,
	commandUpdate,
	commandThrow,
	commandFetch,
	commandRetire,
}

var commandStatus = cli.Command{
	Name:  "status",
	Usage: "Show host status",
	Description: `
`,
	Action: doStatus,
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "verbose, v", Usage: "Verbose output mode"},
	},
}

var commandHosts = cli.Command{
	Name:  "hosts",
	Usage: "Show hosts",
	Description: `
`,
	Action: doHosts,
	Flags: []cli.Flag{
		cli.StringFlag{Name: "name, n", Value: "", Usage: "Show hosts only matched with <name>"},
		cli.StringFlag{Name: "service, s", Value: "", Usage: "Show hosts only belongs to <service>"},
		cli.StringSliceFlag{Name: "role, r", Value: &cli.StringSlice{}, Usage: "Show hosts only belongs to <role>. Multiple choice allow. Required --service"},
		cli.StringSliceFlag{Name: "status, st", Value: &cli.StringSlice{}, Usage: "Show hosts only matched <status>. Multiple choice allow."},
		cli.BoolFlag{Name: "verbose, v", Usage: "Verbose output mode"},
	},
}

var commandCreate = cli.Command{
	Name:  "create",
	Usage: "",
	Description: `
`,
	Action: doCreate,
}

var commandUpdate = cli.Command{
	Name:  "update",
	Usage: "",
	Description: `
`,
	Action: doUpdate,
}

var commandThrow = cli.Command{
	Name:  "throw",
	Usage: "",
	Description: `
`,
	Action: doThrow,
}

var commandFetch = cli.Command{
	Name:  "fetch",
	Usage: "",
	Description: `
`,
	Action: doFetch,
}

var commandRetire = cli.Command{
	Name:  "retire",
	Usage: "",
	Description: `
`,
	Action: doRetire,
}

func debug(v ...interface{}) {
	if os.Getenv("DEBUG") != "" {
		log.Println(v...)
	}
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func newMackerel() *mkr.Client {
	apiKey := os.Getenv("MACKEREL_APIKEY")
	if apiKey == "" {
		utils.Log("error", `
Not set MACKEREL_APIKEY environment variable. (Try "export MACKEREL_APIKEY='<Your apikey>'")
`)
		os.Exit(1)
	}
	mackerel := mkr.NewClient(apiKey)
	return mackerel
}

func doStatus(c *cli.Context) {
	argHostId := c.Args().Get(0)
	isVerbose := c.Bool("verbose")

	if argHostId == "" {
		cli.ShowCommandHelp(c, "status")
		os.Exit(1)
	}

	mackerel := newMackerel()
	host, err := mackerel.FindHost(argHostId)
	utils.DieIf(err)

	if isVerbose {
		data, err := json.MarshalIndent(host, "", "    ")
		utils.DieIf(err)

		fmt.Fprintln(os.Stdout, string(data))
	} else {
		format := &HostFormat{
			Id:            host.Id,
			Name:          host.Name,
			Status:        host.Status,
			RoleFullnames: host.GetRoleFullnames(),
			IsRetired:     host.IsRetired,
			CreatedAt:     host.DateStringFromCreatedAt(),
		}

		data, err := json.MarshalIndent(format, "", "    ")
		utils.DieIf(err)

		fmt.Fprintln(os.Stdout, string(data))
	}
}

func doHosts(c *cli.Context) {
	isVerbose := c.Bool("verbose")
	argName := c.String("name")
	argService := c.String("service")
	argRoles := c.StringSlice("role")
	argStatuses := c.StringSlice("status")

	mackerel := newMackerel()
	hosts, err := mackerel.FindHosts(&mkr.FindHostsParam{
		Name:     argName,
		Service:  argService,
		Roles:    argRoles,
		Statuses: argStatuses,
	})
	utils.DieIf(err)

	if isVerbose {
		data, err := json.MarshalIndent(hosts, "", "    ")
		utils.DieIf(err)

		fmt.Fprintln(os.Stdout, string(data))
	} else {
		var hosts_format []*HostFormat
		for _, host := range hosts {
			format := &HostFormat{
				Id:            host.Id,
				Name:          host.Name,
				Status:        host.Status,
				RoleFullnames: host.GetRoleFullnames(),
				IsRetired:     host.IsRetired,
				CreatedAt:     host.DateStringFromCreatedAt(),
			}
			hosts_format = append(hosts_format, format)
		}

		data, err := json.MarshalIndent(hosts_format, "", "    ")
		utils.DieIf(err)

		fmt.Fprintln(os.Stdout, string(data))
	}
}

func doCreate(c *cli.Context) {
}

func doUpdate(c *cli.Context) {
}

func doThrow(c *cli.Context) {
}

func doFetch(c *cli.Context) {
}

func doRetire(c *cli.Context) {
}
<commit_msg>Dump request/response if DEBUG=1<commit_after>package main

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

	"github.com/codegangsta/cli"
	"github.com/mackerelio/gomkr/utils"
	mkr "github.com/mackerelio/mackerel-client-go"
)

var Commands = []cli.Command{
	commandStatus,
	commandHosts,
	commandCreate,
	commandUpdate,
	commandThrow,
	commandFetch,
	commandRetire,
}

var commandStatus = cli.Command{
	Name:  "status",
	Usage: "Show host status",
	Description: `
`,
	Action: doStatus,
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "verbose, v", Usage: "Verbose output mode"},
	},
}

var commandHosts = cli.Command{
	Name:  "hosts",
	Usage: "Show hosts",
	Description: `
`,
	Action: doHosts,
	Flags: []cli.Flag{
		cli.StringFlag{Name: "name, n", Value: "", Usage: "Show hosts only matched with <name>"},
		cli.StringFlag{Name: "service, s", Value: "", Usage: "Show hosts only belongs to <service>"},
		cli.StringSliceFlag{Name: "role, r", Value: &cli.StringSlice{}, Usage: "Show hosts only belongs to <role>. Multiple choice allow. Required --service"},
		cli.StringSliceFlag{Name: "status, st", Value: &cli.StringSlice{}, Usage: "Show hosts only matched <status>. Multiple choice allow."},
		cli.BoolFlag{Name: "verbose, v", Usage: "Verbose output mode"},
	},
}

var commandCreate = cli.Command{
	Name:  "create",
	Usage: "",
	Description: `
`,
	Action: doCreate,
}

var commandUpdate = cli.Command{
	Name:  "update",
	Usage: "",
	Description: `
`,
	Action: doUpdate,
}

var commandThrow = cli.Command{
	Name:  "throw",
	Usage: "",
	Description: `
`,
	Action: doThrow,
}

var commandFetch = cli.Command{
	Name:  "fetch",
	Usage: "",
	Description: `
`,
	Action: doFetch,
}

var commandRetire = cli.Command{
	Name:  "retire",
	Usage: "",
	Description: `
`,
	Action: doRetire,
}

func debug(v ...interface{}) {
	if os.Getenv("DEBUG") != "" {
		log.Println(v...)
	}
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func newMackerel() *mkr.Client {
	apiKey := os.Getenv("MACKEREL_APIKEY")
	if apiKey == "" {
		utils.Log("error", `
Not set MACKEREL_APIKEY environment variable. (Try "export MACKEREL_APIKEY='<Your apikey>'")
`)
		os.Exit(1)
	}

	if os.Getenv("DEBUG") != "" {
		mackerel, err := mkr.NewClientForTest(apiKey, "https://mackerel.io/api/v0", true)
		utils.DieIf(err)

		return mackerel
	} else {
		return mkr.NewClient(apiKey)
	}
}

func doStatus(c *cli.Context) {
	argHostId := c.Args().Get(0)
	isVerbose := c.Bool("verbose")

	if argHostId == "" {
		cli.ShowCommandHelp(c, "status")
		os.Exit(1)
	}

	mackerel := newMackerel()
	host, err := mackerel.FindHost(argHostId)
	utils.DieIf(err)

	if isVerbose {
		data, err := json.MarshalIndent(host, "", "    ")
		utils.DieIf(err)

		fmt.Fprintln(os.Stdout, string(data))
	} else {
		format := &HostFormat{
			Id:            host.Id,
			Name:          host.Name,
			Status:        host.Status,
			RoleFullnames: host.GetRoleFullnames(),
			IsRetired:     host.IsRetired,
			CreatedAt:     host.DateStringFromCreatedAt(),
		}

		data, err := json.MarshalIndent(format, "", "    ")
		utils.DieIf(err)

		fmt.Fprintln(os.Stdout, string(data))
	}
}

func doHosts(c *cli.Context) {
	isVerbose := c.Bool("verbose")
	argName := c.String("name")
	argService := c.String("service")
	argRoles := c.StringSlice("role")
	argStatuses := c.StringSlice("status")

	mackerel := newMackerel()
	hosts, err := mackerel.FindHosts(&mkr.FindHostsParam{
		Name:     argName,
		Service:  argService,
		Roles:    argRoles,
		Statuses: argStatuses,
	})
	utils.DieIf(err)

	if isVerbose {
		data, err := json.MarshalIndent(hosts, "", "    ")
		utils.DieIf(err)

		fmt.Fprintln(os.Stdout, string(data))
	} else {
		var hosts_format []*HostFormat
		for _, host := range hosts {
			format := &HostFormat{
				Id:            host.Id,
				Name:          host.Name,
				Status:        host.Status,
				RoleFullnames: host.GetRoleFullnames(),
				IsRetired:     host.IsRetired,
				CreatedAt:     host.DateStringFromCreatedAt(),
			}
			hosts_format = append(hosts_format, format)
		}

		data, err := json.MarshalIndent(hosts_format, "", "    ")
		utils.DieIf(err)

		fmt.Fprintln(os.Stdout, string(data))
	}
}

func doCreate(c *cli.Context) {
}

func doUpdate(c *cli.Context) {
}

func doThrow(c *cli.Context) {
}

func doFetch(c *cli.Context) {
}

func doRetire(c *cli.Context) {
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"github.com/codegangsta/cli"
	"golang.org/x/oauth2"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"strings"
)

var DefaultFlags = []cli.Flag{
	cli.StringFlag{
		Name:  "data",
		Usage: "Body data",
	},
}

var Commands = []cli.Command{
	commandGet,
	commandPost,
	commandPut,
	commandDelete,
	commandHead,
	commandOptions,
	commandPatch,
	commandTrace,
}

var commandGet = cli.Command{
	Name:      "get",
	ShortName: "g",
	Usage:     "Make GET request",
	Description: `
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doGet,
}

var commandPost = cli.Command{
	Name:      "post",
	ShortName: "p",
	Usage:     "Make POST request",
	Description: `
The POST method is used to request that the origin server accept the entity enclosed in the request
as a new subordinate of the resource identified by the Request-URI in the Request-Line.
`,
	Flags:  DefaultFlags,
	Action: doPost,
}

var commandPut = cli.Command{
	Name:  "put",
	Usage: "Make PUT request",
	Description: `
The PUT method requests that the enclosed entity be stored under the supplied Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doPut,
}

var commandDelete = cli.Command{
	Name:      "delete",
	ShortName: "d",
	Usage:     "Make DELETE request",
	Description: `
The DELETE method requests that the origin server delete the resource identified by the Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doDelete,
}

var commandHead = cli.Command{
	Name:      "head",
	ShortName: "h",
	Usage:     "Make HEAD request",
	Description: `
The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response.
`,
	Flags:  DefaultFlags,
	Action: doHead,
}

var commandOptions = cli.Command{
	Name:      "options",
	ShortName: "o",
	Usage:     "Make OPTIONS request",
	Description: `
The OPTIONS method represents a request for information about the communication options available
on the request/response chain identified by the Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doOptions,
}

var commandPatch = cli.Command{
	Name:  "patch",
	Usage: "Make PATCH request",
	Description: `
The PATCH method requests that a set of changes described in the request entity be applied
to the resource identified by the Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doPatch,
}

var commandTrace = cli.Command{
	Name:      "trace",
	ShortName: "t",
	Usage:     "Make TRACE request",
	Description: `
The TRACE method is used to invoke a remote, application-layer loop-back of the request message.
`,
	Flags:  DefaultFlags,
	Action: doTrace,
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func doGet(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "GET")
}

func doPost(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "POST")
}

func doPut(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "POST")
}

func doDelete(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "DELETE")
}

func doHead(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "HEAD")
}

func doOptions(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "OPTIONS")
}

func doPatch(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "PATCH")
}

func doTrace(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "TRACE")
}

func loadOptions(ctx *cli.Context) {
	var err error
	CurrentOptions, err = Opts(ctx)
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
}

func doRequest(ctx *cli.Context, method string) {
	var tr = &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: ctx.GlobalBool("insecure"),
		},
	}
	http.DefaultClient = &http.Client{Transport: tr}

	Tracef("doRequest start")
	resp, tok, err := doRequest0(ctx, method)
	if err != nil {
		log.Fatal(err)
		return
	} else {
		Tracef("request done successfully")
		if tok != nil {
			storeToken(tok)
		}
	}

	Tracef("printing headers")
	if ctx.GlobalBool("print-headers") {
		headers, _ := json.Marshal(resp.Header)
		fmt.Println(string(headers))
	}

	if ctx.GlobalBool("no-body") {
		Tracef("printing body is disabled")
	} else {
		Tracef("printing body")
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			Tracef("error on read: %v", err)
		} else if body == nil {
			Tracef("no body")
		} else {
			Tracef("body found")
			fmt.Println(string(body))
		}
	}
	Tracef("doRequest end")
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func doRequest0(ctx *cli.Context, method string) (*http.Response, *oauth2.Token, error) {
	Tracef("profileName = %s", CurrentOptions.ProfileName)

	targetUrl, err := targetUrl(ctx)
	if err != nil {
		return nil, nil, err
	}
	Tracef("targetUrl = %s", targetUrl)
	data := ctx.String("data")
	Tracef("data = %s", data)
	body := strings.NewReader(data)
	req, err := http.NewRequest(method, targetUrl, body)
	if err != nil {
		return nil, nil, err
	}

	var lastError error
	for retrieve := false; retrieve == false; retrieve = true {
		Tracef("=== phase %s start", toString(retrieve))
		tok, r, err := AccessToken(CurrentOptions.ProfileName, retrieve)
		if err != nil {
			Tracef("phase %s failed (token retrieving failed)", toString(retrieve))
			lastError = err
			continue
		}
		retrieve = r
		req.Header.Set("User-Agent", fmt.Sprintf("%s-%s", ctx.App.Name, Version))
		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tok.AccessToken))
		dump, err := httputil.DumpRequestOut(req, true)
		if err != nil {
			Tracef("phase %s failed (request dump failed)", toString(retrieve))
			lastError = err
			continue
		}
		Tracef("request = %s", string(dump))

		tr := &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: ctx.GlobalBool("insecure"),
			},
		}
		client := &http.Client{
			CheckRedirect: func(req *http.Request, via []*http.Request) error {
				Tracef("redirect to %s", req.URL.String())
				req.Header.Set("User-Agent", fmt.Sprintf("%s-%s", ctx.App.Name, Version))
				req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tok.AccessToken))
				return nil
			},
			Transport: tr,
		}
		resp, err := client.Do(req)
		if err != nil {
			Tracef("phase %s failed (request failed)", toString(retrieve))
			lastError = err
			continue
		}

		dumpResp, err := httputil.DumpResponse(resp, true)
		if err != nil {
			log.Printf("%+v%n", err)
		} else {
			Tracef("response = %s", string(dumpResp))
		}

		Tracef("phase %s", toString(retrieve))
		if resp.StatusCode >= 400 && resp.StatusCode < 500 {
			if retrieve {
				Tracef("phase retrieve failed (4XX response)")
				lastError = err
				break
			} else {
				Tracef("phase stored failed (4XX response) -> final result")
			}
		}
		return resp, tok, err
	}
	return nil, nil, fmt.Errorf("%v", lastError)
}

func toString(retrieve bool) string {
	if retrieve {
		return "retrieve"
	}
	return "stored"
}

func targetUrl(ctx *cli.Context) (string, error) {
	if len(ctx.Args()) < 1 {
		return "", fmt.Errorf("target URL required")
	}
	return ctx.Args()[0], nil
}

func storeToken(tok *oauth2.Token) {
	if SaveValues(CurrentOptions.ProfileName, tokenToValues(tok)) {
		Tracef("token stored [%s]", CurrentOptions.ProfileName)
	} else {
		Tracef("fail to store token [%s]", CurrentOptions.ProfileName)
	}
}
<commit_msg>sotre token when the http response is not 401 or 403<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"fmt"
	"github.com/codegangsta/cli"
	"golang.org/x/oauth2"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/httputil"
	"os"
	"strings"
)

var DefaultFlags = []cli.Flag{
	cli.StringFlag{
		Name:  "data",
		Usage: "Body data",
	},
}

var Commands = []cli.Command{
	commandGet,
	commandPost,
	commandPut,
	commandDelete,
	commandHead,
	commandOptions,
	commandPatch,
	commandTrace,
}

var commandGet = cli.Command{
	Name:      "get",
	ShortName: "g",
	Usage:     "Make GET request",
	Description: `
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doGet,
}

var commandPost = cli.Command{
	Name:      "post",
	ShortName: "p",
	Usage:     "Make POST request",
	Description: `
The POST method is used to request that the origin server accept the entity enclosed in the request
as a new subordinate of the resource identified by the Request-URI in the Request-Line.
`,
	Flags:  DefaultFlags,
	Action: doPost,
}

var commandPut = cli.Command{
	Name:  "put",
	Usage: "Make PUT request",
	Description: `
The PUT method requests that the enclosed entity be stored under the supplied Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doPut,
}

var commandDelete = cli.Command{
	Name:      "delete",
	ShortName: "d",
	Usage:     "Make DELETE request",
	Description: `
The DELETE method requests that the origin server delete the resource identified by the Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doDelete,
}

var commandHead = cli.Command{
	Name:      "head",
	ShortName: "h",
	Usage:     "Make HEAD request",
	Description: `
The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response.
`,
	Flags:  DefaultFlags,
	Action: doHead,
}

var commandOptions = cli.Command{
	Name:      "options",
	ShortName: "o",
	Usage:     "Make OPTIONS request",
	Description: `
The OPTIONS method represents a request for information about the communication options available
on the request/response chain identified by the Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doOptions,
}

var commandPatch = cli.Command{
	Name:  "patch",
	Usage: "Make PATCH request",
	Description: `
The PATCH method requests that a set of changes described in the request entity be applied
to the resource identified by the Request-URI.
`,
	Flags:  DefaultFlags,
	Action: doPatch,
}

var commandTrace = cli.Command{
	Name:      "trace",
	ShortName: "t",
	Usage:     "Make TRACE request",
	Description: `
The TRACE method is used to invoke a remote, application-layer loop-back of the request message.
`,
	Flags:  DefaultFlags,
	Action: doTrace,
}

func assert(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func doGet(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "GET")
}

func doPost(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "POST")
}

func doPut(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "POST")
}

func doDelete(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "DELETE")
}

func doHead(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "HEAD")
}

func doOptions(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "OPTIONS")
}

func doPatch(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "PATCH")
}

func doTrace(ctx *cli.Context) {
	loadOptions(ctx)
	doRequest(ctx, "TRACE")
}

func loadOptions(ctx *cli.Context) {
	var err error
	CurrentOptions, err = Opts(ctx)
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}
}

func doRequest(ctx *cli.Context, method string) {
	var tr = &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: ctx.GlobalBool("insecure"),
		},
	}
	http.DefaultClient = &http.Client{Transport: tr}

	Tracef("doRequest start")
	resp, tok, err := doRequest0(ctx, method)
	if tok != nil && resp != nil && resp.StatusCode != 401 && resp.StatusCode != 403 {
		storeToken(tok)
	}
	if err != nil {
		log.Fatal(err)
		return
	} else {
		Tracef("request done successfully")
	}

	Tracef("printing headers")
	if ctx.GlobalBool("print-headers") {
		headers, _ := json.Marshal(resp.Header)
		fmt.Println(string(headers))
	}

	if ctx.GlobalBool("no-body") {
		Tracef("printing body is disabled")
	} else {
		Tracef("printing body")
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			Tracef("error on read: %v", err)
		} else if body == nil {
			Tracef("no body")
		} else {
			Tracef("body found")
			fmt.Println(string(body))
		}
	}
	Tracef("doRequest end")
}

func stringInSlice(a string, list []string) bool {
	for _, b := range list {
		if b == a {
			return true
		}
	}
	return false
}

func doRequest0(ctx *cli.Context, method string) (*http.Response, *oauth2.Token, error) {
	Tracef("profileName = %s", CurrentOptions.ProfileName)

	targetUrl, err := targetUrl(ctx)
	if err != nil {
		return nil, nil, err
	}
	Tracef("targetUrl = %s", targetUrl)
	data := ctx.String("data")
	Tracef("data = %s", data)
	body := strings.NewReader(data)
	req, err := http.NewRequest(method, targetUrl, body)
	if err != nil {
		return nil, nil, err
	}

	var lastError error
	for retrieve := false; retrieve == false; retrieve = true {
		Tracef("=== phase %s start", toString(retrieve))
		tok, r, err := AccessToken(CurrentOptions.ProfileName, retrieve)
		if err != nil {
			Tracef("phase %s failed (token retrieving failed)", toString(retrieve))
			lastError = err
			continue
		}
		retrieve = r
		req.Header.Set("User-Agent", fmt.Sprintf("%s-%s", ctx.App.Name, Version))
		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tok.AccessToken))
		dump, err := httputil.DumpRequestOut(req, true)
		if err != nil {
			Tracef("phase %s failed (request dump failed)", toString(retrieve))
			lastError = err
			continue
		}
		Tracef("request = %s", string(dump))

		tr := &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: ctx.GlobalBool("insecure"),
			},
		}
		client := &http.Client{
			CheckRedirect: func(req *http.Request, via []*http.Request) error {
				Tracef("redirect to %s", req.URL.String())
				req.Header.Set("User-Agent", fmt.Sprintf("%s-%s", ctx.App.Name, Version))
				req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", tok.AccessToken))
				return nil
			},
			Transport: tr,
		}
		resp, err := client.Do(req)
		if err != nil {
			Tracef("phase %s failed (request failed)", toString(retrieve))
			lastError = err
			continue
		}

		dumpResp, err := httputil.DumpResponse(resp, true)
		if err != nil {
			log.Printf("%+v%n", err)
		} else {
			Tracef("response = %s", string(dumpResp))
		}

		Tracef("phase %s", toString(retrieve))
		if resp.StatusCode >= 400 && resp.StatusCode < 500 {
			if retrieve {
				Tracef("phase retrieve failed (4XX response)")
				lastError = err
				break
			} else {
				Tracef("phase stored failed (4XX response) -> final result")
			}
		}
		return resp, tok, err
	}
	return nil, nil, fmt.Errorf("%v", lastError)
}

func toString(retrieve bool) string {
	if retrieve {
		return "retrieve"
	}
	return "stored"
}

func targetUrl(ctx *cli.Context) (string, error) {
	if len(ctx.Args()) < 1 {
		return "", fmt.Errorf("target URL required")
	}
	return ctx.Args()[0], nil
}

func storeToken(tok *oauth2.Token) {
	if SaveValues(CurrentOptions.ProfileName, tokenToValues(tok)) {
		Tracef("token stored [%s]", CurrentOptions.ProfileName)
	} else {
		Tracef("fail to store token [%s]", CurrentOptions.ProfileName)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"fmt"
	"net/url"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"

	"github.com/codegangsta/cli"
	"github.com/motemen/ghq/utils"
)

var Commands = []cli.Command{
	commandGet,
	commandList,
	commandLook,
	commandImport,
}

var commandGet = cli.Command{
	Name:  "get",
	Usage: "Clone/sync with a remote repository",
	Description: `
    Clone a GitHub repository under ghq root direcotry. If the repository is
    already cloned to local, nothing will happen unless '-u' ('--update')
    flag is supplied, in which case 'git remote update' is executed.
    When you use '-p' option, the repository is cloned via SSH.
`,
	Action: doGet,
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "update, u", Usage: "Update local repository if cloned already"},
		cli.BoolFlag{Name: "p", Usage: "Clone with SSH"},
		cli.BoolFlag{Name: "shallow", Usage: "Do a shallow clone"},
	},
}

var commandList = cli.Command{
	Name:  "list",
	Usage: "List local repositories",
	Description: `
    List locally cloned repositories. If a query argument is given, only
    repositories whose names contain that query text are listed. '-e'
    ('--exact') forces the match to be an exact one (i.e. the query equals to
    _project_ or _user_/_project_) If '-p' ('--full-path') is given, the full paths
    to the repository root are printed instead of relative ones.
`,
	Action: doList,
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "exact, e", Usage: "Perform an exact match"},
		cli.BoolFlag{Name: "full-path, p", Usage: "Print full paths"},
		cli.BoolFlag{Name: "unique", Usage: "Print unique subpaths"},
	},
}

var commandLook = cli.Command{
	Name:  "look",
	Usage: "Look into a local repository",
	Description: `
    Look into a locally cloned repository with the shell.
`,
	Action: doLook,
}

var commandImport = cli.Command{
	Name:   "import",
	Usage:  "Bulk get repositories from a file or stdin",
	Action: doImport,
}

type commandDoc struct {
	Parent    string
	Arguments string
}

var commandDocs = map[string]commandDoc{
	"get":    {"", "[-u] <repository URL> | [-u] [-p] <user>/<project>"},
	"list":   {"", "[-p] [-e] [<query>]"},
	"look":   {"", "<project> | <user>/<project> | <host>/<user>/<project>"},
	"import": {"", "< file"},
}

// Makes template conditionals to generate per-command documents.
func mkCommandsTemplate(genTemplate func(commandDoc) string) string {
	template := "{{if false}}"
	for _, command := range append(Commands) {
		template = template + fmt.Sprintf("{{else if (eq .Name %q)}}%s", command.Name, genTemplate(commandDocs[command.Name]))
	}
	return template + "{{end}}"
}

func init() {
	argsTemplate := mkCommandsTemplate(func(doc commandDoc) string { return doc.Arguments })
	parentTemplate := mkCommandsTemplate(func(doc commandDoc) string { return string(strings.TrimLeft(doc.Parent+" ", " ")) })

	cli.CommandHelpTemplate = `NAME:
    {{.Name}} - {{.Usage}}

USAGE:
    ghq ` + parentTemplate + `{{.Name}} ` + argsTemplate + `
{{if (len .Description)}}
DESCRIPTION: {{.Description}}
{{end}}{{if (len .Flags)}}
OPTIONS:
    {{range .Flags}}{{.}}
    {{end}}
{{end}}`
}

func doGet(c *cli.Context) {
	argURL := c.Args().Get(0)
	doUpdate := c.Bool("update")
	isShallow := c.Bool("shallow")

	if argURL == "" {
		cli.ShowCommandHelp(c, "get")
		os.Exit(1)
	}

	url, err := NewURL(argURL)
	utils.DieIf(err)

	isSSH := c.Bool("p")
	if isSSH {
		// Assume Git repository if `-p` is given.
		url, err = ConvertGitURLHTTPToSSH(url)
		utils.DieIf(err)
	}

	remote, err := NewRemoteRepository(url)
	utils.DieIf(err)

	if remote.IsValid() == false {
		utils.Log("error", fmt.Sprintf("Not a valid repository: %s", url))
		os.Exit(1)
	}

	getRemoteRepository(remote, doUpdate, isShallow)
}

// getRemoteRepository clones or updates a remote repository remote.
// If doUpdate is true, updates the locally cloned repository. Otherwise does nothing.
// If isShallow is true, does shallow cloning. (no effect if already cloned or the VCS is Mercurial)
func getRemoteRepository(remote RemoteRepository, doUpdate bool, isShallow bool) {
	remoteURL := remote.URL()
	local := LocalRepositoryFromURL(remoteURL)

	path := local.FullPath
	newPath := false

	_, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			newPath = true
			err = nil
		}
		utils.PanicIf(err)
	}

	if newPath {
		utils.Log("clone", fmt.Sprintf("%s -> %s", remoteURL, path))

		vcs := remote.VCS()
		if vcs == nil {
			utils.Log("error", fmt.Sprintf("Could not find version control system: %s", remoteURL))
			os.Exit(1)
		}

		vcs.Clone(remoteURL, path, isShallow)
	} else {
		if doUpdate {
			utils.Log("update", path)
			local.VCS().Update(path)
		} else {
			utils.Log("exists", path)
		}
	}
}

func doList(c *cli.Context) {
	query := c.Args().First()
	exact := c.Bool("exact")
	printFullPaths := c.Bool("full-path")
	printUniquePaths := c.Bool("unique")

	var filterFn func(*LocalRepository) bool
	if query == "" {
		filterFn = func(_ *LocalRepository) bool {
			return true
		}
	} else if exact {
		filterFn = func(repo *LocalRepository) bool {
			return repo.Matches(query)
		}
	} else {
		filterFn = func(repo *LocalRepository) bool {
			return strings.Contains(repo.NonHostPath(), query)
		}
	}

	repos := []*LocalRepository{}

	walkLocalRepositories(func(repo *LocalRepository) {
		if filterFn(repo) == false {
			return
		}

		repos = append(repos, repo)
	})

	if printUniquePaths {
		subpathCount := map[string]int{} // Count duplicated subpaths (ex. foo/dotfiles and bar/dotfiles)
		reposCount := map[string]int{}   // Check duplicated repositories among roots

		// Primary first
		for _, repo := range repos {
			if reposCount[repo.RelPath] == 0 {
				for _, p := range repo.Subpaths() {
					subpathCount[p] = subpathCount[p] + 1
				}
			}

			reposCount[repo.RelPath] = reposCount[repo.RelPath] + 1
		}

		for _, repo := range repos {
			if reposCount[repo.RelPath] > 1 && repo.IsUnderPrimaryRoot() == false {
				continue
			}

			for _, p := range repo.Subpaths() {
				if subpathCount[p] == 1 {
					fmt.Println(p)
					break
				}
			}
		}
	} else {
		for _, repo := range repos {
			if printFullPaths {
				fmt.Println(repo.FullPath)
			} else {
				fmt.Println(repo.RelPath)
			}
		}
	}
}

func doLook(c *cli.Context) {
	name := c.Args().First()

	if name == "" {
		cli.ShowCommandHelp(c, "look")
		os.Exit(1)
	}

	reposFound := []*LocalRepository{}
	walkLocalRepositories(func(repo *LocalRepository) {
		if repo.Matches(name) {
			reposFound = append(reposFound, repo)
		}
	})

	switch len(reposFound) {
	case 0:
		utils.Log("error", "No repository found")
		os.Exit(1)

	case 1:
		if runtime.GOOS == "windows" {
			cmd := exec.Command(os.Getenv("COMSPEC"))
			cmd.Stdin = os.Stdin
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			cmd.Dir = reposFound[0].FullPath
			err := cmd.Start()
			if err == nil {
				cmd.Wait()
				os.Exit(0)
			}
		} else {
			shell := os.Getenv("SHELL")
			if shell == "" {
				shell = "/bin/sh"
			}

			utils.Log("cd", reposFound[0].FullPath)
			err := os.Chdir(reposFound[0].FullPath)
			utils.PanicIf(err)

			syscall.Exec(shell, []string{shell}, syscall.Environ())
		}

	default:
		utils.Log("error", "More than one repositories are found; Try more precise name")
		for _, repo := range reposFound {
			utils.Log("error", "- "+strings.Join(repo.PathParts, "/"))
		}
	}
}

func doImport(c *cli.Context) {
	var (
		doUpdate  = c.Bool("update")
		isSSH     = c.Bool("p")
		isShallow = c.Bool("shallow")
	)

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line := scanner.Text()
		url, err := url.Parse(line)
		if err != nil {
			utils.Log("error", fmt.Sprintf("Could not parse URL <%s>: %s", line, err))
			continue
		}
		if isSSH {
			url, err = ConvertGitURLHTTPToSSH(url)
			if err != nil {
				utils.Log("error", fmt.Sprintf("Could not convert URL <%s>: %s", url, err))
				continue
			}
		}

		remote, err := NewRemoteRepository(url)
		if utils.ErrorIf(err) {
			continue
		}
		if remote.IsValid() == false {
			utils.Log("error", fmt.Sprintf("Not a valid repository: %s", url))
			continue
		}

		getRemoteRepository(remote, doUpdate, isShallow)
	}
	if err := scanner.Err(); err != nil {
		utils.Log("error", fmt.Sprintf("While reading input: %s", err))
		os.Exit(1)
	}
}
<commit_msg>import: Accept the same clone flags with get command<commit_after>package main

import (
	"bufio"
	"fmt"
	"net/url"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"syscall"

	"github.com/codegangsta/cli"
	"github.com/motemen/ghq/utils"
)

var Commands = []cli.Command{
	commandGet,
	commandList,
	commandLook,
	commandImport,
}

var cloneFlags = []cli.Flag{
	cli.BoolFlag{Name: "update, u", Usage: "Update local repository if cloned already"},
	cli.BoolFlag{Name: "p", Usage: "Clone with SSH"},
	cli.BoolFlag{Name: "shallow", Usage: "Do a shallow clone"},
}

var commandGet = cli.Command{
	Name:  "get",
	Usage: "Clone/sync with a remote repository",
	Description: `
    Clone a GitHub repository under ghq root direcotry. If the repository is
    already cloned to local, nothing will happen unless '-u' ('--update')
    flag is supplied, in which case 'git remote update' is executed.
    When you use '-p' option, the repository is cloned via SSH.
`,
	Action: doGet,
	Flags:  cloneFlags,
}

var commandList = cli.Command{
	Name:  "list",
	Usage: "List local repositories",
	Description: `
    List locally cloned repositories. If a query argument is given, only
    repositories whose names contain that query text are listed. '-e'
    ('--exact') forces the match to be an exact one (i.e. the query equals to
    _project_ or _user_/_project_) If '-p' ('--full-path') is given, the full paths
    to the repository root are printed instead of relative ones.
`,
	Action: doList,
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "exact, e", Usage: "Perform an exact match"},
		cli.BoolFlag{Name: "full-path, p", Usage: "Print full paths"},
		cli.BoolFlag{Name: "unique", Usage: "Print unique subpaths"},
	},
}

var commandLook = cli.Command{
	Name:  "look",
	Usage: "Look into a local repository",
	Description: `
    Look into a locally cloned repository with the shell.
`,
	Action: doLook,
}

var commandImport = cli.Command{
	Name:   "import",
	Usage:  "Bulk get repositories from a file or stdin",
	Action: doImport,
	Flags:  cloneFlags,
}

type commandDoc struct {
	Parent    string
	Arguments string
}

var commandDocs = map[string]commandDoc{
	"get":    {"", "[-u] <repository URL> | [-u] [-p] <user>/<project>"},
	"list":   {"", "[-p] [-e] [<query>]"},
	"look":   {"", "<project> | <user>/<project> | <host>/<user>/<project>"},
	"import": {"", "< file"},
}

// Makes template conditionals to generate per-command documents.
func mkCommandsTemplate(genTemplate func(commandDoc) string) string {
	template := "{{if false}}"
	for _, command := range append(Commands) {
		template = template + fmt.Sprintf("{{else if (eq .Name %q)}}%s", command.Name, genTemplate(commandDocs[command.Name]))
	}
	return template + "{{end}}"
}

func init() {
	argsTemplate := mkCommandsTemplate(func(doc commandDoc) string { return doc.Arguments })
	parentTemplate := mkCommandsTemplate(func(doc commandDoc) string { return string(strings.TrimLeft(doc.Parent+" ", " ")) })

	cli.CommandHelpTemplate = `NAME:
    {{.Name}} - {{.Usage}}

USAGE:
    ghq ` + parentTemplate + `{{.Name}} ` + argsTemplate + `
{{if (len .Description)}}
DESCRIPTION: {{.Description}}
{{end}}{{if (len .Flags)}}
OPTIONS:
    {{range .Flags}}{{.}}
    {{end}}
{{end}}`
}

func doGet(c *cli.Context) {
	argURL := c.Args().Get(0)
	doUpdate := c.Bool("update")
	isShallow := c.Bool("shallow")

	if argURL == "" {
		cli.ShowCommandHelp(c, "get")
		os.Exit(1)
	}

	url, err := NewURL(argURL)
	utils.DieIf(err)

	isSSH := c.Bool("p")
	if isSSH {
		// Assume Git repository if `-p` is given.
		url, err = ConvertGitURLHTTPToSSH(url)
		utils.DieIf(err)
	}

	remote, err := NewRemoteRepository(url)
	utils.DieIf(err)

	if remote.IsValid() == false {
		utils.Log("error", fmt.Sprintf("Not a valid repository: %s", url))
		os.Exit(1)
	}

	getRemoteRepository(remote, doUpdate, isShallow)
}

// getRemoteRepository clones or updates a remote repository remote.
// If doUpdate is true, updates the locally cloned repository. Otherwise does nothing.
// If isShallow is true, does shallow cloning. (no effect if already cloned or the VCS is Mercurial)
func getRemoteRepository(remote RemoteRepository, doUpdate bool, isShallow bool) {
	remoteURL := remote.URL()
	local := LocalRepositoryFromURL(remoteURL)

	path := local.FullPath
	newPath := false

	_, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			newPath = true
			err = nil
		}
		utils.PanicIf(err)
	}

	if newPath {
		utils.Log("clone", fmt.Sprintf("%s -> %s", remoteURL, path))

		vcs := remote.VCS()
		if vcs == nil {
			utils.Log("error", fmt.Sprintf("Could not find version control system: %s", remoteURL))
			os.Exit(1)
		}

		vcs.Clone(remoteURL, path, isShallow)
	} else {
		if doUpdate {
			utils.Log("update", path)
			local.VCS().Update(path)
		} else {
			utils.Log("exists", path)
		}
	}
}

func doList(c *cli.Context) {
	query := c.Args().First()
	exact := c.Bool("exact")
	printFullPaths := c.Bool("full-path")
	printUniquePaths := c.Bool("unique")

	var filterFn func(*LocalRepository) bool
	if query == "" {
		filterFn = func(_ *LocalRepository) bool {
			return true
		}
	} else if exact {
		filterFn = func(repo *LocalRepository) bool {
			return repo.Matches(query)
		}
	} else {
		filterFn = func(repo *LocalRepository) bool {
			return strings.Contains(repo.NonHostPath(), query)
		}
	}

	repos := []*LocalRepository{}

	walkLocalRepositories(func(repo *LocalRepository) {
		if filterFn(repo) == false {
			return
		}

		repos = append(repos, repo)
	})

	if printUniquePaths {
		subpathCount := map[string]int{} // Count duplicated subpaths (ex. foo/dotfiles and bar/dotfiles)
		reposCount := map[string]int{}   // Check duplicated repositories among roots

		// Primary first
		for _, repo := range repos {
			if reposCount[repo.RelPath] == 0 {
				for _, p := range repo.Subpaths() {
					subpathCount[p] = subpathCount[p] + 1
				}
			}

			reposCount[repo.RelPath] = reposCount[repo.RelPath] + 1
		}

		for _, repo := range repos {
			if reposCount[repo.RelPath] > 1 && repo.IsUnderPrimaryRoot() == false {
				continue
			}

			for _, p := range repo.Subpaths() {
				if subpathCount[p] == 1 {
					fmt.Println(p)
					break
				}
			}
		}
	} else {
		for _, repo := range repos {
			if printFullPaths {
				fmt.Println(repo.FullPath)
			} else {
				fmt.Println(repo.RelPath)
			}
		}
	}
}

func doLook(c *cli.Context) {
	name := c.Args().First()

	if name == "" {
		cli.ShowCommandHelp(c, "look")
		os.Exit(1)
	}

	reposFound := []*LocalRepository{}
	walkLocalRepositories(func(repo *LocalRepository) {
		if repo.Matches(name) {
			reposFound = append(reposFound, repo)
		}
	})

	switch len(reposFound) {
	case 0:
		utils.Log("error", "No repository found")
		os.Exit(1)

	case 1:
		if runtime.GOOS == "windows" {
			cmd := exec.Command(os.Getenv("COMSPEC"))
			cmd.Stdin = os.Stdin
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			cmd.Dir = reposFound[0].FullPath
			err := cmd.Start()
			if err == nil {
				cmd.Wait()
				os.Exit(0)
			}
		} else {
			shell := os.Getenv("SHELL")
			if shell == "" {
				shell = "/bin/sh"
			}

			utils.Log("cd", reposFound[0].FullPath)
			err := os.Chdir(reposFound[0].FullPath)
			utils.PanicIf(err)

			syscall.Exec(shell, []string{shell}, syscall.Environ())
		}

	default:
		utils.Log("error", "More than one repositories are found; Try more precise name")
		for _, repo := range reposFound {
			utils.Log("error", "- "+strings.Join(repo.PathParts, "/"))
		}
	}
}

func doImport(c *cli.Context) {
	var (
		doUpdate  = c.Bool("update")
		isSSH     = c.Bool("p")
		isShallow = c.Bool("shallow")
	)

	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		line := scanner.Text()
		url, err := url.Parse(line)
		if err != nil {
			utils.Log("error", fmt.Sprintf("Could not parse URL <%s>: %s", line, err))
			continue
		}
		if isSSH {
			url, err = ConvertGitURLHTTPToSSH(url)
			if err != nil {
				utils.Log("error", fmt.Sprintf("Could not convert URL <%s>: %s", url, err))
				continue
			}
		}

		remote, err := NewRemoteRepository(url)
		if utils.ErrorIf(err) {
			continue
		}
		if remote.IsValid() == false {
			utils.Log("error", fmt.Sprintf("Not a valid repository: %s", url))
			continue
		}

		getRemoteRepository(remote, doUpdate, isShallow)
	}
	if err := scanner.Err(); err != nil {
		utils.Log("error", fmt.Sprintf("While reading input: %s", err))
		os.Exit(1)
	}
}
<|endoftext|>