<commit_before>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path"
	"strings"
)

var initial_environ, current_environ map[string]string

// Convert a []string environment from os.Environ() to a more usable map.
func environ_to_map(environ []string) (m map[string]string) {
	m = make(map[string]string)
	for _, kv := range environ {
		if !strings.HasPrefix(kv, "HTTPCLI_") {
			continue
		}
		equ := strings.IndexByte(kv, '=')
		if equ == -1 {
			continue
		}
		name, value := kv[:equ], kv[equ+1:]
		m[name] = value
	}
	return
}

func Error(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

func get_headers() (headers http.Header) {
	// Get HTTP headers from environment:
	headers = make(http.Header)
	for _, kv := range os.Environ() {
		if !strings.HasPrefix(kv, "HTTPCLI_") {
			continue
		}
		h := kv[len("HTTPCLI_"):]
		equ := strings.IndexByte(h, '=')
		if equ == -1 {
			continue
		}
		name, value := h[:equ], h[equ+1:]
		headers.Set(name, value)
	}
	return
}

func set_headers(headers http.Header) {
	for key, values := range headers {
		err := os.Setenv("HTTPCLI_"+key, strings.Join(values, " "))
		if err != nil {
			Error("Error setting $HTTPCLI_HEADERS: %s\n", err)
			os.Exit(2)
			return
		}
	}
}

func get_abs_url() *url.URL {
	url_s := os.Getenv("HTTPCLI_URL")
	if url_s == "" {
		Error("Missing $HTTPCLI_URL env var\n")
		os.Exit(2)
		return nil
	}
	base_url, err := url.Parse(url_s)
	if err != nil {
		Error("Error parsing $HTTPCLI_URL: %s\n", err)
		os.Exit(2)
		return nil
	}
	if !base_url.IsAbs() {
		Error("$HTTPCLI_URL must be an absolute URL\n")
		os.Exit(2)
		return nil
	}
	return base_url
}

func set_abs_url(base_url *url.URL) {
	err := os.Setenv("HTTPCLI_URL", base_url.String())
	if err != nil {
		Error("Error setting $HTTPCLI_URL: %s\n", err)
		os.Exit(2)
		return
	}
}

func output_bash_env() {
	// Unset removed headers first:

	curr_environ := os.Environ()

	// Output the bash script to modify the environment:
	for _, key := range curr_environ {
		value := os.Getenv(key)
		// Bash-escape the value as a single-quoted string with escaping rules:
		bash_escape_value := strings.Replace(value, "\\", "\\\\", -1)
		bash_escape_value = strings.Replace(bash_escape_value, "'", "\\'", -1)
		fmt.Printf("export %s=$'%s'\n", key, bash_escape_value)
	}
	fmt.Println()
	fmt.Println("# This output must be `eval`ed in bash in order to have effect on the current environment.")
	fmt.Println("# Example: $ eval `http-cli ...`")
}

func do_http(http_method string, body_required bool, args []string) {
	// Get environment:
	base_url := get_abs_url()
	headers := get_headers()

	if len(args) == 0 {
		Error("Missing required relative URL\n")
		os.Exit(1)
		return
	}

	// Parse relative URL:
	rel_url_s := args[0]
	rel_url, err := url.Parse(rel_url_s)
	if err != nil {
		Error("Error parsing relative URL: %s\n", err)
		os.Exit(1)
		return
	}

	// Combine absolute URL base with relative URL argument:
	api_url := &url.URL{
		Scheme:   base_url.Scheme,
		Host:     base_url.Host,
		User:     base_url.User,
		Path:     path.Join(base_url.Path, rel_url.Path),
		RawQuery: rel_url.RawQuery,
		Fragment: rel_url.Fragment,
	}

	// Set up the request:
	req := &http.Request{
		URL:    api_url,
		Method: http_method,
		Header: headers,
	}

	// Exclude named headers:
	// TODO: parse args for this!
	exclude_headers_arg := ""
	if exclude_headers_arg != "" {
		// Remove excluded headers:
		exclude_headers := strings.Split(exclude_headers_arg, ",")
		for _, name := range exclude_headers {
			delete(req.Header, name)
		}
	}

	// Set up body content-type and data:
	var body_data []byte
	if body_required {
		// Read all of stdin to a `[]byte` buffer:
		body_data, err = ioutil.ReadAll(os.Stdin)
		if err != nil {
			Error("Error reading stdin: %s", err)
			os.Exit(3)
			return
		}

		if len(args) >= 2 {
			req.Header.Set("Content-Type", args[1])
		}

		// Create a Buffer to read the `[]byte` as the HTTP body:
		buf := bytes.NewBuffer(body_data)
		req.Body = ioutil.NopCloser(buf)
		req.ContentLength = int64(buf.Len())
	}

	// for debugging:
	Error("%s %s\n", http_method, api_url)
	for key, values := range req.Header {
		Error("%s: %s\n", key, strings.Join(values, " "))
	}
	Error("\n%s\n", body_data)

	// Make the request:
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		Error("HTTP error: %s\n", err)
		os.Exit(3)
		return
	}

	if resp.StatusCode != 200 {
		Error("%d\n", resp.StatusCode)
	}
	if resp.Body != nil {
		_, err = io.Copy(os.Stdout, resp.Body)
		if err != nil {
			Error("Error copying: %s\n", err)
		}
		fmt.Println()
	}
}

func main() {
	args := os.Args[1:][:]
	if len(args) == 0 {
		Error(`Usage:
http-cli <command> [args...]

Commands:
  url    [absolute_url]
    Get or set base URL in environment.

  header-clear
    Clears all HTTP headers in environment.

  header-set <header_name> <header_value>
    Sets a custom HTTP header in environment.

  header-list
    List current HTTP headers in environment.

  GET    <relative-url>
  DELETE <relative-url>
    Invoke HTTP GET or DELETE. No body data is sent.

  POST   <relative_url> [content-type]
  PUT    <relative_url> [content-type]
    Invoke HTTP POST or PUT. Body data is read from stdin.
`)
		os.Exit(1)
		return
	}

	// Determine what to do:
	cmd := args[0]
	args = args[1:]

	// Copy current environment:
	initial_environ = environ_to_map(os.Environ())

	body_required := true
	switch strings.ToLower(cmd) {
	case "get", "delete":
		body_required = false
		fallthrough
	case "post", "put":
		do_http(strings.ToUpper(cmd), body_required, args)
		break

	case "url":
		// Must be evaluated on the bash console as "eval `http-cli header-set ...`"
		if len(args) == 0 {
			base_url := get_abs_url()
			fmt.Printf("%s\n", base_url)
		} else if len(args) == 1 {
			base_url, err := url.Parse(args[0])
			if err != nil {
				Error("Error parsing absolute URL: %s\n", err)
				os.Exit(1)
				return
			}
			set_abs_url(base_url)
			output_bash_env()
		}
		break

	case "list":
		// Get HTTP headers from environment:
		headers := get_headers()
		for key, values := range headers {
			fmt.Printf("%s: %s\n", key, strings.Join(values, " "))
		}
		break

	case "set":
		// Must be evaluated on the bash console as "eval `http-cli header-set ...`"

		// Get HTTP headers from environment:
		headers := get_headers()
		if len(args) == 2 {
			// Set a new HTTP header:
			headers.Set(args[0], args[1])
		} else if len(args) == 1 {
			delete(headers, args[0])
		} else {

		}

		set_headers(headers)

		// Output the bash evaluation statements:
		output_bash_env()
		break

	case "clear":
		// Must be evaluated on the bash console as "eval `http-cli header-clear ...`"
		set_headers(nil)

		// Output the bash evaluation statements:
		output_bash_env()
		break

	default:
		os.Exit(1)
		break
	}

}
<commit_msg>More correct handling of env vars.<commit_after>package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"path"
	"strings"
)

func Error(format string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, format, a...)
}

var initial_environ, current_environ map[string]string

// Convert a []string environment from os.Environ() to a more usable map.
func environ_to_map(environ []string) (m map[string]string) {
	m = make(map[string]string)
	for _, kv := range environ {
		// Ignore things we don't care about:
		if !strings.HasPrefix(kv, "HTTPCLI_") {
			continue
		}
		// Split by first '=':
		equ := strings.IndexByte(kv, '=')
		if equ == -1 {
			continue
		}
		name, value := kv[:equ], kv[equ+1:]
		m[name] = value
	}
	return
}

func setenv(key, value string) (err error) {
	err = setenv(key, value)
	if err != nil {
		return err
	}

	// Replicate the setting in the current_environ map:
	if value == "" {
		delete(current_environ, key)
		return nil
	}

	current_environ[key] = value
	return nil
}

// Get HTTP headers from environment:
func get_headers() (headers http.Header) {
	headers = make(http.Header)
	for key, value := range current_environ {
		name := key[len("HTTPCLI_"):]
		headers.Set(name, value)
	}
	return
}

// Set HTTP headers back to environment:
func set_headers(headers http.Header) {
	// Unset removed headers first:
	for key, _ := range current_environ {
		if _, ok := headers[key]; !ok {
			setenv(key, "")
		}
	}

	for key, values := range headers {
		err := setenv("HTTPCLI_"+key, strings.Join(values, " "))
		if err != nil {
			Error("Error setting $HTTPCLI_%s: %s\n", key, err)
			os.Exit(2)
			return
		}
	}
}

func get_abs_url() *url.URL {
	url_s := current_environ["HTTPCLI_URL"]
	if url_s == "" {
		Error("Missing $HTTPCLI_URL env var\n")
		os.Exit(2)
		return nil
	}
	base_url, err := url.Parse(url_s)
	if err != nil {
		Error("Error parsing $HTTPCLI_URL: %s\n", err)
		os.Exit(2)
		return nil
	}
	if !base_url.IsAbs() {
		Error("$HTTPCLI_URL must be an absolute URL\n")
		os.Exit(2)
		return nil
	}
	return base_url
}

func set_abs_url(base_url *url.URL) {
	err := setenv("HTTPCLI_URL", base_url.String())
	if err != nil {
		Error("Error setting $HTTPCLI_URL: %s\n", err)
		os.Exit(2)
		return
	}
}

// Output a bash script to modify the environment:
func output_bash_env() {
	// Unset removed headers first:
	for key, _ := range initial_environ {
		if _, ok := current_environ[key]; !ok {
			fmt.Printf("unset %s\n", key)
		}
	}

	// Set new or existing headers:
	for key, value := range current_environ {
		// Bash-escape the value as a single-quoted string with escaping rules:
		bash_escape_value := strings.Replace(value, "\\", "\\\\", -1)
		bash_escape_value = strings.Replace(bash_escape_value, "'", "\\'", -1)

		fmt.Printf("export %s=$'%s'\n", key, bash_escape_value)
	}

	// Comments cannot come first if using `eval`.
	fmt.Println()
	fmt.Println("# This output must be `eval`ed in bash in order to have effect on the current environment.")
	fmt.Println("# Example: $ eval `http-cli ...`")
}

func do_http(http_method string, body_required bool, args []string) {
	// Get environment:
	base_url := get_abs_url()
	headers := get_headers()

	if len(args) == 0 {
		Error("Missing required relative URL\n")
		os.Exit(1)
		return
	}

	// Parse relative URL:
	rel_url_s := args[0]
	rel_url, err := url.Parse(rel_url_s)
	if err != nil {
		Error("Error parsing relative URL: %s\n", err)
		os.Exit(1)
		return
	}

	// Combine absolute URL base with relative URL argument:
	api_url := &url.URL{
		Scheme:   base_url.Scheme,
		Host:     base_url.Host,
		User:     base_url.User,
		Path:     path.Join(base_url.Path, rel_url.Path),
		RawQuery: rel_url.RawQuery,
		Fragment: rel_url.Fragment,
	}

	// Set up the request:
	req := &http.Request{
		URL:    api_url,
		Method: http_method,
		Header: headers,
	}

	// Exclude named headers:
	// TODO: parse args for this!
	exclude_headers_arg := ""
	if exclude_headers_arg != "" {
		// Remove excluded headers:
		exclude_headers := strings.Split(exclude_headers_arg, ",")
		for _, name := range exclude_headers {
			delete(req.Header, name)
		}
	}

	// Set up body content-type and data:
	var body_data []byte
	if body_required {
		// Read all of stdin to a `[]byte` buffer:
		body_data, err = ioutil.ReadAll(os.Stdin)
		if err != nil {
			Error("Error reading stdin: %s", err)
			os.Exit(3)
			return
		}

		if len(args) >= 2 {
			req.Header.Set("Content-Type", args[1])
		}

		// Create a Buffer to read the `[]byte` as the HTTP body:
		buf := bytes.NewBuffer(body_data)
		req.Body = ioutil.NopCloser(buf)
		req.ContentLength = int64(buf.Len())
	}

	// for debugging:
	Error("%s %s\n", http_method, api_url)
	for key, values := range req.Header {
		Error("%s: %s\n", key, strings.Join(values, " "))
	}
	Error("\n%s\n", body_data)

	// Make the request:
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		Error("HTTP error: %s\n", err)
		os.Exit(3)
		return
	}

	if resp.StatusCode != 200 {
		Error("%d\n", resp.StatusCode)
	}
	if resp.Body != nil {
		_, err = io.Copy(os.Stdout, resp.Body)
		if err != nil {
			Error("Error copying: %s\n", err)
		}
		fmt.Println()
	}
}

