<commit_before>package main

import (
	"bufio"
	"crypto/tls"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"
)

// urlsInProgress is a wait group, for concurrency
var urlsInProgress sync.WaitGroup

// Responses is a channel to store the concurrent responses from the target
var responses chan *http.Response

// RedirectError is a custom error type for following redirects, and can be safely ignored
type RedirectError struct {
	RedirectRequest *http.Request
}

// Error method returns a string of the error
func (err *RedirectError) Error() string {
	return fmt.Sprintf("Redirect not followed to: %v", err.RedirectRequest.URL.String())
}

// Request body content
var body string

// Target URL value
var targetURL *url.URL

// Cookie jar value
var jar *cookiejar.Jar

// Number of requests
var numRequests int

// Request type
var requestType string

// Follow redirects
var followRedirects bool

// Verbose logging enabled
var verbose bool

// Command-line flags
var flagTargetURL = flag.String("url", "", "URL to send the request to.")
var flagBodyFile = flag.String("body", "", "The location (relative or absolute path) of a file containing the body of the request.")
var flagCookiesFile = flag.String("cookies", "", "The location (relative or absolute path) of a file containing newline-separate cookie values being sent along with the request. Cookie names and values are separated by a comma. For example: cookiename,cookieval")
var flagNumRequests = flag.Int("requests", 100, "The number of requests to send to the destination URL.")
var flagRequestType = flag.String("request", "POST", "The request type. Can be either `POST, GET, HEAD, PUT`.")
var flagFollowRedirects = flag.Bool("redirects", false, "Follow redirects (3xx status code in responses)")
var flagVerbose = flag.Bool("v", false, "Enable verbose logging.")

func main() {
	// Change output location of logs
	log.SetOutput(os.Stdout)

	// Check the flags
	err := checkFlags()
	if err != nil {
		log.Println(err.Error())
		flag.Usage()
		os.Exit(1)
	}

	// Send the requests concurrently
	log.Println("Requests begin.")
	errChan := sendRequests()
	if len(errChan) != 0 {
		for err := range errChan {
			log.Printf("[ERROR] %s\n", err.Error())
		}
	}

	// Compare the responses for uniqueness
	uniqueResponses := compareResponses()

	// Output the responses
	outputResponses(uniqueResponses)

	// Echo completion
	log.Println("Complete.")
}

// Function checkFlags checks that all necessary flags are entered, and parses them for contents.
// Returns a custom error if something went wrong.
func checkFlags() error {
	// Parse the flags
	flag.Parse()

	// Set verbose logging explicitely
	verbose = *flagVerbose

	// Determine whether to follow redirects
	followRedirects = *flagFollowRedirects

	// Set the request type
	switch strings.ToUpper(*flagRequestType) {
	case "POST":
		requestType = "POST"
	case "GET":
		requestType = "GET"
	case "PUT":
		requestType = "PUT"
	case "HEAD":
		requestType = "HEAD"
	default:
		// Invalid request type specified
		return fmt.Errorf("Invalid request type specified.")
	}

	// Ensure that the destination URL is present
	if *flagTargetURL == "" {
		return fmt.Errorf("Destination URL required.")
	}

	// Parse the URL
	var err error
	targetURL, err = url.Parse(*flagTargetURL)
	if err != nil {
		return fmt.Errorf("Invalid URL provided: %s", *flagTargetURL)
	}

	// Get the request body content
	if *flagBodyFile != "" {
		file, err := os.Open(*flagBodyFile)
		if err != nil {
			// Error opening the file
			return fmt.Errorf("Unable to open the file: %s\n", *flagBodyFile)
		}

		// Ensure that the file is closed
		defer file.Close()

		// Initialize the file scanner
		scanner := bufio.NewScanner(file)

		// Iterate through the first line of the file
		line := 0
		for scanner.Scan() && line < 1 {
			body = scanner.Text()
			line++
		}
	} else {
		// Body file flag not present, exit.
		return fmt.Errorf("Request body contents required.")
	}

	// Check the number of requests used for testing
	numRequests = *flagNumRequests

	// Initialize the cookie jar
	jar, _ = cookiejar.New(nil)
	var cookies []*http.Cookie
	// Get the cookies to pass to the request
	if *flagCookiesFile != "" {
		file, err := os.Open(*flagCookiesFile)
		if err != nil {
			// Error opening the file
			return fmt.Errorf("Unable to open the file: %s", *flagCookiesFile)
		}

		// Ensure the file is closed
		defer file.Close()

		// Initialize the file scanner
		scanner := bufio.NewScanner(file)

		// Iterate through the file to get the cookies
		for scanner.Scan() {
			// Parse the line to separate the cookie names and values
			nextLine := scanner.Text()
			vals := strings.Split(nextLine, ",")
			cookieName := strings.TrimSpace(vals[0])
			cookieValue := strings.TrimSpace(vals[1])

			// Create the cookie
			cookie := &http.Cookie{
				Name:  cookieName,
				Value: cookieValue,
			}

			// Add the cookie to the existing slice of cookies
			cookies = append(cookies, cookie)
		}

		// Set the cookies to the appropriate URL
		jar.SetCookies(targetURL, cookies)

	}

	// Made it through with no errors, return
	return nil
}

// Function sendRequests takes care of sending the requests to the target concurrently.
// Errors are passed back in a channel of errors. If the length is zero, there were no errors.
func sendRequests() chan error {
	// Initialize the concurrency objects
	responses = make(chan *http.Response, numRequests)
	errorChannel := make(chan error, numRequests)
	urlsInProgress.Add(numRequests)

	// VERBOSE
	if verbose {
		log.Printf("[VERBOSE] Sending %d %s requests to %s\n", numRequests, requestType, targetURL.String())
		if body != "" {
			log.Printf("[VERBOSE] Request body: %s", body)
		}
	}
	for i := 0; i < numRequests; i++ {
		go func(index int) {
			// Ensure that the waitgroup element is returned
			defer urlsInProgress.Done()

			// Convert the request body to an io.Reader interface, to pass to the request.
			// This must be done in the loop, because any call to client.Do() will
			// read the body contents on the first time, but not any subsequent requests.
			requestBody := strings.NewReader(body)

			// Declare HTTP request method and URL
			req, err := http.NewRequest(requestType, targetURL.String(), requestBody)
			if err != nil {
				errorChannel <- fmt.Errorf("Error in forming request: %v", err.Error())
				return
			}

			// Create the HTTP client
			// Using Cookie jar
			// Ignoring TLS errors
			// Ignoring redirects (more accurate output), depending on user flag
			// Implementing a connection timeouts, for slow clients & servers (especially important with race conditions on the server)
			var client http.Client
			if followRedirects {
				client = http.Client{
					Jar: jar,
					Transport: &http.Transport{
						TLSClientConfig: &tls.Config{
							InsecureSkipVerify: true,
						},
					},
					Timeout: 20 * time.Second,
				}
			} else {
				client = http.Client{
					Jar: jar,
					Transport: &http.Transport{
						TLSClientConfig: &tls.Config{
							InsecureSkipVerify: true,
						},
					},
					CheckRedirect: func(req *http.Request, via []*http.Request) error {
						// Craft the custom error
						redirectError := RedirectError{req}
						return &redirectError
					},
					Timeout: 20 * time.Second,
				}
			}

			// Make the request
			resp, err := client.Do(req)
			// Check the error type from the request
			if err != nil {
				if uErr, ok := err.(*url.Error); ok {
					if rErr, ok2 := uErr.Err.(*RedirectError); ok2 {
						// Redirect error
						// VERBOSE
						if verbose {
							log.Printf("[VERBOSE] %v\n", rErr)
						}
						// Add the response to the responses channel, because it is still valid
						responses <- resp
					} else {
						// URL Error, but not a redirect error
						errorChannel <- fmt.Errorf("Error in request #%v: %v\n", index, err)
					}
				} else {
					// Other type of error
					errorChannel <- fmt.Errorf("Error in request #%v: %v\n", index, err)
				}
			} else {
				// Add the response to the responses channel
				responses <- resp
			}
		}(i)
	}

	// Wait for the URLs to finish sending
	urlsInProgress.Wait()

	// VERBOSE
	if verbose {
		log.Printf("[VERBOSE] Requests complete.")
	}

	// Close the response and error chanels, so they don't block on the range read
	close(responses)
	close(errorChannel)

	return errorChannel
}

// Function compareResponses compares the responses returned from the requests,
// and adds them to a map, where the key is an *http.Response, and the value is
// the number of similar responses observed.
func compareResponses() (uniqueResponses map[*http.Response]int) {
	// Initialize the unique responses map
	uniqueResponses = make(map[*http.Response]int)

	// VERBOSE
	if verbose {
		log.Printf("[VERBOSE] Unique response comparison begin.\n")
	}

	// Compare the responses, one at a time
	for resp := range responses {
		// Add an entry, if the unique responses map is empty
		if len(uniqueResponses) == 0 {
			uniqueResponses[resp] = 0
		} else {
			// Add to the unique responses map, if no similar ones exist
			for uResp := range uniqueResponses {
				// Compare response status code & content length
				if resp.StatusCode == uResp.StatusCode && resp.ContentLength == uResp.ContentLength {
					// Similar, increase count
					uniqueResponses[uResp]++
					// Exit inner loop
					continue
				} else {
					// Unique, add to unique responses
					uniqueResponses[resp] = 0
					// Exit inner loop
					continue
				}
			}
		}
	}

	// VERBOSE
	if verbose {
		log.Printf("[VERBOSE] Unique response comparision complete.\n")
	}

	return
}

func outputResponses(uniqueResponses map[*http.Response]int) {
	// Display the responses
	log.Printf("Responses:\n")
	for resp, count := range uniqueResponses {
		fmt.Printf("Response:\n")
		fmt.Printf("[Status Code] %v\n", resp.StatusCode)
		fmt.Printf("[Protocol] %v\n", resp.Proto)
		if len(resp.Header) != 0 {
			fmt.Println("[Headers]")
			for header, value := range resp.Header {
				fmt.Printf("\t%v: %v\n", header, value)
			}
		}
		location, err := resp.Location()
		if err != http.ErrNoLocation {
			fmt.Printf("[Location] %v\n", location.String())
		}
		respBody, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("[Body] ")
		} else {
			fmt.Printf("[Body]\n%s\n", respBody)
			// Close the response body
			resp.Body.Close()
		}
		fmt.Printf("Similar: %v\n\n", count)
	}
}

// BUG: Not reading some response bodies. Might be a timeout issue?
// TODO: Compare response body as well (if content-length != 0)
<commit_msg>Optimization More concise read from the body file.<commit_after>package main

import (
	"bufio"
	"crypto/tls"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"os"
	"strings"
	"sync"
	"time"
)

// urlsInProgress is a wait group, for concurrency
var urlsInProgress sync.WaitGroup

// Responses is a channel to store the concurrent responses from the target
var responses chan *http.Response

// RedirectError is a custom error type for following redirects, and can be safely ignored
type RedirectError struct {
	RedirectRequest *http.Request
}

// Error method returns a string of the error
func (err *RedirectError) Error() string {
	return fmt.Sprintf("Redirect not followed to: %v", err.RedirectRequest.URL.String())
}

