<commit_before>package main

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	gorillasession "github.com/gorilla/sessions"
	"github.com/ory-am/common/env"
	"github.com/ory-am/common/mgopath"
	"github.com/ory-am/event"
	gde "github.com/ory-am/gitdeploy/event"
	"github.com/ory-am/gitdeploy/job"
	gdLog "github.com/ory-am/gitdeploy/log"
	"github.com/ory-am/gitdeploy/sse"
	"github.com/ory-am/gitdeploy/storage"
	"github.com/ory-am/gitdeploy/storage/mongo"
	"github.com/ory-am/google-json-style-response/responder"
	"gopkg.in/mgo.v2"
	"log"
	"net/http"
	"os/exec"
	"regexp"
	"time"
	"runtime"
	"os"
    "strings"
)

const (
	sessionCurrentDeployment = "cdid"
	sessionName = "gdp"
)

var (
// API Version
	ApiVersion = "1.0"

// Generic configuration
	host = env.Getenv("HOST", "")
	port = env.Getenv("PORT", "7654")

	envAppTtl = env.Getenv("APP_TTL", "30m")
    envClusterConf = env.Getenv("FLYNN_CLUSTER_CONFIG", "")

// Configuration for CORS
	corsAllowOrigin = env.Getenv("CORS_ALLOW_ORIGIN", "http://localhost:9000")

	sessionStore = gorillasession.NewCookieStore([]byte(env.Getenv("SESSION_SECRET", "changme")))

// MongoDB
	envMongoPath = env.Getenv("MONGODB", "mongodb://localhost:27017/gitdeploy")
)

type deployRequest struct {
	Repository string `json:"repository"`
}

type appResponse struct {
	App string `json:"app"`
}

func main() {
	checkDependencies()
	eventManager := event.New()

	// mgo
	mongoDatabase, err := mgopath.Connect(envMongoPath)
	if err != nil {
		log.Fatal(err)
	}

	storage := mongo.New(mongoDatabase)
	eventManager.AttachListenerAggregate(storage)

	// SSE broker
	sseBroker := sse.New(storage)

	// Log listener
	eventManager.AttachListenerAggregate(new(gdLog.Listener))

	// Mux router
	r := mux.NewRouter()
	r.HandleFunc("/config", configHandler).Methods("GET")
	r.HandleFunc("/deployments", deployWrapperAction(sseBroker, eventManager, storage)).Methods("POST")
	r.HandleFunc("/deployments", setCORSHeaders).Methods("OPTIONS")
	r.HandleFunc("/deployments/{app:.+}/events", eventWrapperAction(sseBroker)).Methods("GET")
	r.HandleFunc("/apps/{app:.+}", getAppHandler(storage)).Methods("GET")
	r.PathPrefix("/").HandlerFunc(publicHandler("./app/dist"))
	http.Handle("/", r)

	go job.KillAppsOnHitList(storage)

	listen := fmt.Sprintf("%s:%s", host, port)
	log.Printf("Listening on %s", listen)
	log.Fatal(http.ListenAndServe(listen, nil))
}

func publicHandler(dir string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		path := dir + r.URL.Path
		if r.URL.Path == "/" {
			path = dir + "/index.html"
		}
		pattern := `!\.html|\.js|\.svg|\.css|\.png|\.jpg$`

		if f, err := os.Stat(path); err == nil {
			if !f.IsDir() {
				http.ServeFile(w, r, path)
				return
			} else {
                http.NotFound(w, r)
				return
			}
		}

		if matched, err := regexp.MatchString(pattern, path); err != nil {
			log.Printf("Could not exec regex: %s", err.Error())
		} else if !matched {
            http.ServeFile(w, r, dir + "/index.html")
            return
		} else {
			http.NotFound(w, r)
		}
	}
}

func configHandler(w http.ResponseWriter, r *http.Request) {
	setCORSHeaders(w, r)
	responseSuccess(w, struct {
		Now time.Time `json:"now"`
	}{
		time.Now(),
	})
}

func getAppHandler(store *mongo.MongoStorage) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if cleanUpSession(w, r) != nil {
			return
		}
		setCORSHeaders(w, r)
		vars := mux.Vars(r)
		id := vars["app"]
		app, err := store.GetApp(id)
		if err == mgo.ErrNotFound {
			responseError(w, http.StatusNotFound, fmt.Sprintf("App %s does not exist.", id))
			return
		} else if app.Killed {
			responseError(w, http.StatusNotFound, "App timed out and is no longer available.")
			return
		} else if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}
		logs, err := job.GetLogs(app.ID)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		ps, err := job.GetPS(app.ID)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		deployLogs, err := store.FindDeployLogsForApp(id)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		responseSuccess(w, struct {
			*storage.App
			Logs       string                 `json:"logs"`
			DeployLogs []*storage.DeployEvent `json:"deployLogs"`
			PS         string                 `json:"ps"`
		}{app, logs, deployLogs, ps})
	}
}

func cleanUpSession(w http.ResponseWriter, r *http.Request) error {
	session, err := sessionStore.Get(r, sessionName)
	if err != nil {
		responseError(w, http.StatusBadRequest, "Please delete your cookies.")
		return err
	}
	delete(session.Values, sessionCurrentDeployment)
	if err := session.Save(r, w); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return err
	}
	return nil
}

func eventWrapperAction(sseBroker *sse.Broker) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCORSHeaders(w, r)
		sseBroker.EventHandler(w, r)
	}
}

func deployWrapperAction(sseBroker *sse.Broker, em *event.EventManager, store *mongo.MongoStorage) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCORSHeaders(w, r)
		deployAction(w, r, sseBroker, em, store)
	}
}

func deployAction(w http.ResponseWriter, r *http.Request, sseBroker *sse.Broker, em *event.EventManager, store *mongo.MongoStorage) {
	session, err := sessionStore.Get(r, sessionName)
	if err != nil {
		responseError(w, http.StatusBadRequest, "Please delete your cookies.")
		return
	}

	// Check if the user is currently deploying an application and switch to that one.
	if v, ok := session.Values[sessionCurrentDeployment].(string); ok && len(v) > 0 {
		app, err := store.GetApp(v)
		if err != nil {
			cleanUpSession(w, r)
			log.Printf("Could not fetch app from cookie: %s", err.Error())
		} else {
			responseSuccess(w, app)
		}
	}

	// Parse body
	dr := new(deployRequest)
	decoder := json.NewDecoder(r.Body)
	decoder.Decode(dr)

	// Validate URL
	regExpression := "(https|http):\\/\\/github\\.com\\/[a-zA-Z0-9\\-\\_]+/[a-zA-Z0-9\\-\\_]+\\.git"
	if match, _ := regexp.MatchString(regExpression, dr.Repository); !match {
		responseError(w, http.StatusBadRequest, "I only support GitHub.")
		return
	}

	app := uuid.NewRandom().String()
	if ttl, err := time.ParseDuration(envAppTtl); err != nil {
		log.Println(err.Error())
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	} else {
		appEntity, err := store.AddApp(app, time.Now().Add(ttl), dr.Repository, getIP(r))
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}
		session.Values[sessionCurrentDeployment] = appEntity.ID
		if err := session.Save(r, w); err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}
		go runJobs(w, r, em, dr, appEntity, sseBroker, session, store)
		responseSuccess(w, appEntity)
	}
}

func runJobs(w http.ResponseWriter, r *http.Request, em *event.EventManager, dr *deployRequest, app *storage.App, sseBroker *sse.Broker, session *gorillasession.Session, store *mongo.MongoStorage) {
	sseBroker.OpenChannel(app.ID)
	sseBroker.Start(app.ID)
	defer func() {
		// Give the client the chance to read the output...
		time.Sleep(2 * time.Minute)
		sseBroker.CloseChannel(app.ID)
	}()

	em.Trigger("app.created", gde.New(app.ID, app.ID))

	destination, err := job.Clone(em, app.ID, dr.Repository)
	if err != nil {
		log.Printf("Error in job.clone %s: %s", app.ID, err.Error())
		return
	}

	if err = job.Parse(em, app.ID, destination); err != nil {
		log.Printf("Error in job.parse %s: %s", app.ID, err.Error())
		return
	}

	if err = job.Deploy(em, app.ID, destination); err != nil {
		log.Printf("Error in job.deploy %s: %s", app.ID, err.Error())
		return
	}

	cluster, err := job.GetCluster(em, app.ID)
	if err != nil {
		log.Printf("Error in job.deploy %s: %s", app.ID, err.Error())
		return
	}

	app.URL = fmt.Sprintf("%s.%s", app.ID, cluster.Host)
	if err := store.UpdateApp(app); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		log.Printf("Error %s: %s", app.ID, err.Error())
		return
	}

	log.Println("Deployment successful.")
	em.Trigger("app.deployed", gde.New(app.ID, app.URL))
}

// Set the different CORS headers required for CORS request
func setCORSHeaders(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
	w.Header().Set("Access-Control-Allow-Origin", corsAllowOrigin)
	w.Header().Set("Access-Control-Allow-Credentials", "true")
	w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
}

func responseError(w http.ResponseWriter, code int, message string) {
	log.Printf("Error %d: %s", code, message)
	response := responder.New(ApiVersion)
	response.Write(w, response.Error(code, message))
}

func responseSuccess(w http.ResponseWriter, data interface{}) {
	response := responder.New(ApiVersion)
	response.Write(w, response.Success(data))
}

func checkDependencies() {
	go func() {
		_, err := exec.LookPath("git")
		if err != nil {
			log.Fatal("Git CLI is required but not installed or not in path.")
		}
	}()
	go checkIfFlynnExists()
}

func checkIfFlynnExists() {
	func() {
		_, err := exec.LookPath("flynn")
		if err != nil {
			if runtime.GOOS == "windows" {
				log.Fatal("Flynn CLI is required but not installed or not in path.")
			}
			log.Println("Could not find Flynn CLI, trying to install...")
			if o, err := exec.Command("sh", "bin/flynn-install.sh").CombinedOutput(); err != nil {
				log.Printf("Could not install Flynn CLI (%s): %s", err.Error(), o)
			} else if _, err := exec.LookPath("flynn"); err != nil {
				log.Fatal("Could not install Flynn CLI.")
			}
            log.Println("Flynn installed successfully!")
            log.Println("Adding flynn cluster...")
            log.Println(envClusterConf)
            args := append([]string{"cluster", "add"}, strings.Split(envClusterConf, " ")...)
            log.Printf("%s", args)
            if o, err := exec.Command("flynn", args...).CombinedOutput(); err != nil {
                log.Fatalf("Could not add cluster (status: %s) (output: %s) (args: %s)", err.Error(), o, args)
            } else {
                log.Printf("Adding cluster successful: %s", o)
            }
		}
	}()
}

func getIP(r *http.Request) string {
    ip := removePort(r.RemoteAddr)
    if len(r.Header.Get("X-FORWARDED-FOR")) > 0 {
        ip = r.Header.Get("X-FORWARDED-FOR")
    }
    return ip
}

func removePort(ip string) string {
    split := strings.Split(ip, ":")
    if len(split) < 2 {
        return ip
    }
    return strings.Join(split[:len(split)-1], ":")
}
<commit_msg>Cluster adding improved<commit_after>package main

import (
	"code.google.com/p/go-uuid/uuid"
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	gorillasession "github.com/gorilla/sessions"
	"github.com/ory-am/common/env"
	"github.com/ory-am/common/mgopath"
	"github.com/ory-am/event"
	gde "github.com/ory-am/gitdeploy/event"
	"github.com/ory-am/gitdeploy/job"
	gdLog "github.com/ory-am/gitdeploy/log"
	"github.com/ory-am/gitdeploy/sse"
	"github.com/ory-am/gitdeploy/storage"
	"github.com/ory-am/gitdeploy/storage/mongo"
	"github.com/ory-am/google-json-style-response/responder"
	"gopkg.in/mgo.v2"
	"log"
	"net/http"
	"os/exec"
	"regexp"
	"time"
	"runtime"
	"os"
    "strings"
)

const (
	sessionCurrentDeployment = "cdid"
	sessionName = "gdp"
)

var (
// API Version
	ApiVersion = "1.0"

// Generic configuration
	host = env.Getenv("HOST", "")
	port = env.Getenv("PORT", "7654")

	envAppTtl = env.Getenv("APP_TTL", "30m")
    envClusterConf = env.Getenv("FLYNN_CLUSTER_CONFIG", "")

// Configuration for CORS
	corsAllowOrigin = env.Getenv("CORS_ALLOW_ORIGIN", "http://localhost:9000")

	sessionStore = gorillasession.NewCookieStore([]byte(env.Getenv("SESSION_SECRET", "changme")))

// MongoDB
	envMongoPath = env.Getenv("MONGODB", "mongodb://localhost:27017/gitdeploy")
)

type deployRequest struct {
	Repository string `json:"repository"`
}

type appResponse struct {
	App string `json:"app"`
}

