<commit_before>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/rabbitmq/amqp091-go"
)

var (
	uri         = flag.String("uri", "amqp://guest:guest@localhost:5672/", "AMQP URI")
	insecureTLS = flag.Bool("insecure-tls", false, "Insecure TLS mode: don't check certificates")
	queue       = flag.String("queue", "", "AMQP queue name")
	ack         = flag.Bool("ack", false, "Acknowledge messages")
	maxMessages = flag.Uint("max-messages", 1000, "Maximum number of messages to dump")
	outputDir   = flag.String("output-dir", ".", "Directory in which to save the dumped messages")
	full        = flag.Bool("full", false, "Dump the message, its properties and headers")
	verbose     = flag.Bool("verbose", false, "Print progress")
)

func main() {
	flag.Parse()
	if flag.NArg() > 0 {
		fmt.Fprintf(os.Stderr, "Error: Unused command line arguments detected.\n")
		flag.Usage()
		os.Exit(2)
	}
	err := dumpMessagesFromQueue(*uri, *queue, *maxMessages, *outputDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}

func dial(amqpURI string) (*amqp091.Connection, error) {
	verboseLog(fmt.Sprintf("Dialing %q", amqpURI))
	if *insecureTLS && strings.HasPrefix(amqpURI, "amqps://") {
		tlsConfig := new(tls.Config)
		tlsConfig.InsecureSkipVerify = true
		conn, err := amqp091.DialTLS(amqpURI, tlsConfig)
		return conn, err
	}
	conn, err := amqp091.Dial(amqpURI)
	return conn, err
}

func dumpMessagesFromQueue(amqpURI string, queueName string, maxMessages uint, outputDir string) error {
	if queueName == "" {
		return fmt.Errorf("Must supply queue name")
	}

	conn, err := dial(amqpURI)
	if err != nil {
		return fmt.Errorf("Dial: %s", err)
	}

	defer func() {
		conn.Close()
		verboseLog("AMQP connection closed")
	}()

	channel, err := conn.Channel()
	if err != nil {
		return fmt.Errorf("Channel: %s", err)
	}

	verboseLog(fmt.Sprintf("Pulling messages from queue %q", queueName))
	for messagesReceived := uint(0); messagesReceived < maxMessages; messagesReceived++ {
		msg, ok, err := channel.Get(queueName,
			*ack, // autoAck
		)
		if err != nil {
			return fmt.Errorf("Queue get: %s", err)
		}

		if !ok {
			verboseLog("No more messages in queue")
			break
		}

		err = saveMessageToFile(msg.Body, outputDir, messagesReceived)
		if err != nil {
			return fmt.Errorf("Save message: %s", err)
		}

		if *full {
			err = savePropsAndHeadersToFile(msg, outputDir, messagesReceived)
			if err != nil {
				return fmt.Errorf("Save props and headers: %s", err)
			}
		}
	}

	return nil
}

func saveMessageToFile(body []byte, outputDir string, counter uint) error {
	filePath := generateFilePath(outputDir, counter)
	err := ioutil.WriteFile(filePath, body, 0644)
	if err != nil {
		return err
	}

	fmt.Println(filePath)

	return nil
}

func getProperties(msg amqp091.Delivery) map[string]interface{} {
	props := map[string]interface{}{
		"app_id":           msg.AppId,
		"content_encoding": msg.ContentEncoding,
		"content_type":     msg.ContentType,
		"correlation_id":   msg.CorrelationId,
		"delivery_mode":    msg.DeliveryMode,
		"expiration":       msg.Expiration,
		"message_id":       msg.MessageId,
		"priority":         msg.Priority,
		"reply_to":         msg.ReplyTo,
		"type":             msg.Type,
		"user_id":          msg.UserId,
		"exchange":         msg.Exchange,
		"routing_key":      msg.RoutingKey,
	}

	if !msg.Timestamp.IsZero() {
		props["timestamp"] = msg.Timestamp.String()
	}

	for k, v := range props {
		if v == "" {
			delete(props, k)
		}
	}

	return props
}

func savePropsAndHeadersToFile(msg amqp091.Delivery, outputDir string, counter uint) error {
	extras := make(map[string]interface{})
	extras["properties"] = getProperties(msg)
	extras["headers"] = msg.Headers

	data, err := json.MarshalIndent(extras, "", "  ")
	if err != nil {
		return err
	}

	filePath := generateFilePath(outputDir, counter) + "-headers+properties.json"
	err = ioutil.WriteFile(filePath, data, 0644)
	if err != nil {
		return err
	}

	fmt.Println(filePath)

	return nil
}

func generateFilePath(outputDir string, counter uint) string {
	return path.Join(outputDir, fmt.Sprintf("msg-%04d", counter))
}

func verboseLog(msg string) {
	if *verbose {
		fmt.Println("*", msg)
	}
}
<commit_msg>unlimited<commit_after>package main

import (
	"crypto/tls"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strings"

	"github.com/rabbitmq/amqp091-go"
)

var (
	uri         = flag.String("uri", "amqp://guest:guest@localhost:5672/", "AMQP URI")
	insecureTLS = flag.Bool("insecure-tls", false, "Insecure TLS mode: don't check certificates")
	queue       = flag.String("queue", "", "AMQP queue name")
	ack         = flag.Bool("ack", false, "Acknowledge messages")
	maxMessages = flag.Uint("max-messages", 1000, "Maximum number of messages to dump or 0 for unlimited")
	outputDir   = flag.String("output-dir", ".", "Directory in which to save the dumped messages")
	full        = flag.Bool("full", false, "Dump the message, its properties and headers")
	verbose     = flag.Bool("verbose", false, "Print progress")
)

func main() {
	flag.Parse()
	if flag.NArg() > 0 {
		fmt.Fprintf(os.Stderr, "Error: Unused command line arguments detected.\n")
		flag.Usage()
		os.Exit(2)
	}
	err := dumpMessagesFromQueue(*uri, *queue, *maxMessages, *outputDir)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}

func dial(amqpURI string) (*amqp091.Connection, error) {
	verboseLog(fmt.Sprintf("Dialing %q", amqpURI))
	if *insecureTLS && strings.HasPrefix(amqpURI, "amqps://") {
		tlsConfig := new(tls.Config)
		tlsConfig.InsecureSkipVerify = true
		conn, err := amqp091.DialTLS(amqpURI, tlsConfig)
		return conn, err
	}
	conn, err := amqp091.Dial(amqpURI)
	return conn, err
}

func dumpMessagesFromQueue(amqpURI string, queueName string, maxMessages uint, outputDir string) error {
	if queueName == "" {
		return fmt.Errorf("Must supply queue name")
	}

	conn, err := dial(amqpURI)
	if err != nil {
		return fmt.Errorf("Dial: %s", err)
	}

	defer func() {
		conn.Close()
		verboseLog("AMQP connection closed")
	}()

	channel, err := conn.Channel()
	if err != nil {
		return fmt.Errorf("Channel: %s", err)
	}

	verboseLog(fmt.Sprintf("Pulling messages from queue %q", queueName))
	for messagesReceived := uint(0); maxMessages == 0 || messagesReceived < maxMessages; messagesReceived++ {
		msg, ok, err := channel.Get(queueName,
			*ack, // autoAck
		)
		if err != nil {
			return fmt.Errorf("Queue get: %s", err)
		}

		if !ok {
			verboseLog("No more messages in queue")
			break
		}

		err = saveMessageToFile(msg.Body, outputDir, messagesReceived)
		if err != nil {
			return fmt.Errorf("Save message: %s", err)
		}

		if *full {
			err = savePropsAndHeadersToFile(msg, outputDir, messagesReceived)
			if err != nil {
				return fmt.Errorf("Save props and headers: %s", err)
			}
		}
	}

	return nil
}

func saveMessageToFile(body []byte, outputDir string, counter uint) error {
	filePath := generateFilePath(outputDir, counter)
	err := ioutil.WriteFile(filePath, body, 0644)
	if err != nil {
		return err
	}

	fmt.Println(filePath)

	return nil
}

func getProperties(msg amqp091.Delivery) map[string]interface{} {
	props := map[string]interface{}{
		"app_id":           msg.AppId,
		"content_encoding": msg.ContentEncoding,
		"content_type":     msg.ContentType,
		"correlation_id":   msg.CorrelationId,
		"delivery_mode":    msg.DeliveryMode,
		"expiration":       msg.Expiration,
		"message_id":       msg.MessageId,
		"priority":         msg.Priority,
		"reply_to":         msg.ReplyTo,
		"type":             msg.Type,
		"user_id":          msg.UserId,
		"exchange":         msg.Exchange,
		"routing_key":      msg.RoutingKey,
	}

	if !msg.Timestamp.IsZero() {
		props["timestamp"] = msg.Timestamp.String()
	}

	for k, v := range props {
		if v == "" {
			delete(props, k)
		}
	}

	return props
}

func savePropsAndHeadersToFile(msg amqp091.Delivery, outputDir string, counter uint) error {
	extras := make(map[string]interface{})
	extras["properties"] = getProperties(msg)
	extras["headers"] = msg.Headers

	data, err := json.MarshalIndent(extras, "", "  ")
	if err != nil {
		return err
	}

	filePath := generateFilePath(outputDir, counter) + "-headers+properties.json"
	err = ioutil.WriteFile(filePath, data, 0644)
	if err != nil {
		return err
	}

	fmt.Println(filePath)

	return nil
}

func generateFilePath(outputDir string, counter uint) string {
	return path.Join(outputDir, fmt.Sprintf("msg-%04d", counter))
}

func verboseLog(msg string) {
	if *verbose {
		fmt.Println("*", msg)
	}
}
<|endoftext|>


<commit_before>// Package c2go contains the main function for running the executable.
//
// Installation
//
//     go get -u github.com/elliotchance/c2go
//
// Usage
//
//     c2go myfile.c
//
package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"
	"strings"

	"errors"

	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/preprocessor"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/transpiler"
)

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.20.1 Ytterbium 2018-01-07"

var stderr io.Writer = os.Stderr

// ProgramArgs defines the options available when processing the program. There
// is no constructor since the zeroed out values are the appropriate defaults -
// you need only set the options you need.
//
// TODO: Better separation on CLI modes
// https://github.com/elliotchance/c2go/issues/134
//
// Do not instantiate this directly. Instead use DefaultProgramArgs(); then
// modify any specific attributes.
type ProgramArgs struct {
	verbose     bool
	ast         bool
	inputFiles  []string
	clangFlags  []string
	outputFile  string
	packageName string

	// A private option to output the Go as a *_test.go file.
	outputAsTest bool
}

// DefaultProgramArgs default value of ProgramArgs
func DefaultProgramArgs() ProgramArgs {
	return ProgramArgs{
		verbose:      false,
		ast:          false,
		packageName:  "main",
		clangFlags:   []string{},
		outputAsTest: false,
	}
}

func readAST(data []byte) []string {
	return strings.Split(string(data), "\n")
}

type treeNode struct {
	indent int
	node   ast.Node
}