// Request body content
var body string

// Target URL value
var targetURL *url.URL

// Cookie jar value
var jar *cookiejar.Jar

// Number of requests
var numRequests int

// Request type
var requestType string

// Follow redirects
var followRedirects bool

// Verbose logging enabled
var verbose bool

// Command-line flags
var flagTargetURL = flag.String("url", "", "URL to send the request to.")
var flagBodyFile = flag.String("body", "", "The location (relative or absolute path) of a file containing the body of the request.")
var flagCookiesFile = flag.String("cookies", "", "The location (relative or absolute path) of a file containing newline-separate cookie values being sent along with the request. Cookie names and values are separated by a comma. For example: cookiename,cookieval")
var flagNumRequests = flag.Int("requests", 100, "The number of requests to send to the destination URL.")
var flagRequestType = flag.String("request", "POST", "The request type. Can be either `POST, GET, HEAD, PUT`.")
var flagFollowRedirects = flag.Bool("redirects", false, "Follow redirects (3xx status code in responses)")
var flagVerbose = flag.Bool("v", false, "Enable verbose logging.")

func main() {
	// Change output location of logs
	log.SetOutput(os.Stdout)

	// Check the flags
	err := checkFlags()
	if err != nil {
		log.Println(err.Error())
		flag.Usage()
		os.Exit(1)
	}

	// Send the requests concurrently
	log.Println("Requests begin.")
	errChan := sendRequests()
	if len(errChan) != 0 {
		for err := range errChan {
			log.Printf("[ERROR] %s\n", err.Error())
		}
	}

	// Compare the responses for uniqueness
	uniqueResponses := compareResponses()

	// Output the responses
	outputResponses(uniqueResponses)

	// Echo completion
	log.Println("Complete.")
}

// Function checkFlags checks that all necessary flags are entered, and parses them for contents.
// Returns a custom error if something went wrong.
func checkFlags() error {
	// Parse the flags
	flag.Parse()

	// Set verbose logging explicitely
	verbose = *flagVerbose

	// Determine whether to follow redirects
	followRedirects = *flagFollowRedirects

	// Set the request type
	switch strings.ToUpper(*flagRequestType) {
	case "POST":
		requestType = "POST"
	case "GET":
		requestType = "GET"
	case "PUT":
		requestType = "PUT"
	case "HEAD":
		requestType = "HEAD"
	default:
		// Invalid request type specified
		return fmt.Errorf("Invalid request type specified.")
	}

	// Ensure that the destination URL is present
	if *flagTargetURL == "" {
		return fmt.Errorf("Destination URL required.")
	}

	// Parse the URL
	var err error
	targetURL, err = url.Parse(*flagTargetURL)
	if err != nil {
		return fmt.Errorf("Invalid URL provided: %s", *flagTargetURL)
	}

	// Get the request body content
	if *flagBodyFile != "" {
		buf, err := ioutil.ReadFile(*flagBodyFile)
		if err != nil {
			// Error opening the file
			return fmt.Errorf("Unable to open the file: %s\n", *flagBodyFile)
		}
		body = string(buf)
	} else {
		// Body file flag not present, exit.
		return fmt.Errorf("Request body contents required.")
	}

	// Check the number of requests used for testing
	numRequests = *flagNumRequests

	// Initialize the cookie jar
	jar, _ = cookiejar.New(nil)
	var cookies []*http.Cookie
	// Get the cookies to pass to the request
	if *flagCookiesFile != "" {
		file, err := os.Open(*flagCookiesFile)
		if err != nil {
			// Error opening the file
			return fmt.Errorf("Unable to open the file: %s", *flagCookiesFile)
		}

		// Ensure the file is closed
		defer file.Close()

		// Initialize the file scanner
		scanner := bufio.NewScanner(file)

		// Iterate through the file to get the cookies
		for scanner.Scan() {
			// Parse the line to separate the cookie names and values
			nextLine := scanner.Text()
			vals := strings.Split(nextLine, ",")
			cookieName := strings.TrimSpace(vals[0])
			cookieValue := strings.TrimSpace(vals[1])

			// Create the cookie
			cookie := &http.Cookie{
				Name:  cookieName,
				Value: cookieValue,
			}

			// Add the cookie to the existing slice of cookies
			cookies = append(cookies, cookie)
		}

		// Set the cookies to the appropriate URL
		jar.SetCookies(targetURL, cookies)

	}

	// Made it through with no errors, return
	return nil
}

// Function sendRequests takes care of sending the requests to the target concurrently.
// Errors are passed back in a channel of errors. If the length is zero, there were no errors.
func sendRequests() chan error {
	// Initialize the concurrency objects
	responses = make(chan *http.Response, numRequests)
	errorChannel := make(chan error, numRequests)
	urlsInProgress.Add(numRequests)

	// VERBOSE
	if verbose {
		log.Printf("[VERBOSE] Sending %d %s requests to %s\n", numRequests, requestType, targetURL.String())
		if body != "" {
			log.Printf("[VERBOSE] Request body: %s", body)
		}
	}
	for i := 0; i < numRequests; i++ {
		go func(index int) {
			// Ensure that the waitgroup element is returned
			defer urlsInProgress.Done()

			// Convert the request body to an io.Reader interface, to pass to the request.
			// This must be done in the loop, because any call to client.Do() will
			// read the body contents on the first time, but not any subsequent requests.
			requestBody := strings.NewReader(body)

			// Declare HTTP request method and URL
			req, err := http.NewRequest(requestType, targetURL.String(), requestBody)
			if err != nil {
				errorChannel <- fmt.Errorf("Error in forming request: %v", err.Error())
				return
			}

			// Create the HTTP client
			// Using Cookie jar
			// Ignoring TLS errors
			// Ignoring redirects (more accurate output), depending on user flag
			// Implementing a connection timeouts, for slow clients & servers (especially important with race conditions on the server)
			var client http.Client
			if followRedirects {
				client = http.Client{
					Jar: jar,
					Transport: &http.Transport{
						TLSClientConfig: &tls.Config{
							InsecureSkipVerify: true,
						},
					},
					Timeout: 20 * time.Second,
				}
			} else {
				client = http.Client{
					Jar: jar,
					Transport: &http.Transport{
						TLSClientConfig: &tls.Config{
							InsecureSkipVerify: true,
						},
					},
					CheckRedirect: func(req *http.Request, via []*http.Request) error {
						// Craft the custom error
						redirectError := RedirectError{req}
						return &redirectError
					},
					Timeout: 20 * time.Second,
				}
			}

			// Make the request
			resp, err := client.Do(req)
			// Check the error type from the request
			if err != nil {
				if uErr, ok := err.(*url.Error); ok {
					if rErr, ok2 := uErr.Err.(*RedirectError); ok2 {
						// Redirect error
						// VERBOSE
						if verbose {
							log.Printf("[VERBOSE] %v\n", rErr)
						}
						// Add the response to the responses channel, because it is still valid
						responses <- resp
					} else {
						// URL Error, but not a redirect error
						errorChannel <- fmt.Errorf("Error in request #%v: %v\n", index, err)
					}
				} else {
					// Other type of error
					errorChannel <- fmt.Errorf("Error in request #%v: %v\n", index, err)
				}
			} else {
				// Add the response to the responses channel
				responses <- resp
			}
		}(i)
	}

	// Wait for the URLs to finish sending
	urlsInProgress.Wait()

	// VERBOSE
	if verbose {
		log.Printf("[VERBOSE] Requests complete.")
	}

	// Close the response and error chanels, so they don't block on the range read
	close(responses)
	close(errorChannel)

	return errorChannel
}

// Function compareResponses compares the responses returned from the requests,
// and adds them to a map, where the key is an *http.Response, and the value is
// the number of similar responses observed.
func compareResponses() (uniqueResponses map[*http.Response]int) {
	// Initialize the unique responses map
	uniqueResponses = make(map[*http.Response]int)

	// VERBOSE
	if verbose {
		log.Printf("[VERBOSE] Unique response comparison begin.\n")
	}

	// Compare the responses, one at a time
	for resp := range responses {
		// Add an entry, if the unique responses map is empty
		if len(uniqueResponses) == 0 {
			uniqueResponses[resp] = 0
		} else {
			// Add to the unique responses map, if no similar ones exist
			for uResp := range uniqueResponses {
				// Compare response status code, body content, and content length
				if resp.StatusCode == uResp.StatusCode && resp.ContentLength == uResp.ContentLength {
					// Similar, increase count
					uniqueResponses[uResp]++
					// Exit inner loop
					continue
				} else {
					// Unique, add to unique responses
					uniqueResponses[resp] = 0
					// Exit inner loop
					continue
				}
			}
		}
	}

	// VERBOSE
	if verbose {
		log.Printf("[VERBOSE] Unique response comparision complete.\n")
	}

	return
}

func outputResponses(uniqueResponses map[*http.Response]int) {
	// Display the responses
	log.Printf("Responses:\n")
	for resp, count := range uniqueResponses {
		fmt.Printf("Response:\n")
		fmt.Printf("[Status Code] %v\n", resp.StatusCode)
		fmt.Printf("[Protocol] %v\n", resp.Proto)
		if len(resp.Header) != 0 {
			fmt.Println("[Headers]")
			for header, value := range resp.Header {
				fmt.Printf("\t%v: %v\n", header, value)
			}
		}
		location, err := resp.Location()
		if err != http.ErrNoLocation {
			fmt.Printf("[Location] %v\n", location.String())
		}
		respBody, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			fmt.Println("[Body] ")
		} else {
			fmt.Printf("[Body]\n%s\n", respBody)
			// Close the response body
			resp.Body.Close()
		}
		fmt.Printf("Similar: %v\n\n", count)
	}
}

// BUG: Not reading some response bodies. Might be a timeout issue?
// TODO: Compare response body as well (if content-length != 0)
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/isotopsweden/docker-farmer/config"
	"github.com/isotopsweden/docker-farmer/docker"
	"github.com/isotopsweden/docker-farmer/handlers"
)

var (
	configFlag = flag.String("config", "", "Path to config file")
)