func main() {
	checkDependencies()
	eventManager := event.New()

	// mgo
	mongoDatabase, err := mgopath.Connect(envMongoPath)
	if err != nil {
		log.Fatal(err)
	}

	storage := mongo.New(mongoDatabase)
	eventManager.AttachListenerAggregate(storage)

	// SSE broker
	sseBroker := sse.New(storage)

	// Log listener
	eventManager.AttachListenerAggregate(new(gdLog.Listener))

	// Mux router
	r := mux.NewRouter()
	r.HandleFunc("/config", configHandler).Methods("GET")
	r.HandleFunc("/deployments", deployWrapperAction(sseBroker, eventManager, storage)).Methods("POST")
	r.HandleFunc("/deployments", setCORSHeaders).Methods("OPTIONS")
	r.HandleFunc("/deployments/{app:.+}/events", eventWrapperAction(sseBroker)).Methods("GET")
	r.HandleFunc("/apps/{app:.+}", getAppHandler(storage)).Methods("GET")
	r.PathPrefix("/").HandlerFunc(publicHandler("./app/dist"))
	http.Handle("/", r)

	go job.KillAppsOnHitList(storage)

	listen := fmt.Sprintf("%s:%s", host, port)
	log.Printf("Listening on %s", listen)
	log.Fatal(http.ListenAndServe(listen, nil))
}

func publicHandler(dir string) func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		path := dir + r.URL.Path
		if r.URL.Path == "/" {
			path = dir + "/index.html"
		}
		pattern := `!\.html|\.js|\.svg|\.css|\.png|\.jpg$`

		if f, err := os.Stat(path); err == nil {
			if !f.IsDir() {
				http.ServeFile(w, r, path)
				return
			} else {
                http.NotFound(w, r)
				return
			}
		}

		if matched, err := regexp.MatchString(pattern, path); err != nil {
			log.Printf("Could not exec regex: %s", err.Error())
		} else if !matched {
            http.ServeFile(w, r, dir + "/index.html")
            return
		} else {
			http.NotFound(w, r)
		}
	}
}

func configHandler(w http.ResponseWriter, r *http.Request) {
	setCORSHeaders(w, r)
	responseSuccess(w, struct {
		Now time.Time `json:"now"`
	}{
		time.Now(),
	})
}

func getAppHandler(store *mongo.MongoStorage) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if cleanUpSession(w, r) != nil {
			return
		}
		setCORSHeaders(w, r)
		vars := mux.Vars(r)
		id := vars["app"]
		app, err := store.GetApp(id)
		if err == mgo.ErrNotFound {
			responseError(w, http.StatusNotFound, fmt.Sprintf("App %s does not exist.", id))
			return
		} else if app.Killed {
			responseError(w, http.StatusNotFound, "App timed out and is no longer available.")
			return
		} else if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}
		logs, err := job.GetLogs(app.ID)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		ps, err := job.GetPS(app.ID)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		deployLogs, err := store.FindDeployLogsForApp(id)
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}

		responseSuccess(w, struct {
			*storage.App
			Logs       string                 `json:"logs"`
			DeployLogs []*storage.DeployEvent `json:"deployLogs"`
			PS         string                 `json:"ps"`
		}{app, logs, deployLogs, ps})
	}
}

func cleanUpSession(w http.ResponseWriter, r *http.Request) error {
	session, err := sessionStore.Get(r, sessionName)
	if err != nil {
		responseError(w, http.StatusBadRequest, "Please delete your cookies.")
		return err
	}
	delete(session.Values, sessionCurrentDeployment)
	if err := session.Save(r, w); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		return err
	}
	return nil
}

func eventWrapperAction(sseBroker *sse.Broker) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCORSHeaders(w, r)
		sseBroker.EventHandler(w, r)
	}
}

func deployWrapperAction(sseBroker *sse.Broker, em *event.EventManager, store *mongo.MongoStorage) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		setCORSHeaders(w, r)
		deployAction(w, r, sseBroker, em, store)
	}
}

func deployAction(w http.ResponseWriter, r *http.Request, sseBroker *sse.Broker, em *event.EventManager, store *mongo.MongoStorage) {
	session, err := sessionStore.Get(r, sessionName)
	if err != nil {
		responseError(w, http.StatusBadRequest, "Please delete your cookies.")
		return
	}

	// Check if the user is currently deploying an application and switch to that one.
	if v, ok := session.Values[sessionCurrentDeployment].(string); ok && len(v) > 0 {
		app, err := store.GetApp(v)
		if err != nil {
			cleanUpSession(w, r)
			log.Printf("Could not fetch app from cookie: %s", err.Error())
		} else {
			responseSuccess(w, app)
		}
	}

	// Parse body
	dr := new(deployRequest)
	decoder := json.NewDecoder(r.Body)
	decoder.Decode(dr)

	// Validate URL
	regExpression := "(https|http):\\/\\/github\\.com\\/[a-zA-Z0-9\\-\\_]+/[a-zA-Z0-9\\-\\_]+\\.git"
	if match, _ := regexp.MatchString(regExpression, dr.Repository); !match {
		responseError(w, http.StatusBadRequest, "I only support GitHub.")
		return
	}

	app := uuid.NewRandom().String()
	if ttl, err := time.ParseDuration(envAppTtl); err != nil {
		log.Println(err.Error())
		responseError(w, http.StatusInternalServerError, err.Error())
		return
	} else {
		appEntity, err := store.AddApp(app, time.Now().Add(ttl), dr.Repository, getIP(r))
		if err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}
		session.Values[sessionCurrentDeployment] = appEntity.ID
		if err := session.Save(r, w); err != nil {
			responseError(w, http.StatusInternalServerError, err.Error())
			return
		}
		go runJobs(w, r, em, dr, appEntity, sseBroker, session, store)
		responseSuccess(w, appEntity)
	}
}

func runJobs(w http.ResponseWriter, r *http.Request, em *event.EventManager, dr *deployRequest, app *storage.App, sseBroker *sse.Broker, session *gorillasession.Session, store *mongo.MongoStorage) {
	sseBroker.OpenChannel(app.ID)
	sseBroker.Start(app.ID)
	defer func() {
		// Give the client the chance to read the output...
		time.Sleep(2 * time.Minute)
		sseBroker.CloseChannel(app.ID)
	}()

	em.Trigger("app.created", gde.New(app.ID, app.ID))

	destination, err := job.Clone(em, app.ID, dr.Repository)
	if err != nil {
		log.Printf("Error in job.clone %s: %s", app.ID, err.Error())
		return
	}

	if err = job.Parse(em, app.ID, destination); err != nil {
		log.Printf("Error in job.parse %s: %s", app.ID, err.Error())
		return
	}

	if err = job.Deploy(em, app.ID, destination); err != nil {
		log.Printf("Error in job.deploy %s: %s", app.ID, err.Error())
		return
	}

	cluster, err := job.GetCluster(em, app.ID)
	if err != nil {
		log.Printf("Error in job.getCluster %s: %s", app.ID, err.Error())
		return
	}

	app.URL = fmt.Sprintf("%s.%s", app.ID, cluster.Host)
	if err := store.UpdateApp(app); err != nil {
		responseError(w, http.StatusInternalServerError, err.Error())
		log.Printf("Error %s: %s", app.ID, err.Error())
		return
	}

	log.Println("Deployment successful.")
	em.Trigger("app.deployed", gde.New(app.ID, app.URL))
}

// Set the different CORS headers required for CORS request
func setCORSHeaders(w http.ResponseWriter, r *http.Request) {
	w.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
	w.Header().Set("Access-Control-Allow-Origin", corsAllowOrigin)
	w.Header().Set("Access-Control-Allow-Credentials", "true")
	w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept")
}

func responseError(w http.ResponseWriter, code int, message string) {
	log.Printf("Error %d: %s", code, message)
	response := responder.New(ApiVersion)
	response.Write(w, response.Error(code, message))
}

func responseSuccess(w http.ResponseWriter, data interface{}) {
	response := responder.New(ApiVersion)
	response.Write(w, response.Success(data))
}

func checkDependencies() {
	go func() {
		_, err := exec.LookPath("git")
		if err != nil {
			log.Fatal("Git CLI is required but not installed or not in path.")
		}
	}()
	go checkIfFlynnExists()
}

func checkIfFlynnExists() {
	func() {
		_, err := exec.LookPath("flynn")
		if err != nil {
			if runtime.GOOS == "windows" {
				log.Fatal("Flynn CLI is required but not installed or not in path.")
			}
			log.Println("Could not find Flynn CLI, trying to install...")
			if o, err := exec.Command("sh", "bin/flynn-install.sh").CombinedOutput(); err != nil {
				log.Printf("Could not install Flynn CLI (%s): %s", err.Error(), o)
			} else if _, err := exec.LookPath("flynn"); err != nil {
				log.Fatal("Could not install Flynn CLI.")
			}
            log.Println("Flynn installed successfully!")
            log.Println("Adding flynn cluster...")
            log.Println(envClusterConf)
            args := append([]string{"cluster", "add"}, strings.Split(envClusterConf, " ")...)
            log.Printf("%s", args)
            if o, err := exec.Command("flynn", args...).CombinedOutput(); err != nil {
                log.Fatalf("Could not add cluster (status: %s) (output: %s) (args: %s)", err.Error(), o, args)
            } else {
                log.Printf("Adding cluster successful: %s", o)
            }
		}
	}()
}

func getIP(r *http.Request) string {
    ip := removePort(r.RemoteAddr)
    if len(r.Header.Get("X-FORWARDED-FOR")) > 0 {
        ip = r.Header.Get("X-FORWARDED-FOR")
    }
    return ip
}

func removePort(ip string) string {
    split := strings.Split(ip, ":")
    if len(split) < 2 {
        return ip
    }
    return strings.Join(split[:len(split)-1], ":")
}
<|endoftext|>


<commit_before>// Copyright 2016 The etcd Authors
//
// 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 integration

import (
	"fmt"
	"io"
	"net"
	"sync"

	"github.com/coreos/etcd/pkg/transport"
)

// bridge creates a unix socket bridge to another unix socket, making it possible
// to disconnect grpc network connections without closing the logical grpc connection.
type bridge struct {
	inaddr  string
	outaddr string
	l       net.Listener
	conns   map[*bridgeConn]struct{}

	stopc  chan struct{}
	pausec chan struct{}
	wg     sync.WaitGroup

	mu sync.Mutex
}

func newBridge(addr string) (*bridge, error) {
	b := &bridge{
		// bridge "port" is ("%05d%05d0", port, pid) since go1.8 expects the port to be a number
		inaddr:  addr + "0",
		outaddr: addr,
		conns:   make(map[*bridgeConn]struct{}),
		stopc:   make(chan struct{}),
		pausec:  make(chan struct{}),
	}
	close(b.pausec)

	l, err := transport.NewUnixListener(b.inaddr)
	if err != nil {
		return nil, fmt.Errorf("listen failed on socket %s (%v)", addr, err)
	}
	b.l = l
	b.wg.Add(1)
	go b.serveListen()
	return b, nil
}

func (b *bridge) URL() string { return "unix://" + b.inaddr }

func (b *bridge) Close() {
	b.l.Close()
	b.mu.Lock()
	select {
	case <-b.stopc:
	default:
		close(b.stopc)
	}
	b.mu.Unlock()
	b.wg.Wait()
}

func (b *bridge) Reset() {
	b.mu.Lock()
	defer b.mu.Unlock()
	for bc := range b.conns {
		bc.Close()
	}
	b.conns = make(map[*bridgeConn]struct{})
}

func (b *bridge) Pause() {
	b.mu.Lock()
	b.pausec = make(chan struct{})
	b.mu.Unlock()
}

func (b *bridge) Unpause() {
	b.mu.Lock()
	select {
	case <-b.pausec:
	default:
		close(b.pausec)
	}
	b.mu.Unlock()
}

func (b *bridge) serveListen() {
	defer func() {
		b.l.Close()
		b.mu.Lock()
		for bc := range b.conns {
			bc.Close()
		}
		b.mu.Unlock()
		b.wg.Done()
	}()

	for {
		inc, ierr := b.l.Accept()
		if ierr != nil {
			return
		}
		b.mu.Lock()
		pausec := b.pausec
		b.mu.Unlock()
		select {
		case <-b.stopc:
			return
		case <-pausec:
		}

		outc, oerr := net.Dial("unix", b.outaddr)
		if oerr != nil {
			inc.Close()
			return
		}

		bc := &bridgeConn{inc, outc, make(chan struct{})}
		b.wg.Add(1)
		b.mu.Lock()
		b.conns[bc] = struct{}{}
		go b.serveConn(bc)
		b.mu.Unlock()
	}
}

func (b *bridge) serveConn(bc *bridgeConn) {
	defer func() {
		close(bc.donec)
		bc.Close()
		b.mu.Lock()
		delete(b.conns, bc)
		b.mu.Unlock()
		b.wg.Done()
	}()

	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		io.Copy(bc.out, bc.in)
		wg.Done()
	}()
	go func() {
		io.Copy(bc.in, bc.out)
		wg.Done()
	}()
	wg.Wait()
}

type bridgeConn struct {
	in    net.Conn
	out   net.Conn
	donec chan struct{}
}

func (bc *bridgeConn) Close() {
	bc.in.Close()
	bc.out.Close()
	<-bc.donec
}
<commit_msg>integration: close accepted connection on stopc path<commit_after>// Copyright 2016 The etcd Authors
//
// 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 integration

import (
	"fmt"
	"io"
	"net"
	"sync"

	"github.com/coreos/etcd/pkg/transport"
)

// bridge creates a unix socket bridge to another unix socket, making it possible
// to disconnect grpc network connections without closing the logical grpc connection.
type bridge struct {
	inaddr  string
	outaddr string
	l       net.Listener
	conns   map[*bridgeConn]struct{}

	stopc  chan struct{}
	pausec chan struct{}
	wg     sync.WaitGroup

	mu sync.Mutex
}