func convertLinesToNodes(lines []string) []treeNode {
	nodes := make([]treeNode, len(lines))
	var counter int
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}

		// It is tempting to discard null AST nodes, but these may
		// have semantic importance: for example, they represent omitted
		// for-loop conditions, as in for(;;).
		line = strings.Replace(line, "<<<NULL>>>", "NullStmt", 1)
		trimmed := strings.TrimLeft(line, "|\\- `")
		node := ast.Parse(trimmed)
		indentLevel := (len(line) - len(trimmed)) / 2
		nodes[counter] = treeNode{indentLevel, node}
		counter++
	}
	nodes = nodes[0:counter]

	return nodes
}

func convertLinesToNodesParallel(lines []string) []treeNode {
	// function f separate full list on 2 parts and
	// then each part can recursive run function f
	var f func([]string, int) []treeNode

	f = func(lines []string, deep int) []treeNode {
		deep = deep - 2
		part := len(lines) / 2

		var tr1 = make(chan []treeNode)
		var tr2 = make(chan []treeNode)

		go func(lines []string, deep int) {
			if deep <= 0 || len(lines) < deep {
				tr1 <- convertLinesToNodes(lines)
				return
			}
			tr1 <- f(lines, deep)
		}(lines[0:part], deep)

		go func(lines []string, deep int) {
			if deep <= 0 || len(lines) < deep {
				tr2 <- convertLinesToNodes(lines)
				return
			}
			tr2 <- f(lines, deep)
		}(lines[part:], deep)

		defer close(tr1)
		defer close(tr2)

		return append(<-tr1, <-tr2...)
	}

	// Parameter of deep - can be any, but effective to use
	// same amount of CPU
	return f(lines, runtime.NumCPU())
}

// buildTree converts an array of nodes, each prefixed with a depth into a tree.
func buildTree(nodes []treeNode, depth int) []ast.Node {
	if len(nodes) == 0 {
		return []ast.Node{}
	}

	// Split the list into sections, treat each section as a tree with its own
	// root.
	sections := [][]treeNode{}
	for _, node := range nodes {
		if node.indent == depth {
			sections = append(sections, []treeNode{node})
		} else {
			sections[len(sections)-1] = append(sections[len(sections)-1], node)
		}
	}

	results := []ast.Node{}
	for _, section := range sections {
		slice := []treeNode{}
		for _, n := range section {
			if n.indent > depth {
				slice = append(slice, n)
			}
		}

		children := buildTree(slice, depth+1)
		for _, child := range children {
			section[0].node.AddChild(child)
		}
		results = append(results, section[0].node)
	}

	return results
}

// Start begins transpiling an input file.
func Start(args ProgramArgs) (err error) {
	if args.verbose {
		fmt.Println("Start tanspiling ...")
	}

	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("The $GOPATH must be set")
	}

	// 1. Compile it first (checking for errors)
	for _, in := range args.inputFiles {
		_, err := os.Stat(in)
		if err != nil {
			return fmt.Errorf("Input file %s is not found", in)
		}
	}

	// 2. Preprocess
	if args.verbose {
		fmt.Println("Running clang preprocessor...")
	}

	pp, err := preprocessor.Analyze(args.inputFiles, args.clangFlags)
	if err != nil {
		return err
	}

	if args.verbose {
		fmt.Println("Writing preprocessor ...")
	}
	dir, err := ioutil.TempDir("", "c2go")
	if err != nil {
		return fmt.Errorf("Cannot create temp folder: %v", err)
	}
	defer os.RemoveAll(dir) // clean up

	ppFilePath := path.Join(dir, "pp.c")
	err = ioutil.WriteFile(ppFilePath, pp, 0644)
	if err != nil {
		return fmt.Errorf("writing to %s failed: %v", ppFilePath, err)
	}

	// 3. Generate JSON from AST
	if args.verbose {
		fmt.Println("Running clang for AST tree...")
	}
	astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", "-fno-color-diagnostics", ppFilePath).Output()
	if err != nil {
		// If clang fails it still prints out the AST, so we have to run it
		// again to get the real error.
		errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput()

		panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
	}

	if args.verbose {
		fmt.Println("Reading clang AST tree...")
	}
	lines := readAST(astPP)
	if args.ast {
		for _, l := range lines {
			fmt.Println(l)
		}
		fmt.Println()

		return nil
	}

	p := program.NewProgram()
	p.Verbose = args.verbose
	p.OutputAsTest = args.outputAsTest

	// Converting to nodes
	if args.verbose {
		fmt.Println("Converting to nodes...")
	}
	nodes := convertLinesToNodesParallel(lines)

	// build tree
	if args.verbose {
		fmt.Println("Building tree...")
	}
	tree := buildTree(nodes, 0)
	ast.FixPositions(tree)

	// Repair the floating literals. See RepairFloatingLiteralsFromSource for
	// more information.
	floatingErrors := ast.RepairFloatingLiteralsFromSource(tree[0], ppFilePath)

	for _, fErr := range floatingErrors {
		message := fmt.Sprintf("could not read exact floating literal: %s",
			fErr.Err.Error())
		p.AddMessage(p.GenerateWarningMessage(errors.New(message), fErr.Node))
	}

	outputFilePath := args.outputFile

	if outputFilePath == "" {
		// Choose inputFile for creating name of output file
		input := args.inputFiles[0]
		// We choose name for output Go code at the base
		// on filename for choosed input file
		cleanFileName := filepath.Clean(filepath.Base(input))
		extension := filepath.Ext(input)
		outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go"
	}

	// transpile ast tree
	if args.verbose {
		fmt.Println("Transpiling tree...")
	}

	err = transpiler.TranspileAST(args.outputFile, args.packageName, p, tree[0].(ast.Node))
	if err != nil {
		return fmt.Errorf("cannot transpile AST : %v", err)
	}

	// write the output Go code
	if args.verbose {
		fmt.Println("Writing the output Go code...")
	}
	err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0644)
	if err != nil {
		return fmt.Errorf("writing Go output file failed: %v", err)
	}

	return nil
}

type inputDataFlags []string

func (i *inputDataFlags) String() (s string) {
	for pos, item := range *i {
		s += fmt.Sprintf("Flag %d. %s\n", pos, item)
	}
	return
}

func (i *inputDataFlags) Set(value string) error {
	*i = append(*i, value)
	return nil
}

var clangFlags inputDataFlags

func init() {
	transpileCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
}

var (
	versionFlag       = flag.Bool("v", false, "print the version and exit")
	transpileCommand  = flag.NewFlagSet("transpile", flag.ContinueOnError)
	verboseFlag       = transpileCommand.Bool("V", false, "print progress as comments")
	outputFlag        = transpileCommand.String("o", "", "output Go generated code to the specified file")
	packageFlag       = transpileCommand.String("p", "main", "set the name of the generated package")
	transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
	astCommand        = flag.NewFlagSet("ast", flag.ContinueOnError)
	astHelpFlag       = astCommand.Bool("h", false, "print help information")
)

func main() {
	code := runCommand()
	if code != 0 {
		os.Exit(code)
	}
}

func runCommand() int {

	flag.Usage = func() {
		usage := "Usage: %s [-v] [<command>] [<flags>] file1.c ...\n\n"
		usage += "Commands:\n"
		usage += "  transpile\ttranspile an input C source file or files to Go\n"
		usage += "  ast\t\tprint AST before translated Go code\n\n"

		usage += "Flags:\n"
		fmt.Fprintf(stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	transpileCommand.SetOutput(stderr)
	astCommand.SetOutput(stderr)

	flag.Parse()

	if *versionFlag {
		// Simply print out the version and exit.
		fmt.Println(Version)
		return 0
	}

	if flag.NArg() < 1 {
		flag.Usage()
		return 1
	}

	args := DefaultProgramArgs()

	switch os.Args[1] {
	case "ast":
		err := astCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("ast command cannot parse: %v", err)
			return 1
		}

		if *astHelpFlag || astCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s ast file.c\n", os.Args[0])
			astCommand.PrintDefaults()
			return 1
		}

		args.ast = true
		args.inputFiles = astCommand.Args()
	case "transpile":
		err := transpileCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("transpile command cannot parse: %v", err)
			return 1
		}

		if *transpileHelpFlag || transpileCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file1.c ...\n", os.Args[0])
			transpileCommand.PrintDefaults()
			return 1
		}

		args.inputFiles = transpileCommand.Args()
		args.outputFile = *outputFlag
		args.packageName = *packageFlag
		args.verbose = *verboseFlag
		args.clangFlags = clangFlags
	default:
		flag.Usage()
		return 1
	}

	if err := Start(args); err != nil {
		fmt.Printf("Error: %v\n", err)
		return 1
	}

	return 0
}
<commit_msg>Bump version: v0.20.2 Ytterbium 2018-01-08<commit_after>// Package c2go contains the main function for running the executable.
//
// Installation
//
//     go get -u github.com/elliotchance/c2go
//
// Usage
//
//     c2go myfile.c
//
package main

import (
	"flag"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"runtime"
	"strings"

	"errors"

	"github.com/elliotchance/c2go/ast"
	"github.com/elliotchance/c2go/preprocessor"
	"github.com/elliotchance/c2go/program"
	"github.com/elliotchance/c2go/transpiler"
)

// Version can be requested through the command line with:
//
//     c2go -v
//
// See https://github.com/elliotchance/c2go/wiki/Release-Process
const Version = "v0.20.2 Ytterbium 2018-01-08"

var stderr io.Writer = os.Stderr

// ProgramArgs defines the options available when processing the program. There
// is no constructor since the zeroed out values are the appropriate defaults -
// you need only set the options you need.
//
// TODO: Better separation on CLI modes
// https://github.com/elliotchance/c2go/issues/134
//
// Do not instantiate this directly. Instead use DefaultProgramArgs(); then
// modify any specific attributes.
type ProgramArgs struct {
	verbose     bool
	ast         bool
	inputFiles  []string
	clangFlags  []string
	outputFile  string
	packageName string

	// A private option to output the Go as a *_test.go file.
	outputAsTest bool
}

// DefaultProgramArgs default value of ProgramArgs
func DefaultProgramArgs() ProgramArgs {
	return ProgramArgs{
		verbose:      false,
		ast:          false,
		packageName:  "main",
		clangFlags:   []string{},
		outputAsTest: false,
	}
}

func readAST(data []byte) []string {
	return strings.Split(string(data), "\n")
}

type treeNode struct {
	indent int
	node   ast.Node
}

func convertLinesToNodes(lines []string) []treeNode {
	nodes := make([]treeNode, len(lines))
	var counter int
	for _, line := range lines {
		if strings.TrimSpace(line) == "" {
			continue
		}

		// It is tempting to discard null AST nodes, but these may
		// have semantic importance: for example, they represent omitted
		// for-loop conditions, as in for(;;).
		line = strings.Replace(line, "<<<NULL>>>", "NullStmt", 1)
		trimmed := strings.TrimLeft(line, "|\\- `")
		node := ast.Parse(trimmed)
		indentLevel := (len(line) - len(trimmed)) / 2
		nodes[counter] = treeNode{indentLevel, node}
		counter++
	}
	nodes = nodes[0:counter]

	return nodes
}