func main() {
	flag.Parse()

	// Init config.
	config.Init(*configFlag)
	c := config.Get()

	if c.Listen[0] == ':' {
		c.Listen = "0.0.0.0" + c.Listen
	}

	// Index route.
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		containers, err := docker.GetContainers(c.Domain)

		if err != nil {
			fmt.Fprintf(w, err.Error())
		} else {
			sites := []string{}

			for _, c := range containers {
				name := c.Names[0][1:]
				sites = append(sites, name)
			}

			j, err := json.Marshal(map[string]interface{}{
				"sites": sites,
			})

			if err != nil {
				fmt.Fprintf(w, err.Error())
			} else {
				fmt.Fprintf(w, string(j))
			}
		}
	})

	// Containers route.
	http.HandleFunc("/containers", func(w http.ResponseWriter, r *http.Request) {
		containers, err := docker.GetContainers(c.Domain)

		if err != nil {
			fmt.Fprintf(w, err.Error())
		} else {
			j, err := json.Marshal(containers)

			if err != nil {
				fmt.Fprintf(w, err.Error())
			} else {
				fmt.Fprintf(w, string(j))
			}
		}
	})

	// Database route.
	http.HandleFunc("/database", func(w http.ResponseWriter, r *http.Request) {
		name := r.URL.Query().Get("name")

		if name == "" {
			fmt.Fprintf(w, "No name query string")
			return
		}

		conf := config.Get()
		ok, err := docker.DeleteDatabase(conf.Database.User, conf.Database.Password, conf.Database.Prefix, name, conf.Database.Container)

		if err != nil {
			fmt.Fprintf(w, err.Error())
		} else {
			j, err := json.Marshal(map[string]bool{
				"success": ok,
			})

			if err != nil {
				fmt.Fprintf(w, err.Error())
			} else {
				fmt.Fprintf(w, string(j))
			}
		}
	})

	// BitBucket service route.
	http.HandleFunc("/services/bitbucket", handlers.BitbucketHandler)

	// GitHub service route.
	http.HandleFunc("/services/github", handlers.GithubHandler)

	// GitLab service route.
	http.HandleFunc("/services/gitlab", handlers.GitlabHandler)

	// Jira service route.
	http.HandleFunc("/services/jira", handlers.JiraHandler)

	fmt.Printf("Listening to http://%s\n", c.Listen)

	// Listen to port.
	log.Fatal(http.ListenAndServe(c.Listen, nil))
}
<commit_msg>Check for database type in database route<commit_after>package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net/http"

	"github.com/isotopsweden/docker-farmer/config"
	"github.com/isotopsweden/docker-farmer/docker"
	"github.com/isotopsweden/docker-farmer/handlers"
)

var (
	configFlag = flag.String("config", "", "Path to config file")
)

func main() {
	flag.Parse()

	// Init config.
	config.Init(*configFlag)
	c := config.Get()

	if c.Listen[0] == ':' {
		c.Listen = "0.0.0.0" + c.Listen
	}

	// Index route.
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		containers, err := docker.GetContainers(c.Domain)

		if err != nil {
			fmt.Fprintf(w, err.Error())
		} else {
			sites := []string{}

			for _, c := range containers {
				name := c.Names[0][1:]
				sites = append(sites, name)
			}

			j, err := json.Marshal(map[string]interface{}{
				"sites": sites,
			})

			if err != nil {
				fmt.Fprintf(w, err.Error())
			} else {
				fmt.Fprintf(w, string(j))
			}
		}
	})

	// Containers route.
	http.HandleFunc("/containers", func(w http.ResponseWriter, r *http.Request) {
		containers, err := docker.GetContainers(c.Domain)

		if err != nil {
			fmt.Fprintf(w, err.Error())
		} else {
			j, err := json.Marshal(containers)

			if err != nil {
				fmt.Fprintf(w, err.Error())
			} else {
				fmt.Fprintf(w, string(j))
			}
		}
	})

	// Database route.
	http.HandleFunc("/database", func(w http.ResponseWriter, r *http.Request) {
		name := r.URL.Query().Get("name")
		typ := r.URL.Query().Get("type")

		if name == "" {
			fmt.Fprintf(w, "No name query string")
			return
		}

		if typ == "" {
			typ = "mysql"
		}

		conf := config.Get()

		ok := false
		var err error

		switch typ {
		case "mysql":
			ok, err = docker.DeleteDatabase(conf.Database.User, conf.Database.Password, conf.Database.Prefix, name, conf.Database.Container)
			break
		default:
			break
		}

		if err != nil {
			fmt.Fprintf(w, err.Error())
		} else {
			j, err := json.Marshal(map[string]bool{
				"success": ok,
			})

			if err != nil {
				fmt.Fprintf(w, err.Error())
			} else {
				fmt.Fprintf(w, string(j))
			}
		}
	})

	// BitBucket service route.
	http.HandleFunc("/services/bitbucket", handlers.BitbucketHandler)

	// GitHub service route.
	http.HandleFunc("/services/github", handlers.GithubHandler)

	// GitLab service route.
	http.HandleFunc("/services/gitlab", handlers.GitlabHandler)

	// Jira service route.
	http.HandleFunc("/services/jira", handlers.JiraHandler)

	fmt.Printf("Listening to http://%s\n", c.Listen)

	// Listen to port.
	log.Fatal(http.ListenAndServe(c.Listen, nil))
}
<|endoftext|>


<commit_before>// See LICENSE.txt for licensing information.

package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"time"
)

const (
	VERSION = `0.2`
	timeFmt = `2006-01-02 15:04:05`
	fileFmt = `2006-01-02_150405`
)

var (
	flagConfig  string
	flagVerbose bool
	cfg         *Config
	idRange     = regexp.MustCompile(`(\d+)-(\d+)`)
)

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s (options...) <command>\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "saver v%s by Piotr S. Staszewski, see LICENSE.txt\n\n", VERSION)
		fmt.Fprintln(os.Stderr, "Options:")
		flag.PrintDefaults()
		fmt.Fprintln(os.Stderr, "\nCommands:")
		fmt.Fprintln(os.Stderr, "  [a]dd <name> <path>                 - add new game")
		fmt.Fprintln(os.Stderr, "  [d]el <name>                        - delete game and all saves")
		fmt.Fprintln(os.Stderr, "  [l]ist                              - list games")
		fmt.Fprintln(os.Stderr, "  [g]ame <name> [l]ist                - list saves")
		fmt.Fprintln(os.Stderr, "  [g]ame <name> [b]backup (note)      - backup current save")
		fmt.Fprintln(os.Stderr, "  [g]ame <name> [r]estore <id|ref>    - restore given save")
		fmt.Fprintln(os.Stderr, "  [g]ame <name> [d]elete <id|from-to> - delete given save(s)")
	}
	flag.StringVar(&flagConfig, "c", "saver.json", "path to config file")
	flag.BoolVar(&flagVerbose, "v", false, "be very verbose")
}

func main() {
	flag.Parse()
	checkArgs(false, 1)

	if flagConfig == "" {
		fmt.Fprintln(os.Stderr, "Config file path can't be empty")
		os.Exit(2)
	}
	flagConfig, err := filepath.Abs(flagConfig)
	dieOnErr("Can't resolve config path", err)

	save := false
	if _, err := os.Stat(flagConfig); err != nil {
		r, err := os.Getwd()
		dieOnErr("Can't get current path", err)
		cfg = &Config{
			Root:  r,
			Games: make([]*Game, 0),
		}
		fmt.Println("Will save fresh config to", flagConfig)
		save = true
	} else {
		c, err := loadConfig(flagConfig)
		dieOnErr("Config load error", err)
		cfg = c
	}

	switch flag.Arg(0)[0] {
	case 'g': // games command
		checkArgs(false, 3)
		g := cfg.GetGame(flag.Arg(1))
		if g == nil {
			fmt.Fprintf(os.Stderr, "Game \"%s\" not found\n", flag.Arg(1))
			os.Exit(1)
		}
		switch flag.Arg(2)[0] {
		case 'l': // game list
			g.PrintWhole()
		case 'b': // game backup
			sv, err := g.Backup()
			dieOnErr("ERROR", err)
			g.Stamp = time.Now()
			if flag.NArg() > 3 {
				sv.Note = flag.Arg(3)
			}
			fmt.Println("Backed up at", sv.Stamp.Format(timeFmt))
			save = true
		case 'r': // game restore
			checkArgs(true, 4)
			if len(g.Saves) < 1 {
				fmt.Fprintf(os.Stderr, "Game \"%s\" has no saves backed up\n", g.Name)
				os.Exit(1)
			}
			i, err := strconv.Atoi(flag.Arg(3))
			dieOnErr(fmt.Sprintf("Malformed index \"%s\"", flag.Arg(3)), err)
			sv, err := g.Restore(i)
			dieOnErr("ERROR", err)
			g.Stamp = time.Now()
			fmt.Println("Restored save from", sv.Stamp.Format(timeFmt))
			save = true
		case 'd': // game delete saves
			checkArgs(true, 4)
			if len(g.Saves) < 1 {
				fmt.Fprintf(os.Stderr, "Game \"%s\" has no saves backed up\n", g.Name)
				os.Exit(1)
			}
			var err error
			var f, t int
			f, err = strconv.Atoi(flag.Arg(3))
			t = f
			if err != nil {
				m := idRange.FindStringSubmatch(flag.Arg(3))
				f, err = strconv.Atoi(m[1])
				dieOnErr(fmt.Sprintf("Malformed index/range \"%s\"", flag.Arg(3)), err)
				t, err = strconv.Atoi(m[2])
				dieOnErr(fmt.Sprintf("Malformed index/range \"%s\"", flag.Arg(3)), err)
			}
			n, err := g.Delete(f, t)
			if err != nil {
				fmt.Fprintln(os.Stderr, "ERROR:", err)
			}
			fmt.Printf("Deleted %d save(s)\n", n)
			save = true
		default:
			flag.Usage()
			os.Exit(1)
		}
	case 'a': // add game
		checkArgs(true, 3)
		if g := cfg.GetGame(flag.Arg(1)); g != nil {
			fmt.Fprintf(os.Stderr, "Game \"%s\" already exist\n", flag.Arg(1))
			os.Exit(1)
		}
		p, err := filepath.Abs(flag.Arg(2))
		dieOnErr("Can't resolve path", err)
		gm, err := cfg.AddGame(flag.Arg(1), p)
		dieOnErr("ERROR", err)
		gm.PrintHeader()
		gm.Print()
		save = true
	case 'd': // delete game
		checkArgs(true, 2)
		g := cfg.GetGame(flag.Arg(1))
		if g == nil {
			fmt.Fprintf(os.Stderr, "Game \"%s\" not found\n", flag.Arg(1))
			os.Exit(1)
		}
		err := cfg.DelGame(flag.Arg(1))
		dieOnErr("ERROR", err)
		fmt.Printf("Deleted game \"%s\" and all backed up saves\n", flag.Arg(1))
		save = true
	case 'l': // list games
		cfg.PrintWhole()
	default:
		flag.Usage()
		os.Exit(1)
	}

	if save {
		err := cfg.Save(flagConfig)
		dieOnErr("Can't save config", err)
	}
}

func dieOnErr(msg string, err error) {
	if err != nil {
		fmt.Fprintln(os.Stderr, msg+":", err)
		os.Exit(3)
	}
}

func checkArgs(exact bool, num int) {
	if (exact && flag.NArg() != num) ||
		(!exact && flag.NArg() < num) {
		flag.Usage()
		os.Exit(1)
	}
}
<commit_msg>Print save on backup<commit_after>// See LICENSE.txt for licensing information.

package main

import (
	"flag"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"time"
)

const (
	VERSION = `0.2`
	timeFmt = `2006-01-02 15:04:05`
	fileFmt = `2006-01-02_150405`
)

var (
	flagConfig  string
	flagVerbose bool
	cfg         *Config
	idRange     = regexp.MustCompile(`(\d+)-(\d+)`)
)