func main() {
	args := os.Args[1:][:]
	if len(args) == 0 {
		Error(`Usage:
http-cli <command> [args...]

Commands:
  url    [absolute_url]
    Get or set base URL in environment.

  header-clear
    Clears all HTTP headers in environment.

  header-set <header_name> <header_value>
    Sets a custom HTTP header in environment.

  header-list
    List current HTTP headers in environment.

  GET    <relative-url>
  DELETE <relative-url>
    Invoke HTTP GET or DELETE. No body data is sent.

  POST   <relative_url> [content-type]
  PUT    <relative_url> [content-type]
    Invoke HTTP POST or PUT. Body data is read from stdin.
`)
		os.Exit(1)
		return
	}

	// Determine what to do:
	cmd := args[0]
	args = args[1:]

	// Copy current environment:
	initial_environ = environ_to_map(os.Environ())

	body_required := true
	switch strings.ToLower(cmd) {
	case "get", "delete":
		body_required = false
		fallthrough
	case "post", "put":
		do_http(strings.ToUpper(cmd), body_required, args)
		break

	case "url":
		// Must be evaluated on the bash console as "eval `http-cli header-set ...`"
		if len(args) == 0 {
			base_url := get_abs_url()
			fmt.Printf("%s\n", base_url)
		} else if len(args) == 1 {
			base_url, err := url.Parse(args[0])
			if err != nil {
				Error("Error parsing absolute URL: %s\n", err)
				os.Exit(1)
				return
			}
			set_abs_url(base_url)
			output_bash_env()
		}
		break

	case "list":
		// Get HTTP headers from environment:
		headers := get_headers()
		for key, values := range headers {
			fmt.Printf("%s: %s\n", key, strings.Join(values, " "))
		}
		break

	case "set":
		// Must be evaluated on the bash console as "eval `http-cli header-set ...`"

		// Get HTTP headers from environment:
		headers := get_headers()
		if len(args) == 2 {
			// Set a new HTTP header:
			headers.Set(args[0], args[1])
		} else if len(args) == 1 {
			delete(headers, args[0])
		} else {

		}

		set_headers(headers)

		// Output the bash evaluation statements:
		output_bash_env()
		break

	case "clear":
		// Must be evaluated on the bash console as "eval `http-cli header-clear ...`"
		set_headers(nil)

		// Output the bash evaluation statements:
		output_bash_env()
		break

	default:
		os.Exit(1)
		break
	}

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"github.com/boredomist/gob/parse"
	"os"
)

const GOB_VERSION = "0.0.0"

var (
	showVersion = flag.Bool("version", false, "Show version info")
	// TODO: other
)

func main() {
	flag.Parse()

	if *showVersion {
		fmt.Printf("Gob v%s\n", GOB_VERSION)
	}

	for _, name := range flag.Args() {
		file, err := os.Open(name)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		parser := parse.NewParser(name, file)

		node, err := parser.Parse()
		if err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(*node)
		}
	}

}
<commit_msg>Update main<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/boredomist/gob/parse"
	"os"
)

const GOB_VERSION = "0.0.0"

var (
	showVersion = flag.Bool("version", false, "Show version info")
	// TODO: other
)

func main() {
	flag.Parse()

	if *showVersion {
		fmt.Printf("Gob v%s\n", GOB_VERSION)
	}

	for _, name := range flag.Args() {
		file, err := os.Open(name)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}

		parser := parse.NewParser(name, file)

		unit, err := parser.Parse()
		if err != nil {
			fmt.Println(err)
		} else {
			fmt.Println(unit)
		}
	}

}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime/pprof"
	"strings"

	"github.com/tinzenite/shared"
)