func convertLinesToNodesParallel(lines []string) []treeNode {
	// function f separate full list on 2 parts and
	// then each part can recursive run function f
	var f func([]string, int) []treeNode

	f = func(lines []string, deep int) []treeNode {
		deep = deep - 2
		part := len(lines) / 2

		var tr1 = make(chan []treeNode)
		var tr2 = make(chan []treeNode)

		go func(lines []string, deep int) {
			if deep <= 0 || len(lines) < deep {
				tr1 <- convertLinesToNodes(lines)
				return
			}
			tr1 <- f(lines, deep)
		}(lines[0:part], deep)

		go func(lines []string, deep int) {
			if deep <= 0 || len(lines) < deep {
				tr2 <- convertLinesToNodes(lines)
				return
			}
			tr2 <- f(lines, deep)
		}(lines[part:], deep)

		defer close(tr1)
		defer close(tr2)

		return append(<-tr1, <-tr2...)
	}

	// Parameter of deep - can be any, but effective to use
	// same amount of CPU
	return f(lines, runtime.NumCPU())
}

// buildTree converts an array of nodes, each prefixed with a depth into a tree.
func buildTree(nodes []treeNode, depth int) []ast.Node {
	if len(nodes) == 0 {
		return []ast.Node{}
	}

	// Split the list into sections, treat each section as a tree with its own
	// root.
	sections := [][]treeNode{}
	for _, node := range nodes {
		if node.indent == depth {
			sections = append(sections, []treeNode{node})
		} else {
			sections[len(sections)-1] = append(sections[len(sections)-1], node)
		}
	}

	results := []ast.Node{}
	for _, section := range sections {
		slice := []treeNode{}
		for _, n := range section {
			if n.indent > depth {
				slice = append(slice, n)
			}
		}

		children := buildTree(slice, depth+1)
		for _, child := range children {
			section[0].node.AddChild(child)
		}
		results = append(results, section[0].node)
	}

	return results
}

// Start begins transpiling an input file.
func Start(args ProgramArgs) (err error) {
	if args.verbose {
		fmt.Println("Start tanspiling ...")
	}

	if os.Getenv("GOPATH") == "" {
		return fmt.Errorf("The $GOPATH must be set")
	}

	// 1. Compile it first (checking for errors)
	for _, in := range args.inputFiles {
		_, err := os.Stat(in)
		if err != nil {
			return fmt.Errorf("Input file %s is not found", in)
		}
	}

	// 2. Preprocess
	if args.verbose {
		fmt.Println("Running clang preprocessor...")
	}

	pp, err := preprocessor.Analyze(args.inputFiles, args.clangFlags)
	if err != nil {
		return err
	}

	if args.verbose {
		fmt.Println("Writing preprocessor ...")
	}
	dir, err := ioutil.TempDir("", "c2go")
	if err != nil {
		return fmt.Errorf("Cannot create temp folder: %v", err)
	}
	defer os.RemoveAll(dir) // clean up

	ppFilePath := path.Join(dir, "pp.c")
	err = ioutil.WriteFile(ppFilePath, pp, 0644)
	if err != nil {
		return fmt.Errorf("writing to %s failed: %v", ppFilePath, err)
	}

	// 3. Generate JSON from AST
	if args.verbose {
		fmt.Println("Running clang for AST tree...")
	}
	astPP, err := exec.Command("clang", "-Xclang", "-ast-dump", "-fsyntax-only", "-fno-color-diagnostics", ppFilePath).Output()
	if err != nil {
		// If clang fails it still prints out the AST, so we have to run it
		// again to get the real error.
		errBody, _ := exec.Command("clang", ppFilePath).CombinedOutput()

		panic("clang failed: " + err.Error() + ":\n\n" + string(errBody))
	}

	if args.verbose {
		fmt.Println("Reading clang AST tree...")
	}
	lines := readAST(astPP)
	if args.ast {
		for _, l := range lines {
			fmt.Println(l)
		}
		fmt.Println()

		return nil
	}

	p := program.NewProgram()
	p.Verbose = args.verbose
	p.OutputAsTest = args.outputAsTest

	// Converting to nodes
	if args.verbose {
		fmt.Println("Converting to nodes...")
	}
	nodes := convertLinesToNodesParallel(lines)

	// build tree
	if args.verbose {
		fmt.Println("Building tree...")
	}
	tree := buildTree(nodes, 0)
	ast.FixPositions(tree)

	// Repair the floating literals. See RepairFloatingLiteralsFromSource for
	// more information.
	floatingErrors := ast.RepairFloatingLiteralsFromSource(tree[0], ppFilePath)

	for _, fErr := range floatingErrors {
		message := fmt.Sprintf("could not read exact floating literal: %s",
			fErr.Err.Error())
		p.AddMessage(p.GenerateWarningMessage(errors.New(message), fErr.Node))
	}

	outputFilePath := args.outputFile

	if outputFilePath == "" {
		// Choose inputFile for creating name of output file
		input := args.inputFiles[0]
		// We choose name for output Go code at the base
		// on filename for choosed input file
		cleanFileName := filepath.Clean(filepath.Base(input))
		extension := filepath.Ext(input)
		outputFilePath = cleanFileName[0:len(cleanFileName)-len(extension)] + ".go"
	}

	// transpile ast tree
	if args.verbose {
		fmt.Println("Transpiling tree...")
	}

	err = transpiler.TranspileAST(args.outputFile, args.packageName, p, tree[0].(ast.Node))
	if err != nil {
		return fmt.Errorf("cannot transpile AST : %v", err)
	}

	// write the output Go code
	if args.verbose {
		fmt.Println("Writing the output Go code...")
	}
	err = ioutil.WriteFile(outputFilePath, []byte(p.String()), 0644)
	if err != nil {
		return fmt.Errorf("writing Go output file failed: %v", err)
	}

	return nil
}

type inputDataFlags []string

func (i *inputDataFlags) String() (s string) {
	for pos, item := range *i {
		s += fmt.Sprintf("Flag %d. %s\n", pos, item)
	}
	return
}

func (i *inputDataFlags) Set(value string) error {
	*i = append(*i, value)
	return nil
}

var clangFlags inputDataFlags

func init() {
	transpileCommand.Var(&clangFlags, "clang-flag", "Pass arguments to clang. You may provide multiple -clang-flag items.")
}

var (
	versionFlag       = flag.Bool("v", false, "print the version and exit")
	transpileCommand  = flag.NewFlagSet("transpile", flag.ContinueOnError)
	verboseFlag       = transpileCommand.Bool("V", false, "print progress as comments")
	outputFlag        = transpileCommand.String("o", "", "output Go generated code to the specified file")
	packageFlag       = transpileCommand.String("p", "main", "set the name of the generated package")
	transpileHelpFlag = transpileCommand.Bool("h", false, "print help information")
	astCommand        = flag.NewFlagSet("ast", flag.ContinueOnError)
	astHelpFlag       = astCommand.Bool("h", false, "print help information")
)

func main() {
	code := runCommand()
	if code != 0 {
		os.Exit(code)
	}
}

func runCommand() int {

	flag.Usage = func() {
		usage := "Usage: %s [-v] [<command>] [<flags>] file1.c ...\n\n"
		usage += "Commands:\n"
		usage += "  transpile\ttranspile an input C source file or files to Go\n"
		usage += "  ast\t\tprint AST before translated Go code\n\n"

		usage += "Flags:\n"
		fmt.Fprintf(stderr, usage, os.Args[0])
		flag.PrintDefaults()
	}

	transpileCommand.SetOutput(stderr)
	astCommand.SetOutput(stderr)

	flag.Parse()

	if *versionFlag {
		// Simply print out the version and exit.
		fmt.Println(Version)
		return 0
	}

	if flag.NArg() < 1 {
		flag.Usage()
		return 1
	}

	args := DefaultProgramArgs()

	switch os.Args[1] {
	case "ast":
		err := astCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("ast command cannot parse: %v", err)
			return 1
		}

		if *astHelpFlag || astCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s ast file.c\n", os.Args[0])
			astCommand.PrintDefaults()
			return 1
		}

		args.ast = true
		args.inputFiles = astCommand.Args()
	case "transpile":
		err := transpileCommand.Parse(os.Args[2:])
		if err != nil {
			fmt.Printf("transpile command cannot parse: %v", err)
			return 1
		}

		if *transpileHelpFlag || transpileCommand.NArg() == 0 {
			fmt.Fprintf(stderr, "Usage: %s transpile [-V] [-o file.go] [-p package] file1.c ...\n", os.Args[0])
			transpileCommand.PrintDefaults()
			return 1
		}

		args.inputFiles = transpileCommand.Args()
		args.outputFile = *outputFlag
		args.packageName = *packageFlag
		args.verbose = *verboseFlag
		args.clangFlags = clangFlags
	default:
		flag.Usage()
		return 1
	}

	if err := Start(args); err != nil {
		fmt.Printf("Error: %v\n", err)
		return 1
	}

	return 0
}
<|endoftext|>


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

package main

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

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

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

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

package main

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

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

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

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


<commit_before>package main

import "github.com/osmano807/joker/jokerd"
import "flag"

func main() {
	var newSquidFormat = flag.Bool("new-format", false, "Defines if joker should output the new Squid 3.HEAD format")
	flag.Parse()
	joker.NewSquidFormat = *newSquidFormat
	joker.Main()
}
<commit_msg>Adds debug enabling, and versioning<commit_after>package main

import (
	"flag"
	"fmt"
	"github.com/osmano807/joker/jokerd"
	"io/ioutil"
	"log"
	"os"
)

var (
	// VERSION is initialised by the linker during compilation if the appropriate flag is specified:
	// e.g. go build -ldflags "-X main.VERSION 0.1.2-abcd" goxc.go
	// thanks to minux for this advice
	// So, goxc does this automatically during 'go build'
	VERSION     = "1.0.0"
	BUILD_DATE  = ""
	SOURCE_DATE = "2014-03-23T20:57:00-03:00"
)

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

	var newSquidFormat = flag.Bool("new-format", false, "Defines if joker should output the new Squid 3.HEAD format")
	var showVersion = flag.Bool("version", false, "Shows joker version")
	var enableDebug = flag.Bool("debug", false, "Enable debug messages")
	flag.Parse()

	if *showVersion {
		fmt.Fprintf(os.Stderr, " joker version: %s\n", VERSION)
		fmt.Fprintf(os.Stderr, " build date: %s\n", BUILD_DATE)
		fmt.Fprintf(os.Stderr, " source date: %s\n", SOURCE_DATE)
		os.Exit(0)
	}

	if !*enableDebug {
		log.SetOutput(ioutil.Discard)
	}

	joker.NewSquidFormat = *newSquidFormat
	joker.Main()
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"database/sql"
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	_ "github.com/mattn/go-sqlite3"
	"github.com/pkg/errors"
)

type tagType int

const (
	GTAGS tagType = iota
	GRTAGS
	GPATH
)

func (t tagType) String() string {
	switch t {
	case GTAGS:
		return "GTAGS"
	case GRTAGS:
		return "GRTAGS"
	case GPATH:
		return "GPATH"
	}
	panic("invalid tagType")
}

type standard struct {
	tagName    string
	fileID     int
	lineNumber int
	lineImage  string
}

func (s standard) String() string {
	return fmt.Sprintf("%d @n %d %s", s.fileID, s.lineNumber, s.lineImage)
}

type compact struct {
	fileID      int
	lineNumbers []int
}