func init() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "Usage: %s (options...) <command>\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "saver v%s by Piotr S. Staszewski, see LICENSE.txt\n\n", VERSION)
		fmt.Fprintln(os.Stderr, "Options:")
		flag.PrintDefaults()
		fmt.Fprintln(os.Stderr, "\nCommands:")
		fmt.Fprintln(os.Stderr, "  [a]dd <name> <path>                 - add new game")
		fmt.Fprintln(os.Stderr, "  [d]el <name>                        - delete game and all saves")
		fmt.Fprintln(os.Stderr, "  [l]ist                              - list games")
		fmt.Fprintln(os.Stderr, "  [g]ame <name> [l]ist                - list saves")
		fmt.Fprintln(os.Stderr, "  [g]ame <name> [b]backup (note)      - backup current save")
		fmt.Fprintln(os.Stderr, "  [g]ame <name> [r]estore <id|ref>    - restore given save")
		fmt.Fprintln(os.Stderr, "  [g]ame <name> [d]elete <id|from-to> - delete given save(s)")
	}
	flag.StringVar(&flagConfig, "c", "saver.json", "path to config file")
	flag.BoolVar(&flagVerbose, "v", false, "be very verbose")
}

func main() {
	flag.Parse()
	checkArgs(false, 1)

	if flagConfig == "" {
		fmt.Fprintln(os.Stderr, "Config file path can't be empty")
		os.Exit(2)
	}
	flagConfig, err := filepath.Abs(flagConfig)
	dieOnErr("Can't resolve config path", err)

	save := false
	if _, err := os.Stat(flagConfig); err != nil {
		r, err := os.Getwd()
		dieOnErr("Can't get current path", err)
		cfg = &Config{
			Root:  r,
			Games: make([]*Game, 0),
		}
		fmt.Println("Will save fresh config to", flagConfig)
		save = true
	} else {
		c, err := loadConfig(flagConfig)
		dieOnErr("Config load error", err)
		cfg = c
	}

	switch flag.Arg(0)[0] {
	case 'g': // games command
		checkArgs(false, 3)
		g := cfg.GetGame(flag.Arg(1))
		if g == nil {
			fmt.Fprintf(os.Stderr, "Game \"%s\" not found\n", flag.Arg(1))
			os.Exit(1)
		}
		switch flag.Arg(2)[0] {
		case 'l': // game list
			g.PrintWhole()
		case 'b': // game backup
			sv, err := g.Backup()
			dieOnErr("ERROR", err)
			g.Stamp = time.Now()
			if flag.NArg() > 3 {
				sv.Note = flag.Arg(3)
			}
			fmt.Printf("%3d ", len(g.Saves))
			sv.Print()
			save = true
		case 'r': // game restore
			checkArgs(true, 4)
			if len(g.Saves) < 1 {
				fmt.Fprintf(os.Stderr, "Game \"%s\" has no saves backed up\n", g.Name)
				os.Exit(1)
			}
			i, err := strconv.Atoi(flag.Arg(3))
			dieOnErr(fmt.Sprintf("Malformed index \"%s\"", flag.Arg(3)), err)
			sv, err := g.Restore(i)
			dieOnErr("ERROR", err)
			g.Stamp = time.Now()
			fmt.Println("Restored save from", sv.Stamp.Format(timeFmt))
			save = true
		case 'd': // game delete saves
			checkArgs(true, 4)
			if len(g.Saves) < 1 {
				fmt.Fprintf(os.Stderr, "Game \"%s\" has no saves backed up\n", g.Name)
				os.Exit(1)
			}
			var err error
			var f, t int
			f, err = strconv.Atoi(flag.Arg(3))
			t = f
			if err != nil {
				m := idRange.FindStringSubmatch(flag.Arg(3))
				f, err = strconv.Atoi(m[1])
				dieOnErr(fmt.Sprintf("Malformed index/range \"%s\"", flag.Arg(3)), err)
				t, err = strconv.Atoi(m[2])
				dieOnErr(fmt.Sprintf("Malformed index/range \"%s\"", flag.Arg(3)), err)
			}
			n, err := g.Delete(f, t)
			if err != nil {
				fmt.Fprintln(os.Stderr, "ERROR:", err)
			}
			fmt.Printf("Deleted %d save(s)\n", n)
			save = true
		default:
			flag.Usage()
			os.Exit(1)
		}
	case 'a': // add game
		checkArgs(true, 3)
		if g := cfg.GetGame(flag.Arg(1)); g != nil {
			fmt.Fprintf(os.Stderr, "Game \"%s\" already exist\n", flag.Arg(1))
			os.Exit(1)
		}
		p, err := filepath.Abs(flag.Arg(2))
		dieOnErr("Can't resolve path", err)
		gm, err := cfg.AddGame(flag.Arg(1), p)
		dieOnErr("ERROR", err)
		gm.PrintHeader()
		gm.Print()
		save = true
	case 'd': // delete game
		checkArgs(true, 2)
		g := cfg.GetGame(flag.Arg(1))
		if g == nil {
			fmt.Fprintf(os.Stderr, "Game \"%s\" not found\n", flag.Arg(1))
			os.Exit(1)
		}
		err := cfg.DelGame(flag.Arg(1))
		dieOnErr("ERROR", err)
		fmt.Printf("Deleted game \"%s\" and all backed up saves\n", flag.Arg(1))
		save = true
	case 'l': // list games
		cfg.PrintWhole()
	default:
		flag.Usage()
		os.Exit(1)
	}

	if save {
		err := cfg.Save(flagConfig)
		dieOnErr("Can't save config", err)
	}
}

func dieOnErr(msg string, err error) {
	if err != nil {
		fmt.Fprintln(os.Stderr, msg+":", err)
		os.Exit(3)
	}
}

func checkArgs(exact bool, num int) {
	if (exact && flag.NArg() != num) ||
		(!exact && flag.NArg() < num) {
		flag.Usage()
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"

	"github.com/nelsam/hkslugdeploy/github"
	"github.com/nelsam/hkslugdeploy/heroku"
	"github.com/nelsam/hkslugdeploy/release"
)

const (
	herokuAppDir = "app"
)

var (
	sequential        bool
	tarName           string
	githubReleaseName string
	githubReleaseDesc string
	githubRepo        string
	githubToken       string
	gitCommitish      string
	herokuApp         string
	herokuWebProc     string
	herokuEmail       string
	herokuKey         string
	selectedFilenames []string
)

func init() {
	flag.BoolVar(&sequential, "sequential", false,
		"Enable this flag if you don't want releases to run concurrently.")
	flag.StringVar(&tarName, "tarball-name", "release.tar.gz",
		"The name of the release tarball file that will be uploaded to github.")
	flag.StringVar(&githubRepo, "github-repo", "",
		"Your github repo, in user/repo form.")
	flag.StringVar(&githubToken, "github-token", "",
		"Your github token for pushing a release.")
	flag.StringVar(&gitCommitish, "github-commitish", "",
		"The commitish that you're creating a github release of.")
	flag.StringVar(&githubReleaseName, "github-release-name", "",
		"The name to use when creating a release on github.")
	flag.StringVar(&githubReleaseDesc, "github-release-desc", "",
		"A description of this release for uploading to github.")
	flag.StringVar(&herokuApp, "heroku-app", "",
		"Your heroku app's name.")
	flag.StringVar(&herokuWebProc, "heroku-web-proc", "",
		"The web process type to use when creating a heroku slug.")
	flag.StringVar(&herokuEmail, "heroku-login", "",
		"The email address for logging in to heroku.")
	flag.StringVar(&herokuKey, "heroku-token", "",
		"The password or access token to use when logging in to heroku.")
	flag.Parse()
	selectedFilenames = flag.Args()
}

func main() {
	release.CreateTarball(tarName, herokuAppDir, selectedFilenames)
	waiting := make([]chan bool, 0, 2)
	if githubRepo != "" {
		done := github.StartRelease(githubReleaseName, githubReleaseDesc, gitCommitish, githubRepo, githubToken, tarName)
		if sequential {
			<-done
		} else {
			waiting = append(waiting, done)
		}
	}
	if herokuApp != "" {
		done := heroku.StartRelease(herokuApp, map[string]string{"web": herokuWebProc}, herokuEmail, herokuKey, tarName)
		if sequential {
			<-done
		} else {
			waiting = append(waiting, done)
		}
	}
	for _, wait := range waiting {
		<-wait
	}
	if err := os.Remove(tarName); err != nil {
		log.Fatal(err)
	}
}
<commit_msg>Update usage, add -clean for cleaning up tarball<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
	"os"

	"github.com/nelsam/hkslugdeploy/github"
	"github.com/nelsam/hkslugdeploy/heroku"
	"github.com/nelsam/hkslugdeploy/release"
)

const (
	herokuAppDir = "app"
)

var (
	sequential        bool
	clean             bool
	tarName           string
	githubReleaseName string
	githubReleaseDesc string
	githubRepo        string
	githubToken       string
	gitCommitish      string
	herokuApp         string
	herokuWebProc     string
	herokuEmail       string
	herokuKey         string
	selectedFilenames []string
)

func init() {
	flag.BoolVar(&sequential, "sequential", false,
		"Enable this flag if you don't want releases to run concurrently.")
	flag.BoolVar(&clean, "clean", false,
		"Clean up any files that are created during deployment (including the release tarball).")
	flag.StringVar(&tarName, "tarball-name", "release.tar.gz",
		"The name of the release tarball file that will be uploaded to github.")
	flag.StringVar(&githubRepo, "github-repo", "",
		"Your github repo, in user/repo form.")
	flag.StringVar(&githubToken, "github-token", "",
		"Your github token for pushing a release.")
	flag.StringVar(&gitCommitish, "github-commitish", "",
		"The commitish that you're creating a github release of.")
	flag.StringVar(&githubReleaseName, "github-release-name", "",
		"The name to use when creating a release on github.")
	flag.StringVar(&githubReleaseDesc, "github-release-desc", "",
		"A description of this release for uploading to github.")
	flag.StringVar(&herokuApp, "heroku-app", "",
		"Your heroku app's name.")
	flag.StringVar(&herokuWebProc, "heroku-web-proc", "",
		"The web process type to use when creating a heroku slug.")
	flag.StringVar(&herokuEmail, "heroku-login", "",
		"The email address for logging in to heroku.")
	flag.StringVar(&herokuKey, "heroku-token", "",
		"The password or access token to use when logging in to heroku.")
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: %s [options] release_files...\n\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Creates a heroku slug tarball (.tar.gz) out of the provided release_files, and "+
			"optionally uploads the slug tarball to a github release and/or deploys it to heroku.  Make sure "+
			"that you provide *all* github options if you want to create a github release with the resulting "+
			"tarball, and the same for heroku if you want to deploy the slug to heroku.\n\n")
		fmt.Fprint(os.Stderr, "options:\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	selectedFilenames = flag.Args()
}