func main() {
	log.Println("Starting client.")
	// declare flags
	var commandString string
	var path string
	var cpuProfileFile string
	// write flag stuff
	flag.StringVar(&path, "path", "", "File directory path in which to run the client.")
	flag.StringVar(&commandString, "cmd", "load", "Command for the path: create, load, or bootstrap. Default is load.")
	flag.StringVar(&cpuProfileFile, "profile", "", "By using this flag with a path, a cpu profile will be written to the given path.")
	// parse them
	flag.Parse()
	// cpu profiling
	if cpuProfileFile != "" {
		f, err := os.Create(cpuProfileFile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	// need to do some additional work because flag doesn't allow custom enumeration variables
	command := cmdParse(commandString)
	if path == "" {
		path = getPath()
	}
	if !shared.FileExists(path) {
		/*TODO offer creating it?*/
		logMain("Path", path, "doesn't exist!")
		return
	}
	logMain("Will", command.String(), "Tinzenite at", path, ".")
	switch command {
	case cmdLoad:
		loadTinzenite(path)
	case cmdCreate:
		createTinzenite(path)
	case cmdBootstrap:
		bootstrapTinzenite(path)
	default:
		logMain("No command was chosen, so we'll do nothing.")
	}
	// if we reach this it means the client is closing.
	logMain("Quitting.")
}

/*
getPath gets a path from the user, either manually entered or chosen from the
known paths.

TODO: rewrite, I call the same manual request in 3 places!
*/
func getPath() string {
	// load available dirs
	options, err := shared.ReadDirectoryList()
	if err != nil {
		logMain(err.Error())
		return ""
	}
	// if none saved --> ask for manual entry
	if len(options) == 0 {
		fmt.Println("No previous Tinzenite directories known.")
		return getString("Enter path for Tinzenite directory:")
	}
	newQueston := createYesNo("Choose from existing paths?")
	// if no --> manual entry
	if newQueston.ask() < 0 {
		return getString("Enter path for Tinzenite directory:")
	}
	// if only one choice then that is all they have
	if len(options) == 1 {
		useQuestion := createYesNo("Only one candidate: " + options[0] + ". Use it?")
		if useQuestion.ask() < 0 {
			return getString("Enter path for Tinzenite directory:")
		}
		return options[0]
	}
	fmt.Println("Available paths:")
	for index, path := range options {
		// plus one for human readable numbers
		fmt.Println(index+1, ":", path)
	}
	var pathIndex int
	for {
		pathIndex = getInt("Enter the corresponding number to choose a path:")
		pathIndex-- // need to subtract one to undo human readable numbers
		if pathIndex >= 0 && pathIndex < len(options) {
			break
		}
		fmt.Println("Invalid choice. Choose between 1 and the maximum!")
	}
	return options[pathIndex]
}

/*
Log function that respects the AllowLogging flag.
*/
func logMain(msg ...string) {
	toPrint := []string{"Main:"}
	toPrint = append(toPrint, msg...)
	log.Println(strings.Join(toPrint, " "))
}
<commit_msg>added cmd short form for bootstrap -> boot<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"
	"runtime/pprof"
	"strings"

	"github.com/tinzenite/shared"
)

func main() {
	log.Println("Starting client.")
	// declare flags
	var commandString string
	var path string
	var cpuProfileFile string
	// write flag stuff
	flag.StringVar(&path, "path", "", "File directory path in which to run the client.")
	flag.StringVar(&commandString, "cmd", "load", "Command for the path: create, load, or bootstrap (short: boot). Default is load.")
	flag.StringVar(&cpuProfileFile, "profile", "", "By using this flag with a path, a cpu profile will be written to the given path.")
	// parse them
	flag.Parse()
	// cpu profiling
	if cpuProfileFile != "" {
		f, err := os.Create(cpuProfileFile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	// replace short form with long form
	if commandString == "boot" {
		commandString = "bootstrap"
	}
	// need to do some additional work because flag doesn't allow custom enumeration variables
	command := cmdParse(commandString)
	if path == "" {
		path = getPath()
	}
	if !shared.FileExists(path) {
		/*TODO offer creating it?*/
		logMain("Path", path, "doesn't exist!")
		return
	}
	logMain("Will", command.String(), "Tinzenite at", path, ".")
	switch command {
	case cmdLoad:
		loadTinzenite(path)
	case cmdCreate:
		createTinzenite(path)
	case cmdBootstrap:
		bootstrapTinzenite(path)
	default:
		logMain("No command was chosen, so we'll do nothing.")
	}
	// if we reach this it means the client is closing.
	logMain("Quitting.")
}

/*
getPath gets a path from the user, either manually entered or chosen from the
known paths.

TODO: rewrite, I call the same manual request in 3 places!
*/
func getPath() string {
	// load available dirs
	options, err := shared.ReadDirectoryList()
	if err != nil {
		logMain(err.Error())
		return ""
	}
	// if none saved --> ask for manual entry
	if len(options) == 0 {
		fmt.Println("No previous Tinzenite directories known.")
		return getString("Enter path for Tinzenite directory:")
	}
	newQueston := createYesNo("Choose from existing paths?")
	// if no --> manual entry
	if newQueston.ask() < 0 {
		return getString("Enter path for Tinzenite directory:")
	}
	// if only one choice then that is all they have
	if len(options) == 1 {
		useQuestion := createYesNo("Only one candidate: " + options[0] + ". Use it?")
		if useQuestion.ask() < 0 {
			return getString("Enter path for Tinzenite directory:")
		}
		return options[0]
	}
	fmt.Println("Available paths:")
	for index, path := range options {
		// plus one for human readable numbers
		fmt.Println(index+1, ":", path)
	}
	var pathIndex int
	for {
		pathIndex = getInt("Enter the corresponding number to choose a path:")
		pathIndex-- // need to subtract one to undo human readable numbers
		if pathIndex >= 0 && pathIndex < len(options) {
			break
		}
		fmt.Println("Invalid choice. Choose between 1 and the maximum!")
	}
	return options[pathIndex]
}

/*
Log function that respects the AllowLogging flag.
*/
func logMain(msg ...string) {
	toPrint := []string{"Main:"}
	toPrint = append(toPrint, msg...)
	log.Println(strings.Join(toPrint, " "))
}
<|endoftext|>


<commit_before>package main

import (
	"code.google.com/p/gcfg"
	"compress/gzip"
	"flag"
	"github.com/boredomist/mixport/exports"
	"github.com/boredomist/mixport/mixpanel"
	kinesis "github.com/sendgridlabs/go-kinesis"
	"io"
	"log"
	"os"
	"path"
	"runtime"
	"sync"
	"time"
)

// Mixpanel API credentials, used by the configuration parser.
type mixpanelCredentials struct {
	Key    string
	Secret string
	Token  string
}

// Configuration options common to the file export streams (CSV and JSON)
type fileExportConfig struct {
	State     bool
	Gzip      bool
	Directory string
}

// configFormat is the in-memory representation of the mixport configuration
// file.
type configFormat struct {
	Product map[string]*mixpanelCredentials
	Kinesis struct {
		State     bool
		Keyid     string
		Secretkey string
		Stream    string
		Region    string
	}

	JSON fileExportConfig
	CSV  fileExportConfig
}

const (
	defaultConfig = "mixport.conf"
	defaultDate   = ""
)

var configFile string
var dateString string

func init() {
	// XXX: This one goes to 11.
	runtime.GOMAXPROCS(runtime.NumCPU() * 5)

	const (
		confUsage = "path to configuration file"
		dateUsage = "date (YYYY-MM-DD) of data to pull, default is yesterday"
	)

	flag.StringVar(&configFile, "config", defaultConfig, confUsage)
	flag.StringVar(&configFile, "c", defaultConfig, confUsage)
	flag.StringVar(&dateString, "date", defaultDate, dateUsage)
	flag.StringVar(&dateString, "d", defaultDate, dateUsage)
}

func main() {
	flag.Parse()

	cfg := configFormat{}
	if err := gcfg.ReadFileInto(&cfg, configFile); err != nil {
		log.Fatalf("Failed to load %s: %s", configFile, err)
	}

	var exportDate time.Time

	// Default to yesterday (should be newest available data)
	if dateString == "" {
		exportDate = time.Now().UTC().AddDate(0, 0, -1)
	} else {
		if d, err := time.Parse("2006-01-02", dateString); err != nil {
			log.Fatalf("Invalid date: %s, should be in YYYY-MM-DD format",
				dateString)
		} else {
			exportDate = d
		}
	}

	// WaitGroup will hold the process open until all of the child
	// goroutines have completed execution.
	var wg sync.WaitGroup
	wg.Add(len(cfg.Product))

	for product, creds := range cfg.Product {
		// Run each individual product in a new thread.
		go func(product string, creds mixpanelCredentials) {
			defer wg.Done()

			client := mixpanel.New(product, creds.Key, creds.Secret)
			eventData := make(chan mixpanel.EventData)

			// We need to mux eventData into multiple channels
			var chans []chan mixpanel.EventData

			if cfg.Kinesis.State {
				ch := make(chan mixpanel.EventData)
				chans = append(chans, ch)

				ksis := kinesis.New(cfg.Kinesis.Keyid, cfg.Kinesis.Secretkey)
				if cfg.Kinesis.Region != "" {
					ksis.Region = "us-east-1"
				}

				wg.Add(1)
				go func() {
					exports.KinesisStreamer(ksis, cfg.Kinesis.Stream, ch)
					defer wg.Done()
				}()
			}

			type streamFunc func(io.Writer, <-chan mixpanel.EventData)

			// Generalize setup of JSON and CSV streams into a single function.
			setupFileExportStream := func(conf fileExportConfig, ext string, streamer streamFunc) {
				ch := make(chan mixpanel.EventData)
				chans = append(chans, ch)

				name := path.Join(conf.Directory, product+ext)
				if conf.Gzip {
					name += ".gz"
				}

				fp, err := os.Create(name)
				if err != nil {
					log.Fatalf("Couldn't create file: %s", err)
				}

				defer fp.Close()

				var writer io.Writer
				if conf.Gzip {
					writer = gzip.NewWriter(fp)
				} else {
					writer = fp
				}

				wg.Add(1)
				go func() {
					streamer(writer, ch)
					defer wg.Done()
				}()
			}

			if cfg.JSON.State {
				setupFileExportStream(cfg.JSON, ".json", exports.JSONStreamer)
			}

			if cfg.CSV.State {
				setupFileExportStream(cfg.CSV, ".csv", exports.CSVStreamer)
			}

			go client.ExportDate(exportDate, eventData, nil)

			for data := range eventData {
				for _, ch := range chans {
					ch <- data
				}
			}

			for _, ch := range chans {
				close(ch)
			}
		}(product, *creds)
	}

	// Wait for all our goroutines to finish up
	wg.Wait()
}
<commit_msg>Fix potential race condition.<commit_after>package main

import (
	"code.google.com/p/gcfg"
	"compress/gzip"
	"flag"
	"github.com/boredomist/mixport/exports"
	"github.com/boredomist/mixport/mixpanel"
	kinesis "github.com/sendgridlabs/go-kinesis"
	"io"
	"log"
	"os"
	"path"
	"runtime"
	"sync"
	"time"
)

// Mixpanel API credentials, used by the configuration parser.
type mixpanelCredentials struct {
	Key    string
	Secret string
	Token  string
}

// Configuration options common to the file export streams (CSV and JSON)
type fileExportConfig struct {
	State     bool
	Gzip      bool
	Directory string
}

// configFormat is the in-memory representation of the mixport configuration
// file.
type configFormat struct {
	Product map[string]*mixpanelCredentials
	Kinesis struct {
		State     bool
		Keyid     string
		Secretkey string
		Stream    string
		Region    string
	}

	JSON fileExportConfig
	CSV  fileExportConfig
}

const (
	defaultConfig = "mixport.conf"
	defaultDate   = ""
)

var configFile string
var dateString string

func init() {
	// XXX: This one goes to 11.
	runtime.GOMAXPROCS(runtime.NumCPU() * 5)

	const (
		confUsage = "path to configuration file"
		dateUsage = "date (YYYY-MM-DD) of data to pull, default is yesterday"
	)

	flag.StringVar(&configFile, "config", defaultConfig, confUsage)
	flag.StringVar(&configFile, "c", defaultConfig, confUsage)
	flag.StringVar(&dateString, "date", defaultDate, dateUsage)
	flag.StringVar(&dateString, "d", defaultDate, dateUsage)
}

func main() {
	flag.Parse()

	cfg := configFormat{}
	if err := gcfg.ReadFileInto(&cfg, configFile); err != nil {
		log.Fatalf("Failed to load %s: %s", configFile, err)
	}

	var exportDate time.Time

	// Default to yesterday (should be newest available data)
	if dateString == "" {
		exportDate = time.Now().UTC().AddDate(0, 0, -1)
	} else {
		if d, err := time.Parse("2006-01-02", dateString); err != nil {
			log.Fatalf("Invalid date: %s, should be in YYYY-MM-DD format",
				dateString)
		} else {
			exportDate = d
		}
	}

	// WaitGroup will hold the process open until all of the child
	// goroutines have completed execution.
	var wg sync.WaitGroup
	wg.Add(len(cfg.Product))

	for product, creds := range cfg.Product {
		// Run each individual product in a new thread.
		go func(product string, creds mixpanelCredentials) {
			defer wg.Done()

			client := mixpanel.New(product, creds.Key, creds.Secret)
			eventData := make(chan mixpanel.EventData)

			// We need to mux eventData into multiple channels
			var chans []chan mixpanel.EventData

			if cfg.Kinesis.State {
				ch := make(chan mixpanel.EventData)
				chans = append(chans, ch)

				ksis := kinesis.New(cfg.Kinesis.Keyid, cfg.Kinesis.Secretkey)
				if cfg.Kinesis.Region != "" {
					ksis.Region = "us-east-1"
				}

				wg.Add(1)
				go func() {
					exports.KinesisStreamer(ksis, cfg.Kinesis.Stream, ch)
					defer wg.Done()
				}()
			}

			type streamFunc func(io.Writer, <-chan mixpanel.EventData)

			// Generalize setup of JSON and CSV streams into a single function.
			setupFileExportStream := func(conf fileExportConfig, ext string, streamer streamFunc) {
				ch := make(chan mixpanel.EventData)
				chans = append(chans, ch)

				name := path.Join(conf.Directory, product+ext)
				if conf.Gzip {
					name += ".gz"
				}

				fp, err := os.Create(name)
				if err != nil {
					log.Fatalf("Couldn't create file: %s", err)
				}

				wg.Add(1)
				go func(fp *os.File) {

					var writer io.Writer
					if conf.Gzip {
						writer = gzip.NewWriter(fp)
					} else {
						writer = fp
					}

					streamer(writer, ch)
					defer fp.Close()
					defer wg.Done()
				}(fp)
			}

			if cfg.JSON.State {
				setupFileExportStream(cfg.JSON, ".json", exports.JSONStreamer)
			}

			if cfg.CSV.State {
				setupFileExportStream(cfg.CSV, ".csv", exports.CSVStreamer)
			}

			go client.ExportDate(exportDate, eventData, nil)

			for data := range eventData {
				for _, ch := range chans {
					ch <- data
				}
			}

			for _, ch := range chans {
				close(ch)
			}
		}(product, *creds)
	}

	// Wait for all our goroutines to finish up
	wg.Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"gvweb/simplemux"
	"log"
	"net/http"
	"os"
	"runtime"
	"time"
)

const g_DataDir = "data/"

var g_supportedTools = [...]string{"dot", "neato", "twopi", "circo", "fdp", "sfdp", "patchwork"}

func homePage(w http.ResponseWriter, r *http.Request, matches []string) {
	http.ServeFile(w, r, "static/index.html")
}

func isSupportedTool(tool string) bool {
	for _, val := range g_supportedTools {
		if tool == val {
			return true
		}
	}
	return false
}

func generateHandler(w http.ResponseWriter, r *http.Request, matches []string) {
	graph := r.FormValue("graphtext")
	imgType := r.FormValue("imagetype")
	tool := r.FormValue("tool")

	if !isSupportedTool(tool) {
		http.Error(w, fmt.Sprintf("Tool '%s' is not supported", tool), http.StatusBadRequest)
		return
	}
	if len(imgType) == 0 {
		http.Error(w, fmt.Sprintf("imagetype is not specified", tool), http.StatusBadRequest)
		return
	}

	if len(graph) == 0 {
		http.Error(w, "Empty input", http.StatusBadRequest)
		return
	}

	result := runGraphviz(tool, graph, imgType)
	if result.err != nil {
		log.Print(result.err)
		http.Error(w, result.err.Error(), http.StatusNotAcceptable)
		return
	} else {
		w.WriteHeader(http.StatusCreated)
		w.Write([]byte(result.fileName))
		return
	}
}

func accessLogger(l chan string) {
	for {
		log.Print(<-l)
	}
}

func httpLog(l chan string, w http.ResponseWriter, r *http.Request) {

	var remote string
	if len(r.Header["X-Forwarded-For"]) > 0 {
		remote = r.Header["X-Forwarded-For"][0]
	} else {
		remote = r.RemoteAddr
	}
	l <- fmt.Sprintf("%s %s %s", remote, r.Method, r.URL)
}

func httpWrapper(l chan string, handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Server", "Go HTTP handler")
		handler.ServeHTTP(w, r)
		httpLog(l, w, r)
	})
}

func serveHTTP(port string) {
	accessLogChan := make(chan string, 64)
	go accessLogger(accessLogChan)

	reHandler := simplemux.NewRegexpHandler()
	reHandler.AddRoute("^/$", "GET", homePage)
	reHandler.AddRoute("^/generate$", "POST", generateHandler)
	http.Handle("/static/", http.FileServer(http.Dir(".")))
	http.Handle("/"+g_DataDir, http.FileServer(http.Dir(".")))
	http.Handle("/", reHandler)

	var scheme string
	if *g_UseTLS {
		scheme = "https"
	} else {
		scheme = "http"
	}
	log.Printf("gvweb(%s) listening at %s port %s\n", g_Version, port, scheme)

	var err error

	if *g_UseTLS {
		err = http.ListenAndServeTLS(":"+port, *g_TLSCert, *g_TLSKey, httpWrapper(accessLogChan, http.DefaultServeMux))
	} else {
		err = http.ListenAndServe(":"+port, httpWrapper(accessLogChan, http.DefaultServeMux))
	}
	if err != nil {
		log.Fatalln("ListenAndServe: ", err)
	}
}

var g_Port = flag.Int("port", 12345, "port number to listen on")
var g_UseTLS = flag.Bool("usetls", false, "Use TLS(HTTPS) intead of plain HTTP")
var g_TLSCert = flag.String("tlscert", "tls.cert", "Path to TLS certificate file")
var g_TLSKey = flag.String("tlskey", "tls.key", "Path to TLS key file")
var g_CleanupInterval = flag.Int("purge", 24*60*60, "Remove saved graphs that are older than this amount in seconds. 0 to keep them forever.")
var g_Version = "DEVELOPMENT"

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

	flag.Parse()

	runtime.GOMAXPROCS(3)

	if *g_CleanupInterval > 0 {
		interval := time.Duration(*g_CleanupInterval) * time.Second
		initPurge(g_DataDir, interval)
		log.Printf("Purging data older than %v\n", interval)
	}

	serveHTTP(fmt.Sprintf("%d", *g_Port))
}
<commit_msg>Fix startup log string<commit_after>package main

import (
	"flag"
	"fmt"
	"gvweb/simplemux"
	"log"
	"net/http"
	"os"
	"runtime"
	"time"
)

const g_DataDir = "data/"

var g_supportedTools = [...]string{"dot", "neato", "twopi", "circo", "fdp", "sfdp", "patchwork"}

func homePage(w http.ResponseWriter, r *http.Request, matches []string) {
	http.ServeFile(w, r, "static/index.html")
}

func isSupportedTool(tool string) bool {
	for _, val := range g_supportedTools {
		if tool == val {
			return true
		}
	}
	return false
}