func (c compact) String() string {
	continueCounter := 0
	output := fmt.Sprintf("%d", c.lineNumbers[0]) // [0] must be exist
	for l := 1; l < len(c.lineNumbers); l++ {
		diff := c.lineNumbers[l] - c.lineNumbers[l-1]
		if continueCounter == 0 {
			if diff == 1 {
				output += "-"
				continueCounter++
			} else {
				output += fmt.Sprintf(",%d", diff)
			}
		} else {
			if diff == 1 {
				continueCounter++
			} else {
				output += fmt.Sprintf("%d,%d", continueCounter, diff)
				continueCounter = 0
			}
		}
	}
	if continueCounter != 0 {
		output += fmt.Sprintf("%d", continueCounter)
	}
	return fmt.Sprintf("%d @n %s", c.fileID, output)
}

type global struct {
	fileID      int
	gtagsData   []standard
	grtagsData  map[string]*compact
	db          map[tagType]*sql.DB
	transaction map[tagType]*sql.Tx
	// lineImageScanner
	basePath    string
	currentFile *os.File
	currentLine int
	scanner     *bufio.Scanner
	fset        *token.FileSet
}

func newGlobal(fset *token.FileSet, basePath string) (*global, error) {
	g := &global{
		fileID:      0,
		gtagsData:   make([]standard, 0),
		grtagsData:  make(map[string]*compact),
		db:          make(map[tagType]*sql.DB),
		transaction: make(map[tagType]*sql.Tx),
		basePath:    basePath,
		currentFile: nil,
		currentLine: 0,
		scanner:     nil,
		fset:        fset,
	}

	dbfiles := []tagType{
		GTAGS,
		GRTAGS,
		GPATH,
	}

	var err error
	for _, file := range dbfiles {
		os.Remove("./" + file.String())
		g.db[file], err = sql.Open("sqlite3", file.String())
		if err != nil {
			return nil, err
		}
		_, err = g.db[file].Exec(`create table db (key text, dat text, extra text)`)
		if err != nil {
			return nil, err
		}
		g.transaction[file], err = g.db[file].Begin()
		if err != nil {
			return nil, err
		}
	}

	g.insertEntry(GTAGS, " __.COMPRESS", " __.COMPRESS ddefine ttypedef", nil)
	g.insertEntry(GTAGS, " __.COMPNAME", " __.COMPNAME", nil)
	g.insertEntry(GTAGS, " __.VERSION", " __.VERSION 6", nil)

	g.insertEntry(GRTAGS, " __.COMPACT", " __.COMPACT", nil)
	g.insertEntry(GRTAGS, " __.COMPLINE", " __.COMPLINE", nil)
	g.insertEntry(GRTAGS, " __.COMPNAME", " __.COMPNAME", nil)
	g.insertEntry(GRTAGS, " __.VERSION", " __.VERSION 6", nil)

	g.insertEntry(GPATH, " __.VERSION", " __.VERSION 2", nil)
	g.insertEntry(GPATH, " __.NEXTKEY", "1", nil)

	return g, nil
}

func (g *global) insertEntry(tag tagType, key, dat, extra interface{}) {
	_, err := g.transaction[tag].Exec(`insert into db (key, dat, extra) values (?, ?, ?)`, key, dat, extra)
	if err != nil {
		log.Panicln("failed to exec", err, "tag:", tag, "|key:", key, "|dat:", dat, "|extra:", extra)
	}
}

func (g *global) dump() {
	if g.fileID == 0 {
		return
	}

	for _, s := range g.gtagsData {
		g.insertEntry(GTAGS, s.tagName, s.String(), strconv.Itoa(s.fileID))
	}
	for tagName, compact := range g.grtagsData {
		g.insertEntry(GRTAGS, tagName, compact.String(), strconv.Itoa(compact.fileID))
	}

	filepath, _ := filepath.Rel(g.basePath, g.currentFile.Name())
	filepath = "./" + filepath
	if *verbose {
		log.Println(filepath)
	}

	g.insertEntry(GPATH, filepath, g.fileID, nil)
	g.insertEntry(GPATH, g.fileID, filepath, nil)
	g.insertEntry(GPATH, " __.NEXTKEY", strconv.Itoa(g.fileID+1), nil)
}

func (g *global) finalize() error {
	if g.currentFile != nil {
		err := g.currentFile.Close()
		if err != nil {
			return err
		}
	}
	g.dump()

	dbfiles := []tagType{
		GTAGS,
		GRTAGS,
		GPATH,
	}

	for _, file := range dbfiles {
		g.transaction[file].Commit()
		g.db[file].Close()
	}

	return nil
}

func (g *global) switchFile(abspath string) (err error) {
	// Close and Setup Scanner
	if g.currentFile != nil {
		err := g.currentFile.Close()
		if err != nil {
			return errors.Wrapf(err, "failed to close current file, current: %s abspath: %s", g.currentFile.Name(), abspath)
		}
	}
	g.currentFile, err = os.Open(abspath)
	if err != nil {
		return errors.Wrap(err, "failed to open next file ")
	}
	g.scanner = bufio.NewScanner(g.currentFile)
	g.currentLine = 0

	// Reset parsed data
	g.gtagsData = make([]standard, 0)
	g.grtagsData = make(map[string]*compact)
	g.fileID++

	return nil
}

func (g *global) addFuncDecl(node *ast.FuncDecl) {
	ident := node.Name
	pos := g.fset.Position(node.Pos())
	for ; g.currentLine < pos.Line; g.currentLine++ {
		g.scanner.Scan()
	}
	lineImage := strings.Replace(strings.TrimSpace(g.scanner.Text()), ident.Name, "@n", -1)

	g.gtagsData = append(g.gtagsData, standard{
		tagName:    ident.Name,
		fileID:     g.fileID,
		lineNumber: pos.Line,
		lineImage:  lineImage,
	})
}

func (g *global) addIdent(ident *ast.Ident) {
	pos := g.fset.Position(ident.Pos())
	r, found := g.grtagsData[ident.Name]
	if found {
		r.lineNumbers = append(r.lineNumbers, pos.Line)
	} else {
		g.grtagsData[ident.Name] = &compact{
			fileID:      g.fileID,
			lineNumbers: []int{pos.Line},
		}
	}
}

func (g *global) parse(node ast.Node) bool {
	if node == nil {
		return false
	}
	if _, ok := node.(*ast.Package); ok {
		return true
	}
	pos := g.fset.Position(node.Pos())
	absPath, err := filepath.Abs(pos.Filename)
	if err != nil {
		log.Fatal("failed to get absolute path: ", err)
	}
	if g.currentFile == nil || g.currentFile.Name() != absPath {
		// only add data into gtags file if currentFile is not nil
		if g.currentFile != nil {
			g.dump()
		}

		err = g.switchFile(absPath)
		if err != nil {
			log.Print("failed to switch file: ", err)
			return false
		}
	}

	switch node.(type) {
	case *ast.FuncDecl:
		g.addFuncDecl(node.(*ast.FuncDecl))
	case *ast.Ident:
		g.addIdent(node.(*ast.Ident))
	}
	return true
}

var verbose *bool