func newBridge(addr string) (*bridge, error) {
	b := &bridge{
		// bridge "port" is ("%05d%05d0", port, pid) since go1.8 expects the port to be a number
		inaddr:  addr + "0",
		outaddr: addr,
		conns:   make(map[*bridgeConn]struct{}),
		stopc:   make(chan struct{}),
		pausec:  make(chan struct{}),
	}
	close(b.pausec)

	l, err := transport.NewUnixListener(b.inaddr)
	if err != nil {
		return nil, fmt.Errorf("listen failed on socket %s (%v)", addr, err)
	}
	b.l = l
	b.wg.Add(1)
	go b.serveListen()
	return b, nil
}

func (b *bridge) URL() string { return "unix://" + b.inaddr }

func (b *bridge) Close() {
	b.l.Close()
	b.mu.Lock()
	select {
	case <-b.stopc:
	default:
		close(b.stopc)
	}
	b.mu.Unlock()
	b.wg.Wait()
}

func (b *bridge) Reset() {
	b.mu.Lock()
	defer b.mu.Unlock()
	for bc := range b.conns {
		bc.Close()
	}
	b.conns = make(map[*bridgeConn]struct{})
}

func (b *bridge) Pause() {
	b.mu.Lock()
	b.pausec = make(chan struct{})
	b.mu.Unlock()
}

func (b *bridge) Unpause() {
	b.mu.Lock()
	select {
	case <-b.pausec:
	default:
		close(b.pausec)
	}
	b.mu.Unlock()
}

func (b *bridge) serveListen() {
	defer func() {
		b.l.Close()
		b.mu.Lock()
		for bc := range b.conns {
			bc.Close()
		}
		b.mu.Unlock()
		b.wg.Done()
	}()

	for {
		inc, ierr := b.l.Accept()
		if ierr != nil {
			return
		}
		b.mu.Lock()
		pausec := b.pausec
		b.mu.Unlock()
		select {
		case <-b.stopc:
			inc.Close()
			return
		case <-pausec:
		}

		outc, oerr := net.Dial("unix", b.outaddr)
		if oerr != nil {
			inc.Close()
			return
		}

		bc := &bridgeConn{inc, outc, make(chan struct{})}
		b.wg.Add(1)
		b.mu.Lock()
		b.conns[bc] = struct{}{}
		go b.serveConn(bc)
		b.mu.Unlock()
	}
}

func (b *bridge) serveConn(bc *bridgeConn) {
	defer func() {
		close(bc.donec)
		bc.Close()
		b.mu.Lock()
		delete(b.conns, bc)
		b.mu.Unlock()
		b.wg.Done()
	}()

	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		io.Copy(bc.out, bc.in)
		bc.close()
		wg.Done()
	}()
	go func() {
		io.Copy(bc.in, bc.out)
		bc.close()
		wg.Done()
	}()
	wg.Wait()
}

type bridgeConn struct {
	in    net.Conn
	out   net.Conn
	donec chan struct{}
}

func (bc *bridgeConn) Close() {
	bc.close()
	<-bc.donec
}

func (bc *bridgeConn) close() {
	bc.in.Close()
	bc.out.Close()
}
<|endoftext|>


<commit_before>package main

import "./src"
import "os"
import "io/ioutil"

func main() {
	GoDynamoDB.Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)

	GoDynamoDB.Trace.Println("I have something standard to say")
	GoDynamoDB.Info.Println("Special Information")
	GoDynamoDB.Warning.Println("There is something you need to know about")
	GoDynamoDB.Error.Println("Something has failed")
}
<commit_msg>add import test<commit_after>package main

import GoDynamoDB "github.com/Misfit-John/GoDynamoDB/src"
import "os"
import "io/ioutil"

func main() {
	GoDynamoDB.Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)

	GoDynamoDB.Trace.Println("I have something standard to say")
	GoDynamoDB.Info.Println("Special Information")
	GoDynamoDB.Warning.Println("There is something you need to know about")
	GoDynamoDB.Error.Println("Something has failed")
}
<|endoftext|>


<commit_before>package main

import (
	"log"
	"net/http"

	"./archive"
)

const defaultPort = "5358"

func main() {
	// support       -> support file/archive extension
	// image/info    -> image infomation (json)
	// image/data    -> image binary data
	// image/ext     -> support image extension
	// archive/info  -> archive infomation (json)
	// archive/data  -> archive's image binary data
	// archive/ext   -> support archive extension
	archive.SetHttpRoute()

	log.Println("Listening on " + defaultPort)
	err := http.ListenAndServe(":"+defaultPort, nil)
	if err != nil {
		log.Fatal("Listen And Serve:", err)
	}
}
<commit_msg>add image routing<commit_after>package main

import (
	"log"
	"net/http"

	"./archive"
	"./image"
)

const defaultPort = "5358"

func main() {
	// support       -> support file/archive extension
	// image/info    -> image infomation (json)
	// image/data    -> image binary data
	// image/ext     -> support image extension
	// archive/info  -> archive infomation (json)
	// archive/data  -> archive's image binary data
	// archive/ext   -> support archive extension
	image.SetHttpRoute()
	archive.SetHttpRoute()

	log.Println("Listening on " + defaultPort)
	err := http.ListenAndServe(":"+defaultPort, nil)
	if err != nil {
		log.Fatal("Listen And Serve:", err)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/ActiveState/tail"
	"log"
)

func main() {
	log.Println("PushAlot Auth Notifier")
	t, err := tail.TailFile("/var/log/auth.log", tail.Config{
		Follow: true,
		ReOpen: true})
	if err != nil {
		log.Fatal("Uhh I can't read /var/log/auth.log ... Maybe I am not root? Maybe you are on windows?")
	}
	for line := range t.Lines {
		log.Println(line.Text)
	}
}
<commit_msg>Added sensible catch up<commit_after>package main

import (
	"github.com/ActiveState/tail"
	"log"
)

func main() {
	watchtarget := "/var/log/auth.log"
	log.Println("PushAlot Auth Notifier")
	t, err := tail.TailFile(watchtarget, tail.Config{
		Follow: true,
		ReOpen: true})
	if err != nil {
		log.Fatal("Uhh I can't read /var/log/auth.log ... Maybe I am not root? Maybe you are on windows?")
	}
	lc := CountLines(watchtarget) - 1
	cnt := 0
	for line := range t.Lines {
		if cnt < lc {
			cnt++
		} else {
			log.Println(line.Text)
		}
	}
}
<|endoftext|>


<commit_before>/**
 * @file main.go
 * @author Mikhail Klementyev jollheef<AT>riseup.net
 * @license GNU AGPLv3
 * @date October, 2015
 * @brief task-based ctf daemon
 *
 * Entry point for task-based ctf daemon
 */

package main

import (
	"database/sql"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"syscall"
	"time"

	"github.com/jollheef/henhouse/config"
	"github.com/jollheef/henhouse/db"
	"github.com/jollheef/henhouse/game"
	"github.com/jollheef/henhouse/scoreboard"
	kingpin "gopkg.in/alecthomas/kingpin.v2"
)

var (
	configPath = kingpin.Arg("config",
		"Path to configuration file.").Required().String()

	dbReinit = kingpin.Flag("reinit", "Reinit database.").Bool()
)

var (
	// CommitID fill in ./build.sh
	CommitID string
	// BuildDate fill in ./build.sh
	BuildDate string
	// BuildTime fill in ./build.sh
	BuildTime string
)

func reinitDatabase(database *sql.DB, cfg config.Config) (err error) {
	log.Println("Reinit database")

	for _, team := range cfg.Teams {
		log.Println("Add team", team.Name)
		err = db.AddTeam(database, &db.Team{
			Name:  team.Name,
			Desc:  team.Description,
			Token: team.Token,
			Test:  team.Test,
		})
		if err != nil {
			return
		}
	}

	entries, err := ioutil.ReadDir(cfg.TaskDir)
	if err != nil {
		return
	}

	var categories []db.Category

	for _, entry := range entries {

		if entry.IsDir() {
			continue
		}

		var content []byte
		content, err = ioutil.ReadFile(cfg.TaskDir + "/" +
			entry.Name())
		if err != nil {
			return
		}

		var task config.Task
		task, err = config.ParseXMLTask(content)
		if err != nil {
			return
		}

		var finded bool
		var taskCategory db.Category
		for _, cat := range categories {
			if cat.Name == task.Category {
				finded = true
				taskCategory = cat
				break
			}
		}

		if !finded {
			taskCategory.Name = task.Category

			err = db.AddCategory(database, &taskCategory)
			if err != nil {
				return
			}

			categories = append(categories, taskCategory)

			log.Println("Add category", taskCategory.Name)
		}

		if task.NameEn == "" {
			task.NameEn = task.Name
		}

		if task.Name == "" {
			task.Name = task.NameEn
		}

		if task.DescriptionEn == "" {
			task.DescriptionEn = task.Description
		}

		if task.Description == "" {
			task.Description = task.DescriptionEn
		}

		err = db.AddTask(database, &db.Task{
			Name:          task.Name,
			Desc:          task.Description,
			NameEn:        task.NameEn,
			DescEn:        task.DescriptionEn,
			Tags:          task.Tags,
			CategoryID:    taskCategory.ID,
			Level:         task.Level,
			Flag:          task.Flag,
			Price:         500,   // TODO support non-shared task
			Shared:        true,  // TODO support non-shared task
			MaxSharePrice: 500,   // TODO support value from xml
			MinSharePrice: 100,   // TODO support value from xml
			Opened:        false, // by default task is closed
			Author:        task.Author,
		})

		log.Println("Add task", task.Name)

		if err != nil {
			return
		}
	}

	return
}

func initGame(database *sql.DB, cfg config.Config) (err error) {

	log.Println("Start game at", cfg.Game.Start.Time)
	log.Println("End game at", cfg.Game.End.Time)
	game, err := game.NewGame(database, cfg.Game.Start.Time,
		cfg.Game.End.Time)
	if err != nil {
		return
	}

	if cfg.TaskPrice.P200 == 0 || cfg.TaskPrice.P300 == 0 ||
		cfg.TaskPrice.P400 == 0 || cfg.TaskPrice.P500 == 0 {
		err = errors.New("Error: Task price not setted")
		return
	}

	fmt := "Set task price %d if solved less than %d%%\n"
	log.Printf(fmt, 200, cfg.TaskPrice.P200)
	log.Printf(fmt, 300, cfg.TaskPrice.P300)
	log.Printf(fmt, 400, cfg.TaskPrice.P400)
	log.Printf(fmt, 500, cfg.TaskPrice.P500)

	game.SetTaskPrice(cfg.TaskPrice.P500, cfg.TaskPrice.P400,
		cfg.TaskPrice.P300, cfg.TaskPrice.P200)

	if cfg.TaskPrice.UseTeamsBase {
		game.SetTeamsBase(cfg.TaskPrice.TeamsBase)
		log.Println("Set teams base to", cfg.TaskPrice.TeamsBase)
	} else {
		log.Println("Use teams amount as teams base")
	}

	log.Println("Set task open timeout to", cfg.Task.OpenTimeout.Duration)
	game.OpenTimeout = cfg.Task.OpenTimeout.Duration

	if cfg.Task.AutoOpen {
		log.Println("Auto open tasks after",
			cfg.Task.AutoOpenTimeout.Duration)
	} else {
		log.Println("Auto open tasks disabled")
	}

	game.AutoOpen = cfg.Task.AutoOpen
	game.AutoOpenTimeout = cfg.Task.AutoOpenTimeout.Duration

	go game.Run()

	infoD := cfg.WebsocketTimeout.Info.Duration
	if infoD != 0 {
		scoreboard.InfoTimeout = infoD
	}
	log.Println("Update info timeout:", scoreboard.InfoTimeout)

	scoreboardD := cfg.WebsocketTimeout.Scoreboard.Duration
	if scoreboardD != 0 {
		scoreboard.ScoreboardTimeout = scoreboardD
	}
	log.Println("Update scoreboard timeout:", scoreboard.ScoreboardTimeout)

	tasksD := cfg.WebsocketTimeout.Tasks.Duration
	if tasksD != 0 {
		scoreboard.TasksTimeout = tasksD
	}
	log.Println("Update tasks timeout:", scoreboard.TasksTimeout)

	flagSendD := cfg.Flag.SendTimeout.Duration
	if flagSendD != 0 {
		scoreboard.FlagTimeout = flagSendD
	}
	log.Println("Flag timeout:", scoreboard.FlagTimeout)

	scoreboardRecalcD := cfg.Scoreboard.RecalcTimeout.Duration
	if scoreboardRecalcD != 0 {
		scoreboard.ScoreboardRecalcTimeout = scoreboardRecalcD
	}
	log.Println("Score recalc timeout:", scoreboard.ScoreboardRecalcTimeout)

	log.Println("Use html files from", cfg.Scoreboard.WwwPath)
	log.Println("Listen at", cfg.Scoreboard.Addr)
	err = scoreboard.Scoreboard(database, &game,
		cfg.Scoreboard.WwwPath,
		cfg.Scoreboard.TemplatePath,
		cfg.Scoreboard.Addr)
	if err != nil {
		return
	}

	return
}

func main() {

	if len(CommitID) > 7 {
		CommitID = CommitID[:7] // abbreviated commit hash
	}

	version := BuildDate + " " + CommitID +
		" (Mikhail Klementyev <jollheef@riseup.net>)"

	kingpin.Version(version)

	kingpin.Parse()

	fmt.Println(version)

	cfg, err := config.ReadConfig(*configPath)
	if err != nil {
		log.Fatalln("Cannot open config:", err)
	}

	logFile, err := os.OpenFile(cfg.LogFile,
		os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalln("Cannot open file:", err)
	}
	defer logFile.Close()
	log.SetOutput(logFile)

	log.Println(version)

	var rlim syscall.Rlimit
	err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim)
	if err != nil {
		log.Fatalln("Getrlimit fail:", err)
	}

	log.Println("RLIMIT_NOFILE CUR:", rlim.Cur, "MAX:", rlim.Max)

	var database *sql.DB

	if *dbReinit {

		if cfg.Database.SafeReinit {
			if time.Now().After(cfg.Game.Start.Time) {
				log.Fatalln("Reinit after start not allowed")
			}
		}

		database, err = db.InitDatabase(cfg.Database.Connection)
		if err != nil {
			log.Fatalln("Error:", err)
		}

		err = db.CleanDatabase(database)
		if err != nil {
			log.Fatalln("Error:", err)
		}

		defer database.Close()

		err = reinitDatabase(database, cfg)
		if err != nil {
			log.Fatalln("Error:", err)
		}

	} else {

		database, err = db.OpenDatabase(cfg.Database.Connection)
		if err != nil {
			log.Fatalln("Error:", err)
		}

		defer database.Close()
	}

	log.Println("Set max db connections to", cfg.Database.MaxConnections)
	database.SetMaxOpenConns(cfg.Database.MaxConnections)

	err = initGame(database, cfg)
	if err != nil {
		log.Fatalln("Error:", err)
	}
}
<commit_msg>Fix reinit for force closed<commit_after>/**
 * @file main.go
 * @author Mikhail Klementyev jollheef<AT>riseup.net
 * @license GNU AGPLv3
 * @date October, 2015
 * @brief task-based ctf daemon
 *
 * Entry point for task-based ctf daemon
 */