func generateHandler(w http.ResponseWriter, r *http.Request, matches []string) {
	graph := r.FormValue("graphtext")
	imgType := r.FormValue("imagetype")
	tool := r.FormValue("tool")

	if !isSupportedTool(tool) {
		http.Error(w, fmt.Sprintf("Tool '%s' is not supported", tool), http.StatusBadRequest)
		return
	}
	if len(imgType) == 0 {
		http.Error(w, fmt.Sprintf("imagetype is not specified", tool), http.StatusBadRequest)
		return
	}

	if len(graph) == 0 {
		http.Error(w, "Empty input", http.StatusBadRequest)
		return
	}

	result := runGraphviz(tool, graph, imgType)
	if result.err != nil {
		log.Print(result.err)
		http.Error(w, result.err.Error(), http.StatusNotAcceptable)
		return
	} else {
		w.WriteHeader(http.StatusCreated)
		w.Write([]byte(result.fileName))
		return
	}
}

func accessLogger(l chan string) {
	for {
		log.Print(<-l)
	}
}

func httpLog(l chan string, w http.ResponseWriter, r *http.Request) {

	var remote string
	if len(r.Header["X-Forwarded-For"]) > 0 {
		remote = r.Header["X-Forwarded-For"][0]
	} else {
		remote = r.RemoteAddr
	}
	l <- fmt.Sprintf("%s %s %s", remote, r.Method, r.URL)
}

func httpWrapper(l chan string, handler http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Server", "Go HTTP handler")
		handler.ServeHTTP(w, r)
		httpLog(l, w, r)
	})
}

func serveHTTP(port string) {
	accessLogChan := make(chan string, 64)
	go accessLogger(accessLogChan)

	reHandler := simplemux.NewRegexpHandler()
	reHandler.AddRoute("^/$", "GET", homePage)
	reHandler.AddRoute("^/generate$", "POST", generateHandler)
	http.Handle("/static/", http.FileServer(http.Dir(".")))
	http.Handle("/"+g_DataDir, http.FileServer(http.Dir(".")))
	http.Handle("/", reHandler)

	var scheme string
	if *g_UseTLS {
		scheme = "https"
	} else {
		scheme = "http"
	}
	log.Printf("gvweb(%s) listening at %s port %d\n", g_Version, scheme, port)

	var err error

	if *g_UseTLS {
		err = http.ListenAndServeTLS(":"+port, *g_TLSCert, *g_TLSKey, httpWrapper(accessLogChan, http.DefaultServeMux))
	} else {
		err = http.ListenAndServe(":"+port, httpWrapper(accessLogChan, http.DefaultServeMux))
	}
	if err != nil {
		log.Fatalln("ListenAndServe: ", err)
	}
}

var g_Port = flag.Int("port", 12345, "port number to listen on")
var g_UseTLS = flag.Bool("usetls", false, "Use TLS(HTTPS) intead of plain HTTP")
var g_TLSCert = flag.String("tlscert", "tls.cert", "Path to TLS certificate file")
var g_TLSKey = flag.String("tlskey", "tls.key", "Path to TLS key file")
var g_CleanupInterval = flag.Int("purge", 24*60*60, "Remove saved graphs that are older than this amount in seconds. 0 to keep them forever.")
var g_Version = "DEVELOPMENT"

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

	flag.Parse()

	runtime.GOMAXPROCS(3)

	if *g_CleanupInterval > 0 {
		interval := time.Duration(*g_CleanupInterval) * time.Second
		initPurge(g_DataDir, interval)
		log.Printf("Purging data older than %v\n", interval)
	}

	serveHTTP(fmt.Sprintf("%d", *g_Port))
}
<|endoftext|>


<commit_before>/*
gitlab-git-http-server handles 'smart' Git HTTP requests for GitLab

This HTTP server can service 'git clone', 'git push' etc. commands
from Git clients that use the 'smart' Git HTTP protocol (git-upload-pack
and git-receive-pack). It is intended to be deployed behind NGINX
(for request routing and SSL termination) with access to a GitLab
backend (for authentication and authorization) and local disk access
to Git repositories managed by GitLab.

This HTTP server replaces gitlab-grack.
*/
package main

import (
	"compress/gzip"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"
)

type gitService struct {
	method      string
	regexp      *regexp.Regexp
	handle_func func(string, string, string, http.ResponseWriter, *http.Request)
	rpc         string
}

var http_client = &http.Client{}
var path_traversal = regexp.MustCompile(`/../`)

// Command-line options
var repo_root string
var listen_addr = flag.String("listen_addr", "localhost:8181", "Listen address for HTTP server")
var auth_backend = flag.String("auth_backend", "http://localhost:8080", "Authentication/authorization backend")

var git_services = [...]gitService{
	gitService{"GET", regexp.MustCompile(`\A(/..*)/info/refs\z`), handle_get_info_refs, ""},
	gitService{"POST", regexp.MustCompile(`\A(/..*)/git-upload-pack\z`), handle_post_rpc, "git-upload-pack"},
	gitService{"POST", regexp.MustCompile(`\A(/..*)/git-receive-pack\z`), handle_post_rpc, "git-receive-pack"},
}

func main() {
	// Parse the command-line
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\n  %s [OPTIONS] REPO_ROOT\n\nOptions:\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()
	repo_root = flag.Arg(0)
	if repo_root == "" {
		flag.Usage()
		os.Exit(1)
	}
	log.Printf("repo_root: %s", repo_root)

	http.HandleFunc("/", git_handler)
	log.Fatal(http.ListenAndServe(*listen_addr, nil))
}

func git_handler(w http.ResponseWriter, r *http.Request) {
	var gl_id string
	var path_match []string
	var g gitService
	var found_service bool

	log.Print(r.Method, " ", r.URL)

	// Look for a matching Git service
	for _, g = range git_services {
		path_match = g.regexp.FindStringSubmatch(r.URL.Path)
		if r.Method == g.method && path_match != nil {
			found_service = true
			break
		}
	}
	if !found_service {
		http.Error(w, "Not Found", 404)
		return
	}

	// Ask the auth backend if the request is allowed, and what the
	// user ID (GL_ID) is.
	auth_response, err := do_auth_request(r)
	if err != nil {
		fail_500(w, err)
		return
	}
	if auth_response.StatusCode != 200 {
		// The Git request is not allowed by the backend. Maybe the
		// client needs to send HTTP Basic credentials.  Forward the
		// response from the auth backend to our client. This includes
		// the 'WWW-Authentication' header that acts as a hint that
		// Basic auth credentials are needed.
		for k, v := range auth_response.Header {
			w.Header()[k] = v
		}
		w.WriteHeader(auth_response.StatusCode)
		io.Copy(w, auth_response.Body)
		return
	}

	// The auth backend validated the client request and told us who
	// the user is according to them (GL_ID). We must extract this
	// information from the auth response body.
	if _, err := fmt.Fscan(auth_response.Body, &gl_id); err != nil {
		fail_500(w, err)
		return
	}

	// Validate the path to the Git repository
	found_path := path_match[1]
	if !valid_path(found_path) {
		http.Error(w, "Not Found", 404)
		return
	}

	g.handle_func(gl_id, g.rpc, path.Join(repo_root, found_path), w, r)
}

func valid_path(p string) bool {
	if path_traversal.MatchString(p) {
		log.Printf("path traversal detected in %s", p)
		return false
	}

	// If /path/to/foo.git/objects exists then let's assume it is a valid Git
	// repository.
	if _, err := os.Stat(path.Join(repo_root, p, "objects")); err != nil {
		log.Print(err)
		return false
	}
	return true
}

func do_auth_request(r *http.Request) (result *http.Response, err error) {
	url := fmt.Sprintf("%s%s", *auth_backend, r.URL.RequestURI())
	auth_req, err := http.NewRequest(r.Method, url, nil)
	if err != nil {
		return nil, err
	}
	// Forward all headers from our client to the auth backend. This includes
	// HTTP Basic authentication credentials (the 'Authorization' header).
	for k, v := range r.Header {
		auth_req.Header[k] = v
	}
	return http_client.Do(auth_req)
}

func handle_get_info_refs(gl_id string, _ string, path string, w http.ResponseWriter, r *http.Request) {
	rpc := r.URL.Query().Get("service")
	if !(rpc == "git-upload-pack" || rpc == "git-receive-pack") {
		// The 'dumb' Git HTTP protocol is not supported
		http.Error(w, "Not Found", 404)
		return
	}

	// Prepare our Git subprocess
	cmd := exec.Command("git", sub_command(rpc), "--stateless-rpc", "--advertise-refs", path)
	set_cmd_env(cmd, gl_id)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail_500(w, err)
		return
	}
	defer stdout.Close()
	if err := cmd.Start(); err != nil {
		fail_500(w, err)
		return
	}
	defer cmd.Wait()

	// Start writing the response
	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-advertisement", rpc))
	header_no_cache(w)
	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just panic
	if err := pkt_line(w, fmt.Sprintf("# service=%s\n", rpc)); err != nil {
		panic(err)
	}
	if err := pkt_flush(w); err != nil {
		panic(err)
	}
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func sub_command(rpc string) string {
	return strings.TrimPrefix(rpc, "git-")
}

func set_cmd_env(cmd *exec.Cmd, gl_id string) {
	cmd.Env = []string{
		fmt.Sprintf("PATH=%s", os.Getenv("PATH")),
		fmt.Sprintf("GL_ID=%s", gl_id),
	}
}

func handle_post_rpc(gl_id string, rpc string, path string, w http.ResponseWriter, r *http.Request) {
	var body io.Reader
	var err error

	// The client request body may have been gzipped.
	if r.Header.Get("Content-Encoding") == "gzip" {
		body, err = gzip.NewReader(r.Body)
		if err != nil {
			fail_500(w, err)
			return
		}
	} else {
		body = r.Body
	}

	// Prepare our Git subprocess
	cmd := exec.Command("git", sub_command(rpc), "--stateless-rpc", path)
	set_cmd_env(cmd, gl_id)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail_500(w, err)
		return
	}
	defer stdout.Close()
	stdin, err := cmd.StdinPipe()
	if err != nil {
		fail_500(w, err)
		return
	}
	defer stdin.Close()
	if err := cmd.Start(); err != nil {
		fail_500(w, err)
		return
	}
	defer cmd.Wait()

	// Write the client request body to Git's standard input
	if _, err := io.Copy(stdin, body); err != nil {
		fail_500(w, err)
		return
	}
	stdin.Close()

	// Start writing the response
	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-result", rpc))
	header_no_cache(w)
	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just panic
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func pkt_line(w io.Writer, s string) error {
	_, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s)
	return err
}

func pkt_flush(w io.Writer) error {
	_, err := fmt.Fprint(w, "0000")
	return err
}

func fail_500(w http.ResponseWriter, err error) {
	http.Error(w, "Internal server error", 500)
	log.Print(err)
}

func header_no_cache(w http.ResponseWriter) {
	w.Header().Add("Cache-Control", "no-cache")
}
<commit_msg>Get rid of underscores<commit_after>/*
gitlab-git-http-server handles 'smart' Git HTTP requests for GitLab

This HTTP server can service 'git clone', 'git push' etc. commands
from Git clients that use the 'smart' Git HTTP protocol (git-upload-pack
and git-receive-pack). It is intended to be deployed behind NGINX
(for request routing and SSL termination) with access to a GitLab
backend (for authentication and authorization) and local disk access
to Git repositories managed by GitLab.

This HTTP server replaces gitlab-grack.
*/
package main

import (
	"compress/gzip"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"
	"path"
	"regexp"
	"strings"
)

type gitService struct {
	method     string
	regexp     *regexp.Regexp
	handleFunc func(string, string, string, http.ResponseWriter, *http.Request)
	rpc        string
}

var httpClient = &http.Client{}
var pathTraversal = regexp.MustCompile(`/../`)

// Command-line options
var repoRoot string
var listenAddr = flag.String("listenAddr", "localhost:8181", "Listen address for HTTP server")
var authBackend = flag.String("authBackend", "http://localhost:8080", "Authentication/authorization backend")

var gitServices = [...]gitService{
	gitService{"GET", regexp.MustCompile(`\A(/..*)/info/refs\z`), handleGetInfoRefs, ""},
	gitService{"POST", regexp.MustCompile(`\A(/..*)/git-upload-pack\z`), handlePostRPC, "git-upload-pack"},
	gitService{"POST", regexp.MustCompile(`\A(/..*)/git-receive-pack\z`), handlePostRPC, "git-receive-pack"},
}