func main() {
	verbose = flag.Bool("v", false, "Verbose mode.")
	flag.Parse()

	basePath, err := filepath.Abs(".")
	if err != nil {
		log.Fatal("failed to get absolute path: ", err)
	}

	fset := token.NewFileSet() // positions are relative to fset
	g, err := newGlobal(fset, basePath)
	if err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error {
		// Skip files if hidden
		if !info.IsDir() && info.Name()[0] == '.' {
			fmt.Println("Hidden file, skipping: ", path)
			return nil
		}
		if info.IsDir() {
			// if hidden directory - skip the entire dir
			if info.Name()[0] == '.' {
				fmt.Println("Hidden folder, skipping: ", path)
				return filepath.SkipDir
			}
			pkgs, err := parser.ParseDir(fset, path, nil, 0)
			if err != nil {
				log.Println("Error in parsing directory, skipping: ", path, err)
				return nil
			}
			for _, p := range pkgs {
				ast.Inspect(p, g.parse)
			}
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}

	err = g.finalize()
	if err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Refactoring<commit_after>package main

import (
	"bufio"
	"database/sql"
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	_ "github.com/mattn/go-sqlite3"
	"github.com/pkg/errors"
)

type tagType int

const (
	GTAGS tagType = iota
	GRTAGS
	GPATH
)

func (t tagType) String() string {
	switch t {
	case GTAGS:
		return "GTAGS"
	case GRTAGS:
		return "GRTAGS"
	case GPATH:
		return "GPATH"
	}
	panic("invalid tagType")
}

type standard struct {
	tagName    string
	fileID     int
	lineNumber int
	lineImage  string
}

func (s standard) String() string {
	return fmt.Sprintf("%d @n %d %s", s.fileID, s.lineNumber, s.lineImage)
}

type compact struct {
	fileID      int
	lineNumbers []int
}

func (c compact) String() string {
	continueCounter := 0
	output := fmt.Sprintf("%d", c.lineNumbers[0]) // [0] must be exist
	for l := 1; l < len(c.lineNumbers); l++ {
		diff := c.lineNumbers[l] - c.lineNumbers[l-1]
		if continueCounter == 0 {
			if diff == 1 {
				output += "-"
				continueCounter++
			} else {
				output += fmt.Sprintf(",%d", diff)
			}
		} else {
			if diff == 1 {
				continueCounter++
			} else {
				output += fmt.Sprintf("%d,%d", continueCounter, diff)
				continueCounter = 0
			}
		}
	}
	if continueCounter != 0 {
		output += fmt.Sprintf("%d", continueCounter)
	}
	return fmt.Sprintf("%d @n %s", c.fileID, output)
}

type global struct {
	fileID      int
	gtagsData   []standard
	grtagsData  map[string]*compact
	db          map[tagType]*sql.DB
	transaction map[tagType]*sql.Tx
	// lineImageScanner
	basePath    string
	currentFile *os.File
	currentLine int
	scanner     *bufio.Scanner
	fset        *token.FileSet
}

func newGlobal(fset *token.FileSet, basePath string) (*global, error) {
	g := &global{
		fileID:      0,
		gtagsData:   make([]standard, 0),
		grtagsData:  make(map[string]*compact),
		db:          make(map[tagType]*sql.DB),
		transaction: make(map[tagType]*sql.Tx),
		basePath:    basePath,
		currentFile: nil,
		currentLine: 0,
		scanner:     nil,
		fset:        fset,
	}

	dbfiles := []tagType{
		GTAGS,
		GRTAGS,
		GPATH,
	}

	var err error
	for _, file := range dbfiles {
		os.Remove("./" + file.String())
		g.db[file], err = sql.Open("sqlite3", file.String())
		if err != nil {
			return nil, err
		}
		_, err = g.db[file].Exec(`create table db (key text, dat text, extra text)`)
		if err != nil {
			return nil, err
		}
		g.transaction[file], err = g.db[file].Begin()
		if err != nil {
			return nil, err
		}
	}

	g.insertEntry(GTAGS, " __.COMPRESS", " __.COMPRESS ddefine ttypedef", nil)
	g.insertEntry(GTAGS, " __.COMPNAME", " __.COMPNAME", nil)
	g.insertEntry(GTAGS, " __.VERSION", " __.VERSION 6", nil)

	g.insertEntry(GRTAGS, " __.COMPACT", " __.COMPACT", nil)
	g.insertEntry(GRTAGS, " __.COMPLINE", " __.COMPLINE", nil)
	g.insertEntry(GRTAGS, " __.COMPNAME", " __.COMPNAME", nil)
	g.insertEntry(GRTAGS, " __.VERSION", " __.VERSION 6", nil)

	g.insertEntry(GPATH, " __.VERSION", " __.VERSION 2", nil)
	g.insertEntry(GPATH, " __.NEXTKEY", "1", nil)

	return g, nil
}

func (g *global) insertEntry(tag tagType, key, dat, extra interface{}) {
	_, err := g.transaction[tag].Exec(`insert into db (key, dat, extra) values (?, ?, ?)`, key, dat, extra)
	if err != nil {
		log.Panicln("failed to exec", err, "tag:", tag, "|key:", key, "|dat:", dat, "|extra:", extra)
	}
}

func (g *global) dump() {
	if g.fileID == 0 {
		return
	}

	for _, s := range g.gtagsData {
		g.insertEntry(GTAGS, s.tagName, s.String(), strconv.Itoa(s.fileID))
	}
	for tagName, compact := range g.grtagsData {
		g.insertEntry(GRTAGS, tagName, compact.String(), strconv.Itoa(compact.fileID))
	}

	filepath, _ := filepath.Rel(g.basePath, g.currentFile.Name())
	filepath = "./" + filepath
	if *verbose {
		log.Println(filepath)
	}

	g.insertEntry(GPATH, filepath, g.fileID, nil)
	g.insertEntry(GPATH, g.fileID, filepath, nil)
	g.insertEntry(GPATH, " __.NEXTKEY", strconv.Itoa(g.fileID+1), nil)
}

func (g *global) finalize() error {
	if g.currentFile != nil {
		err := g.currentFile.Close()
		if err != nil {
			return err
		}
	}
	g.dump()

	dbfiles := []tagType{
		GTAGS,
		GRTAGS,
		GPATH,
	}

	for _, file := range dbfiles {
		g.transaction[file].Commit()
		g.db[file].Close()
	}

	return nil
}

func (g *global) switchFile(abspath string) (err error) {
	// Close and Setup Scanner
	if g.currentFile != nil {
		err := g.currentFile.Close()
		if err != nil {
			return errors.Wrapf(err, "failed to close current file, current: %s abspath: %s", g.currentFile.Name(), abspath)
		}
	}
	g.currentFile, err = os.Open(abspath)
	if err != nil {
		return errors.Wrap(err, "failed to open next file ")
	}
	g.scanner = bufio.NewScanner(g.currentFile)
	g.currentLine = 0

	// Reset parsed data
	g.gtagsData = make([]standard, 0)
	g.grtagsData = make(map[string]*compact)
	g.fileID++

	return nil
}

func (g *global) addFuncDecl(node *ast.FuncDecl) {
	ident := node.Name
	pos := g.fset.Position(node.Pos())
	for ; g.currentLine < pos.Line; g.currentLine++ {
		g.scanner.Scan()
	}
	lineImage := strings.Replace(strings.TrimSpace(g.scanner.Text()), ident.Name, "@n", -1)

	g.gtagsData = append(g.gtagsData, standard{
		tagName:    ident.Name,
		fileID:     g.fileID,
		lineNumber: pos.Line,
		lineImage:  lineImage,
	})
}

func (g *global) addIdent(ident *ast.Ident) {
	pos := g.fset.Position(ident.Pos())
	r, found := g.grtagsData[ident.Name]
	if found {
		r.lineNumbers = append(r.lineNumbers, pos.Line)
	} else {
		g.grtagsData[ident.Name] = &compact{
			fileID:      g.fileID,
			lineNumbers: []int{pos.Line},
		}
	}
}

func (g *global) parse(node ast.Node) bool {
	if node == nil {
		return false
	}
	if _, ok := node.(*ast.Package); ok {
		return true
	}
	pos := g.fset.Position(node.Pos())
	absPath, err := filepath.Abs(pos.Filename)
	if err != nil {
		log.Fatal("failed to get absolute path: ", err)
	}
	if g.currentFile == nil || g.currentFile.Name() != absPath {
		// only add data into gtags file if currentFile is not nil
		if g.currentFile != nil {
			g.dump()
		}

		err = g.switchFile(absPath)
		if err != nil {
			log.Print("failed to switch file: ", err)
			return false
		}
	}

	switch node.(type) {
	case *ast.FuncDecl:
		g.addFuncDecl(node.(*ast.FuncDecl))
	case *ast.Ident:
		g.addIdent(node.(*ast.Ident))
	}
	return true
}

var verbose *bool

func main() {
	verbose = flag.Bool("v", false, "Verbose mode.")
	flag.Parse()

	basePath, err := filepath.Abs(".")
	if err != nil {
		log.Fatalf("failed to get absolute path: %s", err)
	}

	g, err := do(basePath)
	if err != nil {
		log.Fatal(err)
	}

	err = g.finalize()
	if err != nil {
		log.Fatal(err)
	}
}

func do(basePath string) (*global, error) {
	fset := token.NewFileSet() // positions are relative to fset
	g, err := newGlobal(fset, basePath)
	if err != nil {
		log.Fatal(err)
	}

	err = filepath.Walk(basePath, func(path string, info os.FileInfo, err error) error {
		// Skip files if hidden
		if !info.IsDir() && info.Name()[0] == '.' {
			fmt.Println("Hidden file, skipping: ", path)
			return nil
		}
		if info.IsDir() {
			// if hidden directory - skip the entire dir
			if info.Name()[0] == '.' {
				fmt.Println("Hidden folder, skipping: ", path)
				return filepath.SkipDir
			}
			pkgs, err := parser.ParseDir(fset, path, nil, 0)
			if err != nil {
				log.Println("Error in parsing directory, skipping: ", path, err)
				return nil
			}
			for _, p := range pkgs {
				ast.Inspect(p, g.parse)
			}
		}
		return nil
	})
	return g, err
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	mandibleConf "github.com/Imgur/mandible/config"
	processors "github.com/Imgur/mandible/imageprocessor"
	mandible "github.com/Imgur/mandible/server"
)

func main() {
	configFile := os.Getenv("MANDIBLE_CONF")

	config := mandibleConf.NewConfiguration(configFile)

	var server *mandible.Server
	var stats mandible.RuntimeStats

	if config.DatadogEnabled {
		var err error
		stats, err = mandible.NewDatadogStats(config.DatadogHostname)
		if err != nil {
			log.Printf("Invalid Datadog Hostname: %s", config.DatadogHostname)
			os.Exit(1)
		}
		log.Println("Stats init success")
	} else {
		stats = &mandible.DiscardStats{}
	}

	if os.Getenv("AUTHENTICATION_HMAC_KEY") != "" {
		key := []byte(os.Getenv("AUTHENTICATION_HMAC_KEY"))
		auth := mandible.NewHMACAuthenticatorSHA256(key)
		server = mandible.NewAuthenticatedServer(config, processors.EverythingStrategy, auth, stats)
	} else {
		server = mandible.NewServer(config, processors.EverythingStrategy, stats)
	}

	muxer := http.NewServeMux()
	server.Configure(muxer)

	port := fmt.Sprintf(":%d", server.Config.Port)

	log.Printf("Listening on Port: %s", port)

	http.ListenAndServe(port, muxer)
}
<commit_msg>Log startups using the stats object<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	mandibleConf "github.com/Imgur/mandible/config"
	processors "github.com/Imgur/mandible/imageprocessor"
	mandible "github.com/Imgur/mandible/server"
)

func main() {
	configFile := os.Getenv("MANDIBLE_CONF")

	config := mandibleConf.NewConfiguration(configFile)

	var server *mandible.Server
	var stats mandible.RuntimeStats

	if config.DatadogEnabled {
		var err error
		stats, err = mandible.NewDatadogStats(config.DatadogHostname)
		if err != nil {
			log.Printf("Invalid Datadog Hostname: %s", config.DatadogHostname)
			os.Exit(1)
		}
		log.Println("Stats init success")
	} else {
		stats = &mandible.DiscardStats{}
	}

	if os.Getenv("AUTHENTICATION_HMAC_KEY") != "" {
		key := []byte(os.Getenv("AUTHENTICATION_HMAC_KEY"))
		auth := mandible.NewHMACAuthenticatorSHA256(key)
		server = mandible.NewAuthenticatedServer(config, processors.EverythingStrategy, auth, stats)
	} else {
		server = mandible.NewServer(config, processors.EverythingStrategy, stats)
	}

	muxer := http.NewServeMux()
	server.Configure(muxer)

	port := fmt.Sprintf(":%d", server.Config.Port)

	log.Printf("Listening on Port: %s", port)

	stats.LogStartup()
	http.ListenAndServe(port, muxer)
}
<|endoftext|>


<commit_before>/*
Command xo is a command line utility that takes an input string from stdin and
formats the regexp matches.
*/
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

func main() {
	if len(os.Args) == 1 {
		help()
	}

	arg := os.Args[1]
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) != 0 {
		throw("Nothing passed to stdin")
	}

	delimiter := string(arg[0])
	parts := compact(strings.Split(arg, delimiter))
	if len(parts) <= 1 {
		throw("No pattern or formatter specified")
	}

	var (
		flags   string
		pattern string
		format  string
	)

	pattern = parts[0]
	format = parts[1]
	if len(parts) > 2 {
		flags = parts[2]
	}

	rx, err := regexp.Compile(fmt.Sprintf(`(?%s)%s`, flags, pattern))
	if err != nil {
		throw("Invalid regular expression", err.Error())
	}

	in, _ := ioutil.ReadAll(os.Stdin)
	matches := rx.FindAllSubmatch(in, -1)
	if matches == nil {
		throw("No matches found")
	}

	var (
		fallbacks = make(map[int]string)
	)

	for _, group := range matches {
		result := format

		for i, match := range group {
			value := string(match)

			rxFallback, err := regexp.Compile(fmt.Sprintf(`(\$%d)\?:([-_$A-za-z1-9]+)`, i))
			if err != nil {
				throw("Failed to parse default arguments", err.Error())
			}

			fallback := rxFallback.FindStringSubmatch(result)
			if len(fallback) > 1 {
				// Store fallback values if key does not already exist
				if _, ok := fallbacks[i]; !ok {
					fallbacks[i] = string(fallback[2])
				}
				result = rxFallback.ReplaceAllString(result, "$1")
			}

			// Set default for empty values
			if value == "" {
				value = fallbacks[i]
			}

			// Replace values
			rxRepl, _ := regexp.Compile(fmt.Sprintf(`\$%d`, i))
			result = rxRepl.ReplaceAllString(result, value)
		}

		fmt.Printf("%s\n", result)
	}
}

// compact removes empty string values from an array of strings.
func compact(strs []string) []string {
	var result []string

	for _, str := range strs {
		if str != "" {
			result = append(result, str)
		}
	}

	return result
}

// help prints how to use this whole `xo` thing.
func help() {
	fmt.Printf("%s\n", "Usage: xo '/<pattern>/<formatter>/[flags]'")
	os.Exit(0)
}