func main() {
	release.CreateTarball(tarName, herokuAppDir, selectedFilenames)
	waiting := make([]chan bool, 0, 2)
	if githubRepo != "" {
		done := github.StartRelease(githubReleaseName, githubReleaseDesc, gitCommitish, githubRepo, githubToken, tarName)
		if sequential {
			<-done
		} else {
			waiting = append(waiting, done)
		}
	}
	if herokuApp != "" {
		done := heroku.StartRelease(herokuApp, map[string]string{"web": herokuWebProc}, herokuEmail, herokuKey, tarName)
		if sequential {
			<-done
		} else {
			waiting = append(waiting, done)
		}
	}
	for _, wait := range waiting {
		<-wait
	}
	if clean {
		if err := os.Remove(tarName); err != nil {
			log.Fatal(err)
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"os"

	"github.com/emicklei/proto"
	"github.com/jamesk/apidoc-proto/apidoc"
)

func main() {
	aSpec, err := apidoc.GetSpecFromFile("test_service.json")
	if err != nil {
		panic(err)
	}

	pFile := getProtoFromAPISpec(aSpec)

	//TODO: safe name?
	f, err := os.Create(aSpec.Name + ".proto")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	w := bufio.NewWriter(f)
	proto.NewFormatter(w, "  ").Format(&pFile)
	w.Flush()
}

const (
	syntaxVersion = "proto3"
)

func getProtoFromAPISpec(spec apidoc.Spec) proto.Proto {
	pFile := proto.Proto{}

	pFile.Elements = append(
		pFile.Elements,
		&proto.Syntax{Value: syntaxVersion},
	)

	for _, aEnum := range spec.Enums {
		pEnum := proto.Enum{Name: aEnum.Name}
		for i, aValue := range aEnum.Values {

			pEnum.Elements = append(
				pEnum.Elements,
				&proto.EnumField{Name:aValue.Name, Integer:i},
			)
		}
		pFile.Elements = append(pFile.Elements, &pEnum)
	}

	return pFile
}

<commit_msg>Started adding translation of Models<commit_after>package main

import (
	"bufio"
	"os"

	"github.com/emicklei/proto"
	"github.com/jamesk/apidoc-proto/apidoc"
	"strings"
	"errors"
)

func main() {
	aSpec, err := apidoc.GetSpecFromFile("test_service.json")
	if err != nil {
		panic(err)
	}

	pFile := getProtoFromAPISpec(aSpec)

	//TODO: safe name?
	f, err := os.Create(aSpec.Name + ".proto")
	if err != nil {
		panic(err)
	}
	defer f.Close()

	w := bufio.NewWriter(f)
	proto.NewFormatter(w, "  ").Format(&pFile)
	w.Flush()
}

const (
	syntaxVersion = "proto3"
)

func getProtoFromAPISpec(spec apidoc.Spec) proto.Proto {
	pFile := proto.Proto{}

	pFile.Elements = append(
		pFile.Elements,
		&proto.Syntax{Value: syntaxVersion},
	)

	for _, aEnum := range spec.Enums {
		pEnum := proto.Enum{Name: aEnum.Name}
		for i, aValue := range aEnum.Values {

			pEnum.Elements = append(
				pEnum.Elements,
				&proto.EnumField{Name:aValue.Name, Integer:i},
			)
		}
		pFile.Elements = append(pFile.Elements, &pEnum)
	}

	//Models
	for _, aModel := range spec.Models {
		pMessage := proto.Message{Name: aModel.Name}
		for i, aField := range aModel.Fields {

			//Apidoc types: boolean, date-iso8601, date-time-iso8601, decimal, double, integer, long, object, string, unit, uuid

			pMessage.Elements = append(
				pMessage.Elements,
				&proto. {Name:aValue.Name, Integer:i},
			)
		}
		pFile.Elements = append(pFile.Elements, &pMessage)
	}

	//Unions

	//Resources

	return pFile
}

func getProtoFieldFromApidoc(aField apidoc.Field, sequenceNumber int) (proto.Visitee, error) {
	//Apidoc types: boolean, date-iso8601, date-time-iso8601, decimal, double, integer, long, object, string, unit, uuid
	if strings.HasPrefix(aField.FieldType, "map[") {
		return getMapProtoFieldFromApidoc(aField, sequenceNumber)
	}

	getNormalProtoFieldFromApidoc(aField, sequenceNumber)
}

func getNormalProtoFieldFromApidoc(aField apidoc.Field, sequenceNumber int) (proto.NormalField, error) {
	pField := proto.NormalField{}

	fieldType := aField.FieldType
	if strings.HasPrefix(fieldType, "[") {
		if !strings.HasSuffix(fieldType, "]") {
			return pField, errors.New("Invalid type, starts with a [ but does not end with one")
		}

		pField.Repeated = true
		fieldType = fieldType[1:len(fieldType)-1]
	}

	pType, err := getProtoTypeFromBasicApidocType(fieldType)
	if err != nil {
		return pField, err
	}
	pField.Type = pType

	pField.Sequence = sequenceNumber

	return pField, nil
}

func getMapProtoFieldFromApidoc(aField apidoc.Field) (proto.MapField, error) {
	return proto.MapField{}, errors.New("Map fields are unsupported at the moment")
}

func getProtoTypeFromBasicApidocType(basicType string) (string, error) {
	switch basicType {
	case "boolean":
		return "bool", nil
	case "date-iso8601":
		return "string", nil
	case "date-time-iso8601":
		return "string", nil
	case "decimal":
		return "", errors.New("Cannot translate decimal field types to proto type")
	case "double":
		return "double", nil
	case "integer":
		return "int32", nil
	case "long":
		return "int64", nil
	case "object":
		return "", errors.New("Cannot translate object field types to proto type")
	case "string":
		return "string", nil
	case "unit":
		return "", errors.New("Cannot translate unit field types to proto type")
	case "uuid":
		return "string", nil
	default:
		//Custom type or wrong type
		return basicType, nil
	}
}<|endoftext|>


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

package main

import (
	"log"
	"os"

	"menteslibres.net/gosexy/cli"
)

// Handy path separator.
const pathSeparator = string(os.PathSeparator)

// Version holds the software version.
const Version = "0.9"

func main() {
	var err error

	// Software properties.
	cli.Name = "Luminos Markdown Server"
	cli.Homepage = "https://menteslibres.net/luminos"
	cli.Author = "Carlos Reventlov"
	cli.Version = Version
	cli.AuthorEmail = "carlos@reventlov.com"

	// Shows banner
	cli.Banner()

	// Dispatches the command.
	err = cli.Dispatch()

	if err != nil {
		log.Fatalf("Could not start Luminos: %q\n", err)
	}

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

package main

import (
	"log"
	"os"

	"menteslibres.net/gosexy/cli"
)

// Handy path separator.
const pathSeparator = string(os.PathSeparator)

// Version holds the software version.
const Version = "0.9"

func main() {
	// Software properties.
	cli.Name = "Luminos Markdown Server"
	cli.Homepage = "https://menteslibres.net/luminos"
	cli.Author = "Carlos Reventlov"
	cli.Version = Version
	cli.AuthorEmail = "carlos@reventlov.com"

	// Shows banner
	cli.Banner()

	// Dispatches the command.
	if err := cli.Dispatch(); err != nil {
		log.Fatal("Could not start Luminos: ", err)
	}

}
<|endoftext|>


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

// A fuse file system for Google Cloud Storage buckets.
//
// Usage:
//
//     gcsfuse [flags] bucket mount_point
//
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"runtime"
	"runtime/pprof"
	"syscall"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"

	"github.com/codegangsta/cli"
	"github.com/jacobsa/daemonize"
	"github.com/jacobsa/fuse"
	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/syncutil"
	"github.com/kardianos/osext"
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func registerSIGINTHandler(mountPoint string) {
	// Register for SIGINT.
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)

	// Start a goroutine that will unmount when the signal is received.
	go func() {
		for {
			<-signalChan
			log.Println("Received SIGINT, attempting to unmount...")

			err := fuse.Unmount(mountPoint)
			if err != nil {
				log.Printf("Failed to unmount in response to SIGINT: %v", err)
			} else {
				log.Printf("Successfully unmounted in response to SIGINT.")
				return
			}
		}
	}()
}

func handleCPUProfileSignals() {
	profileOnce := func(duration time.Duration, path string) (err error) {
		// Set up the file.
		var f *os.File
		f, err = os.Create(path)
		if err != nil {
			err = fmt.Errorf("Create: %v", err)
			return
		}

		defer func() {
			closeErr := f.Close()
			if err == nil {
				err = closeErr
			}
		}()

		// Profile.
		pprof.StartCPUProfile(f)
		time.Sleep(duration)
		pprof.StopCPUProfile()
		return
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGUSR1)
	for range c {
		const path = "/tmp/cpu.pprof"
		const duration = 10 * time.Second

		log.Printf("Writing %v CPU profile to %s...", duration, path)

		err := profileOnce(duration, path)
		if err == nil {
			log.Printf("Done writing CPU profile to %s.", path)
		} else {
			log.Printf("Error writing CPU profile: %v", err)
		}
	}
}

func handleMemoryProfileSignals() {
	profileOnce := func(path string) (err error) {
		// Trigger a garbage collection to get up to date information (cf.
		// https://goo.gl/aXVQfL).
		runtime.GC()

		// Open the file.
		var f *os.File
		f, err = os.Create(path)
		if err != nil {
			err = fmt.Errorf("Create: %v", err)
			return
		}

		defer func() {
			closeErr := f.Close()
			if err == nil {
				err = closeErr
			}
		}()

		// Dump to the file.
		err = pprof.Lookup("heap").WriteTo(f, 0)
		if err != nil {
			err = fmt.Errorf("WriteTo: %v", err)
			return
		}

		return
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGUSR2)
	for range c {
		const path = "/tmp/mem.pprof"

		err := profileOnce(path)
		if err == nil {
			log.Printf("Wrote memory profile to %s.", path)
		} else {
			log.Printf("Error writing memory profile: %v", err)
		}
	}
}

// Create token source from the JSON file at the supplide path.
func newTokenSourceFromPath(
	path string,
	scope string) (ts oauth2.TokenSource, err error) {
	// Read the file.
	contents, err := ioutil.ReadFile(path)
	if err != nil {
		err = fmt.Errorf("ReadFile(%q): %v", path, err)
		return
	}

	// Create a config struct based on its contents.
	jwtConfig, err := google.JWTConfigFromJSON(contents, scope)
	if err != nil {
		err = fmt.Errorf("JWTConfigFromJSON: %v", err)
		return
	}

	// Create the token source.
	ts = jwtConfig.TokenSource(context.Background())

	return
}

func getConn(flags *flagStorage) (c gcs.Conn, err error) {
	// Create the oauth2 token source.
	const scope = gcs.Scope_FullControl

	var tokenSrc oauth2.TokenSource
	if flags.KeyFile != "" {
		tokenSrc, err = newTokenSourceFromPath(flags.KeyFile, scope)
		if err != nil {
			err = fmt.Errorf("newTokenSourceFromPath: %v", err)
			return
		}
	} else {
		tokenSrc, err = google.DefaultTokenSource(context.Background(), scope)
		if err != nil {
			err = fmt.Errorf("DefaultTokenSource: %v", err)
			return
		}
	}

	// Create the connection.
	const userAgent = "gcsfuse/0.0"
	cfg := &gcs.ConnConfig{
		TokenSource: tokenSrc,
		UserAgent:   userAgent,
	}

	if flags.DebugHTTP {
		cfg.HTTPDebugLogger = log.New(os.Stderr, "http: ", 0)
	}

	if flags.DebugGCS {
		cfg.GCSDebugLogger = log.New(os.Stderr, "gcs: ", 0)
	}

	return gcs.NewConn(cfg)
}

////////////////////////////////////////////////////////////////////////
// main logic
////////////////////////////////////////////////////////////////////////

// Mount the file system according to arguments in the supplied context.
func mountWithArgs(
	bucketName string,
	mountPoint string,
	flags *flagStorage,
	mountStatus *log.Logger) (mfs *fuse.MountedFileSystem, err error) {
	// Enable invariant checking if requested.
	if flags.DebugInvariants {
		syncutil.EnableInvariantChecking()
	}

	// Grab the connection.
	mountStatus.Println("Opening GCS connection...")

	conn, err := getConn(flags)
	if err != nil {
		err = fmt.Errorf("getConn: %v", err)
		return
	}

	// Mount the file system.
	mfs, err = mountWithConn(
		context.Background(),
		bucketName,
		mountPoint,
		flags,
		conn,
		mountStatus)

	if err != nil {
		err = fmt.Errorf("mountWithConn: %v", err)
		return
	}

	return
}

func runCLIApp(c *cli.Context) (err error) {
	flags := populateFlags(c)

	// Extract arguments.
	if len(c.Args()) != 2 {
		err = fmt.Errorf(
			"%s takes exactly two arguments. Run `%s --help` for more info.",
			path.Base(os.Args[0]),
			path.Base(os.Args[0]))

		return
	}

	bucketName := c.Args()[0]
	mountPoint := c.Args()[1]

	// Canonicalize the mount point, making it absolute. This is important when
	// daemonizing below, since the daemon will change its working directory
	// before running this code again.
	mountPoint, err = filepath.Abs(mountPoint)
	if err != nil {
		err = fmt.Errorf("canonicalizing mount point: %v", err)
		return
	}

	fmt.Fprintf(os.Stderr, "Using mount point: %s\n", mountPoint)

	// If we haven't been asked to run in foreground mode, we should run a daemon
	// with the foreground flag set and wait for it to mount.
	if !flags.Foreground {
		// Find the executable.
		var path string
		path, err = osext.Executable()
		if err != nil {
			err = fmt.Errorf("osext.Executable: %v", err)
			return
		}

		// Set up arguments. Be sure to use foreground mode, and to send along the
		// potentially-modified mount point.
		args := append([]string{"--foreground"}, os.Args[1:]...)
		args[len(args)-1] = mountPoint

		// Pass along PATH so that the daemon can find fusermount on Linux.
		env := []string{
			fmt.Sprintf("PATH=%s", os.Getenv("PATH")),
		}

		// Run.
		err = daemonize.Run(path, args, env, os.Stderr)
		if err != nil {
			err = fmt.Errorf("daemonize.Run: %v", err)
			return
		}

		return
	}

	// Mount, writing information about our progress to the writer that package
	// daemonize gives us and telling it about the outcome.
	var mfs *fuse.MountedFileSystem
	{
		mountStatus := log.New(daemonize.StatusWriter, "", 0)
		mfs, err = mountWithArgs(bucketName, mountPoint, flags, mountStatus)

		if err == nil {
			mountStatus.Println("File system has been successfully mounted.")
			daemonize.SignalOutcome(nil)
		} else {
			err = fmt.Errorf("mountWithArgs: %v", err)
			daemonize.SignalOutcome(err)
			return
		}
	}

	// Let the user unmount with Ctrl-C (SIGINT).
	registerSIGINTHandler(mfs.Dir())

	// Wait for the file system to be unmounted.
	err = mfs.Join(context.Background())
	if err != nil {
		err = fmt.Errorf("MountedFileSystem.Join: %v", err)
		return
	}

	return
}

func run() (err error) {
	// Set up the app.
	app := newApp()

	var appErr error
	app.Action = func(c *cli.Context) {
		appErr = runCLIApp(c)
	}

	// Run it.
	err = app.Run(os.Args)
	if err != nil {
		return
	}

	err = appErr
	return
}

func main() {
	// Make logging output better.
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

	// Set up profiling handlers.
	go handleCPUProfileSignals()
	go handleMemoryProfileSignals()

	// Run.
	err := run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<commit_msg>Don't look for GCS credentials when mounting the fake bucket.<commit_after>// Copyright 2015 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// A fuse file system for Google Cloud Storage buckets.
//
// Usage:
//
//     gcsfuse [flags] bucket mount_point
//
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"os/signal"
	"path"
	"path/filepath"
	"runtime"
	"runtime/pprof"
	"syscall"
	"time"

	"golang.org/x/net/context"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"

	"github.com/codegangsta/cli"
	"github.com/googlecloudplatform/gcsfuse/internal/canned"
	"github.com/jacobsa/daemonize"
	"github.com/jacobsa/fuse"
	"github.com/jacobsa/gcloud/gcs"
	"github.com/jacobsa/syncutil"
	"github.com/kardianos/osext"
)

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func registerSIGINTHandler(mountPoint string) {
	// Register for SIGINT.
	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, os.Interrupt)

	// Start a goroutine that will unmount when the signal is received.
	go func() {
		for {
			<-signalChan
			log.Println("Received SIGINT, attempting to unmount...")

			err := fuse.Unmount(mountPoint)
			if err != nil {
				log.Printf("Failed to unmount in response to SIGINT: %v", err)
			} else {
				log.Printf("Successfully unmounted in response to SIGINT.")
				return
			}
		}
	}()
}

func handleCPUProfileSignals() {
	profileOnce := func(duration time.Duration, path string) (err error) {
		// Set up the file.
		var f *os.File
		f, err = os.Create(path)
		if err != nil {
			err = fmt.Errorf("Create: %v", err)
			return
		}

		defer func() {
			closeErr := f.Close()
			if err == nil {
				err = closeErr
			}
		}()

		// Profile.
		pprof.StartCPUProfile(f)
		time.Sleep(duration)
		pprof.StopCPUProfile()
		return
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGUSR1)
	for range c {
		const path = "/tmp/cpu.pprof"
		const duration = 10 * time.Second

		log.Printf("Writing %v CPU profile to %s...", duration, path)

		err := profileOnce(duration, path)
		if err == nil {
			log.Printf("Done writing CPU profile to %s.", path)
		} else {
			log.Printf("Error writing CPU profile: %v", err)
		}
	}
}

func handleMemoryProfileSignals() {
	profileOnce := func(path string) (err error) {
		// Trigger a garbage collection to get up to date information (cf.
		// https://goo.gl/aXVQfL).
		runtime.GC()

		// Open the file.
		var f *os.File
		f, err = os.Create(path)
		if err != nil {
			err = fmt.Errorf("Create: %v", err)
			return
		}

		defer func() {
			closeErr := f.Close()
			if err == nil {
				err = closeErr
			}
		}()

		// Dump to the file.
		err = pprof.Lookup("heap").WriteTo(f, 0)
		if err != nil {
			err = fmt.Errorf("WriteTo: %v", err)
			return
		}

		return
	}

	c := make(chan os.Signal, 1)
	signal.Notify(c, syscall.SIGUSR2)
	for range c {
		const path = "/tmp/mem.pprof"

		err := profileOnce(path)
		if err == nil {
			log.Printf("Wrote memory profile to %s.", path)
		} else {
			log.Printf("Error writing memory profile: %v", err)
		}
	}
}

// Create token source from the JSON file at the supplide path.
func newTokenSourceFromPath(
	path string,
	scope string) (ts oauth2.TokenSource, err error) {
	// Read the file.
	contents, err := ioutil.ReadFile(path)
	if err != nil {
		err = fmt.Errorf("ReadFile(%q): %v", path, err)
		return
	}

	// Create a config struct based on its contents.
	jwtConfig, err := google.JWTConfigFromJSON(contents, scope)
	if err != nil {
		err = fmt.Errorf("JWTConfigFromJSON: %v", err)
		return
	}

	// Create the token source.
	ts = jwtConfig.TokenSource(context.Background())

	return
}

func getConn(flags *flagStorage) (c gcs.Conn, err error) {
	// Create the oauth2 token source.
	const scope = gcs.Scope_FullControl

	var tokenSrc oauth2.TokenSource
	if flags.KeyFile != "" {
		tokenSrc, err = newTokenSourceFromPath(flags.KeyFile, scope)
		if err != nil {
			err = fmt.Errorf("newTokenSourceFromPath: %v", err)
			return
		}
	} else {
		tokenSrc, err = google.DefaultTokenSource(context.Background(), scope)
		if err != nil {
			err = fmt.Errorf("DefaultTokenSource: %v", err)
			return
		}
	}

	// Create the connection.
	const userAgent = "gcsfuse/0.0"
	cfg := &gcs.ConnConfig{
		TokenSource: tokenSrc,
		UserAgent:   userAgent,
	}

	if flags.DebugHTTP {
		cfg.HTTPDebugLogger = log.New(os.Stderr, "http: ", 0)
	}

	if flags.DebugGCS {
		cfg.GCSDebugLogger = log.New(os.Stderr, "gcs: ", 0)
	}

	return gcs.NewConn(cfg)
}

////////////////////////////////////////////////////////////////////////
// main logic
////////////////////////////////////////////////////////////////////////

// Mount the file system according to arguments in the supplied context.
func mountWithArgs(
	bucketName string,
	mountPoint string,
	flags *flagStorage,
	mountStatus *log.Logger) (mfs *fuse.MountedFileSystem, err error) {
	// Enable invariant checking if requested.
	if flags.DebugInvariants {
		syncutil.EnableInvariantChecking()
	}

	// Grab the connection.
	//
	// Special case: if we're mounting the fake bucket, we don't need an actual
	// connection.
	var conn gcs.Conn
	if bucketName != canned.FakeBucketName {
		mountStatus.Println("Opening GCS connection...")

		conn, err = getConn(flags)
		if err != nil {
			err = fmt.Errorf("getConn: %v", err)
			return
		}
	}

	// Mount the file system.
	mfs, err = mountWithConn(
		context.Background(),
		bucketName,
		mountPoint,
		flags,
		conn,
		mountStatus)

	if err != nil {
		err = fmt.Errorf("mountWithConn: %v", err)
		return
	}

	return
}

func runCLIApp(c *cli.Context) (err error) {
	flags := populateFlags(c)

	// Extract arguments.
	if len(c.Args()) != 2 {
		err = fmt.Errorf(
			"%s takes exactly two arguments. Run `%s --help` for more info.",
			path.Base(os.Args[0]),
			path.Base(os.Args[0]))

		return
	}

	bucketName := c.Args()[0]
	mountPoint := c.Args()[1]

	// Canonicalize the mount point, making it absolute. This is important when
	// daemonizing below, since the daemon will change its working directory
	// before running this code again.
	mountPoint, err = filepath.Abs(mountPoint)
	if err != nil {
		err = fmt.Errorf("canonicalizing mount point: %v", err)
		return
	}

	fmt.Fprintf(os.Stderr, "Using mount point: %s\n", mountPoint)

	// If we haven't been asked to run in foreground mode, we should run a daemon
	// with the foreground flag set and wait for it to mount.
	if !flags.Foreground {
		// Find the executable.
		var path string
		path, err = osext.Executable()
		if err != nil {
			err = fmt.Errorf("osext.Executable: %v", err)
			return
		}

		// Set up arguments. Be sure to use foreground mode, and to send along the
		// potentially-modified mount point.
		args := append([]string{"--foreground"}, os.Args[1:]...)
		args[len(args)-1] = mountPoint

		// Pass along PATH so that the daemon can find fusermount on Linux.
		env := []string{
			fmt.Sprintf("PATH=%s", os.Getenv("PATH")),
		}

		// Run.
		err = daemonize.Run(path, args, env, os.Stderr)
		if err != nil {
			err = fmt.Errorf("daemonize.Run: %v", err)
			return
		}

		return
	}

	// Mount, writing information about our progress to the writer that package
	// daemonize gives us and telling it about the outcome.
	var mfs *fuse.MountedFileSystem
	{
		mountStatus := log.New(daemonize.StatusWriter, "", 0)
		mfs, err = mountWithArgs(bucketName, mountPoint, flags, mountStatus)

		if err == nil {
			mountStatus.Println("File system has been successfully mounted.")
			daemonize.SignalOutcome(nil)
		} else {
			err = fmt.Errorf("mountWithArgs: %v", err)
			daemonize.SignalOutcome(err)
			return
		}
	}

	// Let the user unmount with Ctrl-C (SIGINT).
	registerSIGINTHandler(mfs.Dir())

	// Wait for the file system to be unmounted.
	err = mfs.Join(context.Background())
	if err != nil {
		err = fmt.Errorf("MountedFileSystem.Join: %v", err)
		return
	}

	return
}

func run() (err error) {
	// Set up the app.
	app := newApp()

	var appErr error
	app.Action = func(c *cli.Context) {
		appErr = runCLIApp(c)
	}

	// Run it.
	err = app.Run(os.Args)
	if err != nil {
		return
	}

	err = appErr
	return
}

func main() {
	// Make logging output better.
	log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)

	// Set up profiling handlers.
	go handleCPUProfileSignals()
	go handleMemoryProfileSignals()

	// Run.
	err := run()
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/luismesas/goPi/piface"
	"github.com/luismesas/goPi/spi"
	"github.com/unrolled/render"
	"net/http"
	"strconv"
	"time"
)