func main() {
	// Parse the command-line
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "\n  %s [OPTIONS] REPO_ROOT\n\nOptions:\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()
	repoRoot = flag.Arg(0)
	if repoRoot == "" {
		flag.Usage()
		os.Exit(1)
	}
	log.Printf("repoRoot: %s", repoRoot)

	http.HandleFunc("/", gitHandler)
	log.Fatal(http.ListenAndServe(*listenAddr, nil))
}

func gitHandler(w http.ResponseWriter, r *http.Request) {
	var gl_id string
	var pathMatch []string
	var g gitService
	var foundService bool

	log.Print(r.Method, " ", r.URL)

	// Look for a matching Git service
	for _, g = range gitServices {
		pathMatch = g.regexp.FindStringSubmatch(r.URL.Path)
		if r.Method == g.method && pathMatch != nil {
			foundService = true
			break
		}
	}
	if !foundService {
		http.Error(w, "Not Found", 404)
		return
	}

	// Ask the auth backend if the request is allowed, and what the
	// user ID (GL_ID) is.
	authResponse, err := doAuthRequest(r)
	if err != nil {
		fail500(w, err)
		return
	}
	if authResponse.StatusCode != 200 {
		// The Git request is not allowed by the backend. Maybe the
		// client needs to send HTTP Basic credentials.  Forward the
		// response from the auth backend to our client. This includes
		// the 'WWW-Authentication' header that acts as a hint that
		// Basic auth credentials are needed.
		for k, v := range authResponse.Header {
			w.Header()[k] = v
		}
		w.WriteHeader(authResponse.StatusCode)
		io.Copy(w, authResponse.Body)
		return
	}

	// The auth backend validated the client request and told us who
	// the user is according to them (GL_ID). We must extract this
	// information from the auth response body.
	if _, err := fmt.Fscan(authResponse.Body, &gl_id); err != nil {
		fail500(w, err)
		return
	}

	// Validate the path to the Git repository
	foundPath := pathMatch[1]
	if !validPath(foundPath) {
		http.Error(w, "Not Found", 404)
		return
	}

	g.handleFunc(gl_id, g.rpc, path.Join(repoRoot, foundPath), w, r)
}

func validPath(p string) bool {
	if pathTraversal.MatchString(p) {
		log.Printf("path traversal detected in %s", p)
		return false
	}

	// If /path/to/foo.git/objects exists then let's assume it is a valid Git
	// repository.
	if _, err := os.Stat(path.Join(repoRoot, p, "objects")); err != nil {
		log.Print(err)
		return false
	}
	return true
}

func doAuthRequest(r *http.Request) (result *http.Response, err error) {
	url := fmt.Sprintf("%s%s", *authBackend, r.URL.RequestURI())
	authReq, err := http.NewRequest(r.Method, url, nil)
	if err != nil {
		return nil, err
	}
	// Forward all headers from our client to the auth backend. This includes
	// HTTP Basic authentication credentials (the 'Authorization' header).
	for k, v := range r.Header {
		authReq.Header[k] = v
	}
	return httpClient.Do(authReq)
}

func handleGetInfoRefs(gl_id string, _ string, path string, w http.ResponseWriter, r *http.Request) {
	rpc := r.URL.Query().Get("service")
	if !(rpc == "git-upload-pack" || rpc == "git-receive-pack") {
		// The 'dumb' Git HTTP protocol is not supported
		http.Error(w, "Not Found", 404)
		return
	}

	// Prepare our Git subprocess
	cmd := exec.Command("git", subCommand(rpc), "--stateless-rpc", "--advertise-refs", path)
	setCmdEnv(cmd, gl_id)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdout.Close()
	if err := cmd.Start(); err != nil {
		fail500(w, err)
		return
	}
	defer cmd.Wait()

	// Start writing the response
	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-advertisement", rpc))
	setHeaderNoCache(w)
	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just panic
	if err := pktLine(w, fmt.Sprintf("# service=%s\n", rpc)); err != nil {
		panic(err)
	}
	if err := pktFlush(w); err != nil {
		panic(err)
	}
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func subCommand(rpc string) string {
	return strings.TrimPrefix(rpc, "git-")
}

func setCmdEnv(cmd *exec.Cmd, gl_id string) {
	cmd.Env = []string{
		fmt.Sprintf("PATH=%s", os.Getenv("PATH")),
		fmt.Sprintf("GL_ID=%s", gl_id),
	}
}

func handlePostRPC(gl_id string, rpc string, path string, w http.ResponseWriter, r *http.Request) {
	var body io.Reader
	var err error

	// The client request body may have been gzipped.
	if r.Header.Get("Content-Encoding") == "gzip" {
		body, err = gzip.NewReader(r.Body)
		if err != nil {
			fail500(w, err)
			return
		}
	} else {
		body = r.Body
	}

	// Prepare our Git subprocess
	cmd := exec.Command("git", subCommand(rpc), "--stateless-rpc", path)
	setCmdEnv(cmd, gl_id)
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdout.Close()
	stdin, err := cmd.StdinPipe()
	if err != nil {
		fail500(w, err)
		return
	}
	defer stdin.Close()
	if err := cmd.Start(); err != nil {
		fail500(w, err)
		return
	}
	defer cmd.Wait()

	// Write the client request body to Git's standard input
	if _, err := io.Copy(stdin, body); err != nil {
		fail500(w, err)
		return
	}
	stdin.Close()

	// Start writing the response
	w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-result", rpc))
	setHeaderNoCache(w)
	w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just panic
	if _, err := io.Copy(w, stdout); err != nil {
		panic(err)
	}
	if err := cmd.Wait(); err != nil {
		panic(err)
	}
}

func pktLine(w io.Writer, s string) error {
	_, err := fmt.Fprintf(w, "%04x%s", len(s)+4, s)
	return err
}

func pktFlush(w io.Writer) error {
	_, err := fmt.Fprint(w, "0000")
	return err
}

func fail500(w http.ResponseWriter, err error) {
	http.Error(w, "Internal server error", 500)
	log.Print(err)
}

func setHeaderNoCache(w http.ResponseWriter) {
	w.Header().Add("Cache-Control", "no-cache")
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path"
	"strings"
)

var usage = `Usage: %s githubname backupdir

githubname  github user or organization name to get the repositories from
backupdir   directory path to save the repositories to`

type Repo struct {
	Name   string
	GitUrl string `json:"git_url"`
}

var maxWorkers = 10
var githubApi = "https://api.github.com"

func main() {
	name, backupDir := parseArgs()

	category := getCategory(name)
	repos := getRepos(setMaxPageSize(strings.Join([]string{githubApi, category, name, "repos"}, "/")))

	fmt.Println("Backup for", category[:len(category)-1], name, "with", len(repos), "repositories")

	jobs := make(chan Repo)
	for w := 0; w < maxWorkers; w++ {
		go func() {
			for repo := range jobs {
				updateRepo(backupDir, repo)
			}
		}()
	}
	for _, repo := range repos {
		jobs <- repo
	}
}

// Get the two positional arguments githubname and backupdir
func parseArgs() (string, string) {
	flag.Parse()
	args := flag.Args()
	if len(args) != 2 {
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		os.Exit(1)
	}
	return args[0], args[1]
}

// Returns "users" or "orgs" depending on type of account
func getCategory(name string) string {
	r, err := http.Get(strings.Join([]string{githubApi, "users", name}, "/"))
	if err != nil {
		panic(err)
	}
	defer r.Body.Close()
	if r.StatusCode >= 300 {
		panic(fmt.Sprint("Request to ", r.Request.URL, " with bad status code ", r.StatusCode))
	}

	var account struct {
		Type string
	}
	json.NewDecoder(r.Body).Decode(&account)

	if account.Type == "User" {
		return "users"
	}
	if account.Type == "Organization" {
		return "orgs"
	}
	panic(fmt.Sprint("Unknown type of account ", account.Type, " for name ", name))
}

// Get repositories from Github.
// Follow "next" links recursivly.
func getRepos(u string) []Repo {
	r, err := http.Get(u)
	if err != nil {
		panic(err)
	}
	defer r.Body.Close()

	if r.StatusCode >= 300 {
		panic(fmt.Sprint("Request to ", u, " with bad status code ", r.StatusCode))
	}

	var repos []Repo
	json.NewDecoder(r.Body).Decode(&repos)

	linkHeader := r.Header["Link"]
	if len(linkHeader) > 0 {
		firstLink := strings.Split(linkHeader[0], ",")[0]
		if strings.Contains(firstLink, "rel=\"next\"") {
			urlInBrackets := strings.Split(firstLink, ";")[0]
			return append(repos, getRepos(urlInBrackets[1:len(urlInBrackets)-1])...)
		}
	}

	return repos
}

func setMaxPageSize(rawUrl string) string {
	u, err := url.Parse(rawUrl)
	if err != nil {
		panic(err)
	}
	q := u.Query()
	q.Set("per_page", "100")
	u.RawQuery = q.Encode()
	return u.String()
}

// Clone new repo or pull in existing repo
func updateRepo(backupDir string, repo Repo) {
	repoDir := path.Join(backupDir, repo.Name)

	var cmd *exec.Cmd
	if exists(repoDir) {
		defer fmt.Println("Updated repository:", repo.Name)

		cmd = exec.Command("git", "pull")
		cmd.Dir = repoDir
	} else {
		defer fmt.Println("Cloned  repository:", repo.Name)

		cmd = exec.Command("git", "clone", repo.GitUrl, repoDir)
	}

	err := cmd.Run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
}

// Check if a file or directory exists
func exists(path string) bool {
	_, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		} else {
			panic(err)
		}
	}
	return true
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
<commit_msg>Single worker when too little repos For some reason the goroutines exit without ever working if there are too little jobs.<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path"
	"strings"
)

var usage = `Usage: %s githubname backupdir

githubname  github user or organization name to get the repositories from
backupdir   directory path to save the repositories to`

type Repo struct {
	Name   string
	GitUrl string `json:"git_url"`
}

var maxWorkers = 10
var githubApi = "https://api.github.com"

func main() {
	name, backupDir := parseArgs()

	category := getCategory(name)
	repos := getRepos(setMaxPageSize(strings.Join([]string{githubApi, category, name, "repos"}, "/")))

	fmt.Println("Backup for", category[:len(category)-1], name, "with", len(repos), "repositories")

	jobs := make(chan Repo)
	workers := maxWorkers
	if len(repos) < maxWorkers {
		workers = 1
	}
	for w := 0; w < workers; w++ {
		go func() {
			for repo := range jobs {
				updateRepo(backupDir, repo)
			}
		}()
	}
	for _, repo := range repos {
		jobs <- repo
	}
}

// Get the two positional arguments githubname and backupdir
func parseArgs() (string, string) {
	flag.Parse()
	args := flag.Args()
	if len(args) != 2 {
		fmt.Fprintf(os.Stderr, usage, os.Args[0])
		os.Exit(1)
	}
	return args[0], args[1]
}

// Returns "users" or "orgs" depending on type of account
func getCategory(name string) string {
	r, err := http.Get(strings.Join([]string{githubApi, "users", name}, "/"))
	if err != nil {
		panic(err)
	}
	defer r.Body.Close()
	if r.StatusCode >= 300 {
		panic(fmt.Sprint("Request to ", r.Request.URL, " with bad status code ", r.StatusCode))
	}

	var account struct {
		Type string
	}
	json.NewDecoder(r.Body).Decode(&account)

	if account.Type == "User" {
		return "users"
	}
	if account.Type == "Organization" {
		return "orgs"
	}
	panic(fmt.Sprint("Unknown type of account ", account.Type, " for name ", name))
}

// Get repositories from Github.
// Follow "next" links recursivly.
func getRepos(u string) []Repo {
	r, err := http.Get(u)
	if err != nil {
		panic(err)
	}
	defer r.Body.Close()

	if r.StatusCode >= 300 {
		panic(fmt.Sprint("Request to ", u, " with bad status code ", r.StatusCode))
	}

	var repos []Repo
	json.NewDecoder(r.Body).Decode(&repos)

	linkHeader := r.Header["Link"]
	if len(linkHeader) > 0 {
		firstLink := strings.Split(linkHeader[0], ",")[0]
		if strings.Contains(firstLink, "rel=\"next\"") {
			urlInBrackets := strings.Split(firstLink, ";")[0]
			return append(repos, getRepos(urlInBrackets[1:len(urlInBrackets)-1])...)
		}
	}

	return repos
}