// throw prints a bunch of strings and then exits with a non-zero exit code.
func throw(errs ...string) {
	for _, err := range errs {
		fmt.Printf("%s\n", err)
	}
	os.Exit(1)
}
<commit_msg>add error when extra delimiter is detected<commit_after>/*
Command xo is a command line utility that takes an input string from stdin and
formats the regexp matches.
*/
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"strings"
)

func main() {
	if len(os.Args) == 1 {
		help()
	}

	arg := os.Args[1]
	stat, _ := os.Stdin.Stat()
	if (stat.Mode() & os.ModeCharDevice) != 0 {
		throw("Nothing passed to stdin")
	}

	delimiter := string(arg[0])
	parts := compact(strings.Split(arg, delimiter))
	if len(parts) <= 1 {
		throw("No pattern or formatter specified")
	}
	if len(parts) > 3 {
		throw("Extra delimiter detected (maybe try one other than `/`)")
	}

	var (
		flags   string
		pattern string
		format  string
	)

	pattern = parts[0]
	format = parts[1]
	if len(parts) > 2 {
		flags = parts[2]
	}

	rx, err := regexp.Compile(fmt.Sprintf(`(?%s)%s`, flags, pattern))
	if err != nil {
		throw("Invalid regular expression", err.Error())
	}

	in, _ := ioutil.ReadAll(os.Stdin)
	matches := rx.FindAllSubmatch(in, -1)
	if matches == nil {
		throw("No matches found")
	}

	var (
		fallbacks = make(map[int]string)
	)

	for _, group := range matches {
		result := format

		for i, match := range group {
			value := string(match)

			rxFallback, err := regexp.Compile(fmt.Sprintf(`(\$%d)\?:([-_$A-za-z1-9]+)`, i))
			if err != nil {
				throw("Failed to parse default arguments", err.Error())
			}

			fallback := rxFallback.FindStringSubmatch(result)
			if len(fallback) > 1 {
				// Store fallback values if key does not already exist
				if _, ok := fallbacks[i]; !ok {
					fallbacks[i] = string(fallback[2])
				}
				result = rxFallback.ReplaceAllString(result, "$1")
			}

			// Set default for empty values
			if value == "" {
				value = fallbacks[i]
			}

			// Replace values
			rxRepl, _ := regexp.Compile(fmt.Sprintf(`\$%d`, i))
			result = rxRepl.ReplaceAllString(result, value)
		}

		fmt.Printf("%s\n", result)
	}
}

// compact removes empty string values from an array of strings.
func compact(strs []string) []string {
	var result []string

	for _, str := range strs {
		if str != "" {
			result = append(result, str)
		}
	}

	return result
}

// help prints how to use this whole `xo` thing.
func help() {
	fmt.Printf("%s\n", "Usage: xo '/<pattern>/<formatter>/[flags]'")
	os.Exit(0)
}

// throw prints a bunch of strings and then exits with a non-zero exit code.
func throw(errs ...string) {
	for _, err := range errs {
		fmt.Printf("%s\n", err)
	}
	os.Exit(1)
}
<|endoftext|>


<commit_before>package main

import (
	"os/exec"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/samalba/dockerclient"
)

var (
	// TODO: should this be shared struct property?
	docker dockerclient.Client
)

func getNamesFromRawLinks(rawLinks []string) ([]string, error) {
	names := []string{}
	for _, rawLinks := range rawLinks {
		// ORIGINAL : "/redis:/adoring_stallman/redis"
		// DESIRED  : "redis" (the last bit of the string)
		// TODO: can this be simplified?
		name := strings.Split(strings.Split(rawLinks, ":")[1], "/")[2]
		names = append(names, name)
	}
	return names, nil
}

func getLinks(c dockerclient.Container) ([]string, error) {
	info, err := docker.InspectContainer(c.Id)
	if err != nil {
		return []string{}, err
	}
	rawLinks := info.HostConfig.Links
	links, err := getNamesFromRawLinks(rawLinks)
	if err != nil {
		return []string{}, err
	}
	log.Infoln("links for", info.Name, "are", links)
	return links, nil
}

func pollRestart(c dockerclient.Container, done chan string, rollers chan string) {
	log.Infoln("Initiating poll restart for ", c.Id)
	depRemaining := make(map[string]bool)
	deps, err := getLinks(c)
	if err != nil {
		log.Fatal(err)
	}
	for _, link := range deps {
		depRemaining[link] = true
	}

	if len(deps) > 0 {
	DepCheck:
		for lastRestarted := range rollers {
			log.Warnln("Read", lastRestarted, "from rollers in goroutine for", c.Id[:7])
			depRemaining[lastRestarted] = false
			log.Infoln("depRemaining is", depRemaining)
			for _, depRemains := range depRemaining {
				if depRemains {
					continue DepCheck
				}
			}
			break DepCheck
		}
	}

	// TODO: should we just scrap getLinks() function
	// altogether if I need to inline this anyway?
	info, err := docker.InspectContainer(c.Id)
	if err != nil {
		log.Fatal(err)
	}

	log.Warnln("Starting", c.Id)

	// Alright, all the deps are done restarting,
	// so let's rock and roll!
	if err := docker.StartContainer(c.Id, nil); err != nil {
		log.Fatal(err)
	}

	// lose the "/" on the beginning of container name
	done <- info.Name[1:]

	// Just catch the rest until the channel closes
	for lastRestarted := range rollers {
		log.Warnln("Read", lastRestarted, "from rollers in goroutine for", c.Id[:7])
	}
}

func main() {
	var (
		err error
	)
	docker, err = dockerclient.NewDockerClient("unix:///var/run/docker.sock", nil)
	if err != nil {
		log.Fatal(err)
	}

	restartDone := make(chan string)

	// todo: should this be slice?
	// i.e. is there any reason to track the id in key?
	rMsgs := []chan string{}

	containers, err := docker.ListContainers(false, false, "")
	if err != nil {
		log.Fatal(err)
	}

	stopMsgs := make(chan bool)
	for _, c := range containers {
		log.Infoln(c.Id, c.Names)
		rMsgs = append(rMsgs, make(chan string))
		go func(id string) {
			log.Infoln("Stopping container", id)
			if err := docker.StopContainer(id, 30); err != nil {
				log.Fatal(err)
			}
			stopMsgs <- true
		}(c.Id)
	}

	// wait for all containers to be stopped
	for i := 0; i < len(containers); i++ {
		<-stopMsgs
	}
	close(stopMsgs)

	log.Info("All containers stopped")

	// restart the daemon
	log.Info("Restarting Docker...")
	if err := exec.Command("sudo", "service", "docker", "restart").Run(); err != nil {
		log.Fatal(err)
	}

	// TODO: this actually works
	// to prevent the race condition ಠ_ಠ
	// use something other than a sleep.
	time.Sleep(5 * time.Second)

	// initiate each container polling for its deps to
	// know when it can restart
	for i, c := range containers {
		go pollRestart(c, restartDone, rMsgs[i])
	}

	for i := 0; i < len(containers); i++ {
		r := <-restartDone
		log.Infoln("Read from channel that", r, "started")
		for _, rMsg := range rMsgs {
			go func(rMsg chan string, r string) {
				log.Warnln("SENDING", r)
				// TODO: better way to implement this?
				rMsg <- r
			}(rMsg, r)
		}
	}

	close(restartDone)
	for _, rMsg := range rMsgs {
		close(rMsg)
	}
	log.Infof("Restarted %d containers", len(containers))
}
<commit_msg>Make timeout hack slightly better<commit_after>package main

import (
	"os/exec"
	"strings"
	"time"

	log "github.com/Sirupsen/logrus"
	"github.com/samalba/dockerclient"
)

var (
	// TODO: should this be shared struct property?
	docker dockerclient.Client
)

func getNamesFromRawLinks(rawLinks []string) ([]string, error) {
	names := []string{}
	for _, rawLinks := range rawLinks {
		// ORIGINAL : "/redis:/adoring_stallman/redis"
		// DESIRED  : "redis" (the last bit of the string)
		// TODO: can this be simplified?
		name := strings.Split(strings.Split(rawLinks, ":")[1], "/")[2]
		names = append(names, name)
	}
	return names, nil
}

func getLinks(c dockerclient.Container) ([]string, error) {
	info, err := docker.InspectContainer(c.Id)
	if err != nil {
		return []string{}, err
	}
	rawLinks := info.HostConfig.Links
	links, err := getNamesFromRawLinks(rawLinks)
	if err != nil {
		return []string{}, err
	}
	log.Infoln("links for", info.Name, "are", links)
	return links, nil
}

func pollRestart(c dockerclient.Container, done chan string, rollers chan string) {
	log.Infoln("Initiating poll restart for ", c.Id)
	depRemaining := make(map[string]bool)
	deps, err := getLinks(c)
	if err != nil {
		log.Fatal(err)
	}
	for _, link := range deps {
		depRemaining[link] = true
	}

	if len(deps) > 0 {
	DepCheck:
		for lastRestarted := range rollers {
			log.Warnln("Read", lastRestarted, "from rollers in goroutine for", c.Id[:7])
			depRemaining[lastRestarted] = false
			log.Infoln("depRemaining is", depRemaining)
			for _, depRemains := range depRemaining {
				if depRemains {
					continue DepCheck
				}
			}
			break DepCheck
		}
	}

	// TODO: should we just scrap getLinks() function
	// altogether if I need to inline this anyway?
	info, err := docker.InspectContainer(c.Id)
	if err != nil {
		log.Fatal(err)
	}

	log.Warnln("Starting", c.Id)

	// Alright, all the deps are done restarting,
	// so let's rock and roll!
	if err := docker.StartContainer(c.Id, nil); err != nil {
		log.Fatal(err)
	}

	// lose the "/" on the beginning of container name
	done <- info.Name[1:]

	// Just catch the rest until the channel closes
	for lastRestarted := range rollers {
		log.Warnln("Read", lastRestarted, "from rollers in goroutine for", c.Id[:7])
	}
}

func main() {
	var (
		err error
	)
	docker, err = dockerclient.NewDockerClient("unix:///var/run/docker.sock", nil)
	if err != nil {
		log.Fatal(err)
	}

	restartDone := make(chan string)

	// todo: should this be slice?
	// i.e. is there any reason to track the id in key?
	rMsgs := []chan string{}

	containers, err := docker.ListContainers(false, false, "")
	if err != nil {
		log.Fatal(err)
	}

	stopMsgs := make(chan bool)
	for _, c := range containers {
		log.Infoln(c.Id, c.Names)
		rMsgs = append(rMsgs, make(chan string))
		go func(id string) {
			log.Infoln("Stopping container", id)
			if err := docker.StopContainer(id, 30); err != nil {
				log.Fatal(err)
			}
			stopMsgs <- true
		}(c.Id)
	}

	// wait for all containers to be stopped
	for i := 0; i < len(containers); i++ {
		<-stopMsgs
	}
	close(stopMsgs)

	log.Info("All containers stopped")

	// restart the daemon
	log.Info("Restarting Docker...")
	if err := exec.Command("sudo", "service", "docker", "restart").Run(); err != nil {
		log.Fatal(err)
	}

	// TODO: Hack because the socket accepts
	// connections before the API is ready to
	// accept requests.
	for {
		_, err := docker.Info()
		if err != nil {
			log.Debug(err)
		} else {
			log.Info("Daemon restarted successfully")
			break
		}
		time.Sleep(100 * time.Millisecond)
	}

	// initiate each container polling for its deps to
	// know when it can restart
	for i, c := range containers {
		go pollRestart(c, restartDone, rMsgs[i])
	}

	for i := 0; i < len(containers); i++ {
		r := <-restartDone
		log.Infoln("Read from channel that", r, "started")
		for _, rMsg := range rMsgs {
			go func(rMsg chan string, r string) {
				log.Warnln("SENDING", r)
				// TODO: better way to implement this?
				rMsg <- r
			}(rMsg, r)
		}
	}

	close(restartDone)
	for _, rMsg := range rMsgs {
		close(rMsg)
	}
	log.Infof("Restarted %d containers", len(containers))
}
<|endoftext|>