var progress int

func main() {
	// Render engine
	r := render.New(render.Options{
		Layout: "layout",
	})

	// Handlers
	router := mux.NewRouter()
	router.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		r.HTML(w, http.StatusOK, "home", progress)
	})
	router.HandleFunc("/about", func(w http.ResponseWriter, req *http.Request) {
		r.HTML(w, http.StatusOK, "about", nil)
	})
	router.HandleFunc("/start", func(w http.ResponseWriter, req *http.Request) {
		time := req.FormValue("time")
		stepsPerMinute, _ := strconv.Atoi(req.FormValue("steps"))
		var hours, minutes, seconds int
		fmt.Sscanf(time, "%d:%d:%d", &hours, &minutes, &seconds)
		fmt.Println(hours, minutes, seconds)
		go startLapse((hours*3600)+(minutes*60)+seconds, stepsPerMinute)
		r.HTML(w, http.StatusOK, "home", progress)
	}).Methods("POST")

	// HTTP Server
	n := negroni.Classic()
	n.UseHandler(router)
	n.Run(":3000")
}

func startLapse(seconds int, stepsPerMinute int) {
	go spin(stepsPerMinute)
	time.Sleep(time.Duration(int(time.Second) * seconds))
}

func spin(stepsPerMinute int) {
	var pauseTime float64
	pauseTime = float64(stepsPerMinute) / float64(60.0)
	pfd := piface.NewPiFaceDigital(spi.DEFAULT_HARDWARE_ADDR, spi.DEFAULT_BUS, spi.DEFAULT_CHIP)

	// initializes pifacedigital board
	err := pfd.InitBoard()
	if err != nil {
		fmt.Printf("Error on init board: %s", err)
		return
	}

	pfd.OutputPins[2].SetValue(0)
	for {
		pfd.OutputPins[2].Toggle()
		time.Sleep(time.Second / 10)
		pfd.OutputPins[2].Toggle()
		time.Sleep(time.Duration(float64(time.Second) * pauseTime))
	}
}