package main

import (
	"database/sql"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"syscall"
	"time"

	"github.com/jollheef/henhouse/config"
	"github.com/jollheef/henhouse/db"
	"github.com/jollheef/henhouse/game"
	"github.com/jollheef/henhouse/scoreboard"
	kingpin "gopkg.in/alecthomas/kingpin.v2"
)

var (
	configPath = kingpin.Arg("config",
		"Path to configuration file.").Required().String()

	dbReinit = kingpin.Flag("reinit", "Reinit database.").Bool()
)

var (
	// CommitID fill in ./build.sh
	CommitID string
	// BuildDate fill in ./build.sh
	BuildDate string
	// BuildTime fill in ./build.sh
	BuildTime string
)

func reinitDatabase(database *sql.DB, cfg config.Config) (err error) {
	log.Println("Reinit database")

	for _, team := range cfg.Teams {
		log.Println("Add team", team.Name)
		err = db.AddTeam(database, &db.Team{
			Name:  team.Name,
			Desc:  team.Description,
			Token: team.Token,
			Test:  team.Test,
		})
		if err != nil {
			return
		}
	}

	entries, err := ioutil.ReadDir(cfg.TaskDir)
	if err != nil {
		return
	}

	var categories []db.Category

	for _, entry := range entries {

		if entry.IsDir() {
			continue
		}

		var content []byte
		content, err = ioutil.ReadFile(cfg.TaskDir + "/" +
			entry.Name())
		if err != nil {
			return
		}

		var task config.Task
		task, err = config.ParseXMLTask(content)
		if err != nil {
			return
		}

		var finded bool
		var taskCategory db.Category
		for _, cat := range categories {
			if cat.Name == task.Category {
				finded = true
				taskCategory = cat
				break
			}
		}

		if !finded {
			taskCategory.Name = task.Category

			err = db.AddCategory(database, &taskCategory)
			if err != nil {
				return
			}

			categories = append(categories, taskCategory)

			log.Println("Add category", taskCategory.Name)
		}

		if task.NameEn == "" {
			task.NameEn = task.Name
		}

		if task.Name == "" {
			task.Name = task.NameEn
		}

		if task.DescriptionEn == "" {
			task.DescriptionEn = task.Description
		}

		if task.Description == "" {
			task.Description = task.DescriptionEn
		}

		err = db.AddTask(database, &db.Task{
			Name:          task.Name,
			Desc:          task.Description,
			NameEn:        task.NameEn,
			DescEn:        task.DescriptionEn,
			Tags:          task.Tags,
			CategoryID:    taskCategory.ID,
			Level:         task.Level,
			Flag:          task.Flag,
			Price:         500,   // TODO support non-shared task
			Shared:        true,  // TODO support non-shared task
			MaxSharePrice: 500,   // TODO support value from xml
			MinSharePrice: 100,   // TODO support value from xml
			Opened:        false, // by default task is closed
			Author:        task.Author,
			ForceClosed:   task.ForceClosed,
		})

		log.Println("Add task", task.Name)

		if err != nil {
			return
		}
	}

	return
}

func initGame(database *sql.DB, cfg config.Config) (err error) {

	log.Println("Start game at", cfg.Game.Start.Time)
	log.Println("End game at", cfg.Game.End.Time)
	game, err := game.NewGame(database, cfg.Game.Start.Time,
		cfg.Game.End.Time)
	if err != nil {
		return
	}

	if cfg.TaskPrice.P200 == 0 || cfg.TaskPrice.P300 == 0 ||
		cfg.TaskPrice.P400 == 0 || cfg.TaskPrice.P500 == 0 {
		err = errors.New("Error: Task price not setted")
		return
	}

	fmt := "Set task price %d if solved less than %d%%\n"
	log.Printf(fmt, 200, cfg.TaskPrice.P200)
	log.Printf(fmt, 300, cfg.TaskPrice.P300)
	log.Printf(fmt, 400, cfg.TaskPrice.P400)
	log.Printf(fmt, 500, cfg.TaskPrice.P500)

	game.SetTaskPrice(cfg.TaskPrice.P500, cfg.TaskPrice.P400,
		cfg.TaskPrice.P300, cfg.TaskPrice.P200)

	if cfg.TaskPrice.UseTeamsBase {
		game.SetTeamsBase(cfg.TaskPrice.TeamsBase)
		log.Println("Set teams base to", cfg.TaskPrice.TeamsBase)
	} else {
		log.Println("Use teams amount as teams base")
	}

	log.Println("Set task open timeout to", cfg.Task.OpenTimeout.Duration)
	game.OpenTimeout = cfg.Task.OpenTimeout.Duration

	if cfg.Task.AutoOpen {
		log.Println("Auto open tasks after",
			cfg.Task.AutoOpenTimeout.Duration)
	} else {
		log.Println("Auto open tasks disabled")
	}

	game.AutoOpen = cfg.Task.AutoOpen
	game.AutoOpenTimeout = cfg.Task.AutoOpenTimeout.Duration

	go game.Run()

	infoD := cfg.WebsocketTimeout.Info.Duration
	if infoD != 0 {
		scoreboard.InfoTimeout = infoD
	}
	log.Println("Update info timeout:", scoreboard.InfoTimeout)

	scoreboardD := cfg.WebsocketTimeout.Scoreboard.Duration
	if scoreboardD != 0 {
		scoreboard.ScoreboardTimeout = scoreboardD
	}
	log.Println("Update scoreboard timeout:", scoreboard.ScoreboardTimeout)

	tasksD := cfg.WebsocketTimeout.Tasks.Duration
	if tasksD != 0 {
		scoreboard.TasksTimeout = tasksD
	}
	log.Println("Update tasks timeout:", scoreboard.TasksTimeout)

	flagSendD := cfg.Flag.SendTimeout.Duration
	if flagSendD != 0 {
		scoreboard.FlagTimeout = flagSendD
	}
	log.Println("Flag timeout:", scoreboard.FlagTimeout)

	scoreboardRecalcD := cfg.Scoreboard.RecalcTimeout.Duration
	if scoreboardRecalcD != 0 {
		scoreboard.ScoreboardRecalcTimeout = scoreboardRecalcD
	}
	log.Println("Score recalc timeout:", scoreboard.ScoreboardRecalcTimeout)

	log.Println("Use html files from", cfg.Scoreboard.WwwPath)
	log.Println("Listen at", cfg.Scoreboard.Addr)
	err = scoreboard.Scoreboard(database, &game,
		cfg.Scoreboard.WwwPath,
		cfg.Scoreboard.TemplatePath,
		cfg.Scoreboard.Addr)
	if err != nil {
		return
	}

	return
}

func main() {

	if len(CommitID) > 7 {
		CommitID = CommitID[:7] // abbreviated commit hash
	}

	version := BuildDate + " " + CommitID +
		" (Mikhail Klementyev <jollheef@riseup.net>)"

	kingpin.Version(version)

	kingpin.Parse()

	fmt.Println(version)

	cfg, err := config.ReadConfig(*configPath)
	if err != nil {
		log.Fatalln("Cannot open config:", err)
	}

	logFile, err := os.OpenFile(cfg.LogFile,
		os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		log.Fatalln("Cannot open file:", err)
	}
	defer logFile.Close()
	log.SetOutput(logFile)

	log.Println(version)

	var rlim syscall.Rlimit
	err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim)
	if err != nil {
		log.Fatalln("Getrlimit fail:", err)
	}

	log.Println("RLIMIT_NOFILE CUR:", rlim.Cur, "MAX:", rlim.Max)

	var database *sql.DB

	if *dbReinit {

		if cfg.Database.SafeReinit {
			if time.Now().After(cfg.Game.Start.Time) {
				log.Fatalln("Reinit after start not allowed")
			}
		}

		database, err = db.InitDatabase(cfg.Database.Connection)
		if err != nil {
			log.Fatalln("Error:", err)
		}

		err = db.CleanDatabase(database)
		if err != nil {
			log.Fatalln("Error:", err)
		}

		defer database.Close()

		err = reinitDatabase(database, cfg)
		if err != nil {
			log.Fatalln("Error:", err)
		}

	} else {

		database, err = db.OpenDatabase(cfg.Database.Connection)
		if err != nil {
			log.Fatalln("Error:", err)
		}

		defer database.Close()
	}

	log.Println("Set max db connections to", cfg.Database.MaxConnections)
	database.SetMaxOpenConns(cfg.Database.MaxConnections)

	err = initGame(database, cfg)
	if err != nil {
		log.Fatalln("Error:", err)
	}
}
<|endoftext|>


<commit_before>package main

import(
  "log"
  "net/http"
  "os"
  "encoding/json"
  "fmt"
)

type Response struct {
  RouteDesc string
  StopDesc string
  List []struct {
    Sched string
    Est string
  }
}

func printResults(r Response) {
  fmt.Println("Route:", r.RouteDesc)
  fmt.Println("Stop:", r.StopDesc)
  if len(r.List) > 0 {
    for i, list := range r.List {
      fmt.Printf("Trip #%d\n", i+1)
      fmt.Printf("\tScheduled Time: %s\n", list.Sched)
      fmt.Printf("\tEstimated Time: %s\n", list.Est)
    }
  } else {
    fmt.Printf("No available trips found")
  }
}

func checkArgs(args []string) {
  if len(args) < 2 {
    log.Fatal("Usage: cm-nextbus StopID")
  }
}

func main() {

  checkArgs(os.Args)

  stopID := os.Args[1]

  url := "http://www.capmetro.org/planner/s_nextbus2.asp?stopid=" + stopID + "&opt=2"

  resp, err := http.Get(url)
  if err != nil {
    log.Fatal(err)
  }

  if resp.StatusCode != http.StatusOK {
    log.Fatal(resp.Status)
  }

  r := new(Response)
  err = json.NewDecoder(resp.Body).Decode(r)

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

  printResults(*r)
}
<commit_msg>Updated message when no trips are available<commit_after>package main

import(
  "log"
  "net/http"
  "os"
  "encoding/json"
  "fmt"
)

type Response struct {
  RouteDesc string
  StopDesc string
  List []struct {
    Sched string
    Est string
  }
}

func printResults(r Response) {
  fmt.Println("Route:", r.RouteDesc)
  fmt.Println("Stop:", r.StopDesc)
  if len(r.List) > 0 {
    for i, list := range r.List {
      fmt.Printf("Trip #%d\n", i+1)
      fmt.Printf("\tScheduled Time: %s\n", list.Sched)
      fmt.Printf("\tEstimated Time: %s\n", list.Est)
    }
  } else {
    fmt.Println("No available trips found")
  }
}

func checkArgs(args []string) {
  if len(args) < 2 {
    log.Fatal("Usage: cm-nextbus StopID")
  }
}

func main() {

  checkArgs(os.Args)

  stopID := os.Args[1]

  url := "http://www.capmetro.org/planner/s_nextbus2.asp?stopid=" + stopID + "&opt=2"

  resp, err := http.Get(url)
  if err != nil {
    log.Fatal(err)
  }

  if resp.StatusCode != http.StatusOK {
    log.Fatal(resp.Status)
  }

  r := new(Response)
  err = json.NewDecoder(resp.Body).Decode(r)

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

  printResults(*r)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	flags "github.com/jessevdk/go-flags"
	"github.com/monochromegane/terminal"
	"github.com/monochromegane/the_platinum_searcher/search"
	"github.com/monochromegane/the_platinum_searcher/search/option"
	"os"
	"runtime"
	"strings"
)