func setMaxPageSize(rawUrl string) string {
	u, err := url.Parse(rawUrl)
	if err != nil {
		panic(err)
	}
	q := u.Query()
	q.Set("per_page", "100")
	u.RawQuery = q.Encode()
	return u.String()
}

// Clone new repo or pull in existing repo
func updateRepo(backupDir string, repo Repo) {
	repoDir := path.Join(backupDir, repo.Name)

	var cmd *exec.Cmd
	if exists(repoDir) {
		defer fmt.Println("Updated repository:", repo.Name)

		cmd = exec.Command("git", "pull")
		cmd.Dir = repoDir
	} else {
		defer fmt.Println("Cloned  repository:", repo.Name)

		cmd = exec.Command("git", "clone", repo.GitUrl, repoDir)
	}

	err := cmd.Run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
	}
}

// Check if a file or directory exists
func exists(path string) bool {
	_, err := os.Stat(path)
	if err != nil {
		if os.IsNotExist(err) {
			return false
		} else {
			panic(err)
		}
	}
	return true
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"os"
	"sort"
	"strings"

	"github.com/ryanuber/columnize"
	"github.com/tylerfowle/dtags/db"
)

var database *db.Database

func main() {
	var err error

	database, err = db.Init()
	if err != nil {
		panic(err)
	}

	defer database.Instance.Close()

	cmd := os.Args[1]
	args := os.Args[2:]

	switch cmd {
	case "add":
		addNewTag(args)
		break
	case "del":
		database.DeleteKey(strings.ToLower(args[0]))
		break
	case "list", "completion":
		printAllTags()
		break
	case "ls":
		printBoth()
		break
	default:
		args := os.Args[1:]
		printPath(args)
	}
}

func addNewTag(args []string) {
	k := strings.ToLower(args[0])
	v := database.CurrentDirectory

	if len(args[0:]) > 1 {
		v = args[1]
	}

	if database.Exists(k) {
		fmt.Printf("Overwrite existing tag? [%s] (y/n)", k)
		if confirmation() == false {
			return
		}
	}

	database.AddKey(k, v)
}

func printAllTags() {
	for _, tag := range database.GetTags() {
		fmt.Println(tag)
	}
}

func printBoth() {
	var unformattedlist []string
	for tag, path := range database.All() {
		unformattedlist = append(unformattedlist, fmt.Sprintf("%s|%s\n", tag, path))
	}
	sort.Strings(unformattedlist)
	formattedList := columnize.SimpleFormat(unformattedlist)
	fmt.Println(formattedList)
}

func printPath(args []string) {
	cwd := database.GetValue(args[0])
	if cwd == "" {
		fmt.Printf("tag not found\n")
		os.Exit(1)
	}

	fmt.Fprint(os.Stdout, cwd)
	os.Exit(1)
}

func confirmation() bool {
	var response string

	_, err := fmt.Scanln(&response)
	if err != nil {
		log.Fatal(err)
	}
	y := []string{"y", "yes"}
	n := []string{"n", "no"}

	response = strings.TrimSpace(response)
	response = strings.ToLower(response)

	if containsString(y, response) {
		return true
	} else if containsString(n, response) {
		return false
	} else {
		fmt.Println("yes or no required:")
		return confirmation()
	}
}

func posString(slice []string, element string) int {
	for index, elem := range slice {
		if elem == element {
			return index
		}
	}
	return -1
}

// containsString returns true iff slice contains element
func containsString(slice []string, element string) bool {
	return !(posString(slice, element) == -1)
}
<commit_msg>remove confirmation containsString, add printed logs<commit_after>package main

import (
	"fmt"
	"log"
	"os"
	"sort"
	"strings"

	"github.com/ryanuber/columnize"
	"github.com/tylerfowle/dtags/db"
)

var database *db.Database

func main() {
	var err error

	database, err = db.Init()
	if err != nil {
		panic(err)
	}

	defer database.Instance.Close()

	cmd := os.Args[1]
	args := os.Args[2:]

	switch cmd {
	case "add":
		addNewTag(args)
		break
	case "del":
		if err := database.DeleteKey(strings.ToLower(args[0])); err != nil {
			fmt.Println("Failed.")
		} else {
			fmt.Printf("Successfully deleted tag [%s]\n", args[0])
		}
		break
	case "list", "completion":
		printAllTags()
		break
	case "ls":
		printBoth()
		break
	default:
		args := os.Args[1:]
		printPath(args)
	}
}

func addNewTag(args []string) {
	k := strings.ToLower(args[0])
	v := database.CurrentDirectory

	if len(args[0:]) > 1 {
		v = args[1]
	}

	if database.Exists(k) {
		fmt.Printf("Overwrite existing tag? [%s] (y/n)", k)
		if confirmation() == false {
			return
		}
	}

	if err := database.AddKey(k, v); err != nil {
		fmt.Printf("failed\n")
	} else {
		fmt.Printf("Successfully added tag [%s] to path [%s]\n", k, v)
	}

}

func printAllTags() {
	for _, tag := range database.GetTags() {
		fmt.Println(tag)
	}
}

func printBoth() {
	var unformattedlist []string
	for tag, path := range database.All() {
		unformattedlist = append(unformattedlist, fmt.Sprintf("%s|%s\n", tag, path))
	}
	sort.Strings(unformattedlist)
	formattedList := columnize.SimpleFormat(unformattedlist)
	fmt.Println(formattedList)
}

func printPath(args []string) {
	cwd := database.GetValue(args[0])
	if cwd == "" {
		fmt.Println("")
		os.Exit(1)
	}

	fmt.Fprint(os.Stdout, cwd)
	os.Exit(1)
}

func confirmation() bool {
	var response string

	_, err := fmt.Scanln(&response)
	if err != nil {
		log.Fatal(err)
	}

	response = strings.ToLower(strings.TrimSpace(response))

	switch response {
	case "y", "yes":
		fmt.Printf("Overwriting tag [%s]\n", os.Args[1])
		return true
	case "n", "no":
		fmt.Println("Overwrite cancelled.")
		return false
	default:
		fmt.Println("(yes/no) required:")
		return confirmation()
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/ikawaha/kagome/v2/cmd/lattice"
	"github.com/ikawaha/kagome/v2/cmd/server"
	"github.com/ikawaha/kagome/v2/cmd/tokenize"
)

type subcommand struct {
	Name          string
	Description   string
	Run           func([]string) error
	Usage         func()
	OptionCheck   func([]string) error
	PrintDefaults func(flag.ErrorHandling)
}

var subcommands = []subcommand{
	{
		Name:          tokenize.CommandName,
		Description:   tokenize.Description,
		Run:           tokenize.Run,
		Usage:         tokenize.Usage,
		OptionCheck:   tokenize.OptionCheck,
		PrintDefaults: tokenize.PrintDefaults,
	},
	{
		Name:          server.CommandName,
		Description:   server.Description,
		Run:           server.Run,
		Usage:         server.Usage,
		OptionCheck:   server.OptionCheck,
		PrintDefaults: server.PrintDefaults,
	},
	{
		Name:          lattice.CommandName,
		Description:   lattice.Description,
		Run:           lattice.Run,
		Usage:         lattice.Usage,
		OptionCheck:   lattice.OptionCheck,
		PrintDefaults: lattice.PrintDefaults,
	},
	{
		Name:        "version",
		Description: "show version",
		Run: func([]string) error {
			fmt.Fprintf(os.Stderr, "%s\n", version)
			return nil
		},
		Usage:         func() {},
		OptionCheck:   func([]string) error { return nil },
		PrintDefaults: func(flag.ErrorHandling) {},
	},
}

var (
	// version is the app version.
	version = `!!version undefined!!
This must be specified by -X option during the go build. Such like:
	$ go build --ldflags "-X 'main.version=$(git describe --tag)'"`

	errorWriter       = os.Stderr
	defaultSubcommand = subcommands[0]
)

// Usage prints to stdout information about the tool
func Usage() {
	fmt.Fprintf(errorWriter, "Japanese Morphological Analyzer -- github.com/ikawaha/kagome/v2\n")
	fmt.Fprintf(errorWriter, "usage: %s <command>\n", filepath.Base(os.Args[0]))
}

// PrintDefaults prints out the default flags
func PrintDefaults() {
	fmt.Fprintln(errorWriter, "The commands are:")
	for _, c := range subcommands {
		if c.Name == defaultSubcommand.Name {
			fmt.Fprintf(errorWriter, "   [%s] - %s (*default)\n", c.Name, c.Description)
		} else {
			fmt.Fprintf(errorWriter, "   %s - %s\n", c.Name, c.Description)
		}
	}
}

func main() {
	var (
		cmd     func([]string) error
		options []string
	)
	if len(os.Args) >= 2 {
		options = os.Args[2:]
		for i := range subcommands {
			if os.Args[1] == subcommands[i].Name {
				cmd = subcommands[i].Run
			}
		}
	}
	if cmd == nil {
		options = os.Args[1:]
		if err := defaultSubcommand.OptionCheck(options); err != nil {
			Usage()
			PrintDefaults()
			fmt.Fprintln(errorWriter)
			defaultSubcommand.Usage()
			defaultSubcommand.PrintDefaults(flag.ExitOnError)
			os.Exit(1)
		}
		cmd = defaultSubcommand.Run
	}
	if err := cmd(options); err != nil {
		fmt.Fprintf(errorWriter, "%v\n", err)
		os.Exit(1)
	}
}
<commit_msg>Fix the way of the version display<commit_after>package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"runtime/debug"
	"strings"

	"github.com/ikawaha/kagome/v2/cmd/lattice"
	"github.com/ikawaha/kagome/v2/cmd/server"
	"github.com/ikawaha/kagome/v2/cmd/tokenize"
)

type subcommand struct {
	Name          string
	Description   string
	Run           func([]string) error
	Usage         func()
	OptionCheck   func([]string) error
	PrintDefaults func(flag.ErrorHandling)
}

var (
	version     string // eg. go build --ldflags "-X 'main.version=$(git describe --tag)'"
	errorWriter = os.Stderr
	subcommands = []subcommand{
		{
			Name:          tokenize.CommandName,
			Description:   tokenize.Description,
			Run:           tokenize.Run,
			Usage:         tokenize.Usage,
			OptionCheck:   tokenize.OptionCheck,
			PrintDefaults: tokenize.PrintDefaults,
		},
		{
			Name:          server.CommandName,
			Description:   server.Description,
			Run:           server.Run,
			Usage:         server.Usage,
			OptionCheck:   server.OptionCheck,
			PrintDefaults: server.PrintDefaults,
		},
		{
			Name:          lattice.CommandName,
			Description:   lattice.Description,
			Run:           lattice.Run,
			Usage:         lattice.Usage,
			OptionCheck:   lattice.OptionCheck,
			PrintDefaults: lattice.PrintDefaults,
		},
		{
			Name:        "version",
			Description: "show version",
			Run: func([]string) error {
				ShowVersion()
				return nil
			},
			Usage:         func() {},
			OptionCheck:   func([]string) error { return nil },
			PrintDefaults: func(flag.ErrorHandling) {},
		},
	}
	defaultSubcommand = subcommands[0]
)

// Usage prints information about the tool
func Usage() {
	fmt.Fprintf(errorWriter, "Japanese Morphological Analyzer -- github.com/ikawaha/kagome/v2\n")
	fmt.Fprintf(errorWriter, "usage: %s <command>\n", filepath.Base(os.Args[0]))
}

// ShowVersion prints the version about the tool.
func ShowVersion() {
	info, ok := debug.ReadBuildInfo()
	if version != "" {
		fmt.Fprintln(errorWriter, version)
	} else {
		fmt.Fprintln(errorWriter, info.Main.Version)
	}
	if !ok {
		return
	}
	const prefix = "github.com/ikawaha/kagome-dict/"
	for _, v := range info.Deps {
		if strings.HasPrefix(v.Path, prefix) {
			fmt.Fprintln(errorWriter, "  ", v.Path[len(prefix):], v.Version)
		}
	}
}

// PrintDefaults prints out the default flags
func PrintDefaults() {
	fmt.Fprintln(errorWriter, "The commands are:")
	for _, c := range subcommands {
		if c.Name == defaultSubcommand.Name {
			fmt.Fprintf(errorWriter, "   [%s] - %s (*default)\n", c.Name, c.Description)
		} else {
			fmt.Fprintf(errorWriter, "   %s - %s\n", c.Name, c.Description)
		}
	}
}