func testMotor() {
	// creates a new pifacedigital instance
	pfd := piface.NewPiFaceDigital(spi.DEFAULT_HARDWARE_ADDR, spi.DEFAULT_BUS, spi.DEFAULT_CHIP)

	// initializes pifacedigital board
	err := pfd.InitBoard()
	if err != nil {
		fmt.Printf("Error on init board: %s", err)
		return
	}
	pfd.OutputPins[0].Toggle()
	time.Sleep(time.Second / 10)
	pfd.OutputPins[0].Toggle()
}
<commit_msg>correct calculation of pausetime<commit_after>package main

import (
	"fmt"
	"github.com/codegangsta/negroni"
	"github.com/gorilla/mux"
	"github.com/luismesas/goPi/piface"
	"github.com/luismesas/goPi/spi"
	"github.com/unrolled/render"
	"net/http"
	"strconv"
	"time"
)

var progress int

func main() {
	// Render engine
	r := render.New(render.Options{
		Layout: "layout",
	})

	// Handlers
	router := mux.NewRouter()
	router.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
		r.HTML(w, http.StatusOK, "home", progress)
	})
	router.HandleFunc("/about", func(w http.ResponseWriter, req *http.Request) {
		r.HTML(w, http.StatusOK, "about", nil)
	})
	router.HandleFunc("/start", func(w http.ResponseWriter, req *http.Request) {
		time := req.FormValue("time")
		stepsPerMinute, _ := strconv.Atoi(req.FormValue("steps"))
		var hours, minutes, seconds int
		fmt.Sscanf(time, "%d:%d:%d", &hours, &minutes, &seconds)
		fmt.Println(hours, minutes, seconds)
		go startLapse((hours*3600)+(minutes*60)+seconds, stepsPerMinute)
		r.HTML(w, http.StatusOK, "home", progress)
	}).Methods("POST")

	// HTTP Server
	n := negroni.Classic()
	n.UseHandler(router)
	n.Run(":3000")
}

func startLapse(seconds int, stepsPerMinute int) {
	go spin(stepsPerMinute)
	time.Sleep(time.Duration(int(time.Second) * seconds))
}

func spin(stepsPerMinute int) {
	var pauseTime float64
	pauseTime = float64(60) / float64(stepsPerMinute)
	pfd := piface.NewPiFaceDigital(spi.DEFAULT_HARDWARE_ADDR, spi.DEFAULT_BUS, spi.DEFAULT_CHIP)

	// initializes pifacedigital board
	err := pfd.InitBoard()
	if err != nil {
		fmt.Printf("Error on init board: %s", err)
		return
	}

	pfd.OutputPins[2].SetValue(0)
	for {
		pfd.OutputPins[2].Toggle()
		time.Sleep(time.Second / 10)
		pfd.OutputPins[2].Toggle()
		time.Sleep(time.Duration(float64(time.Second) * pauseTime))
	}
}

func testMotor() {
	// creates a new pifacedigital instance
	pfd := piface.NewPiFaceDigital(spi.DEFAULT_HARDWARE_ADDR, spi.DEFAULT_BUS, spi.DEFAULT_CHIP)

	// initializes pifacedigital board
	err := pfd.InitBoard()
	if err != nil {
		fmt.Printf("Error on init board: %s", err)
		return
	}
	pfd.OutputPins[0].Toggle()
	time.Sleep(time.Second / 10)
	pfd.OutputPins[0].Toggle()
}
<|endoftext|>


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

package main

import (
	"bufio"
	"flag"
	"github.com/akualab/dmx"
	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/all"
	"log"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

type HRMsg struct {
	HeartRate int  // The current heart rate as returned by the polar H7.
	Contact   bool // Does the polar H7 currently have skin contact?
}

func main() {
	f, err := os.OpenFile("WeatherMachine2.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		return // Ah-oh. Unable to log to file.
	}
	defer f.Close()
	log.SetOutput(f)
	log.Printf("INFO: Starting WeatherMachine2")

	var configFile string
	flag.StringVar(&configFile, "configFile", "weather-machine.json", "The path to the configuration file")
	flag.Parse()

	config, err := loadConfiguration(configFile)
	if err != nil {
		log.Printf("INFO: Unable to open '%s', using default values", configFile)
	}

	// If we don't have the address of a heart rate monitor. Look for it.
	if strings.Compare(config.HRMMacAddress, "0") == 0 {
		config.HRMMacAddress = scanHeartRateMonitor()
		saveConfiguration(configFile, config)
	}

	// Connect and initalise our Raspberry Pi GPIO pins.
	err = embd.InitGPIO()
	if err != nil {
		log.Printf("ERROR: Unable to initalize the raspberry pi GPIO ports.")
	}
	defer embd.CloseGPIO()

	embd.SetDirection(config.GPIOPinFan, embd.Out)
	embd.SetDirection(config.GPIOPinPump, embd.Out)
	embd.SetDirection(config.GPIOPinLight, embd.Out)
	embd.DigitalWrite(config.GPIOPinFan, embd.Low)
	embd.DigitalWrite(config.GPIOPinPump, embd.Low)
	embd.DigitalWrite(config.GPIOPinLight, embd.Low)

	// Connect to the DMX controller.
	dmx, e := dmx.NewDMXConnection(config.SmokeAddress)
	if e != nil {
		log.Printf("ERROR: Unable to connect to the DMX interface.")
		return
	}
	defer dmx.Close()

	conf := make(chan Configuration)
	hrMsg := make(chan HRMsg) // Channel for receiving heart rate messages from the PolarH7.
	weatherMachine := WeatherMachine{make(chan bool), dmx, config}
	update := idle

	go pollHeartRateMonitor(config.HRMMacAddress, hrMsg)
	go updateConfiguration(conf, configFile)
	for {
		msg := <-hrMsg
		log.Printf("INFO C: %t HR: %d", msg.Contact, msg.HeartRate)

		select {
		case c := <-conf:
			weatherMachine.config = c
			// Use a new config within the weather machine if the configfile has been updated.
		default:
			// Don't need to do anything. Just don't block.
		}

		update = update(&weatherMachine, msg)
	}
}

func updateConfiguration(c chan Configuration, configFile string) {
	ticker := time.NewTicker(time.Second * 30).C

	for {
		select {
		case <-ticker:
			config, err := loadConfiguration(configFile)
			if err != nil {
				log.Printf("INFO: Unable to open '%s', using default values", configFile)
			}
			c <- config
		}
	}
}

func scanHeartRateMonitor() string {
	cmd := exec.Command("./WeatherMachine2-scan")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("ERROR: Unable to scan HRM.")
		return ""
	}

	scanner := bufio.NewScanner(stdout)
	id := ""
	go func() {
		for scanner.Scan() {
			id = scanner.Text()
			return
		}
	}()

	if err := cmd.Start(); err != nil {
		log.Printf("ERROR: Unable to start scanning HRM.")
		return id
	}

	cmd.Wait()
	return id
}