<commit_before>package main

import (
  "fmt"
  "os"
  "net/http"
  "github.com/urfave/negroni"
  "github.com/Sirupsen/logrus"
)

var log = logrus.New()

func init() {
  log.Formatter = new(logrus.JSONFormatter)
  log.Formatter = new(logrus.TextFormatter) // default

  // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
  // if err == nil {
  //  log.Out = file
  // } else {
  //  log.Info("Failed to log to file, using default stderr")
  // }

  log.Level = logrus.DebugLevel
}

func main() {
  var port = 3000
  if os.Getenv("HTTP_PLATFORM_PORT") != "" {
    port = os.Getenv("HTTP_PLATFORM_PORT")
  }

  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  n := negroni.Classic() // Includes some default middlewares
  n.UseHandler(mux)

  log.WithFields(logrus.Fields{
    "port": port,
  }).Info(fmt.Sprintf("Starting API"))

  http.ListenAndServe(fmt.Sprintf(":%d",port), n)
}
<commit_msg>fix stuff<commit_after>package main

import (
  "fmt"
  "os"
  "net/http"
  "github.com/urfave/negroni"
  "github.com/Sirupsen/logrus"
)

var log = logrus.New()

func init() {
  log.Formatter = new(logrus.JSONFormatter)
  log.Formatter = new(logrus.TextFormatter) // default

  // file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666)
  // if err == nil {
  //  log.Out = file
  // } else {
  //  log.Info("Failed to log to file, using default stderr")
  // }

  log.Level = logrus.DebugLevel
}

func main() {
  var port = "3000"
  if os.Getenv("HTTP_PLATFORM_PORT") != "" {
    port = os.Getenv("HTTP_PLATFORM_PORT")
  }

  mux := http.NewServeMux()
  mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
    fmt.Fprintf(w, "Welcome to the home page!")
  })

  n := negroni.Classic() // Includes some default middlewares
  n.UseHandler(mux)

  log.WithFields(logrus.Fields{
    "port": port,
  }).Info(fmt.Sprintf("Starting API"))

  http.ListenAndServe(fmt.Sprintf(":%s",port), n)
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"os"
	"path/filepath"

	"github.com/nzai/stockrecorder/config"
	"github.com/nzai/stockrecorder/task"
)

const (
	logFileName    = "main.log"
)

func main() {
	//	当前目录
	rootDir := filepath.Dir(os.Args[0])

	//	读取配置文件
	err := config.SetRootDir(rootDir)
	if err != nil {
		log.Fatal(err)
		return
	}

	//	打开日志文件
	file, err := openLogFile(rootDir)
	if err != nil {
		log.Fatal(err)
		return
	}
	defer file.Close()

	//	设置日志输出文件
	log.SetOutput(file)

	//	启动任务
	err = task.StartTasks()
	if err != nil {
		log.Fatal(err)
		return
	}

	//	阻塞，一直运行
	channel := make(chan int)
	<-channel
}

//	打开日志文件
func openLogFile(rootDir string) (*os.File, error) {
	//	日志文件路径
	dataDir := config.GetDataDir()

	logPath := filepath.Join(dataDir, logFileName)

	return os.OpenFile(logPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0660)
}
<commit_msg>增加了捕捉panic的功能<commit_after>package main

import (
	"log"
	"os"
	"path/filepath"

	"github.com/nzai/stockrecorder/config"
	"github.com/nzai/stockrecorder/task"
)

const (
	logFileName = "main.log"
)

func main() {

	defer func() {
		// 捕获panic异常
		log.Print("发生了致命错误")
		if err := recover(); err != nil {
			log.Print(err)
		}
	}()

	//	当前目录
	rootDir := filepath.Dir(os.Args[0])

	//	读取配置文件
	err := config.SetRootDir(rootDir)
	if err != nil {
		log.Fatal(err)
		return
	}

	//	打开日志文件
	file, err := openLogFile(rootDir)
	if err != nil {
		log.Fatal(err)
		return
	}
	defer file.Close()

	//	设置日志输出文件
	log.SetOutput(file)

	//	启动任务
	err = task.StartTasks()
	if err != nil {
		log.Fatal(err)
		return
	}

	//	阻塞，一直运行
	channel := make(chan int)
	<-channel
}

//	打开日志文件
func openLogFile(rootDir string) (*os.File, error) {
	//	日志文件路径
	dataDir := config.GetDataDir()

	logPath := filepath.Join(dataDir, logFileName)

	return os.OpenFile(logPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0660)
}
<|endoftext|>


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

package main

import (
	"bufio"
	"crypto/tls"
	"crypto/x509"
	"encoding/binary"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"gopkg.in/alecthomas/kingpin.v2"

	"github.com/square/certigo/jceks"
	"golang.org/x/crypto/pkcs12"
	"golang.org/x/crypto/ssh/terminal"
)

var (
	app = kingpin.New("certigo", "A command line certificate examination utility.")

	dump      = app.Command("dump", "Display information about a certificate.")
	dumpFiles = dump.Arg("file", "Certificate file to dump (or stdin if not specified).").ExistingFiles()
	dumpType  = dump.Flag("format", "Format of given input (heuristic guess if not specified).").String()

	connect     = app.Command("connect", "Connect to a server and print its certificate.")
	connectTo   = connect.Arg("server:port", "Hostname or IP to connect to.").String()
	connectName = connect.Flag("name", "Override the server name used for SNI.").String()
)

var fileExtToFormat = map[string]string{
	".pem":   "PEM",
	".crt":   "PEM",
	".p12":   "PKCS12",
	".pfx":   "PKCS12",
	".jceks": "JCEKS",
	".jks":   "JCEKS", // Only partially supported
	".der":   "DER",
}

type certWithAlias struct {
	alias string
	file  string
	cert  *x509.Certificate
}

func main() {
	app.Version("1.0.1")

	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
	case dump.FullCommand(): // Dump certificate
		files := []*os.File{}
		if *dumpFiles != nil {
			for _, filename := range *dumpFiles {
				rawFile, err := os.Open(filename)
				if err != nil {
					fmt.Fprintf(os.Stderr, "unable to open file: %s\n", err)
					os.Exit(1)
				}
				files = append(files, rawFile)
				defer rawFile.Close()
			}
		} else {
			files = append(files, os.Stdin)
		}

		wg := &sync.WaitGroup{}
		certs := make(chan certWithAlias, 1)

		go displayCerts(wg, certs, len(files) > 1)

		readCerts(wg, certs, files)

		wg.Wait()
	case connect.FullCommand(): // Get certs by connecting to a server
		conn, err := tls.Dial("tcp", *connectTo, &tls.Config{
			InsecureSkipVerify: true,
			ServerName:         *connectName,
		})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error connecting: %v\n", err)
			os.Exit(1)
		}
		defer conn.Close()
		for i, cert := range conn.ConnectionState().PeerCertificates {
			fmt.Printf("** CERTIFICATE %d **\n", i+1)
			displayCert(certWithAlias{cert: cert})
		}
	}
}

func readCerts(wg *sync.WaitGroup, certs chan<- certWithAlias, files []*os.File) {
	for _, file := range files {
		reader := bufio.NewReaderSize(file, 4)
		format, ok := formatForFile(reader, file.Name(), *dumpType)
		if !ok {
			fmt.Fprintf(os.Stderr, "unable to guess file type (for file %s)\n", file.Name())
			os.Exit(1)
		}

		readCertsFromFile(wg, reader, file.Name(), format, certs)
	}
}

func displayCerts(wg *sync.WaitGroup, certs <-chan certWithAlias, showFiles bool) {
	i := 1
	for cert := range certs {
		fmt.Printf("** CERTIFICATE %d **\n", i)
		if cert.file != "" && showFiles {
			fmt.Printf("File  : %s\n", path.Base(cert.file))
		}
		displayCert(cert)
		fmt.Println()
		wg.Done()
		i++
	}
}

func readPassword(prompt string) string {
	var tty *os.File
	tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
	if err != nil {
		tty = os.Stdin
	} else {
		defer tty.Close()
	}

	tty.WriteString(prompt)
	password, err := terminal.ReadPassword(int(tty.Fd()))
	tty.WriteString("\n")
	if err != nil {
		fmt.Fprintf(os.Stderr, "error reading password: %s", err)
		os.Exit(1)
	}

	return strings.TrimSuffix(string(password), "\n")
}

// formatForFile returns the file format (either from flags or
// based on file extension).
func formatForFile(file *bufio.Reader, filename, format string) (string, bool) {
	// First, honor --format flag we got from user
	if format != "" {
		return format, true
	}

	// Second, attempt to guess based on extension
	guess, ok := fileExtToFormat[strings.ToLower(filepath.Ext(filename))]
	if ok {
		return guess, true
	}

	// Third, attempt to guess based on first 4 bytes of input
	data, err := file.Peek(4)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}

	// Heuristics for guessing -- best effort.
	magic := binary.BigEndian.Uint32(data)
	if magic == 0xCECECECE || magic == 0xFEEDFEED {
		// JCEKS/JKS files always start with this prefix
		return "JCEKS", true
	}
	if magic == 0x2D2D2D2D || magic == 0x434f4e4e {
		// Starts with '----' or 'CONN' (what s_client prints...)
		return "PEM", true
	}
	if magic&0xFFFF0000 == 0x30820000 {
		// Looks like the input is DER-encoded, so it's either PKCS12 or X.509.
		if magic&0x0000FF00 == 0x0300 {
			// Probably X.509
			return "DER", true
		}
		return "PKCS12", true
	}

	return "", false
}

// pemScanner will return a bufio.Scanner that splits the input
// from the given reader into PEM blocks.
func pemScanner(reader io.Reader) *bufio.Scanner {
	scanner := bufio.NewScanner(reader)

	scanner.Split(func(data []byte, atEOF bool) (int, []byte, error) {
		block, rest := pem.Decode(data)
		if block != nil {
			size := len(data) - len(rest)
			return size, data[:size], nil
		}

		return 0, nil, nil
	})

	return scanner
}