func main() {
	var (
		cmd     func([]string) error
		options []string
	)
	if len(os.Args) >= 2 {
		options = os.Args[2:]
		for i := range subcommands {
			if os.Args[1] == subcommands[i].Name {
				cmd = subcommands[i].Run
			}
		}
	}
	if cmd == nil {
		options = os.Args[1:]
		if err := defaultSubcommand.OptionCheck(options); err != nil {
			Usage()
			PrintDefaults()
			fmt.Fprintln(errorWriter)
			defaultSubcommand.Usage()
			defaultSubcommand.PrintDefaults(flag.ExitOnError)
			os.Exit(1)
		}
		cmd = defaultSubcommand.Run
	}
	if err := cmd(options); err != nil {
		fmt.Fprintf(errorWriter, "%v\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"time"

	"github.com/bwmarrin/discordgo"
	"github.com/nhooyr/color/log"
)

const (
	email   = "anmol@aubble.com"
	pass    = "566348aA"
	guild   = "ezekiel"
	channel = "izi"
	message = "_"
)

func main() {
	s, err := discordgo.New(email, pass)
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("logged in")
	g := findGuild(s)
	if g == nil {
		log.Fatalln("could not find guild")
	}
	id := findChannel(s, g)
	if id == "" {
		log.Fatalln("could not find channel")
	}
	sendLoop(s, id)
}

func findGuild(s *discordgo.Session) *discordgo.Guild {
	gs, err := s.UserGuilds()
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("got guilds")
	for _, g := range gs {
		if g.Name == guild {
			log.Println("found guild")
			return g
		}
	}
	return nil
}

func findChannel(s *discordgo.Session, g *discordgo.Guild) string {
	chs, err := s.GuildChannels(g.ID)
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("got channels")
	for _, ch := range chs {
		if ch.Name == channel {
			log.Println("found channel")
			return ch.ID
		}
	}
	return ""
}

func sendLoop(s *discordgo.Session, id string) {
	for t := time.Tick(time.Minute); ; <-t {
		_, err := s.ChannelMessageSend(id, message)
		if err != nil {
			log.Println(err)
			continue
		}
		log.Println("sent message")
	}
}
<commit_msg>added flags<commit_after>package main

import (
	"flag"
	"time"

	"github.com/bwmarrin/discordgo"
	"github.com/nhooyr/color/log"
)

var (
	email    = flag.String("email", "", "account email")
	pass     = flag.String("pass", "", "account password")
	guild    = flag.String("guild", "", "account guild")
	channel  = flag.String("chan", "", "guild channel")
	message  = flag.String("msg", "_", "message to be sent")
	interval = flag.Int64("int", 1, "interval between messages in minutes")
)

func main() {
	flag.Parse()
	if *email == "" || *pass == "" {
		log.Fatalln("please provide an email and password")
	}
	s, err := discordgo.New(*email, *pass)
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("logged in")
	g := findGuild(s)
	if g == nil {
		log.Fatalln("could not find guild")
	}
	id := findChannel(s, g)
	if id == "" {
		log.Fatalln("could not find channel")
	}
	sendLoop(s, id)
}

func findGuild(s *discordgo.Session) *discordgo.Guild {
	gs, err := s.UserGuilds()
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("got guilds")
	for _, g := range gs {
		if g.Name == *guild {
			log.Println("found guild")
			return g
		}
	}
	return nil
}

func findChannel(s *discordgo.Session, g *discordgo.Guild) string {
	chs, err := s.GuildChannels(g.ID)
	if err != nil {
		log.Fatalln(err)
	}
	log.Println("got channels")
	for _, ch := range chs {
		if ch.Name == *channel {
			log.Println("found channel")
			return ch.ID
		}
	}
	return ""
}

func sendLoop(s *discordgo.Session, id string) {
	for t := time.Tick(time.Minute*time.Duration(*interval)); ; <-t {
		_, err := s.ChannelMessageSend(id, *message)
		if err != nil {
			log.Println(err)
			continue
		}
		log.Println("sent message")
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"net/http"
	"regexp"
)

func main() {
	resp, _ := http.Get("http://hichannel.hinet.net/radio/mobile/index.do?id=232")
	defer resp.Body.Close()
	html := new(bytes.Buffer)
	html.ReadFrom(resp.Body)
	fmt.Println(html.String())
	reg := regexp.MustCompile(`var url = '([\S]+)'`)
	bb := reg.FindAllStringSubmatch(html.String(), -1)
	fmt.Println(bb[0][1])

}
<commit_msg>Add replace.<commit_after>package main

import (
	"bytes"
	"fmt"
	"net/http"
	"regexp"
)

func main() {
	resp, _ := http.Get("http://hichannel.hinet.net/radio/mobile/index.do?id=232")
	defer resp.Body.Close()
	html := new(bytes.Buffer)
	html.ReadFrom(resp.Body)
	//fmt.Println(html.String())
	reg := regexp.MustCompile(`var url = '([\S]+)'`)
	url_string := reg.FindAllStringSubmatch(html.String(), -1)
	//fmt.Println(url_string[0][1])

	replace := regexp.MustCompile(`\\\/`)
	replace_string := replace.ReplaceAllString(url_string[0][1], `/`)
	fmt.Println(replace_string)

}
<|endoftext|>


<commit_before>package main

import (
	"os"
	"os/signal"
	"sync"
	"time"

	"github.com/andreas-schroeder/kafka-health-check/check"
)

func main() {
	healthCheck := check.New(checkConfiguration)
	healthCheck.ParseCommandLineArguments()
	updateChannel := healthCheck.ServeBrokerHealth()

	stop, awaitCheck := addShutdownHook()
	healthCheck.CheckHealth(updateChannel, stop)
	awaitCheck.Done()
}

func addShutdownHook() (chan struct{}, sync.WaitGroup) {
	stop := make(chan struct{})
	awaitCheck := sync.WaitGroup{}
	awaitCheck.Add(1)

	interrupts := make(chan os.Signal, 1)
	signal.Notify(interrupts, os.Interrupt)
	go func() {
		for _ = range interrupts {
			close(stop)
			awaitCheck.Wait()
		}
	}()

	return stop, awaitCheck
}

var checkConfiguration = check.HealthCheckConfig{
	MessageLength:    20,
	CheckTimeout:     100 * time.Millisecond,
	DataWaitInterval: 20 * time.Millisecond,
}
<commit_msg>executing shutdown hook also on SIGKILL and SIGTERM.<commit_after>package main

import (
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"

	"github.com/andreas-schroeder/kafka-health-check/check"
)

func main() {
	healthCheck := check.New(checkConfiguration)
	healthCheck.ParseCommandLineArguments()
	updateChannel := healthCheck.ServeBrokerHealth()

	stop, awaitCheck := addShutdownHook()
	healthCheck.CheckHealth(updateChannel, stop)
	awaitCheck.Done()
}

func addShutdownHook() (chan struct{}, sync.WaitGroup) {
	stop := make(chan struct{})
	awaitCheck := sync.WaitGroup{}
	awaitCheck.Add(1)

	shutdown := make(chan os.Signal, 1)
	signal.Notify(shutdown, os.Interrupt)
	signal.Notify(shutdown, os.Kill)
	signal.Notify(shutdown, syscall.SIGTERM)
	go func() {
		for _ = range shutdown {
			close(stop)
			awaitCheck.Wait()
		}
	}()

	return stop, awaitCheck
}

var checkConfiguration = check.HealthCheckConfig{
	MessageLength:    20,
	CheckTimeout:     100 * time.Millisecond,
	DataWaitInterval: 20 * time.Millisecond,
}
<|endoftext|>


<commit_before>package main

import (
	"plugin"
	"os"
	"path/filepath"
	log "github.com/Sirupsen/logrus"
	"path"
	"github.com/patrobinson/go-fish/input"
	"github.com/patrobinson/go-fish/output"
	"sync"
)

type Rule interface {
	Start(*chan interface{}, *chan interface{}, *sync.WaitGroup)
	Process(interface{}) bool
	String() string
}

type Input interface {
	Retrieve(*chan []byte)
}

type Output interface {
	Sink(*chan interface{}, *sync.WaitGroup)
}

func main() {
	rule_folder := os.Args[1]
	event_type_folder := os.Args[2]
	inFile := os.Args[3]
	outFile := os.Args[4]
	in := input.FileInput{FileName: inFile}
	out := output.FileOutput{FileName: outFile}

	run(rule_folder, event_type_folder, in, out)
}

func run(rules_folder string, event_folder string, in interface{}, out interface{}) {
	log.SetLevel(log.DebugLevel)

	var outWg sync.WaitGroup
	var ruleWg sync.WaitGroup

	outChan := startOutput(out, &outWg)
	rChans := startRules(rules_folder, outChan, &ruleWg)
	inChan := startInput(in)
	eventTypes, err := getEventTypes(event_folder)
	if err != nil {
		log.Fatalf("Failed to get Event plugins: %v", err)
	}

	// receive from inputs and send to all rules
	func(iChan *chan []byte, ruleChans []*chan interface{}) {
		for data := range *iChan {
			evt, err := matchEventType(eventTypes, data)
			if err != nil {
				log.Infof("Error matching event: %v", err)
			}
			for _, i := range ruleChans {
				*i <- evt
			}
		}
	}(inChan, rChans)

	log.Debug("Input done, closing rule channels\n")

	for _, c := range rChans {
		close(*c)
	}
	ruleWg.Wait()

	log.Debug("Closing output channels\n")
	close(*outChan)
	outWg.Wait()
}

func startOutput(out interface{}, wg *sync.WaitGroup) *chan interface{} {
	(*wg).Add(1)
	outChan := make(chan interface{})
	outSender := out.(Output)
	go outSender.Sink(&outChan, wg)
	return &outChan
}

func startInput(in interface{}) *chan []byte {
	inChan := make(chan []byte)
	inReceiver := in.(Input)
	go inReceiver.Retrieve(&inChan)
	return &inChan
}

func startRules(rules_folder string, output *chan interface{}, wg *sync.WaitGroup) []*chan interface{} {
	plugin_glob := path.Join(rules_folder, "/*.so")
	plugins, err := filepath.Glob(plugin_glob)
	if err != nil {
		log.Fatal(err)
	}

	var rules []*plugin.Plugin
	for _, p_file := range plugins {
		if plug, err := plugin.Open(p_file); err == nil {
			rules = append(rules, plug)
		}
	}

	log.Infof("Found %v rules", len(rules))

	var inputs []*chan interface{}
	for _, r := range rules {
		symRule, err := r.Lookup("Rule")
		if err != nil {
			log.Errorf("Rule has no Rule symbol: %v", err)
			continue
		}
		var rule Rule
		rule, ok := symRule.(Rule)
		if !ok {
			log.Errorf("Rule is not a rule type. Does it implement the Process() function?")
			continue
		}
		input := make(chan interface{})
		inputs = append(inputs, &input)
		log.Debugf("Starting %v\n", rule.String())
		(*wg).Add(1)
		go rule.Start(&input, output, wg)
	}

	return inputs
}
<commit_msg>Style fixes<commit_after>package main

import (
	"os"
	"path"
	"path/filepath"
	"plugin"
	"sync"

	log "github.com/Sirupsen/logrus"
	"github.com/patrobinson/go-fish/input"
	"github.com/patrobinson/go-fish/output"
)

// Rule is an interface for rule implementations
type Rule interface {
	Start(*chan interface{}, *chan interface{}, *sync.WaitGroup)
	Process(interface{}) bool
	String() string
}

// Input is an interface for input implemenations
type Input interface {
	Retrieve(*chan []byte)
}

// Output is an interface for output implementations
type Output interface {
	Sink(*chan interface{}, *sync.WaitGroup)
}

func main() {
	ruleFolder := os.Args[1]
	eventTypeFolder := os.Args[2]
	inFile := os.Args[3]
	outFile := os.Args[4]
	in := input.FileInput{FileName: inFile}
	out := output.FileOutput{FileName: outFile}

	run(ruleFolder, eventTypeFolder, in, out)
}

func run(rulesFolder string, eventFolder string, in interface{}, out interface{}) {
	log.SetLevel(log.DebugLevel)

	var outWg sync.WaitGroup
	var ruleWg sync.WaitGroup

	outChan := startOutput(out, &outWg)
	rChans := startRules(rulesFolder, outChan, &ruleWg)
	inChan := startInput(in)
	eventTypes, err := getEventTypes(eventFolder)
	if err != nil {
		log.Fatalf("Failed to get Event plugins: %v", err)
	}

	// receive from inputs and send to all rules
	func(iChan *chan []byte, ruleChans []*chan interface{}) {
		for data := range *iChan {
			evt, err := matchEventType(eventTypes, data)
			if err != nil {
				log.Infof("Error matching event: %v", err)
			}
			for _, i := range ruleChans {
				*i <- evt
			}
		}
	}(inChan, rChans)

	log.Debug("Input done, closing rule channels\n")

	for _, c := range rChans {
		close(*c)
	}
	ruleWg.Wait()

	log.Debug("Closing output channels\n")
	close(*outChan)
	outWg.Wait()
}

func startOutput(out interface{}, wg *sync.WaitGroup) *chan interface{} {
	(*wg).Add(1)
	outChan := make(chan interface{})
	outSender := out.(Output)
	go outSender.Sink(&outChan, wg)
	return &outChan
}

func startInput(in interface{}) *chan []byte {
	inChan := make(chan []byte)
	inReceiver := in.(Input)
	go inReceiver.Retrieve(&inChan)
	return &inChan
}

func startRules(rulesFolder string, output *chan interface{}, wg *sync.WaitGroup) []*chan interface{} {
	pluginGlob := path.Join(rulesFolder, "/*.so")
	plugins, err := filepath.Glob(pluginGlob)
	if err != nil {
		log.Fatal(err)
	}

	var rules []*plugin.Plugin
	for _, pFile := range plugins {
		if plug, err := plugin.Open(pFile); err == nil {
			rules = append(rules, plug)
		}
	}

	log.Infof("Found %v rules", len(rules))

	var inputs []*chan interface{}
	for _, r := range rules {
		symRule, err := r.Lookup("Rule")
		if err != nil {
			log.Errorf("Rule has no Rule symbol: %v", err)
			continue
		}
		var rule Rule
		rule, ok := symRule.(Rule)
		if !ok {
			log.Errorf("Rule is not a rule type. Does it implement the Process() function?")
			continue
		}
		input := make(chan interface{})
		inputs = append(inputs, &input)
		log.Debugf("Starting %v\n", rule.String())
		(*wg).Add(1)
		go rule.Start(&input, output, wg)
	}

	return inputs
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/griesbacher/check_influxdb/mode"
	"github.com/griesbacher/check_x"
	"github.com/urfave/cli"
	"os"
	"time"
)

var (
	path        string
	address     string
	username    string
	password    string
	timeout     int
	warning     string
	critical    string
	filterRegex string
	timerange   int
	livestatus  string
	database    string
)

func startTimeout() {
	if timeout != 0 {
		check_x.StartTimeout(time.Duration(timeout) * time.Second)
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "check_influxdb"
	app.Usage = "Checks different influxdb stats\n   Copyright (c) 2016 Philip Griesbacher"
	app.Version = "0.0.3"
	flagAddress := cli.StringFlag{
		Name:        "address",
		Usage:       "InfluxDB address: Protocol + IP + Port",
		Destination: &address,
		Value:       "http://localhost:8086",
	}
	flagUsername := cli.StringFlag{
		Name:        "username",
		Destination: &username,
		Value:       "root",
	}
	flagPassword := cli.StringFlag{
		Name:        "password",
		Destination: &password,
		Value:       "root",
	}
	flagFilter := cli.StringFlag{
		Name:        "filter",
		Usage:       "regex to filter databases",
		Destination: &filterRegex,
	}
	app.Commands = []cli.Command{
		{
			Name:    "mode",
			Aliases: []string{"m"},
			Usage:   "check mode",
			Subcommands: []cli.Command{
				{
					Name:  "ping",
					Usage: "Tests if the influxdb is alive",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.Ping(address, username, password, warning, critical)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: request duration in ms",
							Destination: &warning,
							Value:       "200",
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: request duration in ms",
							Destination: &critical,
							Value:       "400",
						},
					},
				}, {
					Name:  "disk",
					Usage: "Checks the disk size per databases",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.Disk(path, warning, critical, filterRegex)
					},
					Flags: []cli.Flag{
						flagFilter,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: size in bytes",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: size in bytes",
							Destination: &critical,
						},
						cli.StringFlag{
							Name:        "path",
							Usage:       "path to the influxdb folder",
							Destination: &path,
							Value:       "/var/lib/influxdb",
						},
					},
				}, {
					Name:  "num_series",
					Usage: "The numbers of series/measurements",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.NumSeries(address, username, password, warning, critical, filterRegex)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						flagFilter,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: measurements,series (only measurements: 10, only series: ,10)",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: measurements,series (only measurements: 10, only series: ,10)",
							Destination: &critical,
						},
					},
				}, {
					Name:  "div_series",
					Usage: "The diverence of series/measurements between now and x minutes. If a livestatus address is given, the overall state will switch to Warning if a core restart happend and due to that the metric got into Critical.",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.DivSeries(address, username, password, warning, critical, filterRegex, livestatus, timerange)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						flagFilter,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: measurements,series (only measurements: 10, only series: ,10)",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: measurements,series (only measurements: 10, only series: ,10)",
							Destination: &critical,
						},
						cli.IntFlag{
							Name:        "m",
							Usage:       "amount of minutes to look back",
							Destination: &timerange,
							Value:       60,
						},
						cli.StringFlag{
							Name:        "l",
							Usage:       `livestatus address ("unix:/var/lib/nagios/rw/" or "tcp:localhost:6557")`,
							Destination: &livestatus,
						},
					},
				}, {
					Name:  "read_write",
					Usage: "Checks the bytes read and written the last x minutes",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.ReadWrite(address, username, password, warning, critical, timerange)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: read,write Bps (only read: 10, only write: ,10)",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: read,write Bps (only read: 10, only write: ,10)",
							Destination: &critical,
						},
						cli.IntFlag{
							Name:        "m",
							Usage:       "amount of minutes to look back",
							Destination: &timerange,
							Value:       1,
						},
					},
				}, {
					Name:  "memory",
					Usage: "RSS in Byte",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.Memory(address, username, password, warning, critical)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						flagFilter,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning in B",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical in B",
							Destination: &critical,
						},
					},
				}, {
					Name:  "old_series",
					Usage: "Returns a list of series older then x hours. This check makes only sense when the databases hast the tags: hostname and service - it's build for nagflux",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.OldSeries(address, database, username, password, warning, critical, timerange)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning in hours",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical in hours",
							Destination: &critical,
						},
						cli.StringFlag{
							Name:        "database",
							Usage:       "Database to use",
							Destination: &database,
							Value:       "nagflux",
						},
						cli.IntFlag{
							Name:        "d",
							Usage:       "amount of hours",
							Destination: &timerange,
							Value:       24,
						},
					},
				},
			},
		},
	}
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:        "t",
			Usage:       "Seconds till check returns unkown, 0 to disable",
			Value:       10,
			Destination: &timeout,
		},
	}

	if err := app.Run(os.Args); err != nil {
		check_x.ErrorExit(err)
	}
}
<commit_msg>reranged options<commit_after>package main