// pollHeartRateMonitor reads from the bluetooth heartrate monitor at the address specified
// by deviceID. It puts heart rate reatings onto the hr channel.
func pollHeartRateMonitor(deviceID string, hr chan HRMsg) {
	for {
		cmd := exec.Command("./WeatherMachine2-hrm", "--deviceID", deviceID)
		stdout, err := cmd.StdoutPipe()
		if err != nil {
			log.Printf("ERROR: Unable to read from HRM.")
			return
		}

		scanner := bufio.NewScanner(stdout)
		go func() {
			for scanner.Scan() {
				msg := strings.Split(scanner.Text(), ",")
				c, err := strconv.Atoi(msg[0])
				if err != nil {
					log.Printf("ERROR: Unable to parse contact")
				}

				i, err := strconv.Atoi(msg[1])
				if err != nil {
					log.Printf("ERROR: Unable to parse HR")
				}

				hr <- HRMsg{i, c == 1}
			}
		}()

		if err := cmd.Start(); err != nil {
			log.Printf("ERROR: Unable to start HRM.")
			return
		}

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

package main

import (
	"bufio"
	"flag"
	"github.com/akualab/dmx"
	"github.com/kidoman/embd"
	_ "github.com/kidoman/embd/host/all"
	"log"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"
)

type HRMsg struct {
	HeartRate int  // The current heart rate as returned by the polar H7.
	Contact   bool // Does the polar H7 currently have skin contact?
}

func main() {
	f, err := os.OpenFile("WeatherMachine2.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		return // Ah-oh. Unable to log to file.
	}
	defer f.Close()
	log.SetOutput(f)
	log.Printf("INFO: Starting WeatherMachine2")

	var configFile string
	flag.StringVar(&configFile, "configFile", "weather-machine.json", "The path to the configuration file")
	flag.Parse()

	config, err := loadConfiguration(configFile)
	if err != nil {
		log.Printf("INFO: Unable to open '%s', using default values", configFile)
	}

	// If we don't have the address of a heart rate monitor. Look for it.
	if strings.Compare(config.HRMMacAddress, "0") == 0 {
		config.HRMMacAddress = scanHeartRateMonitor()
		saveConfiguration(configFile, config)
	}

	// Connect and initalise our Raspberry Pi GPIO pins.
	err = embd.InitGPIO()
	if err != nil {
		log.Printf("ERROR: Unable to initalize the raspberry pi GPIO ports.")
	}
	defer embd.CloseGPIO()

	embd.SetDirection(config.GPIOPinFan, embd.Out)
	embd.SetDirection(config.GPIOPinPump, embd.Out)
	embd.SetDirection(config.GPIOPinLight, embd.Out)
	embd.DigitalWrite(config.GPIOPinFan, embd.Low)
	embd.DigitalWrite(config.GPIOPinPump, embd.Low)
	embd.DigitalWrite(config.GPIOPinLight, embd.Low)

	// Connect to the DMX controller.
	dmx, e := dmx.NewDMXConnection(config.SmokeAddress)
	if e != nil {
		log.Printf("ERROR: Unable to connect to the DMX interface.")
		return
	}
	defer dmx.Close()

	conf := make(chan Configuration)
	hrMsg := make(chan HRMsg) // Channel for receiving heart rate messages from the PolarH7.
	weatherMachine := WeatherMachine{make(chan bool), dmx, config}
	update := idle

	go pollHeartRateMonitor(config.HRMMacAddress, hrMsg)
	go updateConfiguration(conf, configFile)
	for {
		msg := <-hrMsg
		log.Printf("INFO C: %t HR: %d", msg.Contact, msg.HeartRate)

		select {
		case c := <-conf:
			weatherMachine.config = c
			// Use a new config within the weather machine if the configfile has been updated.
		default:
			// Don't need to do anything. Just don't block.
		}

		update = update(&weatherMachine, msg)
	}
}

func updateConfiguration(c chan Configuration, configFile string) {
	ticker := time.NewTicker(time.Second * 30).C

	for {
		select {
		case <-ticker:
			config, err := loadConfiguration(configFile)
			if err != nil {
				log.Printf("INFO: Unable to open '%s', using default values", configFile)
			}
			c <- config
		}
	}
}

func scanHeartRateMonitor() string {
	cmd := exec.Command("./WeatherMachine2-scan")
	stdout, err := cmd.StdoutPipe()
	if err != nil {
		log.Printf("ERROR: Unable to scan HRM.")
		return "0"
	}

	scanner := bufio.NewScanner(stdout)
	id := "0"
	go func() {
		for scanner.Scan() {
			id = scanner.Text()
			return
		}
	}()

	if err := cmd.Start(); err != nil {
		log.Printf("ERROR: Unable to start scanning HRM.")
		return id
	}

	cmd.Wait()
	return id
}

// pollHeartRateMonitor reads from the bluetooth heartrate monitor at the address specified
// by deviceID. It puts heart rate reatings onto the hr channel.
func pollHeartRateMonitor(deviceID string, hr chan HRMsg) {
	for {
		cmd := exec.Command("./WeatherMachine2-hrm", "--deviceID", deviceID)
		stdout, err := cmd.StdoutPipe()
		if err != nil {
			log.Printf("ERROR: Unable to read from HRM.")
			return
		}

		scanner := bufio.NewScanner(stdout)
		go func() {
			for scanner.Scan() {
				msg := strings.Split(scanner.Text(), ",")
				c, err := strconv.Atoi(msg[0])
				if err != nil {
					log.Printf("ERROR: Unable to parse contact")
				}

				i, err := strconv.Atoi(msg[1])
				if err != nil {
					log.Printf("ERROR: Unable to parse HR")
				}

				hr <- HRMsg{i, c == 1}
			}
		}()

		if err := cmd.Start(); err != nil {
			log.Printf("ERROR: Unable to start HRM.")
			return
		}

		cmd.Wait()
	}
}
<|endoftext|>


<commit_before>package main

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

	"github.com/eBay/fabio/admin"
	"github.com/eBay/fabio/config"
	"github.com/eBay/fabio/proxy"
	"github.com/eBay/fabio/registry"
	"github.com/eBay/fabio/route"
)

// version contains the version number
//
// It is set by build/release.sh for tagged releases
// so that 'go get' just works.
//
// It is also set by the linker when fabio
// is built via the Makefile or the build/docker.sh
// script to ensure the correct version nubmer
var version = "1.0.6"

func main() {
	var filename string
	var v bool
	flag.StringVar(&filename, "cfg", "", "path to config file")
	flag.BoolVar(&v, "v", false, "show version")
	flag.Parse()

	if v {
		fmt.Println(version)
		return
	}
	log.Printf("[INFO] Version %s starting", version)

	cfg := config.DefaultConfig
	if filename != "" {
		cfg = loadConfig(filename)
	}

	initBackend(cfg)
	initMetrics(cfg)
	initRuntime(cfg)
	initRoutes(cfg)
	startAdmin(cfg)
	startListeners(cfg.Listen, cfg.Proxy.ShutdownWait, newProxy(cfg))
	registry.Default.Deregister()
}

func newProxy(cfg *config.Config) *proxy.Proxy {
	if err := route.SetPickerStrategy(cfg.Proxy.Strategy); err != nil {
		log.Fatal("[FATAL] ", err)
	}
	log.Printf("[INFO] Using routing strategy %q", cfg.Proxy.Strategy)

	tr := &http.Transport{
		ResponseHeaderTimeout: cfg.Proxy.ResponseHeaderTimeout,
		MaxIdleConnsPerHost:   cfg.Proxy.MaxConn,
		Dial: (&net.Dialer{
			Timeout:   cfg.Proxy.DialTimeout,
			KeepAlive: cfg.Proxy.KeepAliveTimeout,
		}).Dial,
	}

	return proxy.New(tr, cfg.Proxy)
}

func startAdmin(cfg *config.Config) {
	log.Printf("[INFO] Admin server listening on %q", cfg.UI.Addr)
	go func() {
		if err := admin.ListenAndServe(cfg.UI.Addr, version); err != nil {
			log.Fatal("[FATAL] ui: ", err)
		}
	}()
}
<commit_msg>Bump to 1.0.7-dev<commit_after>package main

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

	"github.com/eBay/fabio/admin"
	"github.com/eBay/fabio/config"
	"github.com/eBay/fabio/proxy"
	"github.com/eBay/fabio/registry"
	"github.com/eBay/fabio/route"
)

// version contains the version number
//
// It is set by build/release.sh for tagged releases
// so that 'go get' just works.
//
// It is also set by the linker when fabio
// is built via the Makefile or the build/docker.sh
// script to ensure the correct version nubmer
var version = "1.0.7-dev"

func main() {
	var filename string
	var v bool
	flag.StringVar(&filename, "cfg", "", "path to config file")
	flag.BoolVar(&v, "v", false, "show version")
	flag.Parse()

	if v {
		fmt.Println(version)
		return
	}
	log.Printf("[INFO] Version %s starting", version)

	cfg := config.DefaultConfig
	if filename != "" {
		cfg = loadConfig(filename)
	}

	initBackend(cfg)
	initMetrics(cfg)
	initRuntime(cfg)
	initRoutes(cfg)
	startAdmin(cfg)
	startListeners(cfg.Listen, cfg.Proxy.ShutdownWait, newProxy(cfg))
	registry.Default.Deregister()
}

func newProxy(cfg *config.Config) *proxy.Proxy {
	if err := route.SetPickerStrategy(cfg.Proxy.Strategy); err != nil {
		log.Fatal("[FATAL] ", err)
	}
	log.Printf("[INFO] Using routing strategy %q", cfg.Proxy.Strategy)

	tr := &http.Transport{
		ResponseHeaderTimeout: cfg.Proxy.ResponseHeaderTimeout,
		MaxIdleConnsPerHost:   cfg.Proxy.MaxConn,
		Dial: (&net.Dialer{
			Timeout:   cfg.Proxy.DialTimeout,
			KeepAlive: cfg.Proxy.KeepAliveTimeout,
		}).Dial,
	}

	return proxy.New(tr, cfg.Proxy)
}

func startAdmin(cfg *config.Config) {
	log.Printf("[INFO] Admin server listening on %q", cfg.UI.Addr)
	go func() {
		if err := admin.ListenAndServe(cfg.UI.Addr, version); err != nil {
			log.Fatal("[FATAL] ui: ", err)
		}
	}()
}
<|endoftext|>


<commit_before>package main

func main() {
	// Scrape a recipe from Vegan Rocks
}
<commit_msg>Connecting to neo4j<commit_after>package main

import (
	bolt "github.com/johnnadratowski/golang-neo4j-bolt-driver"
)

func main() {
	// Scrape a recipe from Vegan Rocks

	// Connect to neo4j
	driver := bolt.NewDriver()
	// @TODO: Put this in a config
	conn, err := driver.OpenNeo("bolt://api.omnomhub.dev:7687")
	if err != nil {
		panic(err)
	}
	defer conn.Close()
}
<|endoftext|>