const version = "1.2.0"

var opts option.Option

func init() {
	if cpu := runtime.NumCPU(); cpu == 1 {
		runtime.GOMAXPROCS(2)
	} else {
		runtime.GOMAXPROCS(cpu)
	}
}

func main() {

	parser := flags.NewParser(&opts, flags.Default)
	parser.Name = "pt"
	parser.Usage = "[OPTIONS] PATTERN [PATH]"

	args, err := parser.Parse()
	if err != nil {
		os.Exit(1)
	}

	if len(args) == 0 {
		parser.WriteHelp(os.Stdout)
		os.Exit(1)
	}

	if opts.Version {
		fmt.Printf("%s\n", version)
		os.Exit(0)
	}

	var root = "."
	if len(args) == 2 {
		root = strings.TrimRight(args[1], "\"")
		_, err := os.Lstat(root)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
			os.Exit(1)
		}
	}

	opts.Proc = runtime.NumCPU()

	if !terminal.IsTerminal(os.Stdout) {
		opts.NoColor = true
		opts.NoGroup = true
	}

	searcher := search.Searcher{root, args[0], &opts}
	err = searcher.Search()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}
<commit_msg>Implemented context option.<commit_after>package main

import (
	"fmt"
	flags "github.com/jessevdk/go-flags"
	"github.com/monochromegane/terminal"
	"github.com/monochromegane/the_platinum_searcher/search"
	"github.com/monochromegane/the_platinum_searcher/search/option"
	"os"
	"runtime"
	"strings"
)

const version = "1.2.0"

var opts option.Option

func init() {
	if cpu := runtime.NumCPU(); cpu == 1 {
		runtime.GOMAXPROCS(2)
	} else {
		runtime.GOMAXPROCS(cpu)
	}
}

func main() {

	parser := flags.NewParser(&opts, flags.Default)
	parser.Name = "pt"
	parser.Usage = "[OPTIONS] PATTERN [PATH]"

	args, err := parser.Parse()
	if err != nil {
		os.Exit(1)
	}

	if len(args) == 0 {
		parser.WriteHelp(os.Stdout)
		os.Exit(1)
	}

	if opts.Version {
		fmt.Printf("%s\n", version)
		os.Exit(0)
	}

	var root = "."
	if len(args) == 2 {
		root = strings.TrimRight(args[1], "\"")
		_, err := os.Lstat(root)
		if err != nil {
			fmt.Fprintf(os.Stderr, "%s\n", err)
			os.Exit(1)
		}
	}

	opts.Proc = runtime.NumCPU()

	if !terminal.IsTerminal(os.Stdout) {
		opts.NoColor = true
		opts.NoGroup = true
	}

	if opts.Context > 0 {
		opts.Before = opts.Context
		opts.After = opts.Context
	}

	searcher := search.Searcher{root, args[0], &opts}
	err = searcher.Search()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/chronos-tachyon/mulberry/daemon"
)

var (
	config = flag.String("config", "", "path to the YAML configuration file")
)

func main() {
	flag.Parse()
	if *config == "" {
		log.Fatalf("fatal: missing required flag: -config")
	}
	d := daemon.New(*config)

	hupch := make(chan os.Signal)
	signal.Notify(hupch, syscall.SIGHUP)
	go (func() {
	Outer:
		for {
			select {
			case sig := <-hupch:
				if sig == nil {
					break Outer
				}
				log.Printf("info: got signal %v", sig)
				d.Reload()
			}
		}
	})()

	sigch := make(chan os.Signal)
	signal.Notify(sigch, syscall.SIGINT, syscall.SIGTERM)
	defer signal.Stop(sigch)
	go (func() {
		sig := <-sigch
		log.Printf("info: got signal %v", sig)
		d.Stop()
		close(hupch)
	})()

	log.Printf("info: looping")
	d.Loop()
	log.Printf("info: graceful shutdown")
}
<commit_msg>Simplify SIGHUP handling.<commit_after>package main

import (
	"flag"
	"log"
	"os"
	"os/signal"
	"syscall"

	"github.com/chronos-tachyon/mulberry/daemon"
)

var (
	config = flag.String("config", "", "path to the YAML configuration file")
)

func main() {
	flag.Parse()
	if *config == "" {
		log.Fatalf("fatal: missing required flag: -config")
	}
	d := daemon.New(*config)

	hupch := make(chan os.Signal)
	signal.Notify(hupch, syscall.SIGHUP)
	defer signal.Stop(hupch)
	go (func() {
		for {
			sig := <-hupch
			if sig == nil {
				break
			}
			log.Printf("info: got signal %v", sig)
			d.Reload()
		}
	})()

	sigch := make(chan os.Signal)
	signal.Notify(sigch, syscall.SIGINT, syscall.SIGTERM)
	defer signal.Stop(sigch)
	go (func() {
		sig := <-sigch
		log.Printf("info: got signal %v", sig)
		d.Stop()
		close(hupch)
	})()

	log.Printf("info: looping")
	d.Loop()
	log.Printf("info: graceful shutdown")
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/gobins/goaws/apihandlers"
)

func main() {
	app := cli.NewApp()
	app.Name = "goaws"
	app.Usage = "Aws cli using Golang SDK"

	//Defining sub-commands
	var environment string
	var tagname string
	var tagvalue string
	var attkey string
	var attvalue string
	var format string
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name: "format",
			Usage: "json or table. defaults to table.",
			Destination: &format,
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "get-subnets",
			Usage: "List all subnets",

			Action: func(c *cli.Context) {
				if format == "" || format == "table" {
					format = "table"
				} else if format != "json" {
					fmt.Println("Unsupported format", format)
					os.Exit(1)
				}
				log.Debug("Calling apihandlers.GetSubnetsFormatted")
				apihandlers.GetSubnetsFormatted(format)
			},
		},
		{
			Name:  "get-trail",
			Usage: "Return Cloudtrail events",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "attkey",
					Usage:       "EventId | EventName | Username | ResourceType | ResourceName",
					Destination: &attkey,
				},
				cli.StringFlag{
					Name:        "attvalue",
					Usage:       "Attribute Value for the LookupAttribute",
					Destination: &attvalue,
				},
			},
			Action: func(c *cli.Context) {
				var errorFlag bool
				if attkey == "" {
					fmt.Println("attkey is required for update-tag subcommand")
					errorFlag = true
				}
				if attvalue == "" {
					fmt.Println("attvalue is required for update-tag subcommand")
					errorFlag = true
				}
				if errorFlag == true {
					os.Exit(1)
				}
				apihandlers.GetTrail(attkey, attvalue, format)
			},
		},
		{
			Name:  "get-instances",
			Usage: "List all subnets",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "environment",
					Usage:       "Environment Name",
					Destination: &environment,
				},
			},
			Action: func(c *cli.Context) {
				log.Debug("Calling apihandlers.GetInstancesFormatted")
				var errorFlag bool
				if environment == "" {
					fmt.Println("environment is required for update-tag subcommand")
					errorFlag = true
				}
				if errorFlag == true {
					os.Exit(1)
				}
				apihandlers.GetInstancesFormatted(environment, format)
			},
		},
		{
			Name:  "update-tag",
			Usage: "Updates tag for all objects in subnet",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "environment",
					Usage:       "Environment Name",
					Destination: &environment,
				},
				cli.StringFlag{
					Name:        "tagname",
					Usage:       "Key of the tag",
					Destination: &tagname,
				},
				cli.StringFlag{
					Name:        "tagvalue",
					Usage:       "Value of the tag",
					Destination: &tagvalue,
				},
			},
			Action: func(c *cli.Context) {
				log.Debug("Calling apihandlers.UpdateEnvTags")
				var errorFlag bool
				if tagname == "" {
					fmt.Println("tagname is required for update-tag subcommand")
					errorFlag = true
				}
				if tagvalue == "" {
					fmt.Println("tagvalue is required for update-tag subcommand")
					errorFlag = true
				}
				if environment == "" {
					fmt.Println("environment is required for update-tag subcommand")
					errorFlag = true
				}
				if errorFlag == true {
					os.Exit(1)
				}
				apihandlers.UpdateEnvTags(tagname, tagvalue, environment)
			},
		},
	}
	app.Run(os.Args)

}
<commit_msg>set default format; remove validation of format from Action;<commit_after>package main

import (
	"fmt"
	"os"

	log "github.com/Sirupsen/logrus"
	"github.com/codegangsta/cli"
	"github.com/gobins/goaws/apihandlers"
)

func main() {
	app := cli.NewApp()
	app.Name = "goaws"
	app.Usage = "Aws cli using Golang SDK"

	//Defining sub-commands
	var environment string
	var tagname string
	var tagvalue string
	var attkey string
	var attvalue string
	var format string = "table" // set a default
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name: "format",
			Usage: "json or table. defaults to table.",
			Destination: &format,
		},
	}
	app.Commands = []cli.Command{
		{
			Name:  "get-subnets",
			Usage: "List all subnets",

			Action: func(c *cli.Context) {
				log.Debug("Calling apihandlers.GetSubnetsFormatted")
				apihandlers.GetSubnetsFormatted(format)
			},
		},
		{
			Name:  "get-trail",
			Usage: "Return Cloudtrail events",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "attkey",
					Usage:       "EventId | EventName | Username | ResourceType | ResourceName",
					Destination: &attkey,
				},
				cli.StringFlag{
					Name:        "attvalue",
					Usage:       "Attribute Value for the LookupAttribute",
					Destination: &attvalue,
				},
			},
			Action: func(c *cli.Context) {
				var errorFlag bool
				if attkey == "" {
					fmt.Println("attkey is required for update-tag subcommand")
					errorFlag = true
				}
				if attvalue == "" {
					fmt.Println("attvalue is required for update-tag subcommand")
					errorFlag = true
				}
				if errorFlag == true {
					os.Exit(1)
				}
				apihandlers.GetTrail(attkey, attvalue, format)
			},
		},
		{
			Name:  "get-instances",
			Usage: "List all subnets",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "environment",
					Usage:       "Environment Name",
					Destination: &environment,
				},
			},
			Action: func(c *cli.Context) {
				log.Debug("Calling apihandlers.GetInstancesFormatted")
				var errorFlag bool
				if environment == "" {
					fmt.Println("environment is required for update-tag subcommand")
					errorFlag = true
				}
				if errorFlag == true {
					os.Exit(1)
				}
				apihandlers.GetInstancesFormatted(environment, format)
			},
		},
		{
			Name:  "update-tag",
			Usage: "Updates tag for all objects in subnet",
			Flags: []cli.Flag{
				cli.StringFlag{
					Name:        "environment",
					Usage:       "Environment Name",
					Destination: &environment,
				},
				cli.StringFlag{
					Name:        "tagname",
					Usage:       "Key of the tag",
					Destination: &tagname,
				},
				cli.StringFlag{
					Name:        "tagvalue",
					Usage:       "Value of the tag",
					Destination: &tagvalue,
				},
			},
			Action: func(c *cli.Context) {
				log.Debug("Calling apihandlers.UpdateEnvTags")
				var errorFlag bool
				if tagname == "" {
					fmt.Println("tagname is required for update-tag subcommand")
					errorFlag = true
				}
				if tagvalue == "" {
					fmt.Println("tagvalue is required for update-tag subcommand")
					errorFlag = true
				}
				if environment == "" {
					fmt.Println("environment is required for update-tag subcommand")
					errorFlag = true
				}
				if errorFlag == true {
					os.Exit(1)
				}
				apihandlers.UpdateEnvTags(tagname, tagvalue, environment)
			},
		},
	}
	app.Run(os.Args)

}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"fmt"
	"github.com/garyburd/redigo/redis"
	"log"
	"math"
	"strconv"
	"strings"
	"time"
)

const (
	SERVER           = ":6379"
	BOARDSIZESQUARED = 25
	BOARDSIZE        = BOARDSIZESQUARED * BOARDSIZESQUARED
)

var (
	STARTINGROOMOFFSET = int(math.Ceil(BOARDSIZE / 2))
)

var pool = &redis.Pool{
	MaxIdle:     3,
	IdleTimeout: 240 * time.Second,
	Dial: func() (redis.Conn, error) {
		c, err := redis.Dial("tcp", SERVER)

		if err != nil {
			return nil, err
		}
		return c, err
	},
	TestOnBorrow: func(c redis.Conn, t time.Time) error {
		_, err := c.Do("PING")
		return err
	},
}

func main() {
	fmt.Println("Welcome to GoQuest")

	TestConnection()

	CreateEmptyDungeon()
	b := GetDungeon()

	paddedDungeon := PadDungeon(b)

	dungeonBoard := DungeonBytesToBoard(paddedDungeon)
	PrintBoard(dungeonBoard)

	bits := 3
	fmt.Println(PadBits(8 - bits))
}

func TestConnection() {
	conn := pool.Get()
	x, err := redis.String(conn.Do("SET", "NAME", "RALPH"))
	if err != nil {
		log.Println("Perhaps Redis is offline or somethin'")
		log.Fatal(err)
	}
	fmt.Println("Success!")
	fmt.Println(x)
}