import (
	"github.com/griesbacher/check_influxdb/mode"
	"github.com/griesbacher/check_x"
	"github.com/urfave/cli"
	"os"
	"time"
)

var (
	path        string
	address     string
	username    string
	password    string
	timeout     int
	warning     string
	critical    string
	filterRegex string
	timerange   int
	livestatus  string
	database    string
)

func startTimeout() {
	if timeout != 0 {
		check_x.StartTimeout(time.Duration(timeout) * time.Second)
	}
}

func main() {
	app := cli.NewApp()
	app.Name = "check_influxdb"
	app.Usage = "Checks different influxdb stats\n   Copyright (c) 2016 Philip Griesbacher"
	app.Version = "0.0.3"
	flagAddress := cli.StringFlag{
		Name:        "address",
		Usage:       "InfluxDB address: Protocol + IP + Port",
		Destination: &address,
		Value:       "http://localhost:8086",
	}
	flagUsername := cli.StringFlag{
		Name:        "username",
		Destination: &username,
		Value:       "root",
	}
	flagPassword := cli.StringFlag{
		Name:        "password",
		Destination: &password,
		Value:       "root",
	}
	flagFilter := cli.StringFlag{
		Name:        "filter",
		Usage:       "regex to filter databases",
		Destination: &filterRegex,
	}
	app.Commands = []cli.Command{
		{
			Name:    "mode",
			Aliases: []string{"m"},
			Usage:   "check mode",
			Subcommands: []cli.Command{
				{
					Name:  "ping",
					Usage: "Tests if the influxdb is alive",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.Ping(address, username, password, warning, critical)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: request duration in ms",
							Destination: &warning,
							Value:       "200",
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: request duration in ms",
							Destination: &critical,
							Value:       "400",
						},
					},
				}, {
					Name:  "disk",
					Usage: "Checks the disk size per databases",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.Disk(path, warning, critical, filterRegex)
					},
					Flags: []cli.Flag{
						flagFilter,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: size in bytes",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: size in bytes",
							Destination: &critical,
						},
						cli.StringFlag{
							Name:        "path",
							Usage:       "path to the influxdb folder",
							Destination: &path,
							Value:       "/var/lib/influxdb",
						},
					},
				}, {
					Name:  "num_series",
					Usage: "The numbers of series/measurements",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.NumSeries(address, username, password, warning, critical, filterRegex)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						flagFilter,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: measurements,series (only measurements: 10, only series: ,10)",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: measurements,series (only measurements: 10, only series: ,10)",
							Destination: &critical,
						},
					},
				}, {
					Name:  "div_series",
					Usage: "The diverence of series/measurements between now and x minutes. If a livestatus address is given, the overall state will switch to Warning if a core restart happend and due to that the metric got into Critical.",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.DivSeries(address, username, password, warning, critical, filterRegex, livestatus, timerange)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						flagFilter,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: measurements,series (only measurements: 10, only series: ,10)",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: measurements,series (only measurements: 10, only series: ,10)",
							Destination: &critical,
						},
						cli.IntFlag{
							Name:        "m",
							Usage:       "amount of minutes to look back",
							Destination: &timerange,
							Value:       60,
						},
						cli.StringFlag{
							Name:        "l",
							Usage:       `livestatus address ("unix:/var/lib/nagios/rw/" or "tcp:localhost:6557")`,
							Destination: &livestatus,
						},
					},
				}, {
					Name:  "read_write",
					Usage: "Checks the bytes read and written the last x minutes",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.ReadWrite(address, username, password, warning, critical, timerange)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning: read,write Bps (only read: 10, only write: ,10)",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical: read,write Bps (only read: 10, only write: ,10)",
							Destination: &critical,
						},
						cli.IntFlag{
							Name:        "m",
							Usage:       "amount of minutes to look back",
							Destination: &timerange,
							Value:       1,
						},
					},
				}, {
					Name:  "memory",
					Usage: "RSS in Byte",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.Memory(address, username, password, warning, critical)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning in B",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical in B",
							Destination: &critical,
						},
					},
				}, {
					Name:  "old_series",
					Usage: "Returns a list of series older then x hours. This check makes only sense when the databases hast the tags: hostname and service - it's build for nagflux",
					Action: func(c *cli.Context) error {
						startTimeout()
						return mode.OldSeries(address, database, username, password, warning, critical, timerange)
					},
					Flags: []cli.Flag{
						flagAddress,
						flagUsername,
						flagPassword,
						cli.StringFlag{
							Name:        "database",
							Usage:       "Database to use",
							Destination: &database,
							Value:       "nagflux",
						},
						cli.IntFlag{
							Name:        "d",
							Usage:       "amount of hours",
							Destination: &timerange,
							Value:       24,
						},
						cli.StringFlag{
							Name:        "w",
							Usage:       "warning in hours",
							Destination: &warning,
						},
						cli.StringFlag{
							Name:        "c",
							Usage:       "critical in hours",
							Destination: &critical,
						},
					},
				},
			},
		},
	}
	app.Flags = []cli.Flag{
		cli.IntFlag{
			Name:        "t",
			Usage:       "Seconds till check returns unkown, 0 to disable",
			Value:       10,
			Destination: &timeout,
		},
	}

	if err := app.Run(os.Args); err != nil {
		check_x.ErrorExit(err)
	}
}
<|endoftext|>