// readCertsFromFile takes in a filename and format type and returns an
// array of all the certificates found in that file along with aliases
// for each cert if the format of the input was jceks. If no format
// is specified for the file, readCertsFromFile guesses what format was used
// based on the file extension used in the file name. If it can't
// guess based on this it returns and error.
func readCertsFromFile(wg *sync.WaitGroup, reader io.Reader, filename string, format string, out chan<- certWithAlias) {
	switch format {
	case "PEM":
		scanner := pemScanner(reader)
		for scanner.Scan() {
			block, _ := pem.Decode(scanner.Bytes())
			cert, err := x509.ParseCertificate(block.Bytes)
			if err != nil {
				fmt.Fprintf(os.Stderr, "error parsing certificate: %s", err)
				os.Exit(1)
			}
			wg.Add(1)
			out <- certWithAlias{file: filename, cert: cert}
		}
	case "DER":
		data, err := ioutil.ReadAll(reader)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error reading input: %s", err)
			os.Exit(1)
		}
		cert, err := x509.ParseCertificate(data)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error parsing certificate: %s", err)
			os.Exit(1)
		}
		wg.Add(1)
		out <- certWithAlias{file: filename, cert: cert}
	case "PKCS12":
		data, err := ioutil.ReadAll(reader)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error reading input: %s", err)
			os.Exit(1)
		}
		password := readPassword("Enter password: ")
		blocks, err := pkcs12.ToPEM(data, password)
		if err != nil || len(blocks) == 0 {
			fmt.Fprint(os.Stderr, "keystore appears to be empty or password was incorrect")
			os.Exit(1)
		}
		for _, block := range blocks {
			if block.Type == "CERTIFICATE" {
				cert, err := x509.ParseCertificate(block.Bytes)
				if err != nil {
					fmt.Fprintf(os.Stderr, "error parsing certificate: %s", err)
					os.Exit(1)
				}
				wg.Add(1)
				out <- certWithAlias{file: filename, cert: cert}
			}
		}
	case "JCEKS":
		password := readPassword("Enter password: ")
		keyStore, err := jceks.LoadFromReader(reader, []byte(password))
		if err != nil {
			fmt.Fprintf(os.Stderr, "error parsing keystore: %s", err)
			os.Exit(1)
		}
		for _, alias := range keyStore.ListCerts() {
			cert, _ := keyStore.GetCert(alias)
			wg.Add(1)
			out <- certWithAlias{file: filename, cert: cert}
		}
		for _, alias := range keyStore.ListPrivateKeys() {
			password := readPassword(fmt.Sprintf("Enter password for alias [%s]: ", alias))
			_, certArr, err := keyStore.GetPrivateKeyAndCerts(alias, []byte(password))
			if err != nil {
				fmt.Fprintf(os.Stderr, "error parsing keystore: %s", err)
				os.Exit(1)
			}
			for _, cert := range certArr {
				wg.Add(1)
				out <- certWithAlias{file: filename, cert: cert}
			}
		}
	default:
		fmt.Fprintf(os.Stderr, "unknown file type: %s", format)
		os.Exit(1)
	}
}
<commit_msg>Print newline after cert dump from connect<commit_after>/*-
 * Copyright 2016 Square Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package main

import (
	"bufio"
	"crypto/tls"
	"crypto/x509"
	"encoding/binary"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
	"sync"

	"gopkg.in/alecthomas/kingpin.v2"

	"github.com/square/certigo/jceks"
	"golang.org/x/crypto/pkcs12"
	"golang.org/x/crypto/ssh/terminal"
)

var (
	app = kingpin.New("certigo", "A command line certificate examination utility.")

	dump      = app.Command("dump", "Display information about a certificate.")
	dumpFiles = dump.Arg("file", "Certificate file to dump (or stdin if not specified).").ExistingFiles()
	dumpType  = dump.Flag("format", "Format of given input (heuristic guess if not specified).").String()

	connect     = app.Command("connect", "Connect to a server and print its certificate.")
	connectTo   = connect.Arg("server:port", "Hostname or IP to connect to.").String()
	connectName = connect.Flag("name", "Override the server name used for SNI.").String()
)

var fileExtToFormat = map[string]string{
	".pem":   "PEM",
	".crt":   "PEM",
	".p12":   "PKCS12",
	".pfx":   "PKCS12",
	".jceks": "JCEKS",
	".jks":   "JCEKS", // Only partially supported
	".der":   "DER",
}

type certWithAlias struct {
	alias string
	file  string
	cert  *x509.Certificate
}

func main() {
	app.Version("1.0.1")

	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
	case dump.FullCommand(): // Dump certificate
		files := []*os.File{}
		if *dumpFiles != nil {
			for _, filename := range *dumpFiles {
				rawFile, err := os.Open(filename)
				if err != nil {
					fmt.Fprintf(os.Stderr, "unable to open file: %s\n", err)
					os.Exit(1)
				}
				files = append(files, rawFile)
				defer rawFile.Close()
			}
		} else {
			files = append(files, os.Stdin)
		}

		wg := &sync.WaitGroup{}
		certs := make(chan certWithAlias, 1)

		go displayCerts(wg, certs, len(files) > 1)

		readCerts(wg, certs, files)

		wg.Wait()
	case connect.FullCommand(): // Get certs by connecting to a server
		conn, err := tls.Dial("tcp", *connectTo, &tls.Config{
			InsecureSkipVerify: true,
			ServerName:         *connectName,
		})
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error connecting: %v\n", err)
			os.Exit(1)
		}
		defer conn.Close()
		for i, cert := range conn.ConnectionState().PeerCertificates {
			fmt.Printf("** CERTIFICATE %d **\n", i+1)
			displayCert(certWithAlias{cert: cert})
			fmt.Println()
		}
	}
}

func readCerts(wg *sync.WaitGroup, certs chan<- certWithAlias, files []*os.File) {
	for _, file := range files {
		reader := bufio.NewReaderSize(file, 4)
		format, ok := formatForFile(reader, file.Name(), *dumpType)
		if !ok {
			fmt.Fprintf(os.Stderr, "unable to guess file type (for file %s)\n", file.Name())
			os.Exit(1)
		}

		readCertsFromFile(wg, reader, file.Name(), format, certs)
	}
}

func displayCerts(wg *sync.WaitGroup, certs <-chan certWithAlias, showFiles bool) {
	i := 1
	for cert := range certs {
		fmt.Printf("** CERTIFICATE %d **\n", i)
		if cert.file != "" && showFiles {
			fmt.Printf("File  : %s\n", path.Base(cert.file))
		}
		displayCert(cert)
		fmt.Println()
		wg.Done()
		i++
	}
}

func readPassword(prompt string) string {
	var tty *os.File
	tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
	if err != nil {
		tty = os.Stdin
	} else {
		defer tty.Close()
	}

	tty.WriteString(prompt)
	password, err := terminal.ReadPassword(int(tty.Fd()))
	tty.WriteString("\n")
	if err != nil {
		fmt.Fprintf(os.Stderr, "error reading password: %s", err)
		os.Exit(1)
	}

	return strings.TrimSuffix(string(password), "\n")
}

// formatForFile returns the file format (either from flags or
// based on file extension).
func formatForFile(file *bufio.Reader, filename, format string) (string, bool) {
	// First, honor --format flag we got from user
	if format != "" {
		return format, true
	}

	// Second, attempt to guess based on extension
	guess, ok := fileExtToFormat[strings.ToLower(filepath.Ext(filename))]
	if ok {
		return guess, true
	}

	// Third, attempt to guess based on first 4 bytes of input
	data, err := file.Peek(4)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}

	// Heuristics for guessing -- best effort.
	magic := binary.BigEndian.Uint32(data)
	if magic == 0xCECECECE || magic == 0xFEEDFEED {
		// JCEKS/JKS files always start with this prefix
		return "JCEKS", true
	}
	if magic == 0x2D2D2D2D || magic == 0x434f4e4e {
		// Starts with '----' or 'CONN' (what s_client prints...)
		return "PEM", true
	}
	if magic&0xFFFF0000 == 0x30820000 {
		// Looks like the input is DER-encoded, so it's either PKCS12 or X.509.
		if magic&0x0000FF00 == 0x0300 {
			// Probably X.509
			return "DER", true
		}
		return "PKCS12", true
	}

	return "", false
}

// pemScanner will return a bufio.Scanner that splits the input
// from the given reader into PEM blocks.
func pemScanner(reader io.Reader) *bufio.Scanner {
	scanner := bufio.NewScanner(reader)

	scanner.Split(func(data []byte, atEOF bool) (int, []byte, error) {
		block, rest := pem.Decode(data)
		if block != nil {
			size := len(data) - len(rest)
			return size, data[:size], nil
		}

		return 0, nil, nil
	})

	return scanner
}

// readCertsFromFile takes in a filename and format type and returns an
// array of all the certificates found in that file along with aliases
// for each cert if the format of the input was jceks. If no format
// is specified for the file, readCertsFromFile guesses what format was used
// based on the file extension used in the file name. If it can't
// guess based on this it returns and error.
func readCertsFromFile(wg *sync.WaitGroup, reader io.Reader, filename string, format string, out chan<- certWithAlias) {
	switch format {
	case "PEM":
		scanner := pemScanner(reader)
		for scanner.Scan() {
			block, _ := pem.Decode(scanner.Bytes())
			cert, err := x509.ParseCertificate(block.Bytes)
			if err != nil {
				fmt.Fprintf(os.Stderr, "error parsing certificate: %s", err)
				os.Exit(1)
			}
			wg.Add(1)
			out <- certWithAlias{file: filename, cert: cert}
		}
	case "DER":
		data, err := ioutil.ReadAll(reader)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error reading input: %s", err)
			os.Exit(1)
		}
		cert, err := x509.ParseCertificate(data)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error parsing certificate: %s", err)
			os.Exit(1)
		}
		wg.Add(1)
		out <- certWithAlias{file: filename, cert: cert}
	case "PKCS12":
		data, err := ioutil.ReadAll(reader)
		if err != nil {
			fmt.Fprintf(os.Stderr, "error reading input: %s", err)
			os.Exit(1)
		}
		password := readPassword("Enter password: ")
		blocks, err := pkcs12.ToPEM(data, password)
		if err != nil || len(blocks) == 0 {
			fmt.Fprint(os.Stderr, "keystore appears to be empty or password was incorrect")
			os.Exit(1)
		}
		for _, block := range blocks {
			if block.Type == "CERTIFICATE" {
				cert, err := x509.ParseCertificate(block.Bytes)
				if err != nil {
					fmt.Fprintf(os.Stderr, "error parsing certificate: %s", err)
					os.Exit(1)
				}
				wg.Add(1)
				out <- certWithAlias{file: filename, cert: cert}
			}
		}
	case "JCEKS":
		password := readPassword("Enter password: ")
		keyStore, err := jceks.LoadFromReader(reader, []byte(password))
		if err != nil {
			fmt.Fprintf(os.Stderr, "error parsing keystore: %s", err)
			os.Exit(1)
		}
		for _, alias := range keyStore.ListCerts() {
			cert, _ := keyStore.GetCert(alias)
			wg.Add(1)
			out <- certWithAlias{file: filename, cert: cert}
		}
		for _, alias := range keyStore.ListPrivateKeys() {
			password := readPassword(fmt.Sprintf("Enter password for alias [%s]: ", alias))
			_, certArr, err := keyStore.GetPrivateKeyAndCerts(alias, []byte(password))
			if err != nil {
				fmt.Fprintf(os.Stderr, "error parsing keystore: %s", err)
				os.Exit(1)
			}
			for _, cert := range certArr {
				wg.Add(1)
				out <- certWithAlias{file: filename, cert: cert}
			}
		}
	default:
		fmt.Fprintf(os.Stderr, "unknown file type: %s", format)
		os.Exit(1)
	}
}
<|endoftext|>