func CreateEmptyDungeon() {
	log.Println("CreateEmptyDungeon()")
	//middle of the grid

	conn := pool.Get()
	_, err := conn.Do("SETBIT", "DUNGEON", STARTINGROOMOFFSET, 1)

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

func GetDungeon() []byte {
	log.Println("GetDungeon()")

	conn := pool.Get()
	repl, err := redis.Bytes(conn.Do("GETRANGE", "DUNGEON", 0, BOARDSIZE))
	if err != nil {
		log.Fatal(err)
	}

	return repl
}

func PadDungeon(dungeon []byte) []byte {

	//TODO: fix board size, somehow we end up with a board that is 632 bits it should be 625 at the most.
	dungeonSizeInBytes := int(math.Ceil(BOARDSIZE / 8.0))

	paddedDungeon := make([]byte, dungeonSizeInBytes)

	for i, b := range dungeon {
		paddedDungeon[i] = b
	}

	return paddedDungeon
}

func PadBits(n int) string {
	pad := ""

	for i := 0; i < n; i++ {
		pad += "0"
	}
	return pad
}

func DungeonBytesToBoard(bSlice []byte) string {

	var buf bytes.Buffer

	for i, b := range bSlice {

		bitString := strconv.FormatInt(int64(b), 2)
		buf.WriteString(PadBits(8-len(bitString)) + bitString)

	}

	return buf.String()
}

func PrintBoard(dungeon string) {
	result := strings.Split(dungeon, "")

	fmt.Println("[" + strings.Join(result, ",") + "]")
}
<commit_msg>Added timer, and ClearAllState() method<commit_after>package main

import (
	"bytes"
	"fmt"
	"github.com/garyburd/redigo/redis"
	"log"
	"math"
	"strconv"
	"strings"
	"time"
)

const (
	SERVER           = ":6379"
	BOARDSIZESQUARED = 25
	BOARDSIZE        = BOARDSIZESQUARED * BOARDSIZESQUARED
)

var (
	STARTINGROOMOFFSET = int(math.Ceil(BOARDSIZE / 2))
)

//TODO: create a command system that allows you to fire off a command either
//		within a transaction as a MULTI EXEC
//	    or singular as a Do()

var pool = &redis.Pool{
	MaxIdle:     3,
	IdleTimeout: 240 * time.Second,
	Dial: func() (redis.Conn, error) {
		c, err := redis.Dial("tcp", SERVER)

		if err != nil {
			return nil, err
		}
		return c, err
	},
	TestOnBorrow: func(c redis.Conn, t time.Time) error {
		_, err := c.Do("PING")
		return err
	},
}

func main() {
	defer un(trace("main()"))
	fmt.Println("Welcome to GoQuest")

	TestConnection()
	ClearAllState()

	CreateEmptyDungeon()

	b := GetDungeon()

	paddedDungeon := PadDungeon(b)

	dungeonBoard := DungeonBytesToBoard(paddedDungeon)
	PrintBoard(dungeonBoard)
}

func trace(s string) (string, time.Time) {
	log.Println("START:", s)
	return s, time.Now()
}

func un(s string, startTime time.Time) {
	endTime := time.Now()
	log.Println("  END:", s, "ElapsedTime in seconds:", endTime.Sub(startTime))
}

func TestConnection() {
	conn := pool.Get()
	x, err := redis.String(conn.Do("SET", "NAME", "RALPH"))
	if err != nil {
		log.Println("Perhaps Redis is offline or somethin'")
		log.Fatal(err)
	}
	fmt.Println("Success!")
	fmt.Println(x)
}

func ClearAllState() {
	log.Println("ClearAllState()")

	conn := pool.Get()
	conn.Send("MULTI")
	conn.Send("DEL", "DUNGEON")
	_, err := conn.Do("EXEC")
	if err != nil {
		log.Fatal("Couldn't clear all state")
	}
}

func AddRoom(offset int) {
	log.Println("AddRoom()")
	//middle of the grid

	conn := pool.Get()

	_, err := conn.Do("SETBIT", "DUNGEON", offset, 1)

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

func CreateEmptyDungeon() {
	log.Println("CreateEmptyDungeon()")

	AddRoom(STARTINGROOMOFFSET)
}

func GetDungeon() []byte {
	log.Println("GetDungeon()")

	conn := pool.Get()
	repl, err := redis.Bytes(conn.Do("GETRANGE", "DUNGEON", 0, BOARDSIZE))
	if err != nil {
		log.Fatal(err)
	}

	return repl
}

func PadDungeon(dungeon []byte) []byte {

	//TODO: fix board size, somehow we end up with a board that is 632 bits it should be 625 at the most.
	dungeonSizeInBytes := int(math.Ceil(BOARDSIZE / 8.0))

	paddedDungeon := make([]byte, dungeonSizeInBytes)

	for i, b := range dungeon {
		paddedDungeon[i] = b
	}

	return paddedDungeon
}

func PadBits(n int) string {
	pad := ""

	for i := 0; i < n; i++ {
		pad += "0"
	}
	return pad
}

func DungeonBytesToBoard(bSlice []byte) string {

	var buf bytes.Buffer

	for _, b := range bSlice {

		bitString := strconv.FormatInt(int64(b), 2)
		buf.WriteString(PadBits(8-len(bitString)) + bitString)

	}

	return buf.String()
}

func PrintBoard(dungeon string) {
	result := strings.Split(dungeon, "")

	//truncate to max size of dungeon because of extra padding of bits remainder of byte at the end
	result = result[0:BOARDSIZE]

	fmt.Println("[" + strings.Join(result, ",") + "]")
}
<|endoftext|>


<commit_before>package main

import (
	"bitbucket.org/kardianos/osext"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/fgrehm/devstep-cli/devstep"
	"github.com/segmentio/go-prompt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	project devstep.Project
	client  devstep.DockerClient
)

var commands = []cli.Command{
	hackCmd,
	buildCmd,
	bootstrapCmd,
	infoCmd,
	runCmd,
	binstubsCmd,
	cleanCmd,
	pristineCmd,
}

func main() {
	app := cli.NewApp()
	app.Name = "devstep"
	app.Author = "Fábio Rehm"
	app.Email = "fgrehm@gmail.com"
	app.Usage = "development environments made easy"
	app.Version = "0.1.0"
	app.EnableBashCompletion = true
	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "log-level, l", Usage: "log level", EnvVar: "DEVSTEP_LOG"},
	}
	app.Before = func(c *cli.Context) error {
		return devstep.SetLogLevel(c.GlobalString("log-level"))
	}
	app.Commands = commands

	app.RunAndExitOnError()
}

var dockerRunFlags = []cli.Flag{
	cli.StringFlag{Name: "w, working_dir", Usage: "Working directory inside the container"},
	cli.StringSliceFlag{Name: "p, publish", Value: &cli.StringSlice{}, Usage: "Publish a container's port to the host (hostPort:containerPort)"},
	cli.StringSliceFlag{Name: "link", Value: &cli.StringSlice{}, Usage: "Add link to another container (name:alias)"},
	cli.StringSliceFlag{Name: "e, env", Value: &cli.StringSlice{}, Usage: "Set environment variables"},
	cli.BoolFlag{Name: "privileged", Usage: "Give extended privileges to this container"},
}

func loadConfig() *devstep.ProjectConfig {
	projectRoot, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "unix:///var/run/docker.sock"
	}

	homeDir := os.Getenv("HOME")
	client = devstep.NewClient(dockerHost)
	loader := devstep.NewConfigLoader(client, homeDir, projectRoot)

	config, err := loader.Load()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	pluginsToLoad, err := filepath.Glob(homeDir + "/devstep/plugins/*/plugin.js")
	if err != nil {
		fmt.Printf("Error searching for plugins under '%s'\n%s\n", homeDir, err.Error())
		os.Exit(1)
	}

	if len(pluginsToLoad) > 0 {
		runtime := devstep.NewPluginRuntime(config)
		for _, pluginPath := range pluginsToLoad {
			runtime.Load(pluginPath)
		}
		runtime.Trigger("configLoaded")
	}

	if devstep.LogLevel != "" {
		config.Defaults.Env["DEVSTEP_LOG"] = devstep.LogLevel
	}

	return config
}

func newProject() devstep.Project {
	config := loadConfig()
	project, _ = devstep.NewProject(config)
	return project
}

var buildCmd = cli.Command{
	Name:  "build",
	Usage: "build a docker image for the current project",
	Action: func(c *cli.Context) {
		err := newProject().Build(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var bootstrapCmd = cli.Command{
	Name:  "bootstrap",
	Usage: "bootstrap an environment for the current project",
	Action: func(c *cli.Context) {
		err := newProject().Bootstrap(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var hackCmd = cli.Command{
	Name:  "hack",
	Usage: "start a hacking session for the current project",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		project := newProject()
		runOpts := parseRunOpts(c)
		err := project.Hack(client, runOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var runCmd = cli.Command{
	Name:  "run",
	Usage: "Run a one off command against the current base image",
	Flags: dockerRunFlags,
	Action: func(c *cli.Context) {
		project := newProject()
		commands := project.Config().Commands

		runOpts := parseRunOpts(c)
		runOpts.Cmd = c.Args()

		// Validate command
		if len(runOpts.Cmd) == 0 {
			fmt.Printf("No command provided to `devstep run`\n\n")
			cli.ShowCommandHelp(c, "run")
			os.Exit(1)
		}

		if cmd, ok := commands[runOpts.Cmd[0]]; ok {
			runOpts = cmd.Merge(runOpts)
			runOpts.Cmd = append(cmd.Cmd, runOpts.Cmd[1:]...)
		}

		// Prepend a `--` so that it doesn't interfere with the current init
		// process args
		runOpts.Cmd = append([]string{"--"}, runOpts.Cmd...)

		err := project.Run(client, runOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var binstubsCmd = cli.Command{
	Name:  "binstubs",
	Usage: "Generate binstubs for the commands specified on devstep.yml",
	Action: func(c *cli.Context) {
		project := newProject()
		commands := project.Config().Commands

		if len(commands) == 0 {
			fmt.Println("No binstubs specified!")
			os.Exit(0)
		}

		binstubsPath := ".devstep/bin"
		os.MkdirAll("./"+binstubsPath, 0700)

		executable, _ := osext.Executable()

		for _, cmd := range commands {
			script := []byte("#!/usr/bin/env bash\neval \"" + executable + " run -- " + cmd.Name + " $@\"")
			err := ioutil.WriteFile(binstubsPath+"/"+cmd.Name, script, 0755)
			if err != nil {
				fmt.Printf("Error creating binstub '%s'\n%s\n", binstubsPath+"/"+cmd.Name, err)
				os.Exit(1)
			}
			fmt.Printf("Generated binstub for '%s' in '%s'\n", cmd.Name, binstubsPath)
		}
	},
}

var cleanCmd = cli.Command{
	Name:  "clean",
	Usage: "remove previously built images for the current environment",
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "force, f", Usage: "skip confirmation"},
	},
	Action: func(c *cli.Context) {
		if !c.Bool("force") {
			if ok := prompt.Confirm("Are you sure? [N/y] "); !ok {
				fmt.Println("Aborting")
				os.Exit(1)
			}
		}

		err := newProject().Clean(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var pristineCmd = cli.Command{
	Name:  "pristine",
	Usage: "rebuild project image from scratch",
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "force, f", Usage: "skip clean confirmation"},
	},
	Action: func(c *cli.Context) {
		// TODO: Figure out if this is the right way to invoke other CLI actions
		cleanCmd.Action(c)
		buildCmd.Action(c)
	},
}

var infoCmd = cli.Command{
	Name:  "info",
	Usage: "show information about the current environment",
	Action: func(c *cli.Context) {
		config := loadConfig()
		printConfig(config)
	},
}

func printConfig(config *devstep.ProjectConfig) {
	fmt.Println("==> Project info")
	fmt.Printf("Repository:   %s\n", config.RepositoryName)
	fmt.Printf("Source image: %s\n", config.SourceImage)
	fmt.Printf("Base image:   %s\n", config.BaseImage)
	fmt.Printf("Host dir:     %s\n", config.HostDir)
	fmt.Printf("Guest dir:    %s\n", config.GuestDir)
	fmt.Printf("Cache dir:    %s\n", config.CacheDir)

	if config.Defaults != nil {
		fmt.Println("\n==> Default options:")
		printDockerRunOpts(config.Defaults, "")
	}

	if config.HackOpts != nil {
		fmt.Println("\n==> Hack options:")
		printDockerRunOpts(config.HackOpts, "")
	}
	if config.Commands != nil {
		fmt.Println("\n==> Commands:")
		for _, cmd := range config.Commands {
			fmt.Printf("* %s\n", cmd.Name)
			fmt.Printf("  Cmd:        %v\n", cmd.Cmd)
			fmt.Printf("  Publish:    %v\n", cmd.Publish)
			printDockerRunOpts(&cmd.DockerRunOpts, "  ")
		}
	}
}

func printDockerRunOpts(opts *devstep.DockerRunOpts, prefix string) {
	fmt.Printf("%sPrivileged: %v\n", prefix, *opts.Privileged)
	fmt.Printf("%sLinks:      %v\n", prefix, opts.Links)
	fmt.Printf("%sVolumes:    %v\n", prefix, opts.Volumes)
	fmt.Printf("%sEnv:        %v\n", prefix, opts.Env)
}

func parseRunOpts(c *cli.Context) *devstep.DockerRunOpts {
	runOpts := &devstep.DockerRunOpts{
		Publish: c.StringSlice("publish"),
		Links:   c.StringSlice("link"),
		Env:     make(map[string]string),
	}

	// Only set the privileged config if it was provided
	if c.IsSet("privileged") {
		privileged := c.Bool("privileged")
		runOpts.Privileged = &privileged
	}

	// Set working dir directly on the project object so that it get passed
	// along properly
	if workingDir := c.String("working_dir"); workingDir != "" {
		project.Config().GuestDir = workingDir
	}

	// Env vars
	for _, envVar := range c.StringSlice("env") {
		varAndValue := strings.Split(envVar, "=")
		runOpts.Env[varAndValue[0]] = varAndValue[1]
	}

	// Validate ports
	validPort := regexp.MustCompile(`^\d+:\d+$`)
	for _, port := range runOpts.Publish {
		if !validPort.MatchString(port) {
			fmt.Println("Invalid publish arg: " + port)
			os.Exit(1)
		}
	}
	// Validate links
	validLink := regexp.MustCompile(`[^:]+:[^:]+`)
	for _, link := range runOpts.Links {
		if !validLink.MatchString(link) {
			fmt.Println("Invalid link: " + link)
			os.Exit(1)
		}
	}
	return runOpts
}
<commit_msg>Bump to 0.2.0<commit_after>package main

import (
	"bitbucket.org/kardianos/osext"
	"fmt"
	"github.com/codegangsta/cli"
	"github.com/fgrehm/devstep-cli/devstep"
	"github.com/segmentio/go-prompt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	project devstep.Project
	client  devstep.DockerClient
)

var commands = []cli.Command{
	hackCmd,
	buildCmd,
	bootstrapCmd,
	infoCmd,
	runCmd,
	binstubsCmd,
	cleanCmd,
	pristineCmd,
}

func main() {
	app := cli.NewApp()
	app.Name = "devstep"
	app.Author = "Fábio Rehm"
	app.Email = "fgrehm@gmail.com"
	app.Usage = "development environments made easy"
	app.Version = "0.2.0"
	app.EnableBashCompletion = true
	app.Flags = []cli.Flag{
		cli.StringFlag{Name: "log-level, l", Usage: "log level", EnvVar: "DEVSTEP_LOG"},
	}
	app.Before = func(c *cli.Context) error {
		return devstep.SetLogLevel(c.GlobalString("log-level"))
	}
	app.Commands = commands

	app.RunAndExitOnError()
}

var dockerRunFlags = []cli.Flag{
	cli.StringFlag{Name: "w, working_dir", Usage: "Working directory inside the container"},
	cli.StringSliceFlag{Name: "p, publish", Value: &cli.StringSlice{}, Usage: "Publish a container's port to the host (hostPort:containerPort)"},
	cli.StringSliceFlag{Name: "link", Value: &cli.StringSlice{}, Usage: "Add link to another container (name:alias)"},
	cli.StringSliceFlag{Name: "e, env", Value: &cli.StringSlice{}, Usage: "Set environment variables"},
	cli.BoolFlag{Name: "privileged", Usage: "Give extended privileges to this container"},
}

func loadConfig() *devstep.ProjectConfig {
	projectRoot, err := os.Getwd()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	dockerHost := os.Getenv("DOCKER_HOST")
	if dockerHost == "" {
		dockerHost = "unix:///var/run/docker.sock"
	}

	homeDir := os.Getenv("HOME")
	client = devstep.NewClient(dockerHost)
	loader := devstep.NewConfigLoader(client, homeDir, projectRoot)

	config, err := loader.Load()
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	pluginsToLoad, err := filepath.Glob(homeDir + "/devstep/plugins/*/plugin.js")
	if err != nil {
		fmt.Printf("Error searching for plugins under '%s'\n%s\n", homeDir, err.Error())
		os.Exit(1)
	}

	if len(pluginsToLoad) > 0 {
		runtime := devstep.NewPluginRuntime(config)
		for _, pluginPath := range pluginsToLoad {
			runtime.Load(pluginPath)
		}
		runtime.Trigger("configLoaded")
	}

	if devstep.LogLevel != "" {
		config.Defaults.Env["DEVSTEP_LOG"] = devstep.LogLevel
	}

	return config
}

func newProject() devstep.Project {
	config := loadConfig()
	project, _ = devstep.NewProject(config)
	return project
}

var buildCmd = cli.Command{
	Name:  "build",
	Usage: "build a docker image for the current project",
	Action: func(c *cli.Context) {
		err := newProject().Build(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var bootstrapCmd = cli.Command{
	Name:  "bootstrap",
	Usage: "bootstrap an environment for the current project",
	Action: func(c *cli.Context) {
		err := newProject().Bootstrap(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var hackCmd = cli.Command{
	Name:  "hack",
	Usage: "start a hacking session for the current project",
	Flags: dockerRunFlags,
	BashComplete: func(c *cli.Context) {
		args := c.Args()
		if len(args) == 0 {
			fmt.Println("-p")
			fmt.Println("--publish")
			fmt.Println("--link")
			fmt.Println("-w")
			fmt.Println("--working_dir")
			fmt.Println("-e")
			fmt.Println("--env")
			fmt.Println("--privileged")
		}
	},
	Action: func(c *cli.Context) {
		project := newProject()
		runOpts := parseRunOpts(c)
		err := project.Hack(client, runOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var runCmd = cli.Command{
	Name:  "run",
	Usage: "Run a one off command against the current base image",
	Flags: dockerRunFlags,
	Action: func(c *cli.Context) {
		project := newProject()
		commands := project.Config().Commands

		runOpts := parseRunOpts(c)
		runOpts.Cmd = c.Args()

		// Validate command
		if len(runOpts.Cmd) == 0 {
			fmt.Printf("No command provided to `devstep run`\n\n")
			cli.ShowCommandHelp(c, "run")
			os.Exit(1)
		}

		if cmd, ok := commands[runOpts.Cmd[0]]; ok {
			runOpts = cmd.Merge(runOpts)
			runOpts.Cmd = append(cmd.Cmd, runOpts.Cmd[1:]...)
		}

		// Prepend a `--` so that it doesn't interfere with the current init
		// process args
		runOpts.Cmd = append([]string{"--"}, runOpts.Cmd...)

		err := project.Run(client, runOpts)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var binstubsCmd = cli.Command{
	Name:  "binstubs",
	Usage: "Generate binstubs for the commands specified on devstep.yml",
	Action: func(c *cli.Context) {
		project := newProject()
		commands := project.Config().Commands

		if len(commands) == 0 {
			fmt.Println("No binstubs specified!")
			os.Exit(0)
		}

		binstubsPath := ".devstep/bin"
		os.MkdirAll("./"+binstubsPath, 0700)

		executable, _ := osext.Executable()

		for _, cmd := range commands {
			script := []byte("#!/usr/bin/env bash\neval \"" + executable + " run -- " + cmd.Name + " $@\"")
			err := ioutil.WriteFile(binstubsPath+"/"+cmd.Name, script, 0755)
			if err != nil {
				fmt.Printf("Error creating binstub '%s'\n%s\n", binstubsPath+"/"+cmd.Name, err)
				os.Exit(1)
			}
			fmt.Printf("Generated binstub for '%s' in '%s'\n", cmd.Name, binstubsPath)
		}
	},
}

var cleanCmd = cli.Command{
	Name:  "clean",
	Usage: "remove previously built images for the current environment",
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "force, f", Usage: "skip confirmation"},
	},
	Action: func(c *cli.Context) {
		if !c.Bool("force") {
			if ok := prompt.Confirm("Are you sure? [N/y] "); !ok {
				fmt.Println("Aborting")
				os.Exit(1)
			}
		}

		err := newProject().Clean(client)
		if err != nil {
			fmt.Println(err)
			os.Exit(1)
		}
	},
}

var pristineCmd = cli.Command{
	Name:  "pristine",
	Usage: "rebuild project image from scratch",
	Flags: []cli.Flag{
		cli.BoolFlag{Name: "force, f", Usage: "skip clean confirmation"},
	},
	Action: func(c *cli.Context) {
		// TODO: Figure out if this is the right way to invoke other CLI actions
		cleanCmd.Action(c)
		buildCmd.Action(c)
	},
}

var infoCmd = cli.Command{
	Name:  "info",
	Usage: "show information about the current environment",
	Action: func(c *cli.Context) {
		config := loadConfig()
		printConfig(config)
	},
}

func printConfig(config *devstep.ProjectConfig) {
	fmt.Println("==> Project info")
	fmt.Printf("Repository:   %s\n", config.RepositoryName)
	fmt.Printf("Source image: %s\n", config.SourceImage)
	fmt.Printf("Base image:   %s\n", config.BaseImage)
	fmt.Printf("Host dir:     %s\n", config.HostDir)
	fmt.Printf("Guest dir:    %s\n", config.GuestDir)
	fmt.Printf("Cache dir:    %s\n", config.CacheDir)

	if config.Defaults != nil {
		fmt.Println("\n==> Default options:")
		printDockerRunOpts(config.Defaults, "")
	}

	if config.HackOpts != nil {
		fmt.Println("\n==> Hack options:")
		printDockerRunOpts(config.HackOpts, "")
	}
	if config.Commands != nil {
		fmt.Println("\n==> Commands:")
		for _, cmd := range config.Commands {
			fmt.Printf("* %s\n", cmd.Name)
			fmt.Printf("  Cmd:        %v\n", cmd.Cmd)
			fmt.Printf("  Publish:    %v\n", cmd.Publish)
			printDockerRunOpts(&cmd.DockerRunOpts, "  ")
		}
	}
}

func printDockerRunOpts(opts *devstep.DockerRunOpts, prefix string) {
	fmt.Printf("%sPrivileged: %v\n", prefix, *opts.Privileged)
	fmt.Printf("%sLinks:      %v\n", prefix, opts.Links)
	fmt.Printf("%sVolumes:    %v\n", prefix, opts.Volumes)
	fmt.Printf("%sEnv:        %v\n", prefix, opts.Env)
}

func parseRunOpts(c *cli.Context) *devstep.DockerRunOpts {
	runOpts := &devstep.DockerRunOpts{
		Publish: c.StringSlice("publish"),
		Links:   c.StringSlice("link"),
		Env:     make(map[string]string),
	}

	// Only set the privileged config if it was provided
	if c.IsSet("privileged") {
		privileged := c.Bool("privileged")
		runOpts.Privileged = &privileged
	}

	// Set working dir directly on the project object so that it get passed
	// along properly
	if workingDir := c.String("working_dir"); workingDir != "" {
		project.Config().GuestDir = workingDir
	}

	// Env vars
	for _, envVar := range c.StringSlice("env") {
		varAndValue := strings.Split(envVar, "=")
		runOpts.Env[varAndValue[0]] = varAndValue[1]
	}

	// Validate ports
	validPort := regexp.MustCompile(`^\d+:\d+$`)
	for _, port := range runOpts.Publish {
		if !validPort.MatchString(port) {
			fmt.Println("Invalid publish arg: " + port)
			os.Exit(1)
		}
	}
	// Validate links
	validLink := regexp.MustCompile(`[^:]+:[^:]+`)
	for _, link := range runOpts.Links {
		if !validLink.MatchString(link) {
			fmt.Println("Invalid link: " + link)
			os.Exit(1)
		}
	}
	return runOpts
}
<|endoftext|>


<commit_before>package main

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

func init() {
	flag.Usage = func() {
		fmt.Print(`usage: migen <command> [option]

Commands:
	new [options] : Generate a migration file
`)
		os.Exit(0)
	}
}

func newCommand(args []string) {
	var (
		format string
		name   string
	)
	fs := flag.NewFlagSet("new", flag.ExitOnError)
	fs.StringVar(&format, "format", "date", "specify the format of prefix")
	fs.StringVar(&name, "name", "", "specify the file name")

	fs.Parse(args)

	fn, err := fileName(format, name)
	if err != nil {
		log.Fatal(err)
		return
	}

	err = createFile(fn, ".")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(fn, "is generated")
}

func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) == 0 {
		flag.Usage()
	}
	switch args[0] {
	case "new":
		newCommand(args[1:])
	default:
		flag.Usage()
	}
}
<commit_msg>Add usage of new command<commit_after>package main

import (
	"flag"
	"fmt"
	"log"
)

var (
	mainUsage = `usage: migen <command> [option]

Commands:
	new [options] : Generate a migration file`

	newUsage = `usage: migen new [option]

Options:
	-f, --format <format> specify the format of file prefix
	                      formats: date, counter, unix, none (Default: date)
	-n, --name <name>     specify the file name
	-h, --help            show this help`
)

func init() {
	flag.Usage = func() {
		fmt.Println(mainUsage)
	}
}

func main() {
	flag.Parse()

	switch flag.Arg(0) {
	case "new":
		newCommand(flag.Args()[1:])
	default:
		flag.Usage()
	}
}

func newCommand(args []string) {
	var (
		format string
		name   string
		help   bool
	)
	fs := flag.NewFlagSet("new", flag.ExitOnError)
	fs.StringVar(&format, "format", "date", "specify the format of prefix")
	fs.StringVar(&format, "f", "date", "shorthand of format")
	fs.StringVar(&name, "name", "", "specify the file name")
	fs.StringVar(&name, "n", "", "shorthand of name")
	fs.BoolVar(&help, "help", false, "show help")
	fs.BoolVar(&help, "h", false, "shorthand of help")

	fs.Parse(args)

	if help {
		fmt.Println(newUsage)
		return
	}

	fn, err := fileName(format, name)
	if err != nil {
		log.Fatal(err)
		return
	}

	err = createFile(fn, ".")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(fn, "is generated")
}
<|endoftext|>


<commit_before>package main

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

	"github.com/icza/gowut/gwu"

	"github.com/udhos/jazigo/dev"
	"github.com/udhos/jazigo/store"
)

const appName = "jazigo"
const appVersion = "0.0"

type app struct {
	configPathPrefix string
	repositoryPath   string
	maxConfigFiles   int
	holdtime         time.Duration
	scanInterval     time.Duration

	table *dev.DeviceTable

	apHome    gwu.Panel
	apAdmin   gwu.Panel
	apLogout  gwu.Panel
	winHome   gwu.Window
	winAdmin  gwu.Window
	winLogout gwu.Window

	cssPath string

	logger hasPrintf
}

type hasPrintf interface {
	Printf(fmt string, v ...interface{})
}

func (a *app) logf(fmt string, v ...interface{}) {
	a.logger.Printf(fmt, v...)
}

func newApp(logger hasPrintf) *app {
	app := &app{
		table:        dev.NewDeviceTable(),
		logger:       logger,
		holdtime:     60 * time.Second, // FIXME: 12h (do not collect/save new backup before this timeout)
		scanInterval: 10 * time.Second, // FIXME: 1h (interval between full table scan)
	}

	app.logf("%s %s starting", appName, appVersion)

	dev.RegisterModels(app.logger, app.table)

	return app
}

func main() {

	logger := log.New(os.Stdout, "", log.LstdFlags)

	jaz := newApp(logger)

	var runOnce bool

	flag.StringVar(&jaz.configPathPrefix, "configPathPrefix", "/etc/jazigo/jazigo.conf.", "configuration path prefix")
	flag.StringVar(&jaz.repositoryPath, "repositoryPath", "/var/jazigo", "repository path")
	flag.IntVar(&jaz.maxConfigFiles, "maxConfigFiles", 10, "limit number of configuration files (negative value means unlimited)")
	flag.BoolVar(&runOnce, "runOnce", false, "exit after scanning all devices once")
	flag.Parse()
	jaz.logf("config path prefix: %s", jaz.configPathPrefix)
	jaz.logf("repository path: %s", jaz.repositoryPath)
	jaz.logf("scan interval: %s", jaz.scanInterval)
	jaz.logf("holdtime: %s", jaz.holdtime)
	jaz.logf("runOnce: %v", runOnce)

	lastConfig, configErr := store.FindLastConfig(jaz.configPathPrefix, logger)
	if configErr != nil {
		jaz.logf("error reading config: '%s': %v", jaz.configPathPrefix, configErr)
	} else {
		jaz.logf("last config: %s", lastConfig)
	}

	//dev.CreateDevice(jaz.table, jaz.logger, "cisco-ios", "lab1", "localhost:2001", "telnet", "lab", "pass", "en")
	//dev.CreateDevice(jaz.table, jaz.logger, "cisco-ios", "lab1", "localhost:2001", "telnet", "lab", "pass", "en") // ugh
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab2", "localhost:2002", "ssh", "lab", "pass", "en")
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab3", "localhost:2003", "telnet,ssh", "lab", "pass", "en")
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab4", "localhost:2004", "ssh,telnet", "lab", "pass", "en")
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab5", "localhost", "telnet", "lab", "pass", "en")
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab6", "localhost", "ssh", "rat", "lab", "en")
	//dev.CreateDevice(jaz.table, jaz.logger, "http", "lab7", "localhost:2009", "telnet", "", "", "")

	dev.CreateDevice(jaz.table, jaz.logger, "linux", "lab8", "localhost", "ssh", "rat", "lab", "lab", false)
	dev.CreateDevice(jaz.table, jaz.logger, "junos", "lab9", "ex4200lab", "ssh", "test", "lab000", "lab", false)
	dev.CreateDevice(jaz.table, jaz.logger, "junos", "lab10", "ex4200lab", "telnet", "test", "lab000", "lab", false)

	//dev.CreateDevice(jaz.table, jaz.logger, "cisco-iosxr", "lab11", "192.168.56.1:2011", "telnet", "user", "pass", "pass", false)
	//dev.CreateDevice(jaz.table, jaz.logger, "cisco-iosxr", "lab12", "192.168.56.1:2012", "ssh", "user", "pass", "cisco8", true)

	dev.UpdateLastSuccess(jaz.table, jaz.logger, jaz.repositoryPath)

	appAddr := "0.0.0.0:8080"
	serverName := fmt.Sprintf("%s application", appName)

	// Create GUI server
	server := gwu.NewServer(appName, appAddr)
	//folder := "./tls/"
	//server := gwu.NewServerTLS(appName, appAddr, folder+"cert.pem", folder+"key.pem")
	server.SetText(serverName)

	gopath := os.Getenv("GOPATH")
	pkgPath := filepath.Join("src", "github.com", "udhos", "jazigo") // from package github.com/udhos/jazigo
	staticDir := filepath.Join(gopath, pkgPath, "www")
	staticPath := "static"
	staticPathFull := fmt.Sprintf("/%s/%s", appName, staticPath)

	jaz.logf("static dir: path=[%s] mapped to dir=[%s]", staticPathFull, staticDir)

	jaz.cssPath = fmt.Sprintf("%s/jazigo.css", staticPathFull)
	jaz.logf("css path: %s", jaz.cssPath)

	server.AddStaticDir(staticPath, staticDir)

	// create account panel
	jaz.apHome = newAccPanel("")
	jaz.apAdmin = newAccPanel("")
	jaz.apLogout = newAccPanel("")
	accountPanelUpdate(jaz, "")

	buildHomeWin(jaz, server)
	buildLoginWin(jaz, server)

	if runOnce {
		dev.ScanDevices(jaz.table, logger, 3, 50*time.Millisecond, 500*time.Millisecond, jaz.repositoryPath, jaz.maxConfigFiles, jaz.holdtime)
		jaz.logf("runOnce: exiting after single scan")
		return
	}

	go func() {
		for {
			begin := time.Now()
			dev.ScanDevices(jaz.table, logger, 3, 50*time.Millisecond, 500*time.Millisecond, jaz.repositoryPath, jaz.maxConfigFiles, jaz.holdtime)
			elap := time.Since(begin)
			sleep := jaz.scanInterval - elap
			if sleep < 1 {
				sleep = 0
			}
			jaz.logf("main: scan loop sleeping for %s (target: scanInterval=%s)", sleep, jaz.scanInterval)
			time.Sleep(sleep)
		}
	}()

	// Start GUI server
	server.SetLogger(logger)
	if err := server.Start(); err != nil {
		jaz.logf("jazigo main: Cound not start GUI server: %s", err)
		return
	}
}
<commit_msg>Option for static www content.<commit_after>package main

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

	"github.com/icza/gowut/gwu"

	"github.com/udhos/jazigo/dev"
	"github.com/udhos/jazigo/store"
)

const appName = "jazigo"
const appVersion = "0.0"

type app struct {
	configPathPrefix string
	repositoryPath   string
	maxConfigFiles   int
	holdtime         time.Duration
	scanInterval     time.Duration

	table *dev.DeviceTable

	apHome    gwu.Panel
	apAdmin   gwu.Panel
	apLogout  gwu.Panel
	winHome   gwu.Window
	winAdmin  gwu.Window
	winLogout gwu.Window

	cssPath string

	logger hasPrintf
}

type hasPrintf interface {
	Printf(fmt string, v ...interface{})
}

func (a *app) logf(fmt string, v ...interface{}) {
	a.logger.Printf(fmt, v...)
}

func newApp(logger hasPrintf) *app {
	app := &app{
		table:        dev.NewDeviceTable(),
		logger:       logger,
		holdtime:     60 * time.Second, // FIXME: 12h (do not collect/save new backup before this timeout)
		scanInterval: 10 * time.Second, // FIXME: 1h (interval between full table scan)
	}

	app.logf("%s %s starting", appName, appVersion)

	dev.RegisterModels(app.logger, app.table)

	return app
}

func defaultStaticDir() string {
	gopath := os.Getenv("GOPATH")
	pkgPath := filepath.Join("src", "github.com", "udhos", "jazigo") // from package github.com/udhos/jazigo
	return filepath.Join(gopath, pkgPath, "www")
}

func main() {

	logger := log.New(os.Stdout, "", log.LstdFlags)

	jaz := newApp(logger)

	var runOnce bool
	var staticDir string

	flag.StringVar(&jaz.configPathPrefix, "configPathPrefix", "/etc/jazigo/jazigo.conf.", "configuration path prefix")
	flag.StringVar(&jaz.repositoryPath, "repositoryPath", "/var/jazigo", "repository path")
	flag.StringVar(&staticDir, "wwwStaticPath", defaultStaticDir(), "directory for static www content")
	flag.IntVar(&jaz.maxConfigFiles, "maxConfigFiles", 10, "limit number of configuration files (negative value means unlimited)")
	flag.BoolVar(&runOnce, "runOnce", false, "exit after scanning all devices once")
	flag.Parse()
	jaz.logf("config path prefix: %s", jaz.configPathPrefix)
	jaz.logf("repository path: %s", jaz.repositoryPath)
	jaz.logf("scan interval: %s", jaz.scanInterval)
	jaz.logf("holdtime: %s", jaz.holdtime)
	jaz.logf("runOnce: %v", runOnce)

	lastConfig, configErr := store.FindLastConfig(jaz.configPathPrefix, logger)
	if configErr != nil {
		jaz.logf("error reading config: '%s': %v", jaz.configPathPrefix, configErr)
	} else {
		jaz.logf("last config: %s", lastConfig)
	}

	//dev.CreateDevice(jaz.table, jaz.logger, "cisco-ios", "lab1", "localhost:2001", "telnet", "lab", "pass", "en")
	//dev.CreateDevice(jaz.table, jaz.logger, "cisco-ios", "lab1", "localhost:2001", "telnet", "lab", "pass", "en") // ugh
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab2", "localhost:2002", "ssh", "lab", "pass", "en")
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab3", "localhost:2003", "telnet,ssh", "lab", "pass", "en")
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab4", "localhost:2004", "ssh,telnet", "lab", "pass", "en")
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab5", "localhost", "telnet", "lab", "pass", "en")
	//dev.CreateDevice(jaz, jaz.logger, "cisco-ios", "lab6", "localhost", "ssh", "rat", "lab", "en")
	//dev.CreateDevice(jaz.table, jaz.logger, "http", "lab7", "localhost:2009", "telnet", "", "", "")

	dev.CreateDevice(jaz.table, jaz.logger, "linux", "lab8", "localhost", "ssh", "rat", "lab", "lab", false)
	dev.CreateDevice(jaz.table, jaz.logger, "junos", "lab9", "ex4200lab", "ssh", "test", "lab000", "lab", false)
	dev.CreateDevice(jaz.table, jaz.logger, "junos", "lab10", "ex4200lab", "telnet", "test", "lab000", "lab", false)

	//dev.CreateDevice(jaz.table, jaz.logger, "cisco-iosxr", "lab11", "192.168.56.1:2011", "telnet", "user", "pass", "pass", false)
	//dev.CreateDevice(jaz.table, jaz.logger, "cisco-iosxr", "lab12", "192.168.56.1:2012", "ssh", "user", "pass", "cisco8", true)

	dev.UpdateLastSuccess(jaz.table, jaz.logger, jaz.repositoryPath)

	appAddr := "0.0.0.0:8080"
	serverName := fmt.Sprintf("%s application", appName)

	// Create GUI server
	server := gwu.NewServer(appName, appAddr)
	//folder := "./tls/"
	//server := gwu.NewServerTLS(appName, appAddr, folder+"cert.pem", folder+"key.pem")
	server.SetText(serverName)

	staticPath := "static"
	staticPathFull := fmt.Sprintf("/%s/%s", appName, staticPath)
	jaz.logf("static dir: path=[%s] mapped to dir=[%s]", staticPathFull, staticDir)
	jaz.cssPath = fmt.Sprintf("%s/jazigo.css", staticPathFull)
	jaz.logf("css path: %s", jaz.cssPath)

	server.AddStaticDir(staticPath, staticDir)

	// create account panel
	jaz.apHome = newAccPanel("")
	jaz.apAdmin = newAccPanel("")
	jaz.apLogout = newAccPanel("")
	accountPanelUpdate(jaz, "")

	buildHomeWin(jaz, server)
	buildLoginWin(jaz, server)

	if runOnce {
		dev.ScanDevices(jaz.table, logger, 3, 50*time.Millisecond, 500*time.Millisecond, jaz.repositoryPath, jaz.maxConfigFiles, jaz.holdtime)
		jaz.logf("runOnce: exiting after single scan")
		return
	}

	go func() {
		for {
			begin := time.Now()
			dev.ScanDevices(jaz.table, logger, 3, 50*time.Millisecond, 500*time.Millisecond, jaz.repositoryPath, jaz.maxConfigFiles, jaz.holdtime)
			elap := time.Since(begin)
			sleep := jaz.scanInterval - elap
			if sleep < 1 {
				sleep = 0
			}
			jaz.logf("main: scan loop sleeping for %s (target: scanInterval=%s)", sleep, jaz.scanInterval)
			time.Sleep(sleep)
		}
	}()

	// Start GUI server
	server.SetLogger(logger)
	if err := server.Start(); err != nil {
		jaz.logf("jazigo main: Cound not start GUI server: %s", err)
		return
	}
}
<|endoftext|>